diff --git a/tezt/lib_cloud/README.md b/tezt/lib_cloud/README.md index 395f709a1f48666bd40a7f8497218f9f3c6682ab..326609df3b6f4e99dec6ce0f5e61a816b89ae2ba 100644 --- a/tezt/lib_cloud/README.md +++ b/tezt/lib_cloud/README.md @@ -54,7 +54,9 @@ Run the following commands: artifact registries of Google (necessary for pushing docker images). 5. `sudo usermod -aG docker $USER` where `$USER` is your user. This is to enable - `docker` commands to be run without being sudo. + `docker` commands to be run without being sudo. This is only required for `Linux` + distributions, as on `macOS` `docker` runs inside a virtualized environment and + the user automatically has the necessary privileges. 6. `gcloud config set project [YOUR_PROJECT_ID]`: For configuring the default project. @@ -91,7 +93,7 @@ provided in `tezt/lib_cloud/dockerfiles/debian.Dockerfile`. The library takes care for you to push this image on a dedicated GCP registry. A docker image such as the one generated from `debian.Dockerfile` may contain some binaries. Tezt cloud always -try to rebuild the docker image to be sure it uses the last version, +tries to rebuild the docker image to be sure it uses the last version, however be sure to compile the binaries beforehand. Finally, do note that with Tezt cloud you can specify for each VM diff --git a/tezt/lib_tezos/agnostic_baker.ml b/tezt/lib_tezos/agnostic_baker.ml index 151838945af3afbb544a3d5e6f23becf6368431c..e1f280dc5da92b34b2e82a892cfc530ecca2d285 100644 --- a/tezt/lib_tezos/agnostic_baker.ml +++ b/tezt/lib_tezos/agnostic_baker.ml @@ -30,6 +30,7 @@ module Parameters = struct node_data_dir : string; node_rpc_endpoint : Endpoint.t; dal_node_rpc_endpoint : Endpoint.t option; + dal_node_timeout_percentage : int option; mutable pending_ready : unit option Lwt.u list; votefile : string option; liquidity_baking_toggle_vote : liquidity_baking_vote option; @@ -82,8 +83,9 @@ let create_from_uris ?runner ?event_pipe ?(delegates = []) ?votefile ?(liquidity_baking_toggle_vote = Some Pass) ?force_apply_from_round ?(remote_mode = false) ?operations_pool ?dal_node_rpc_endpoint - ?(state_recorder = false) ?(node_version_check_bypass = false) - ?node_version_allowed ~base_dir ~node_data_dir ~node_rpc_endpoint () = + ?dal_node_timeout_percentage ?(state_recorder = false) + ?(node_version_check_bypass = false) ?node_version_allowed ~base_dir + ~node_data_dir ~node_rpc_endpoint () = let agnostic_baker = create ~path @@ -104,6 +106,7 @@ let create_from_uris ?runner remote_mode; operations_pool; dal_node_rpc_endpoint; + dal_node_timeout_percentage; state_recorder; node_version_check_bypass; node_version_allowed; @@ -116,7 +119,8 @@ let handle_event node ({name; _} : event) = let create ?runner ?path ?name ?color ?event_pipe ?(delegates = []) ?votefile ?(liquidity_baking_toggle_vote = Some Pass) ?force_apply_from_round - ?(remote_mode = false) ?operations_pool ?dal_node ?(state_recorder = false) + ?(remote_mode = false) ?operations_pool ?dal_node + ?dal_node_timeout_percentage ?(state_recorder = false) ?(node_version_check_bypass = false) ?node_version_allowed node client = let dal_node_rpc_endpoint = Option.map Dal_node.as_rpc_endpoint dal_node in let agnostic_baker = @@ -133,6 +137,7 @@ let create ?runner ?path ?name ?color ?event_pipe ?(delegates = []) ?votefile ~remote_mode ?operations_pool ?dal_node_rpc_endpoint + ?dal_node_timeout_percentage ~state_recorder ~node_version_check_bypass ?node_version_allowed @@ -144,7 +149,7 @@ let create ?runner ?path ?name ?color ?event_pipe ?(delegates = []) ?votefile on_event agnostic_baker (handle_event agnostic_baker) ; agnostic_baker -let run ?event_level ?event_sections_levels (agnostic_baker : t) = +let run ?env ?event_level ?event_sections_levels (agnostic_baker : t) = (match agnostic_baker.status with | Not_running -> () | Running _ -> @@ -194,6 +199,12 @@ let run ?event_level ?event_sections_levels (agnostic_baker : t) = "without-dal" (Option.is_none agnostic_baker.persistent_state.dal_node_rpc_endpoint) in + let dal_node_timeout_percentage = + Cli_arg.optional_arg + "dal-node-timeout-percentage" + string_of_int + agnostic_baker.persistent_state.dal_node_timeout_percentage + in let state_recorder = Cli_arg.optional_switch "record-state" @@ -218,7 +229,8 @@ let run ?event_level ?event_sections_levels (agnostic_baker : t) = ["--"; "--endpoint"; node_addr; "--base-dir"; base_dir; "run"] @ run_args @ delegates @ liquidity_baking_toggle_vote @ votefile @ force_apply_from_round @ operations_pool @ dal_node_endpoint @ without_dal - @ state_recorder @ node_version_check_bypass @ node_version_allowed + @ dal_node_timeout_percentage @ state_recorder @ node_version_check_bypass + @ node_version_allowed in let on_terminate _ = @@ -227,6 +239,7 @@ let run ?event_level ?event_sections_levels (agnostic_baker : t) = unit in run + ?env ?event_level ?event_sections_levels agnostic_baker @@ -253,12 +266,12 @@ let wait_for_ready agnostic_baker = resolver :: agnostic_baker.persistent_state.pending_ready ; check_event agnostic_baker "agnostic baker started" promise -let init ?runner ?(path = Uses.path Constant.octez_experimental_agnostic_baker) - ?name ?color ?event_level ?event_pipe ?event_sections_levels - ?(delegates = []) ?votefile ?liquidity_baking_toggle_vote - ?force_apply_from_round ?remote_mode ?operations_pool ?dal_node - ?state_recorder ?node_version_check_bypass ?node_version_allowed node client - = +let init ?env ?runner + ?(path = Uses.path Constant.octez_experimental_agnostic_baker) ?name ?color + ?event_level ?event_pipe ?event_sections_levels ?(delegates = []) ?votefile + ?liquidity_baking_toggle_vote ?force_apply_from_round ?remote_mode + ?operations_pool ?dal_node ?dal_node_timeout_percentage ?state_recorder + ?node_version_check_bypass ?node_version_allowed node client = let* () = Node.wait_for_ready node in let agnostic_baker = create @@ -273,6 +286,7 @@ let init ?runner ?(path = Uses.path Constant.octez_experimental_agnostic_baker) ?remote_mode ?operations_pool ?dal_node + ?dal_node_timeout_percentage ?state_recorder ?node_version_check_bypass ?node_version_allowed @@ -280,7 +294,7 @@ let init ?runner ?(path = Uses.path Constant.octez_experimental_agnostic_baker) node client in - let* () = run ?event_level ?event_sections_levels agnostic_baker in + let* () = run ?env ?event_level ?event_sections_levels agnostic_baker in let* () = wait_for_ready agnostic_baker in return agnostic_baker diff --git a/tezt/lib_tezos/agnostic_baker.mli b/tezt/lib_tezos/agnostic_baker.mli index bb2b992958a7d919e8f9753ceddfeba12aae9ba5..4109b16f324c85a9f8eb370c978bb6921613614e 100644 --- a/tezt/lib_tezos/agnostic_baker.mli +++ b/tezt/lib_tezos/agnostic_baker.mli @@ -49,6 +49,7 @@ val on_event : t -> (event -> unit) -> unit The resulting promise is fulfilled as soon as the agnostic baker has been spawned. It continues running in the background. *) val run : + ?env:string String_map.t -> ?event_level:Daemon.Level.default_level -> ?event_sections_levels:(string * Daemon.Level.level) list -> t -> @@ -134,6 +135,7 @@ val create : ?remote_mode:bool -> ?operations_pool:string -> ?dal_node:Dal_node.t -> + ?dal_node_timeout_percentage:int -> ?state_recorder:bool -> ?node_version_check_bypass:bool -> ?node_version_allowed:string -> @@ -172,6 +174,7 @@ val create_from_uris : ?remote_mode:bool -> ?operations_pool:string -> ?dal_node_rpc_endpoint:Endpoint.t -> + ?dal_node_timeout_percentage:int -> ?state_recorder:bool -> ?node_version_check_bypass:bool -> ?node_version_allowed:string -> @@ -218,6 +221,7 @@ val create_from_uris : If [remote_mode] is specified, the agnostic baker will run in RPC-only mode. *) val init : + ?env:string String_map.t -> ?runner:Runner.t -> ?path:string -> ?name:string -> @@ -232,6 +236,7 @@ val init : ?remote_mode:bool -> ?operations_pool:string -> ?dal_node:Dal_node.t -> + ?dal_node_timeout_percentage:int -> ?state_recorder:bool -> ?node_version_check_bypass:bool -> ?node_version_allowed:string -> diff --git a/tezt/tests/cloud/layer1.ml b/tezt/tests/cloud/layer1.ml index 90ecbc5ef3e55b09a87428a09b27bfa60cfa0e98..3356682790e02415088d3a49f4003817d4f6df38 100644 --- a/tezt/tests/cloud/layer1.ml +++ b/tezt/tests/cloud/layer1.ml @@ -183,7 +183,7 @@ module Node = struct create the yes-wallet. *) let init_bootstrap_node ~peers ~snapshot ~network (agent, node, name) = - toplog "Initializing a L1 node (public network): %s" name ; + toplog "Initializing an L1 node (public network): %s" name ; let* () = init_bootstrap_node_from_snapshot ~peers (agent, node) snapshot network in @@ -208,7 +208,7 @@ module Node = struct *) let init_baker_node ?(delay = 0) ~accounts ~peers ~snapshot ~network (agent, node, name) = - toplog "Inititializing a L1 node (public network): %s" name ; + toplog "Initializing an L1 node (public network): %s" name ; let* () = init_node_from_snapshot ~delay ~peers ~snapshot ~network (agent, node) in @@ -261,8 +261,14 @@ type stresstest_conf = {pkh : string; pk : string; tps : int; seed : int} snapshot will result in the same delegate repartition. There is a special case using a single number instead of a list, which - must match the number of delegates. This scenario will launch on node - per delegate (i.e. more than 300 nodes if testing on mainnet) + must match the number of delegates. This scenario will launch one node + per delegate (i.e. more than 300 nodes if testing on mainnet). + + - [agnostic_bakers] specifies which bakers will use the agnostic baker + binary and which will use the protocol-dependent one(s). + + e.g: [0,2] means that the first and last bakers will be agnostic, while + the second one will be protocol dependent (if we have 3 bakers in total). - [maintenance_delay]: number of level which will be multiplied by the position in the list of the bakers to define the store merge delay. @@ -274,6 +280,7 @@ type stresstest_conf = {pkh : string; pk : string; tps : int; seed : int} *) type 'network configuration0 = { stake : int list; + agnostic_bakers : int list; network : 'network; snapshot : string; stresstest : stresstest_conf option; @@ -289,10 +296,12 @@ type bootstrap = { client : Client.t; } +type baker_kind = Classic of Baker.t | Agnostic of Agnostic_baker.t + type baker = { agent : Agent.t; node : Node.t; - baker : Baker.t; + kind : baker_kind; accounts : string list; } @@ -311,7 +320,7 @@ type 'network t = { stresstesters : stresstester list; } -let init_baker_i i (configuration : configuration) cloud ~peers +let init_baker_i i (configuration : configuration) cloud ~peers ~use_agnostic (accounts : baker_account list) (agent, node, name) = let delay = i * configuration.maintenance_delay in let* client = @@ -325,30 +334,47 @@ let init_baker_i i (configuration : configuration) cloud ~peers ~network:configuration.network (agent, node, name) in - let* baker = - toplog "init_baker: Initialize baker" ; - let name = name ^ "-baker" in - let* baker = - let protocol = Network.default_protocol configuration.network in - Baker.Agent.init - ~env:yes_crypto_env - ~name - ~delegates:(List.map (fun ({pkh; _} : baker_account) -> pkh) accounts) - ~protocol - ~client - node - cloud - agent - in - let* () = Baker.wait_for_ready baker in - toplog "init_baker: %s is ready!" name ; - Lwt.return baker + let* baker_kind = + if use_agnostic then ( + toplog "init_baker: Initialize agnostic baker" ; + let name = name ^ "-agnostic-baker" in + let* agnostic_baker = + Agnostic_baker.Agent.init + ~env:yes_crypto_env + ~name + ~delegates:(List.map (fun ({pkh; _} : baker_account) -> pkh) accounts) + ~client + node + cloud + agent + in + let* () = Agnostic_baker.wait_for_ready agnostic_baker in + toplog "init_baker: %s is ready!" name ; + Lwt.return @@ Agnostic agnostic_baker) + else ( + toplog "init_baker: Initialize baker" ; + let name = name ^ "-baker" in + let* baker = + let protocol = Network.default_protocol configuration.network in + Baker.Agent.init + ~env:yes_crypto_env + ~name + ~delegates:(List.map (fun ({pkh; _} : baker_account) -> pkh) accounts) + ~protocol + ~client + node + cloud + agent + in + let* () = Baker.wait_for_ready baker in + toplog "init_baker: %s is ready!" name ; + Lwt.return @@ Classic baker) in Lwt.return { agent; node; - baker; + kind = baker_kind; accounts = List.map (fun ({pkh; _} : baker_account) -> pkh) accounts; } @@ -624,7 +650,14 @@ let init ~(configuration : configuration) cloud next_agent = (fun i accounts -> let ((_, node, _) as agent) = List.nth baker_agents i in let peers = List.filter (( <> ) (Node.point_str node)) peers in - init_baker_i i ~peers configuration cloud accounts agent) + init_baker_i + i + ~peers + ~use_agnostic:(List.mem i configuration.agnostic_bakers) + configuration + cloud + accounts + agent) distribution in let* stresstesters = @@ -851,6 +884,7 @@ let parse_conf encoding file = let register (module Cli : Scenarios_cli.Layer1) = let configuration = let stake = Option.value ~default:[] Cli.stake in + let agnostic_bakers = Option.value ~default:[] Cli.agnostic_bakers in let network : Network.t option = match Cli.network with | `Mainnet -> Some `Mainnet @@ -863,7 +897,7 @@ let register (module Cli : Scenarios_cli.Layer1) = in let maintenance_delay = Option.value ~default:0 Cli.maintenance_delay in let snapshot = Option.value ~default:"" Cli.snapshot in - {stake; network; stresstest; maintenance_delay; snapshot} + {stake; agnostic_bakers; network; stresstest; maintenance_delay; snapshot} in let vms_conf = Option.map (parse_conf vms_conf_encoding) Cli.vms_config in toplog "Parsing CLI done" ; diff --git a/tezt/tests/cloud/layer1.mli b/tezt/tests/cloud/layer1.mli index 04b51f8ecb3f82492b7d2ee945096b0034bc2e72..67a63feb85eeeb9f11a5c1c32ab0693b55a14383 100644 --- a/tezt/tests/cloud/layer1.mli +++ b/tezt/tests/cloud/layer1.mli @@ -16,7 +16,7 @@ with the latest block metadata - Disconnect the node from this network - From here, every node will be ran with --private-mode and a known list - of peer (i.e. the full set of nodes involved in the experiment) + of peers (i.e. the full set of nodes involved in the experiment) - Start bakers - Wait for the nodes to sync - Launch some nodes and clients and use them for stresstesting the network @@ -50,16 +50,16 @@ v} On ghostnet, the goto account to use is the faucet account (the one used above). - For mainnet, you can either ask a local node or try with and indexer and find a + For mainnet, you can either ask a local node or try with an indexer and find a big account. - Along these step, monitoring tools common to tezt cloud scenarios can be + Along these steps, monitoring tools common to tezt cloud scenarios can be started (prometheus, grafana). Teztale service is started automatically. - Every nodes (bootstrap one, bakers ones and stresstest ones) are + All nodes (bootstrap one, bakers ones and stresstest ones) are registered as a prometheus source. - If you use the --prometheus option, you should automatically obtain a + If you use the [--prometheus] option, you should automatically obtain a snapshot of data scraped during the experiment. For now, teztale database has to be dowloaded manually before the bootstrap diff --git a/tezt/tests/cloud/scenarios_cli.ml b/tezt/tests/cloud/scenarios_cli.ml index 7d532ce06b1609c13f8c145f0de3d0fa133829b5..5a2d384dbd8ab04476674b082ebcf9ae8829be02 100644 --- a/tezt/tests/cloud/scenarios_cli.ml +++ b/tezt/tests/cloud/scenarios_cli.ml @@ -415,6 +415,8 @@ module type Layer1 = sig val stake : int list option + val agnostic_bakers : int list option + val stresstest : (string * string * int * int) option val maintenance_delay : int option @@ -465,17 +467,30 @@ module Layer1 () = struct ~long:"stake" ~placeholder:",,,..." ~description: - "By default, each delegate will run its own baker node. In that is \ - what you want, --stake option only takes one integers that is the \ + "By default, each delegate will run its own baker node. If that is \ + what you want, --stake option only takes one integer that is the \ number of active bakers on the network (you need to know that number \ before starting the experiment). If you want to aggregate delegates \ - into pools, use a comma-separated list of integers representating \ + into pools, use a comma-separated list of integers representing \ relative weights defining the expected stake repartition. Delegates \ - will be distributed amongs pools in order to (approximately) respect \ + will be distributed amongst pools in order to (approximately) respect \ the given stake distribution." (Clap.list_of_int ~dummy:[] "stake") () + let agnostic_bakers = + Clap.optional + ~section + ~long:"agnostic-bakers" + ~placeholder:",,,..." + ~description: + "By default all the bakers run in the experiment will use protocol \ + specific octez binaries. This list contains the indices of the bakers \ + that are going to be agnostic, meaning that they will use the \ + agnostic-baker binary, instead of the protocol specific one." + (Clap.list_of_int ~dummy:[] "agnostic-bakers") + () + let stresstest = let typ = let parse string = diff --git a/tezt/tests/cloud/tezos.ml b/tezt/tests/cloud/tezos.ml index fc10b4b0c4163164ded66ee4634cc648667a853f..fb41c2cad6775db73b03b04696d1c7b045d71827 100644 --- a/tezt/tests/cloud/tezos.ml +++ b/tezt/tests/cloud/tezos.ml @@ -409,6 +409,37 @@ module Baker = struct end end +module Agnostic_baker = struct + include Agnostic_baker + + module Agent = struct + let init ?(group = "L1") ?env ?name ~delegates + ?(path = Uses.path Constant.octez_experimental_agnostic_baker) ~client + ?dal_node ?dal_node_timeout_percentage node cloud agent = + let* path = Agent.copy agent ~source:path in + let* () = + Cloud.register_binary + cloud + ~agents:[agent] + ~group + ~name:(Filename.basename path) + () + in + let runner = Agent.runner agent in + init + ?env + ?name + ~event_level:`Notice + ?runner + ~path + ~delegates + ?dal_node + ?dal_node_timeout_percentage + node + client + end +end + module Accuser = struct include Accuser