From 4acebb697cc1fb5bb87109087817a1ec6dca19b4 Mon Sep 17 00:00:00 2001 From: lowit Date: Thu, 7 Dec 2023 13:43:37 +0300 Subject: [PATCH 1/4] dc_as_zone: add dirty hack for using datacenter as zone --- .gitignore | 3 +++ src/task/cluster.rs | 2 +- src/task/cluster/hst/test.rs | 2 +- src/task/cluster/hst/v2.rs | 17 ++++++++++++++--- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 90afb10..2edc61b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,9 @@ CMakeFiles cmake_install.cmake *.dylib *.idea +*.vscode +cluster.genin.yml +inventory.yml __pycache__ *pyc .cache diff --git a/src/task/cluster.rs b/src/task/cluster.rs index 7a109f8..9ac9398 100644 --- a/src/task/cluster.rs +++ b/src/task/cluster.rs @@ -628,7 +628,7 @@ impl Cluster { /// - that's it, when there may only be single domain name in instance's `failure_domains`. pub fn use_failure_domain_as_zone_for_instances(mut self, args: &ArgMatches) -> Self { if args.get_flag("fd-as-zone") { - self.hosts.use_failure_domain_as_zone(); + self.hosts.use_failure_domain_as_zone(None); } self } diff --git a/src/task/cluster/hst/test.rs b/src/task/cluster/hst/test.rs index a066eca..2e126de 100644 --- a/src/task/cluster/hst/test.rs +++ b/src/task/cluster/hst/test.rs @@ -515,7 +515,7 @@ fn hosts_use_failure_domain_as_zone() { assert_eq!(failure_domain_instance_zone(&host, "cache-2-1"), None); assert_eq!(failure_domain_instance_zone(&host, "cache-2-2"), None); - host.use_failure_domain_as_zone(); + host.use_failure_domain_as_zone(None); assert_eq!( failure_domain_instance_zone(&host, "cache-2-1"), Some("dc-2") diff --git a/src/task/cluster/hst/v2.rs b/src/task/cluster/hst/v2.rs index 90219e3..c9c35b7 100644 --- a/src/task/cluster/hst/v2.rs +++ b/src/task/cluster/hst/v2.rs @@ -774,14 +774,25 @@ impl HostV2 { } /// For every instance that has finalized failure domain, replace its zone with that domain name. - pub fn use_failure_domain_as_zone(&mut self) { + pub fn use_failure_domain_as_zone(&mut self, dc: Option) { + let dc = if dc.is_some() { + dc + } else if self.name == Name::from("cluster") { + None + } else { + Some(self.name.to_string()) + }; for instance in self.instances.iter_mut() { if let FailureDomains::Finished(failure_domain) = &instance.failure_domains { - instance.config.zone = Some(failure_domain.clone()); + if let Some(dc) = &dc { + instance.config.zone = Some(dc.clone()); + } else { + instance.config.zone = Some(failure_domain.clone()); + } } } for sub_host in self.hosts.iter_mut() { - sub_host.use_failure_domain_as_zone() + sub_host.use_failure_domain_as_zone(dc.clone()) } } From a8f515b454ff59063561d5228163d68d777330d8 Mon Sep 17 00:00:00 2001 From: Alexandr Sorokin Date: Fri, 19 Apr 2024 15:21:15 +0300 Subject: [PATCH 2/4] Set the level in hosts as zone --- src/task/args.rs | 5 ++++- src/task/cluster.rs | 4 ++-- src/task/cluster/hst/test.rs | 8 ++++++-- src/task/cluster/hst/v2.rs | 29 +++++++++++++++-------------- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/task/args.rs b/src/task/args.rs index 645bd0c..e3eb2f2 100644 --- a/src/task/args.rs +++ b/src/task/args.rs @@ -316,6 +316,9 @@ pub(super) fn read() -> ArgMatches { fn fd_as_zone_arg() -> Arg { Arg::new("fd-as-zone") .long("fd-as-zone") - .action(ArgAction::SetTrue) + .action(ArgAction::Set) + .num_args(0..=1) + .default_missing_value("1") + .value_parser(clap::value_parser!(u8)) .help("Used to insert 'failure_domain' field's value of instances in their 'zone' field.") } diff --git a/src/task/cluster.rs b/src/task/cluster.rs index 9ac9398..b22a1e6 100644 --- a/src/task/cluster.rs +++ b/src/task/cluster.rs @@ -627,8 +627,8 @@ impl Cluster { /// Note that method is intended to be called after cluster is spread /// - that's it, when there may only be single domain name in instance's `failure_domains`. pub fn use_failure_domain_as_zone_for_instances(mut self, args: &ArgMatches) -> Self { - if args.get_flag("fd-as-zone") { - self.hosts.use_failure_domain_as_zone(None); + if let Ok(Some(lvl)) = args.try_get_one::("fd-as-zone") { + self.hosts.use_failure_domain_as_zone(*lvl); } self } diff --git a/src/task/cluster/hst/test.rs b/src/task/cluster/hst/test.rs index 2e126de..25c6673 100644 --- a/src/task/cluster/hst/test.rs +++ b/src/task/cluster/hst/test.rs @@ -515,14 +515,18 @@ fn hosts_use_failure_domain_as_zone() { assert_eq!(failure_domain_instance_zone(&host, "cache-2-1"), None); assert_eq!(failure_domain_instance_zone(&host, "cache-2-2"), None); - host.use_failure_domain_as_zone(None); + host.use_failure_domain_as_zone(1); assert_eq!( failure_domain_instance_zone(&host, "cache-2-1"), Some("dc-2") ); assert_eq!( failure_domain_instance_zone(&host, "cache-2-2"), - Some("server-5") + Some("dc-2") + ); + assert_eq!( + failure_domain_instance_zone(&host, "stateboard-1-1"), + Some("dc-1") ); } diff --git a/src/task/cluster/hst/v2.rs b/src/task/cluster/hst/v2.rs index c9c35b7..a62d88d 100644 --- a/src/task/cluster/hst/v2.rs +++ b/src/task/cluster/hst/v2.rs @@ -774,25 +774,26 @@ impl HostV2 { } /// For every instance that has finalized failure domain, replace its zone with that domain name. - pub fn use_failure_domain_as_zone(&mut self, dc: Option) { - let dc = if dc.is_some() { - dc - } else if self.name == Name::from("cluster") { - None - } else { - Some(self.name.to_string()) - }; + pub fn use_failure_domain_as_zone(&mut self, dc_lvl: u8) { + let lvl: u8 = 0; + let zone: Option = None; + self.set_zone(lvl, dc_lvl, zone) + } + + pub fn set_zone(&mut self, mut lvl: u8, dc_lvl: u8, mut zone: Option) { + if dc_lvl == lvl { + zone = Some(self.name.to_string()); + } + for instance in self.instances.iter_mut() { if let FailureDomains::Finished(failure_domain) = &instance.failure_domains { - if let Some(dc) = &dc { - instance.config.zone = Some(dc.clone()); - } else { - instance.config.zone = Some(failure_domain.clone()); - } + instance.config.zone = zone.clone().or(Some(failure_domain.clone())); } } + + lvl = lvl + 1; for sub_host in self.hosts.iter_mut() { - sub_host.use_failure_domain_as_zone(dc.clone()) + sub_host.set_zone(lvl, dc_lvl, zone.clone()) } } From 744f5f2ca8a060d8ace891d57888899b187d3695 Mon Sep 17 00:00:00 2001 From: Alexandr Sorokin Date: Tue, 23 Apr 2024 12:43:38 +0300 Subject: [PATCH 3/4] The `--fd-as-zone` option takes the value 1..255, which indicates at what level nesting `hosts` contains the required name `zone` For example, when configuring: ```yaml hosts: - name: region hosts: - name: datacenter hosts: - name: host ``` Team: ```shell genin build --fd-as-zone=2 ``` We get: ```yaml hosts: role: zone: datacenter config: ``` --- README.md | 25 +++++++++++++++++++++++++ README.ru.md | 24 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/README.md b/README.md index 9338f9d..d3ca033 100644 --- a/README.md +++ b/README.md @@ -541,8 +541,33 @@ will be on the specified hosts. You can also use a failure domain name as a value for the [`zone`](https://github.com/tarantool/ansible-cartridge/blob/master/doc/variables.md?plain=1#L90) property of the instances config. Just add the `--fd-as-zone` flag to your `build` command, for example: `genin build --fd-as-zone`. +The `--fd-as-zone` option takes the value 1..255, which indicates at what level +nesting `hosts` contains the required name `zone` + With this flag, once the instances are distributed over the target hosts according to the failure_domains algorithm, the final host name of each instance becomes its zone parameter and gets stored in the instance's config. + +For example, when configuring: +```yaml +hosts: + - name: region + hosts: + - name: datacenter + hosts: + - name: host +``` +Team: +```shell +genin build --fd-as-zone=2 +``` +We get: +```yaml +hosts: + role: + zone: datacenter + config: +``` + --- #### Configuration `ansible-host` diff --git a/README.ru.md b/README.ru.md index bd62319..4ec842b 100644 --- a/README.ru.md +++ b/README.ru.md @@ -561,11 +561,35 @@ hosts: Есть возможность использовать финальный хост (конкретный `failure_domain`, куда распределяется инстанс) в качестве параметра [`zone`](https://github.com/tarantool/ansible-cartridge/blob/master/doc/variables.md?plain=1#L90) в ansible-конфигурации инстанса. Для этого необходимо передать флаг `--fd-as-zone` в команду `build`, например: `genin build --fd-as-zone`. +Опция `--fd-as-zone` принимает значение 1..255, которое указываение на каком уровне +вложенности `hosts` находится нужное наименование `zone` + Точное поведение `Genin` при передаче этого флага будет следующим: 0. После работы стандартного алгоритма `failure_domains`, инстансы будут распределены на некоторые хосты согласно их конфигурации; 1. Имя итогового хоста, на который был распределен инстанс, будет использовано в качестве параметра `zone` в ansible-конфигурации инстанса. +Например, при конфигурации: +```yaml +hosts: + - name: region + hosts: + - name: datacenter + hosts: + - name: host +``` +Команда: +```shell +genin build --fd-as-zone=2 +``` +Получим: +```yaml +hosts: + role: + zone: datacenter + config: +``` + --- #### Параметр `ansible-host` From 1773b2043f5f60e9613e8a3f25ef4c44ee367c7e Mon Sep 17 00:00:00 2001 From: Alexandr Sorokin Date: Wed, 24 Apr 2024 15:33:58 +0300 Subject: [PATCH 4/4] ### State --- After each execution of the `genin build` command, the cluster state will be generated. By default, the state will be stored in the `.geninstate` directory. For all cluster changes, Genin is based on the "latest" state and after updating it overwrites it. :exclamation: Loss of `.geninstate` directory or `latest` state, `genin build` command recreates configuration with new state :exclamation: `genin build --recreate` recreates the configuration with a new state --- The `--fd-as-zone` option takes the value 1..255, which indicates at what level nesting `hosts` contains the required name `zone` For example, when configuring: ```yaml hosts: - name: region hosts: - name: datacenter hosts: - name: host ``` Team: ```shell genin build --fd-as-zone=2 ``` We get: ```yaml hosts: role: zone: datacenter config: ``` --- README.md | 16 ++++++++++++++++ README.ru.md | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/README.md b/README.md index d3ca033..2c3abc5 100644 --- a/README.md +++ b/README.md @@ -312,6 +312,22 @@ launched `Genin`. Now we can set up the cluster: ansible-playbook -i inventory.yaml playbook.yaml ``` +### State + +--- + +After each execution of the `genin build` command, the cluster state will be generated. +By default, the state will be stored in the `.geninstate` directory. +For all cluster changes, Genin is based on the "latest" state and +after updating it overwrites it. + +:exclamation: Loss of `.geninstate` directory or `latest` state, `genin build` command recreates +configuration with new state + +:exclamation: `genin build --recreate` recreates the configuration with a new state + +--- + --- ### Editing the cluster configuration diff --git a/README.ru.md b/README.ru.md index 4ec842b..8f5871f 100644 --- a/README.ru.md +++ b/README.ru.md @@ -331,6 +331,22 @@ ansible-playbook -i inventory.yaml playbook.yaml --- +### Состояние + +--- + +После каждого выполнения команды `genin build` будет сформировано состояние кластера. +По умолчанию состояние будет храниться в директории `.geninstate`. +При всех последующих обновлениях кластера `Genin` основывается на состоянии `latest` и +после обновления перезапишет его. + +:exclamation: Потеря директории `.geninstate` или состояния `latest` команда `genin build` пересоздаст +конфигруацию с новым состоянием + +:exclamation: `genin build --recreate` пересоздаст конфигурацию с новым состоянием + +--- + ### Редактирование конфигурации кластера ---