2023-10-20 13:48:37 +00:00
|
|
|
(ns jepsen.garage.nemesis
|
|
|
|
(:require [clojure.tools.logging :refer :all]
|
|
|
|
[jepsen [control :as c]
|
|
|
|
[core :as jepsen]
|
|
|
|
[generator :as gen]
|
|
|
|
[nemesis :as nemesis]]
|
2023-10-25 09:41:34 +00:00
|
|
|
[jepsen.nemesis.combined :as combined]
|
2023-10-20 13:48:37 +00:00
|
|
|
[jepsen.garage.daemon :as grg]
|
|
|
|
[jepsen.control.util :as cu]))
|
|
|
|
|
2023-10-24 09:39:45 +00:00
|
|
|
; ---- reconfiguration nemesis ----
|
|
|
|
|
2023-10-20 13:48:37 +00:00
|
|
|
(defn configure-present!
|
|
|
|
"Configure node to be active in new cluster layout"
|
2023-10-25 09:41:34 +00:00
|
|
|
[test nodes]
|
|
|
|
(info "configure-present!" nodes)
|
|
|
|
(let [node-ids (c/on-many nodes (c/exec grg/binary :node :id :-q))
|
|
|
|
node-id-strs (map (fn [[_ v]] (subs v 0 16)) node-ids)]
|
|
|
|
(c/on
|
|
|
|
(jepsen/primary test)
|
|
|
|
(apply c/exec (concat [grg/binary :layout :assign :-c :1G] node-id-strs)))))
|
2023-10-20 13:48:37 +00:00
|
|
|
|
|
|
|
(defn configure-absent!
|
2023-10-25 09:41:34 +00:00
|
|
|
"Configure nodes to be active in new cluster layout"
|
|
|
|
[test nodes]
|
|
|
|
(info "configure-absent!" nodes)
|
|
|
|
(let [node-ids (c/on-many nodes (c/exec grg/binary :node :id :-q))
|
|
|
|
node-id-strs (map (fn [[_ v]] (subs v 0 16)) node-ids)]
|
|
|
|
(c/on
|
|
|
|
(jepsen/primary test)
|
|
|
|
(apply c/exec (concat [grg/binary :layout :assign :-g] node-id-strs)))))
|
2023-10-20 13:48:37 +00:00
|
|
|
|
|
|
|
(defn finalize-config!
|
|
|
|
"Apply the proposed cluster layout"
|
|
|
|
[test]
|
|
|
|
(let [layout-show (c/on (jepsen/primary test) (c/exec grg/binary :layout :show))
|
|
|
|
[_ layout-next-version] (re-find #"apply --version (\d+)\n" layout-show)]
|
2023-10-24 14:39:50 +00:00
|
|
|
(if layout-next-version
|
|
|
|
(do
|
|
|
|
(info "layout show: " layout-show "; next-version: " layout-next-version)
|
|
|
|
(c/on (jepsen/primary test)
|
|
|
|
(c/exec grg/binary :layout :apply :--version layout-next-version)))
|
|
|
|
(info "no layout changes to apply"))))
|
2023-10-20 13:48:37 +00:00
|
|
|
|
|
|
|
(defn reconfigure-subset
|
|
|
|
"Reconfigure cluster with only a subset of nodes"
|
|
|
|
[cnt]
|
|
|
|
(reify nemesis/Nemesis
|
|
|
|
(setup! [this test] this)
|
|
|
|
|
|
|
|
(invoke! [this test op] op
|
|
|
|
(case (:f op)
|
|
|
|
:start
|
|
|
|
(let [[keep-nodes remove-nodes]
|
|
|
|
(->> (:nodes test)
|
|
|
|
shuffle
|
|
|
|
(split-at cnt))]
|
|
|
|
(info "layout split: keep " keep-nodes ", remove " remove-nodes)
|
2023-10-25 09:41:34 +00:00
|
|
|
(configure-present! test keep-nodes)
|
|
|
|
(configure-absent! test remove-nodes)
|
2023-10-20 13:48:37 +00:00
|
|
|
(finalize-config! test)
|
|
|
|
(assoc op :value keep-nodes))
|
|
|
|
:stop
|
|
|
|
(do
|
|
|
|
(info "layout un-split: all nodes=" (:nodes test))
|
2023-10-25 09:41:34 +00:00
|
|
|
(configure-present! test (:nodes test))
|
2023-10-20 13:48:37 +00:00
|
|
|
(finalize-config! test)
|
|
|
|
(assoc op :value (:nodes test)))))
|
|
|
|
|
|
|
|
(teardown! [this test] this)))
|
|
|
|
|
2023-10-24 09:39:45 +00:00
|
|
|
; ---- nemesis scenari ----
|
|
|
|
|
2023-10-24 14:39:50 +00:00
|
|
|
(defn nemesis-op
|
|
|
|
"A generator for a single nemesis operation"
|
|
|
|
[op]
|
|
|
|
(fn [_ _] {:type :info, :f op}))
|
|
|
|
|
2023-10-25 09:41:34 +00:00
|
|
|
(defn reconfiguration-package
|
|
|
|
"Cluster reconfiguration nemesis package"
|
2023-10-24 09:39:45 +00:00
|
|
|
[opts]
|
2023-10-24 14:39:50 +00:00
|
|
|
{:generator (->>
|
2023-10-25 09:41:34 +00:00
|
|
|
(gen/mix [(nemesis-op :reconfigure-start)
|
|
|
|
(nemesis-op :reconfigure-stop)])
|
|
|
|
(gen/stagger (:interval opts 5)))
|
|
|
|
:final-generator {:type :info, :f :reconfigure-stop}
|
2023-10-24 09:39:45 +00:00
|
|
|
:nemesis (nemesis/compose
|
2023-10-25 09:41:34 +00:00
|
|
|
{{:reconfigure-start :start
|
|
|
|
:reconfigure-stop :stop} (reconfigure-subset 3)})
|
|
|
|
:perf #{{:name "reconfigure"
|
|
|
|
:start #{:reconfigure-start}
|
|
|
|
:stop #{:reconfigur-stop}
|
|
|
|
:color "#A197E9"}}})
|
|
|
|
|
|
|
|
(defn scenario-c
|
|
|
|
"Clock modifying scenario"
|
|
|
|
[opts]
|
|
|
|
(combined/clock-package {:db (:db opts), :interval 1, :faults #{:clock}}))
|
2023-10-24 09:39:45 +00:00
|
|
|
|
2023-10-20 13:48:37 +00:00
|
|
|
(defn scenario-cp
|
2023-10-25 09:41:34 +00:00
|
|
|
"Clock modifying + partition scenario"
|
2023-10-20 13:48:37 +00:00
|
|
|
[opts]
|
2023-10-25 09:41:34 +00:00
|
|
|
(combined/compose-packages
|
|
|
|
[(combined/clock-package {:db (:db opts), :interval 1, :faults #{:clock}})
|
|
|
|
(combined/partition-package {:db (:db opts), :interval 1, :faults #{:partition}})]))
|
2023-10-20 13:48:37 +00:00
|
|
|
|
|
|
|
(defn scenario-r
|
|
|
|
"Cluster reconfiguration scenario"
|
|
|
|
[opts]
|
2023-10-25 09:41:34 +00:00
|
|
|
(reconfiguration-package {:interval 1}))
|
2023-10-24 09:39:45 +00:00
|
|
|
|
|
|
|
(defn scenario-pr
|
|
|
|
"Partition + cluster reconfiguration scenario"
|
|
|
|
[opts]
|
2023-10-25 09:41:34 +00:00
|
|
|
(combined/compose-packages
|
|
|
|
[(combined/partition-package {:db (:db opts), :interval 1, :faults #{:partition}})
|
|
|
|
(reconfiguration-package {:interval 1})]))
|
2023-10-24 13:44:05 +00:00
|
|
|
|
|
|
|
(defn scenario-cpr
|
|
|
|
"Clock scramble + partition + cluster reconfiguration scenario"
|
|
|
|
[opts]
|
2023-10-25 09:41:34 +00:00
|
|
|
(combined/compose-packages
|
|
|
|
[(combined/clock-package {:db (:db opts), :interval 1, :faults #{:clock}})
|
|
|
|
(combined/partition-package {:db (:db opts), :interval 1, :faults #{:partition}})
|
|
|
|
(reconfiguration-package {:interval 1})]))
|
|
|
|
|
2023-10-25 12:43:24 +00:00
|
|
|
(defn scenario-cdp
|
|
|
|
"Clock modifying + db + partition scenario"
|
|
|
|
[opts]
|
|
|
|
(combined/compose-packages
|
|
|
|
[(combined/clock-package {:db (:db opts), :interval 1, :faults #{:clock}})
|
|
|
|
(combined/db-package {:db (:db opts), :interval 1, :faults #{:db :pause :kill}})
|
|
|
|
(combined/partition-package {:db (:db opts), :interval 1, :faults #{:partition}})]))
|
|
|
|
|
2023-10-25 09:41:34 +00:00
|
|
|
(defn scenario-dpr
|
|
|
|
"Db + partition + cluster reconfiguration scenario"
|
|
|
|
[opts]
|
|
|
|
(combined/compose-packages
|
|
|
|
[(combined/db-package {:db (:db opts), :interval 1, :faults #{:db :pause :kill}})
|
|
|
|
(combined/partition-package {:db (:db opts), :interval 1, :faults #{:partition}})
|
|
|
|
(reconfiguration-package {:interval 1})]))
|
2023-10-25 12:43:24 +00:00
|
|
|
|