#!/usr/bin/python3 """Zephir-cmd-input script """ from sys import exit, argv from yaml import load, SafeLoader, YAMLError from time import sleep from os.path import isfile from json import dumps from cucchiaiata import Configuration, JsonError, config from cucchiaiata.common import Common from cucchiaiata.i18n import _ class Import(Common): def __init__(self, config_file: str, ) -> None: super().__init__() with open(config_file, 'r') as stream: try: self.config = load(stream, Loader=SafeLoader, ) except YAMLError as err: raise Exception(_('unable to lead the YAML file {}').format(err)) self.remote_config = self.remote_json_to_config(self.cucchiaiata_config.remote_url) def parse_zones(self) -> None: for zone in self.config.get('zones', []): self.configuration('infra', 'zone', zone, ) self.send('v1.infra.zone.deploy', zone_name=zone['name'], ) def parse_clusters(self) -> None: for cluster in self.config.get('clusters', []): self.configuration('infra', 'cluster', cluster, zone_name=cluster['zone'], zones_name=cluster['zones'], ) for node in cluster.get('nodes', []): self.configuration('infra', 'cluster.node', node, cluster_name=cluster['name'], ) self.send('v1.infra.cluster.deploy', cluster_name=cluster['name'], ) def parse_servermodels(self) -> None: for servermodel in self.config.get('servermodels', []): self.add_servermodel(servermodel) def parse_organizations(self) -> None: for organization in self.config.get('organizations', []): self.configuration('infra', 'organization', organization, ) for site in organization.get('sites', []): self.configuration('infra', 'site', site, organization_name=organization['name'], zones_name=site['zones'], ) for server in site.get('servers', []): self.configuration('infra', 'server', server, site_name=site['name'], cluster_name=server['cluster'], zones_name=server['zones'], servermodel_name=server['servermodel'], ) self.send('v1.infra.server.deploy', server_name=server['name'], ) def configuration(self, domain: str, element: str, dico: dict, **kwargs, ) -> None: self.upset_element(domain, element, dico['name'], kwargs, ) if 'settings' in dico: #FIXME sleep(1) try: self.apply_settings(element, dico, ) except JsonError as err: raise Exception(f'unable to configure {element} "{dico["name"]}": {err.message["reason"]}') def apply_settings(self, element: str, dico: dict, ) -> None: session_id = self.send(f'v1.setting.session.{element}.start', **{f'{element}_name': dico['name']}, )['session_id'] config = Configuration() config.message = 'v1.setting.session.configure' config.session_id = session_id tiramisu = None tiramisu_namespace = None for key, value in self.settings_paths(dico['settings']): current_namespace = key.split('.', 1)[0] if tiramisu_namespace != current_namespace: if tiramisu is not None: self.send_configuration(tiramisu, session_id, ) tiramisu_namespace = current_namespace self.send('v1.setting.session.filter', session_id=session_id, namespace=tiramisu_namespace, ) tiramisu = config.configure_server() try: if tiramisu.option(key).option.isfollower(): for val in value: tiramisu.option(key, val['index']).value.set(val['value']) else: if tiramisu.option(key).option.ismulti() and \ not isinstance(value, list): value = [value] tiramisu.option(key).value.set(value) except ValueError as err: print(_(f'error when setting "{element}" "{dico["name"]}": "{key}" with value "{value}": {err}')) exit(1) except Exception as err: print(_(f'unexpected error when setting "{element}" "{dico["name"]}": "{key}" with value "{value}": {err}')) exit(1) self.send_configuration(tiramisu, session_id, ) self.send('v1.setting.session.stop', session_id=session_id, save=True, ) def upset_element(self, domain: str, element: str, name: str, kwargs: dict, ) -> None: message_name = element if '.' in message_name: message_name = message_name.rsplit('.', 1)[-1] try: self.send(f'v1.{domain}.{element}.describe', **{f'{message_name}_name': name}, ) except: # not exists print(f'add "{element}" "{name}"') kwargs[f'{message_name}_name'] = name self.send(f'v1.{domain}.{element}.create', **kwargs, ) def settings_paths(self, dico: dict, subpath: str=None, ) -> list: ret = [] for key, value in dico.items(): if subpath: key_path = f'{subpath}.{key}' else: key_path = key if isinstance(value, dict): ret.extend(self.settings_paths(value, key_path)) else: ret.append((key_path, value)) return ret def add_servermodel(self, servermodel: dict, parents: list=[], ) -> None: if 'other_parents' in servermodel: parents = parents.copy() parents.extend(servermodel['other_parents']) self.configuration('setting', 'servermodel', servermodel, parents_name=parents, applicationservices_name=servermodel.get('applicationservices', []), ) if 'children' in servermodel: child_parents = parents.copy() child_parents.append(servermodel['name']) for child in servermodel['children']: self.add_servermodel(child, child_parents, ) if __name__ == "__main__": if len(argv) != 2 or not isfile(argv[1]): print(_(f'usage: {argv[0]} filename.yaml')) exit(1) imp = Import(argv[1]) try: imp.parse_zones() imp.parse_clusters() imp.parse_servermodels() imp.parse_organizations() except JsonError as err: print(err.message['reason']) exit(1) except Exception as err: print(err) exit(1)