diff --git a/Makefile b/Makefile index 47ad0a2a826..ccf37e892d3 100644 --- a/Makefile +++ b/Makefile @@ -51,11 +51,17 @@ cluster-shell: ## Enter Nix shell and start the workbench cluster nix-shell --max-jobs 8 --cores 0 --show-trace --argstr profileName ${PROFILE} --arg 'autoStartCluster' true shell-dev: ARGS += --arg 'workbenchDevMode' true ## Enter Nix shell, dev mode (workbench run from checkout) -cluster-shell: ARGS += --arg 'autoStartCluster' true --arg 'workbenchDevMode' true ## Enter Nix shell, and start workbench cluster +cluster-shell: ARGS += --arg 'autoStartCluster' true ## Enter Nix shell, and start workbench cluster cluster-shell-dev: ARGS += --arg 'autoStartCluster' true --arg 'workbenchDevMode' true ## Enter Nix shell, dev mode, and start workbench cluster cluster-shell-trace: ARGS += --arg 'autoStartCluster' true --argstr 'autoStartClusterArgs' '--trace --trace-workbench' ## Enter Nix shell, start workbench cluster, with shell tracing cluster-shell-dev-trace: ARGS += --arg 'autoStartCluster' true --arg 'workbenchDevMode' true --argstr 'autoStartClusterArgs' '--trace --trace-workbench' ## Enter Nix shell, dev mode, start workbench cluster, with shell tracing -shell-dev cluster-shell-dev cluster-shell-trace cluster-shell-dev-trace: shell +fixed: ARGS += --arg 'autoStartCluster' true +fixed: PROFILE = fixed-alzo +smoke: ARGS += --arg 'autoStartCluster' true --run "grep TraceOpenEvent.ClosedDB run/current/node-0/stdout >/dev/null && echo 'Smoke test: PASS' || echo 'Smoke test: FAIL'" +smoke: PROFILE = smoke-alzo +smoke-loaded: ARGS += --arg 'autoStartCluster' true --run "grep TraceOpenEvent.ClosedDB run/current/node-0/stdout >/dev/null && echo 'Smoke test: PASS' || echo 'Smoke test: FAIL'" +smoke-loaded: PROFILE = smoke-loaded-alzo +shell-dev cluster-shell-dev cluster-shell-trace cluster-shell-dev-trace fixed smoke smoke-loaded: shell shell: ## Enter Nix shell, CI mode (workbench run from Nix store) nix-shell --max-jobs 8 --cores 0 --show-trace --argstr profileName ${PROFILE} ${ARGS} diff --git a/default.nix b/default.nix index 0321efd441a..4165d1f299f 100644 --- a/default.nix +++ b/default.nix @@ -45,16 +45,18 @@ let withHoogle = true; }; + clusterCabal = workbench-supervisord { inherit profileName haskellPackages; useCabalRun = true; }; + clusterNix = workbench-supervisord { inherit profileName haskellPackages; useCabalRun = false; }; + workbench-smoke-test = clusterNix.smoke-test { profileName = "smoke-loaded-alzo"; }; + packages = { inherit haskellPackages shell cardano-node cardano-node-profiled cardano-node-eventlogged cardano-cli db-converter cardano-ping locli locli-profiled tx-generator tx-generator-profiled - scripts environments dockerImage submitApiDockerImage bech32; - - clusterCabal = mkSupervisordCluster { inherit profileName; useCabalRun = true; }; - clusterNix = mkSupervisordCluster { inherit profileName; useCabalRun = false; }; + scripts environments dockerImage submitApiDockerImage bech32 + clusterNix clusterCabal workbench-smoke-test; devopsShell = shell.devops; diff --git a/nix/default.nix b/nix/default.nix index 2899e60a314..1ddfe0b19cf 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -53,6 +53,16 @@ let inherit system; gitrev = sources.plutus-example.rev; }).haskellPackages.plutus-example.components.exes) plutus-example; + + # This provides a supervisord-backed instance of a the workbench development environment + # that can be used with nix-shell or lorri. + # See https://input-output-hk.github.io/haskell.nix/user-guide/development/ + workbench-supervisord = + { useCabalRun, profileName, haskellPackages }: + pkgs.callPackage ./supervisord-cluster + { inherit profileName useCabalRun haskellPackages; + workbench = pkgs.callPackage ./workbench { inherit useCabalRun; }; + }; }) # And, of course, our haskell-nix-ified cabal project: (import ./pkgs.nix) diff --git a/nix/supervisord-cluster/default.nix b/nix/supervisord-cluster/default.nix index f6b22f1b4fb..8a30bb21ef1 100644 --- a/nix/supervisord-cluster/default.nix +++ b/nix/supervisord-cluster/default.nix @@ -5,6 +5,7 @@ let profileNameDefault = "default-alzo"; in { pkgs +, haskellPackages , workbench , lib , bech32 @@ -55,7 +56,7 @@ let finaliseNodeConfig = { port, ... }: cfg: recursiveUpdate cfg ({ - AlonzoGenesisFile = "../genesis-alonzo.json"; + AlonzoGenesisFile = "../genesis.alonzo.json"; ShelleyGenesisFile = "../genesis-shelley.json"; ByronGenesisFile = "../genesis/byron/genesis.json"; } // optionalAttrs enableEKG { @@ -66,6 +67,9 @@ let ]; }); + finaliseNodeArgs = + { port, ... }: cfg: cfg; + finaliseGeneratorService = svc: recursiveUpdate svc ({ @@ -79,7 +83,7 @@ let finaliseGeneratorConfig = cfg: recursiveUpdate cfg ({ - AlonzoGenesisFile = "../genesis-alonzo.json"; + AlonzoGenesisFile = "../genesis.alonzo.json"; ShelleyGenesisFile = "../genesis-shelley.json"; ByronGenesisFile = "../genesis/byron/genesis.json"; }); @@ -114,28 +118,22 @@ let }; }; - ## IMPORTANT: keep in sync with envArgs in 'workbench/default.nix/generateProfiles/environment'. - envArgs = - { - inherit (pkgs) cardanoLib; - inherit - stateDir - cacheDir basePort; - staggerPorts = true; - }; - - workbenchProfiles = workbench.generateProfiles - { inherit pkgs backend envArgs; }; + inherit + (workbench.with-workbench-profile + { inherit pkgs backend profileName; + + ## IMPORTANT: keep in sync with envArgs in 'workbench/default.nix/generateProfiles/environment'. + envArgs = + { + inherit (pkgs) cardanoLib; + inherit stateDir cacheDir basePort; + staggerPorts = true; + }; + }) + profile profileOut; in let - profile = workbenchProfiles.profiles."${profileName}" - or (throw "No such profile: ${profileName}; Known profiles: ${toString (__attrNames workbenchProfiles.profiles)}"); - - profileOut = workbench.profileOutput { inherit profile; - backendProfileOutput = - backend.profileOutput { inherit profile; }; - }; inherit (profile.value) era composition monetary; @@ -152,6 +150,7 @@ let export PATH=$PATH:${path} + set -x wb start \ --batch-name ${batchName} \ --profile-name ${profileName} \ @@ -163,6 +162,67 @@ let echo 'workbench: cluster started. Run `stop-cluster` to stop' >&2 ''; + smoke-test = + { profileName }: + let inherit + (workbench.with-workbench-profile + { inherit pkgs backend profileName; + + ## IMPORTANT: keep in sync with envArgs in 'workbench/default.nix/generateProfiles/environment'. + envArgs = + { + inherit (pkgs) cardanoLib; + inherit basePort; + cacheDir = "./cache"; + stateDir = "./"; + staggerPorts = true; + }; + }) + profile profileOut; + in + pkgs.runCommand "workbench-test-${profileName}" + { requiredSystemFeatures = [ "benchmark" ]; + nativeBuildInputs = with haskellPackages; with pkgs; [ + bash + bech32 + coreutils + gnused + jq + moreutils + nixWrapped + psmisc + python3Packages.supervisor + workbench.workbench + ]; + } + '' + mkdir -p $out/cache + cd $out + + ${workbench.shellHook} + + export CARDANO_NODE_SOCKET_PATH=$(wb backend get-node-socket-path ${stateDir}) + + wb start \ + --batch-name smoke-test \ + --profile-name ${profileName} \ + --profile-out ${profileOut} \ + --cache-dir ./cache \ + --base-port ${toString basePort} \ + + ## Cleanup: + rm -rf cache + rm -f run/{current,-current} genesis + mv run/env.json . + + tag=$(cd run; ls) + echo "workbench-test: completed run $tag" + + mv run/$tag/* . + rmdir run/$tag run + rm -f node-*/node.socket + ''; + stop = pkgs.writeScriptBin "stop-cluster" '' set -euo pipefail @@ -175,10 +235,10 @@ let wb run restart "$@" && \ echo "workbench: alternate command for this action: wb run restart" >&2 ''; - in { inherit workbench; inherit (workbenchProfiles) profilesJSON; inherit profile stateDir start stop restart; + inherit smoke-test; } diff --git a/nix/supervisord-cluster/supervisor-conf.nix b/nix/supervisord-cluster/supervisor-conf.nix index 497bc56122d..f6e1479e9fc 100644 --- a/nix/supervisord-cluster/supervisor-conf.nix +++ b/nix/supervisord-cluster/supervisor-conf.nix @@ -38,10 +38,11 @@ let { "program:generator" = { directory = "${stateDir}/generator"; - command = "${stateDir}/generator/start.sh"; + command = "sh start.sh"; stdout_logfile = "${stateDir}/generator/stdout"; stderr_logfile = "${stateDir}/generator/stderr"; autostart = false; + startretries = 0; }; } // @@ -58,6 +59,8 @@ let command = "sh start.sh"; stdout_logfile = "${service.value.stateDir}/stdout"; stderr_logfile = "${service.value.stateDir}/stderr"; + startretries = 0; + autorestart = false; }; in diff --git a/nix/supervisord-cluster/tests/default.nix b/nix/supervisord-cluster/tests/default.nix index f9770432b07..ccb30c495e6 100644 --- a/nix/supervisord-cluster/tests/default.nix +++ b/nix/supervisord-cluster/tests/default.nix @@ -1,9 +1,9 @@ { pkgs }: let - inherit (pkgs) mkSupervisordCluster cardano-cli cardanolib-py cardano-node; + inherit (pkgs) workbench-supervisord cardano-cli cardanolib-py cardano-node; stateDir = "./state-cluster-test"; # We want a really short duration for tests - cluster' = mkSupervisordCluster { + cluster' = workbench-supervisord { genesisParams = { slotLength = 0.1; decentralisationParam = 0.8; diff --git a/nix/svclib.nix b/nix/svclib.nix index f73bb70ef53..0558c637a65 100644 --- a/nix/svclib.nix +++ b/nix/svclib.nix @@ -232,23 +232,11 @@ let name: decl: extractServiceScript (decl // { svcName = name; }); - # This provides a development environment that can be used with nix-shell or - # lorri. See https://input-output-hk.github.io/haskell.nix/user-guide/development/ - # NOTE: due to some cabal limitation, - # you have to remove all `source-repository-package` entries from cabal.project - # after entering nix-shell for cabal to use nix provided dependencies for them. - mkSupervisordCluster = - { useCabalRun, profileName }: - pkgs.callPackage ./supervisord-cluster - { inherit profileName useCabalRun; - workbench = pkgs.callPackage ./workbench { inherit useCabalRun; }; - }; in { inherit defServiceModule mkScriptOfService mkServiceScript - mkSupervisordCluster ; } diff --git a/nix/workbench/backend.sh b/nix/workbench/backend.sh index 69650e3fc02..96f31bfbb61 100644 --- a/nix/workbench/backend.sh +++ b/nix/workbench/backend.sh @@ -20,6 +20,8 @@ usage_backend() { Start generator cleanup-cluster RUNDIR Wipe cluster state to pristine + wait-pools-stopped RUNDIR + Wait until all pools are stopped stop-cluster RUNDIR lostream-fixup-jqargs RUNDIR @@ -44,6 +46,7 @@ case "${op}" in start-cluster ) backend_$WORKBENCH_BACKEND "$@";; start-generator ) backend_$WORKBENCH_BACKEND "$@";; cleanup-cluster ) backend_$WORKBENCH_BACKEND "$@";; + wait-pools-stopped ) backend_$WORKBENCH_BACKEND "$@";; stop-cluster ) backend_$WORKBENCH_BACKEND "$@";; lostream-fixup-jqargs ) backend_$WORKBENCH_BACKEND "$@";; lostream-fixup-jqexpr ) backend_$WORKBENCH_BACKEND "$@";; diff --git a/nix/workbench/default.nix b/nix/workbench/default.nix index cd76286c02a..4681eb6eec1 100644 --- a/nix/workbench/default.nix +++ b/nix/workbench/default.nix @@ -88,13 +88,12 @@ let else "nix-exes+checkout-wb"; shellHook = '' + echo 'workbench shellHook: workbenchDevMode=${toString workbenchDevMode} useCabalRun=${toString useCabalRun}' export WORKBENCH_BACKEND=supervisor ${optionalString workbenchDevMode '' - echo 'workbench: dev mode enabled, calling wb directly from checkout (instead of using Nix store)' >&2 - export WORKBENCH_CARDANO_NODE_REPO_ROOT=$(git rev-parse --show-toplevel) export WORKBENCH_EXTRA_FLAGS= @@ -102,15 +101,15 @@ let $WORKBENCH_CARDANO_NODE_REPO_ROOT/nix/workbench/wb --set-mode ${checkoutWbMode} $WORKBENCH_EXTRA_FLAGS "$@" } export -f wb + ''} ${optionalString useCabalRun '' + . nix/workbench/lib.sh . nix/workbench/lib-cabal.sh ''} - ''} - export CARDANO_NODE_SOCKET_PATH=run/current/node-0/node.socket ''; @@ -197,9 +196,26 @@ let cp $nodeServicesPath $out/node-services.json cp $generatorServicePath $out/generator-service.json ''; + + with-workbench-profile = + { pkgs, backend, envArgs, profileName }: + let + workbenchProfiles = generateProfiles + { inherit pkgs backend envArgs; }; + + profile = workbenchProfiles.profiles."${profileName}" + or (throw "No such profile: ${profileName}; Known profiles: ${toString (__attrNames workbenchProfiles.profiles)}"); + + profileOut = profileOutput + { inherit profile; + backendProfileOutput = + backend.profileOutput { inherit profile; }; + }; + in { inherit profile profileOut; }; + in { - inherit workbench runWorkbench runJq; + inherit workbench runWorkbench runJq with-workbench-profile; inherit generateProfiles profileOutput shellHook; } diff --git a/nix/workbench/genesis.sh b/nix/workbench/genesis.sh index 4acc5329575..87ad12f0e47 100644 --- a/nix/workbench/genesis.sh +++ b/nix/workbench/genesis.sh @@ -3,7 +3,7 @@ global_genesis_format_version=September-10-2021 usage_genesis() { usage "genesis" "Genesis" < "$dir"/genesis-alonzo.json;; + "$global_basedir"/profiles/presets/mainnet/genesis/genesis-alonzo.json \ + > "$dir"/genesis.alonzo.json;; * ) usage_genesis;; esac } @@ -289,14 +297,14 @@ key_depl() { none ) suffix=;; sig ) suffix='.skey';; ver ) suffix='.vkey';; - * ) fail "key_depl: unknown key kind: '$kind'";; esac + * ) fatal "key_depl: unknown key kind: '$kind'";; esac case "$type" in bulk ) stem=node-keys/bulk$id;; cold ) stem=node-keys/cold/operator$id;; opcert ) stem=node-keys/node$id.opcert;; KES ) stem=node-keys/node-kes$id;; VRF ) stem=node-keys/node-vrf$id;; - * ) fail "key_depl: unknown key type: '$type'";; esac + * ) fatal "key_depl: unknown key type: '$type'";; esac echo "$__KEY_ROOT"/$stem$suffix } @@ -309,7 +317,7 @@ key_genesis() { none ) suffix=;; sig ) suffix='.skey';; ver ) suffix='.vkey';; - * ) fail "key_genesis: unknown key kind: '$kind'";; esac + * ) fatal "key_genesis: unknown key kind: '$kind'";; esac case "$type" in bulk ) stem=pools/bulk$id;; cold ) stem=pools/cold$id;; @@ -320,7 +328,7 @@ key_genesis() { delegCert )stem=delegate-keys/opcert$id;; delegKES ) stem=delegate-keys/delegate$id.kes;; delegVRF ) stem=delegate-keys/delegate$id.vrf;; - * ) fail "key_genesis: unknown key type: '$type'";; esac + * ) fatal "key_genesis: unknown key type: '$type'";; esac echo "$__KEY_ROOT"/$stem$suffix } diff --git a/nix/workbench/lib-cabal.sh b/nix/workbench/lib-cabal.sh index 39598ecd00f..1cb85b548f9 100644 --- a/nix/workbench/lib-cabal.sh +++ b/nix/workbench/lib-cabal.sh @@ -8,10 +8,10 @@ function workbench-prebuild-executables() git --no-pager log -n1 --alternate-refs --pretty=format:"%Cred%cr %Cblue%h %Cgreen%D %Cblue%s%Creset" --color echo - echo -n "workbench: prebuilding executables (because of useCabalRun): " + echo "workbench: prebuilding executables (because of useCabalRun)" unset NIX_ENFORCE_PURITY - for exe in cardano-cli cardano-node cardano-topology - do echo -n "$exe " + for exe in cardano-node cardano-cli cardano-topology + do echo "workbench: $(with_color blue prebuilding) $(with_color red $exe)" cabal -v0 build -- exe:$exe 2>&1 >/dev/null | { grep -v 'Temporary modify'; true; } || return 1 done diff --git a/nix/workbench/lib.sh b/nix/workbench/lib.sh index ac0ebf66704..d93e277f45e 100644 --- a/nix/workbench/lib.sh +++ b/nix/workbench/lib.sh @@ -64,6 +64,10 @@ msg() { echo "workbench: $*" >&2 } +msg_ne() { + echo -ne "workbench: $*" >&2 +} + fail() { msg "$*" exit 1 diff --git a/nix/workbench/profiles/adhoc.jq b/nix/workbench/profiles/adhoc.jq index 2298a0b485a..a883c3f4658 100644 --- a/nix/workbench/profiles/adhoc.jq +++ b/nix/workbench/profiles/adhoc.jq @@ -13,12 +13,12 @@ def adhoc_profiles: , tolerances: { finish_patience: 4 } , genesis: { genesis_future_offset: "3 minutes" } } -, { name: "smoke" - , generator: { tx_count: 100, add_tx_size: 0, inputs_per_tx: 1, outputs_per_tx: 1, tps: 100 - , init_cooldown: 25 } - , tolerances: { finish_patience: 4 } - , genesis: { genesis_future_offset: "3 minutes" } - } +# , { name: "smoke" +# , generator: { tx_count: 100, add_tx_size: 0, inputs_per_tx: 1, outputs_per_tx: 1, tps: 100 +# , init_cooldown: 25 } +# , tolerances: { finish_patience: 4 } +# , genesis: { genesis_future_offset: "3 minutes", delegators: 4 } +# } , { name: "smoke-plutus" , generator: { tx_count: 100, add_tx_size: 0, inputs_per_tx: 1, outputs_per_tx: 1, tps: 100 , init_cooldown: 25 diff --git a/nix/workbench/profiles/defaults.jq b/nix/workbench/profiles/defaults.jq index 3e174088960..a49991617cb 100644 --- a/nix/workbench/profiles/defaults.jq +++ b/nix/workbench/profiles/defaults.jq @@ -12,8 +12,8 @@ def era_defaults($era): ## Cluster topology and composition: , composition: { locations: ["LO"] - , n_bft_hosts: 1 - , n_singular_hosts: 1 + , n_bft_hosts: 0 + , n_singular_hosts: 2 , n_dense_hosts: 1 , dense_pool_density: 1 , with_proxy: false @@ -71,11 +71,12 @@ def era_defaults($era): , node: { rts_flags_override: [] + , shutdown_on_slot_synced: null , tracing_backend: "iohk-monitoring" ## or "trace-dispatcher" } , tolerances: - { cluster_startup_overhead_s: 60 + { cluster_startup_overhead_s: 10 , start_log_spread_s: 120 , last_log_spread_s: 120 , silence_since_last_block_s: 120 diff --git a/nix/workbench/profiles/derived.jq b/nix/workbench/profiles/derived.jq index d4463b08e80..f53dbc3ef1a 100644 --- a/nix/workbench/profiles/derived.jq +++ b/nix/workbench/profiles/derived.jq @@ -125,6 +125,11 @@ def add_derived_params: } , tolerances: { minimum_chain_density: ($gsis.active_slots_coeff * 0.5) + , cluster_startup_overhead_s: + (($gsis.utxo + $gsis.delegators) as $dataset_size + | if $dataset_size < 10000 then 5 + else $dataset_size / 25000 + end) } } } @@ -166,4 +171,9 @@ def profile_pretty_describe($p): , " - delegators: \($p.genesis.delegators)" , "" ] + | . + if $p.node.shutdown_on_slot_synced == null then [] + else [ + " - terminate at slot: \($p.node.shutdown_on_slot_synced)" + ] end + | . + [""] | join("\n"); diff --git a/nix/workbench/profiles/node-services.nix b/nix/workbench/profiles/node-services.nix index 74b474d356c..24053e958b1 100644 --- a/nix/workbench/profiles/node-services.nix +++ b/nix/workbench/profiles/node-services.nix @@ -137,13 +137,20 @@ let ## For the definition of 'nodeConfigBits', please see below. nodeConfig = - backend.finaliseNodeConfig nodeSpec - (recursiveUpdate - nodeConfigBits.base - (if __hasAttr "preset" profile.value - then readJSONMay (./presets + "/${profile.value.preset}/config.json") - else nodeConfigBits.era_setup_hardforks // - nodeConfigBits.tracing.${profile.value.node.tracing_backend})); + backend.finaliseNodeConfig nodeSpec + (recursiveUpdate + nodeConfigBits.base + (if __hasAttr "preset" profile.value + then readJSONMay (./presets + "/${profile.value.preset}/config.json") + else nodeConfigBits.era_setup_hardforks // + nodeConfigBits.tracing.${profile.value.node.tracing_backend})); + + extraArgs = + let shutdownSlot = profile.value.node.shutdown_on_slot_synced; + in backend.finaliseNodeArgs nodeSpec + (if shutdownSlot != null + then ["--shutdown-on-slot-synced" (toString shutdownSlot)] + else []); }; ## Given an env config, evaluate it and produce the node service. diff --git a/nix/workbench/profiles/variants.jq b/nix/workbench/profiles/variants.jq index 0f4a9cc764f..e86ac5e937a 100644 --- a/nix/workbench/profiles/variants.jq +++ b/nix/workbench/profiles/variants.jq @@ -37,6 +37,29 @@ def genesis_profile_variants: , { genesis: { utxo: 2000000, delegators: 500000, max_block_size: 2048000 } , generator: { tps: 256 } } + ## Fixed + , { name: "fixed" + , scenario: "fixed" + , genesis: { utxo: 4000000, delegators: 1000000 } + , node: + { shutdown_on_slot_synced: 150 + } + } + , { name: "smoke" + , scenario: "fixed" + , genesis: { utxo: 100, delegators: 9 } + , node: + { shutdown_on_slot_synced: 150 + } + } + , { name: "smoke-loaded" + , scenario: "fixed-loaded" + , genesis: { utxo: 100, delegators: 9 } + , node: + { shutdown_on_slot_synced: 150 + } + , generator: { tps: 10 } + } ## Chainsync: , { name: "chainsync" diff --git a/nix/workbench/run.sh b/nix/workbench/run.sh index 1faa89ac9d6..c64abf1835d 100644 --- a/nix/workbench/run.sh +++ b/nix/workbench/run.sh @@ -71,8 +71,7 @@ case "$op" in if test ! -f "$dir"/genesis-shelley.json then msg "fixing up genesis naming in: $dir" - mv "$dir"/genesis.json "$dir"/genesis-shelley.json - ln -s genesis-shelley.json "$dir"/genesis.json; fi + mv "$dir"/genesis.json "$dir"/genesis-shelley.json; fi if test -z "$(ls -d "$dir"/node-* 2>/dev/null)" then msg "fixing up a legacy cardano-ops run in: $dir" @@ -315,6 +314,22 @@ case "$op" in topology make "$dir"/profile.json "$dir"/topology + local cacheDir=$(jq -r .cacheDir "$global_envjson") + test "$cacheDir" != 'null' -a -d "$cacheDir" || + fatal "invalid global env JSON" + + local genesis_args=( + ## Positionals: + "$cacheDir"/genesis "$dir"/profile.json + "$dir"/topology + "$dir"/genesis + ) + genesis prepare "${genesis_args[@]}" + + ## Record geneses + cp "$dir"/genesis/genesis-shelley.json "$dir"/genesis-shelley.json + cp "$dir"/genesis/genesis.alonzo.json "$dir"/genesis.alonzo.json + local svcs=$profileOut/node-services.json for node in $(jq_tolist 'keys' "$dir"/node-specs.json) do local node_dir="$dir"/$node @@ -332,6 +347,7 @@ case "$op" in cp $(jq '."run-script"' -r $gtor) "$gen_dir"/run-script.json cp $(jq '."service-config"' -r $gtor) "$gen_dir"/service-config.json cp $(jq '."start"' -r $gtor) "$gen_dir"/start.sh + ln -s ../node-0/config.json "$gen_dir" backend allocate-run "$dir" @@ -340,7 +356,7 @@ case "$op" in run set-current "$tag" - msg "current run is: $tag / $dir" + msg "current run is: $(with_color yellow $tag) @ $dir" ;; list-hosts | hosts ) @@ -450,23 +466,10 @@ EOF local tag=${1:-?$usage}; shift local dir=$(run get "$tag") + test -d "$dir" || + fatal "invalid run tag: $tag" run set-current "$tag" - local cacheDir=$(jq -r .cacheDir "$global_envjson") - if test "$cacheDir" = 'null' - then fatal "invalid meta.json in current run: $dir/meta.json"; fi - - local genesis_args=( - ## Positionals: - "$cacheDir"/genesis "$dir"/profile.json - "$dir"/topology - "$dir"/genesis - ) - genesis prepare "${genesis_args[@]}" - - ## Record geneses - cp "$dir"/genesis/genesis-shelley.json "$dir"/genesis-shelley.json - cp "$dir"/genesis/genesis-alonzo.json "$dir"/genesis-alonzo.json ## Execute the scenario local scenario=${scenario_override:-$(jq -r .scenario "$dir"/profile.json)} @@ -490,7 +493,7 @@ EOF local dir=$(run get "$tag") test -d "$dir" || - fail "no valid current run to restart: please set run/current appropriately" + fatal "no valid current run to restart: please set run/current appropriately" msg "restarting cluster in the same run directory: $dir" diff --git a/nix/workbench/scenario.sh b/nix/workbench/scenario.sh index 26b49c4db20..911887e8919 100644 --- a/nix/workbench/scenario.sh +++ b/nix/workbench/scenario.sh @@ -11,7 +11,8 @@ usage_scenario() { 1. start the preset-defined proxy node, using its respective connected topology mode, fetching the chain up to the specified slot - 2. restart the proxy with a disconnected topogy mode, effectively making it an idle chaindb server + 2. restart the proxy with a disconnected topogy mode, + effectively making it an idle chaindb server 3. start the fetcher node, connected to the proxy EOF @@ -22,17 +23,30 @@ local op=${1:---help}; shift local usage="USAGE: wb scenario SCENARIO-OP OP-ARGS.." local dir=${1:?$usage}; shift -msg "starting scenario: $(with_color blue $op)" +msg "starting scenario: $(with_color blue $op)" case "$op" in idle | default ) backend start-cluster "$dir" ;; + fixed ) + backend start-cluster "$dir" + backend wait-pools-stopped "$dir" + backend stop-cluster "$dir" + ;; + loaded ) backend start-cluster "$dir" backend start-generator "$dir" ;; + fixed-loaded ) + backend start-cluster "$dir" + backend start-generator "$dir" + backend wait-pools-stopped "$dir" + backend stop-cluster "$dir" + ;; + chainsync ) ## This starts all nodes, due to unconditional start-up, ## to start in default mode -- meaning that: diff --git a/nix/workbench/supervisor.sh b/nix/workbench/supervisor.sh index fd36f86f51d..db2f9b0a56f 100755 --- a/nix/workbench/supervisor.sh +++ b/nix/workbench/supervisor.sh @@ -18,6 +18,7 @@ usage_supervisor() { start-cluster RUN-DIR start-generator RUN-DIR cleanup-cluster RUN-DIR + wait-pools-stopped RUNDIR stop-cluster RUN-DIR Supervisor-specific: @@ -115,11 +116,20 @@ EOF then export CARDANO_NODE_SOCKET_PATH=$(backend_supervisor get-node-socket-path "$dir") fi - echo -n "workbench: supervisor: waiting for $CARDANO_NODE_SOCKET_PATH to appear: " >&2 + local patience=$(jq .tolerances.cluster_startup_overhead_s $dir/profile.json) i=0 + echo -n "workbench: supervisor: waiting ${patience}s for $CARDANO_NODE_SOCKET_PATH to appear: " >&2 while test ! -S $CARDANO_NODE_SOCKET_PATH - do echo -n '.'; sleep 1 + do printf "%3d" $i; sleep 1 + i=$((i+1)) + if test $i -ge $patience + then echo + msg "FATAL: workbench: supervisor: patience ran out after ${patience}s" + backend_supervisor stop-cluster "$dir" + fatal "node startup did not succeed: check logs in $dir/node-0" + fi + echo -ne "\b\b\b" done >&2 - echo >&2 + echo " node-0 online after $i seconds" >&2 backend_supervisor save-pids "$dir";; @@ -142,6 +152,19 @@ EOF rm -f $dir/*/std{out,err} $dir/node-*/*.socket $dir/*/logs/* 2>/dev/null || true rm -fr $dir/node-*/state-cluster/;; + wait-pools-stopped ) + local usage="USAGE: wb supervisor $op RUN-DIR" + local dir=${1:?$usage}; shift + + local i=0 pools=$(jq .composition.n_pool_hosts $dir/profile.json) + msg_ne "supervisor: waiting until all pool nodes are stopped: 000000" + for ((pool_ix=0; pool_ix < $pools; pool_ix++)) + do while supervisorctl status node-${pool_ix} > /dev/null + do echo -ne "\b\b\b\b\b\b"; printf "%6d" $i; i=$((i+1)); sleep 1; done + echo -ne "\b\b\b\b\b\b"; echo -n "node-${pool_ix} 000000" + done >&2 + echo " done." >&2;; + stop-cluster ) local usage="USAGE: wb supervisor $op RUN-DIR" local dir=${1:?$usage}; shift diff --git a/nix/workbench/topology.sh b/nix/workbench/topology.sh index 0946e75d936..a3c2b48f87b 100644 --- a/nix/workbench/topology.sh +++ b/nix/workbench/topology.sh @@ -55,8 +55,6 @@ case "${op}" in args=( --topology-output "$outdir"/topology-nixops.json --dot-output "$outdir"/topology.dot --size $n_hosts - ## TODO: drop this, once we fully deprecate BFT in all scenarios - --with-bft-node-0 $(jq '.composition.locations | map("--loc " + .) diff --git a/nix/workbench/wb b/nix/workbench/wb index 5c930e557ae..eedfaf323c2 100755 --- a/nix/workbench/wb +++ b/nix/workbench/wb @@ -68,7 +68,7 @@ Usage: Flags: - --batch-name NAME Override the batch name (default: ${batchName}) + --batch-name NAME Override the batch name (default: ${batchName:-default}) --no-generator | --no-gen Don't auto-start the tx-generator --cabal 'cabal run' mode for cardano-* executables diff --git a/release.nix b/release.nix index 6bcce4482e4..afc3b385c49 100644 --- a/release.nix +++ b/release.nix @@ -130,6 +130,7 @@ let [ "tx-generator" ] [ "tx-generator-profiled" ] [ "locli-profiled" ] + [ "workbench-smoke-test" ] ]; # Paths or prefix of paths for which cross-builds (mingwW64, musl64) are disabled: noCrossBuild = [ @@ -205,6 +206,7 @@ let (collectJobs jobs.linux.native.shell) (collectJobs jobs.linux.native.devopsShell) (collectJobs jobs.linux.native.devShell) + (collectJobs jobs.linux.native.workbench-smoke-test) [ jobs.cardano-node-linux ] ])) # macOS builds: diff --git a/shell.nix b/shell.nix index af1e745fa31..37088824941 100644 --- a/shell.nix +++ b/shell.nix @@ -50,8 +50,8 @@ let haveGlibcLocales = pkgs.glibcLocales != null && stdenv.hostPlatform.libc == "glibc"; shell = - let cluster = pkgs.commonLib.mkSupervisordCluster - { inherit profileName; + let cluster = pkgs.workbench-supervisord + { inherit haskellPackages profileName; useCabalRun = true; }; in cardanoNodeProject.shellFor { @@ -108,7 +108,7 @@ let exactDeps = true; shellHook = '' - echo 'nix-shell options & flags: withHoogle=${toString withHoogle} profileName=${profileName} autoStartCluster=${toString autoStartCluster} workbenchDevMode=${toString workbenchDevMode}' + echo 'nix-shell top-level shellHook: withHoogle=${toString withHoogle} profileName=${profileName} autoStartCluster=${toString autoStartCluster} workbenchDevMode=${toString workbenchDevMode}' ${cluster.workbench.shellHook} @@ -136,8 +136,9 @@ let }; devops = - let cluster = pkgs.commonLib.mkSupervisordCluster - { profileName = "devops-alzo"; + let cluster = pkgs.workbench-supervisord + { inherit haskellPackages; + profileName = "devops-alzo"; useCabalRun = false; }; in cardanoNodeProject.shellFor {