def _deploy_dcos_conf(self): """Deploy aggregated DC/OS configuration object.""" LOG.debug(f'{self.msg_src}: Execute: Deploy aggregated config: ...') for element in self.config.dcos_conf.get('package', []): target_path = Path(element.get('path')) content = element.get('content') if not target_path.parent.exists(): try: target_path.parent.mkdir(parents=True, exist_ok=True) LOG.debug(f'{self.msg_src}: Execute: Deploy aggregated' f' config: Create directory:' f' {target_path.parent}: OK') except (OSError, RuntimeError) as e: err_msg = (f'Execute: Deploy aggregated config: Create' f' directory: {target_path.parent}:' f' {type(e).__name__}: {e}') raise cr_exc.SetupCommandError(err_msg) from e try: target_path.write_text(content) LOG.debug(f'{self.msg_src}: Execute: Deploy aggregated config:' f'Save content: {target_path}: OK') except (OSError, RuntimeError) as e: err_msg = (f'Execute: Deploy aggregated config: Save content:' f' {target_path}: {type(e).__name__}: {e}') raise cr_exc.SetupCommandError(err_msg) from e LOG.debug(f'{self.msg_src}: Execute: Deploy aggregated config: OK')
def execute(self): """Execute command.""" msg_src = self.__class__.__name__ LOG.debug(f'{msg_src}: Execute: Target:' f' {self.cmd_opts.get(CLI_CMDOPT.CMD_TARGET)}') if self.cmd_opts.get(CLI_CMDOPT.CMD_TARGET) == CLI_CMDTARGET.STORAGE: # (Re)build/repair the installation storage structure. self.config.inst_storage.construct( clean=self.cmd_opts.get(CLI_CMDOPT.INST_CLEAN)) elif self.cmd_opts.get(CLI_CMDOPT.CMD_TARGET) == CLI_CMDTARGET.PKGALL: dstor_root_url = self.config.cluster_conf.get( 'distribution-storage', {}).get('rooturl', '') dstor_pkgrepo_path = self.config.cluster_conf.get( 'distribution-storage', {}).get('pkgrepopath', '') # Add packages to the local package repository and initialize their # manager objects packages_bulk = [] for item in self.config.ref_pkg_list: pkg_id = PackageId(pkg_id=item) try: self.config.inst_storage.add_package( pkg_id=pkg_id, dstor_root_url=dstor_root_url, dstor_pkgrepo_path=dstor_pkgrepo_path) except cr_exc.RCError as e: err_msg = (f'{msg_src}: Execute: Add package to local' f' repository: {pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) from e try: package = Package( pkg_id=pkg_id, istor_nodes=self.config.inst_storage.istor_nodes, cluster_conf=self.config.cluster_conf) except cr_exc.RCError as e: err_msg = (f'{msg_src}: Execute: Initialize package:' f' {pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) from e packages_bulk.append(package) # Finalize package setup procedures taking package mutual # dependencies into account. for package in cr_utl.pkg_sort_by_deps(packages_bulk): self._handle_pkg_inst_extras(package) self._handle_pkg_svc_setup(package) try: package.manifest.save() except cr_exc.RCError as e: err_msg = (f'{msg_src}: Execute: Register package:' f' {package.manifest.pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) LOG.info(f'{msg_src}: Setup package:' f' {package.manifest.pkg_id.pkg_id}: OK')
def _handle_pkg_svc_setup(self, package): """Execute steps on package service setup. :param package: Package, DC/OS package manager object """ msg_src = self.__class__.__name__ if package.svc_manager: try: ret_code, stdout, stderr = package.svc_manager.status() except svcm_exc.ServiceManagerCommandError as e: LOG.debug(f'{msg_src}: Execute: Get initial service status:' f' {package.manifest.pkg_id.pkg_name}: {e}') # Try to setup, as a service (expectedly) doesn't exist and # checking it's status naturally would yield an error. try: package.svc_manager.setup() except svcm_exc.ServiceManagerCommandError as e: err_msg = (f'Execute: Setup service:' f' {package.manifest.pkg_id.pkg_name}: {e}') raise cr_exc.SetupCommandError(err_msg) from e else: LOG.debug(f'{msg_src}: Execute: Get initial service status:' f' {package.manifest.pkg_id.pkg_name}:' f' stdout[{stdout}] stderr[{stderr}]') svc_status = str(stdout).strip().rstrip('\n') # Try to remove existing service try: if svc_status == SVC_STATUS.RUNNING: package.svc_manager.stop() package.svc_manager.remove() LOG.debug(f'{msg_src}: Execute: Remove existing service:' f' {package.manifest.pkg_id.pkg_name}: OK') except svcm_exc.ServiceManagerCommandError as e: err_msg = (f'Execute: Remove existing service:' f' {package.manifest.pkg_id.pkg_name}: {e}') raise cr_exc.SetupCommandError(err_msg) from e # Setup a replacement service try: package.svc_manager.setup() ret_code, stdout, stderr = (package.svc_manager.status()) svc_status = str(stdout).strip().rstrip('\n') except svcm_exc.ServiceManagerCommandError as e: err_msg = (f'Execute: Setup replacement service:' f' {package.manifest.pkg_id.pkg_name}: {e}') raise cr_exc.SetupCommandError(err_msg) from e else: if svc_status != SVC_STATUS.STOPPED: err_msg = (f'Execute: Setup replacement service:' f' {package.manifest.pkg_id.pkg_name}:' f' Invalid status: {svc_status}') raise cr_exc.SetupCommandError(err_msg) LOG.debug(f'{msg_src}: Setup service:' f' {package.manifest.pkg_id.pkg_name}: OK')
def _handle_pkg_inst_extras(self, package: Package): """Process package extra installation options. :param package: Package, DC/OS package manager object """ # TODO: This method should be removed after transition to use of # Package.handle_inst_extras() msg_src = self.__class__.__name__ pkg_id = package.manifest.pkg_id if package.ext_manager: LOG.debug(f'{msg_src}: Execute: {pkg_id.pkg_name}:' f' Handle extra installation options: ...') try: package.ext_manager.handle_install_extras() except extm_exc.InstExtrasManagerError as e: err_msg = (f'Execute: {pkg_id.pkg_name}:' f' Handle extra installation options: {e}') raise cr_exc.SetupCommandError(err_msg) from e LOG.debug(f'{msg_src}: Execute: {pkg_id.pkg_name}:' f' Handle extra installation options: OK') else: LOG.debug(f'{msg_src}: Execute: {pkg_id.pkg_name}:' f' Handle extra installation options: NOP')
def _register_istate(self, inst_state): """""" # TODO: Move this method to the abstract base parent class Command to # avoid code duplication in command manager classes. msg_base = (f'{self.msg_src}:' f' Execute: Register installation state: {inst_state}') try: self.config.inst_state.istate = inst_state LOG.debug(f'{msg_base}: OK') except cr_exc.RCError as e: raise cr_exc.SetupCommandError(f'Execute: {type(e).__name__}: {e}')
def _handle_pkg_inst_extras(self, package): """Process package extra installation options. :param package: Package, DC/OS package manager object """ msg_src = self.__class__.__name__ LOG.debug(f'{msg_src}: Handle extra install options:' f' ext_manager: {package.ext_manager}') if package.ext_manager: try: package.ext_manager.handle_install_extras() except extm_exc.InstExtrasManagerError as e: err_msg = (f'Execute: Handle extra install options:' f' {package.manifest.pkg_id.pkg_name}: {e}') raise cr_exc.SetupCommandError(err_msg) from e LOG.debug(f'{msg_src}: Handle extra install options:' f' {package.manifest.pkg_id.pkg_name}: OK')
def _handle_pkg_cfg_setup(self, package): """Execute steps on package configuration files setup. :param package: Package, DC/OS package manager object """ pkg_id = package.manifest.pkg_id LOG.debug(f'{self.msg_src}: Execute: {pkg_id.pkg_name}: Setup' f' configuration: ...') try: package.cfg_manager.setup_conf() except cfgm_exc.PkgConfNotFoundError as e: LOG.debug(f'{self.msg_src}: Execute: {pkg_id.pkg_name}: Setup' f' configuration: NOP') except cfgm_exc.PkgConfManagerError as e: err_msg = (f'Execute: {pkg_id.pkg_name}: Setup configuration:' f'{type(e).__name__}: {e}') raise cr_exc.SetupCommandError(err_msg) from e else: LOG.debug(f'{self.msg_src}: Execute: {pkg_id.pkg_name}: Setup' f' configuration: OK')
def _deploy_dcos_conf(self): """Deploy aggregated DC/OS configuration object.""" LOG.debug(f'{self.msg_src}: Execute: Deploy aggregated config: ...') context = ResourceContext( istor_nodes=self.config.inst_storage.istor_nodes, cluster_conf=self.config.cluster_conf, extra_values=self.config.dcos_conf.get('values')) context_items = context.get_items() context_items_jr = context.get_items(json_ready=True) t_elements = self.config.dcos_conf.get('template').get('package', []) for t_element in t_elements: path = t_element.get('path') content = t_element.get('content') try: j2t = j2.Environment().from_string(path) rendered_path = j2t.render(**context_items) dst_fpath = Path(rendered_path) j2t = j2.Environment().from_string(content) if '.json' in dst_fpath.suffixes[-1:]: rendered_content = j2t.render(**context_items_jr) else: rendered_content = j2t.render(**context_items) except j2.TemplateError as e: err_msg = (f'Execute: Deploy aggregated config: Render:' f' {path}: {type(e).__name__}: {e}') raise cfgm_exc.PkgConfFileInvalidError(err_msg) from e if not dst_fpath.parent.exists(): try: dst_fpath.parent.mkdir(parents=True, exist_ok=True) LOG.debug(f'{self.msg_src}: Execute: Deploy aggregated' f' config: Create directory:' f' {dst_fpath.parent}: OK') except (OSError, RuntimeError) as e: err_msg = (f'Execute: Deploy aggregated config: Create' f' directory: {dst_fpath.parent}:' f' {type(e).__name__}: {e}') raise cr_exc.SetupCommandError(err_msg) from e elif not dst_fpath.parent.is_dir(): err_msg = (f'Execute: Deploy aggregated config: Save content:' f' {dst_fpath}: Existing parent is not a directory:' f' {dst_fpath.parent}') raise cr_exc.SetupCommandError(err_msg) elif dst_fpath.exists(): err_msg = (f'Execute: Deploy aggregated config: Save content:' f' {dst_fpath}: Same-named file already exists!') raise cr_exc.SetupCommandError(err_msg) try: dst_fpath.write_text(rendered_content) LOG.debug(f'{self.msg_src}: Execute: Deploy aggregated config:' f' Save content: {dst_fpath}: OK') except (OSError, RuntimeError) as e: err_msg = (f'Execute: Deploy aggregated config: Save content:' f' {dst_fpath}: {type(e).__name__}: {e}') raise cr_exc.SetupCommandError(err_msg) from e LOG.debug(f'{self.msg_src}: Execute: Deploy aggregated config: OK')
def execute(self): """Execute command.""" LOG.debug(f'{self.msg_src}: Execute: Target:' f' {self.cmd_opts.get(CLI_CMDOPT.CMD_TARGET)}') if self.cmd_opts.get(CLI_CMDOPT.CMD_TARGET) == CLI_CMDTARGET.STORAGE: # (Re)build/repair the installation storage structure. self.config.inst_storage.construct( clean=self.cmd_opts.get(CLI_CMDOPT.INST_CLEAN)) elif self.cmd_opts.get(CLI_CMDOPT.CMD_TARGET) == CLI_CMDTARGET.PKGALL: dstor_root_url = self.config.cluster_conf.get( 'distribution-storage', {}).get('rooturl', '') dstor_pkgrepo_path = self.config.cluster_conf.get( 'distribution-storage', {}).get('pkgrepopath', '') # Add packages to the local package repository and initialize their # manager objects packages_bulk = {} for item in self.config.ref_pkg_list: pkg_id = PackageId(pkg_id=item) try: self.config.inst_storage.add_package( pkg_id=pkg_id, dstor_root_url=dstor_root_url, dstor_pkgrepo_path=dstor_pkgrepo_path) except cr_exc.RCError as e: err_msg = (f'{self.msg_src}: Execute: Add package to local' f' repository: {pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) from e try: package = Package( pkg_id=pkg_id, istor_nodes=self.config.inst_storage.istor_nodes, cluster_conf=self.config.cluster_conf, extra_context=self.config.dcos_conf.get('values')) except cr_exc.RCError as e: err_msg = (f'{self.msg_src}: Execute: Initialize package:' f' {pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) from e packages_bulk[pkg_id.pkg_name] = package # Finalize package setup procedures taking package mutual # dependencies into account. packages_sorted_by_deps = cr_utl.pkg_sort_by_deps(packages_bulk) # Prepare base per package configuration objects for package in packages_sorted_by_deps: self._handle_pkg_dir_setup(package) self._handle_pkg_cfg_setup(package) # Deploy DC/OS aggregated configuration object self._deploy_dcos_conf() # Run per package extra installation helpers, setup services and # save manifests for package in packages_sorted_by_deps: self._handle_pkg_inst_extras(package) self._handle_pkg_svc_setup(package) try: package.manifest.save() except cr_exc.RCError as e: err_msg = (f'{self.msg_src}: Execute: Register package:' f' {package.manifest.pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) LOG.info(f'{self.msg_src}: Setup package:' f' {package.manifest.pkg_id.pkg_id}: OK')
def _handle_clean_setup(self): """Perform all the steps on DC/OS installation remaining after the preparation stage is done (the CmdUpgrade._handle_upgrade_pre()). """ # TODO: This code duplicates the CmdSetup._handle_cmdtarget_pkgall() # stuff and so should be made standalone to be reused in both # classes avoiding massive code duplication. dstor_root_url = self.config.cluster_conf.get('distribution-storage', {}).get('rooturl', '') dstor_pkgrepo_path = self.config.cluster_conf.get( 'distribution-storage', {}).get('pkgrepopath', '') # Deploy DC/OS aggregated configuration object self._deploy_dcos_conf() result = subprocess.run( ('powershell', '-executionpolicy', 'Bypass', '-File', 'C:\\d2iq\\dcos\\bin\\detect_ip.ps1'), stdout=subprocess.PIPE, check=True) local_priv_ipaddr = result.stdout.decode('ascii').strip() self.config.dcos_conf['values']['privateipaddr'] = local_priv_ipaddr # Add packages to the local package repository and initialize their # manager objects packages_bulk = {} for item in self.config.ref_pkg_list: pkg_id = PackageId(pkg_id=item) try: self.config.inst_storage.add_package( pkg_id=pkg_id, dstor_root_url=dstor_root_url, dstor_pkgrepo_path=dstor_pkgrepo_path) except cr_exc.RCError as e: err_msg = (f'{self.msg_src}: Execute: Add package to local' f' repository: {pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) from e try: package = Package( pkg_id=pkg_id, istor_nodes=self.config.inst_storage.istor_nodes, cluster_conf=self.config.cluster_conf, extra_context=self.config.dcos_conf.get('values')) except cr_exc.RCError as e: err_msg = (f'{self.msg_src}: Execute: Initialize package:' f' {pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) from e packages_bulk[pkg_id.pkg_name] = package # Finalize package setup procedures taking package mutual # dependencies into account. packages_sorted_by_deps = cr_utl.pkg_sort_by_deps(packages_bulk) # Prepare base per package configuration objects for package in packages_sorted_by_deps: # TODO: This method moves parts of individual packages which should # be shared with other packages to DC/OS installation shared # directories (<inst_root>\[bin|etc|lib]). It should be # redesigned to deal with only required parts of packages and # not populating shared DC/OS installation directories with # unnecessary stuff. self._handle_pkg_dir_setup(package) # TODO: This should be replaced with Package.handle_config_setup() # method to avoid code duplication in command manager classes # CmdSetup and CmdUpgrade self._handle_pkg_cfg_setup(package) # Run per package extra installation helpers, setup services and # save manifests for package in packages_sorted_by_deps: # TODO: This should be replaced with Package.handle_inst_extras() # method to avoid code duplication in command manager classes # CmdSetup and CmdUpgrade self._handle_pkg_inst_extras(package) # TODO: This should be replaced with Package.handle_svc_setup() # method to avoid code duplication in command manager classes # CmdSetup and CmdUpgrade self._handle_pkg_svc_setup(package) # TODO: This part should be replaced with Package.save_manifest() # method to avoid code duplication in command manager classes # CmdSetup and CmdUpgrade try: package.manifest.save() except cr_exc.RCError as e: err_msg = (f'{self.msg_src}: Execute: Register package:' f' {package.manifest.pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) LOG.info(f'{self.msg_src}: Setup package:' f' {package.manifest.pkg_id.pkg_id}: OK')
def execute(self): """Execute command.""" msg_src = self.__class__.__name__ LOG.debug(f'{msg_src}: Execute: Target:' f' {self.cmd_opts.get(CLI_CMDOPT.CMD_TARGET)}') if self.cmd_opts.get(CLI_CMDOPT.CMD_TARGET) == CLI_CMDTARGET.STORAGE: # (Re)build/repair the installation storage structure. self.config.inst_storage.construct( clean=self.cmd_opts.get(CLI_CMDOPT.INST_CLEAN) ) elif self.cmd_opts.get(CLI_CMDOPT.CMD_TARGET) == CLI_CMDTARGET.PKGALL: # Add packages to the local package repository dstor_root_url = self.config.cluster_conf.get( 'distribution-storage', {} ).get('rooturl', '') dstor_pkgrepo_path = self.config.cluster_conf.get( 'distribution-storage', {} ).get('pkgrepopath', '') for item in self.config.ref_pkg_list: pkg_id = PackageId(pkg_id=item) try: self.config.inst_storage.add_package( pkg_id=pkg_id, dstor_root_url=dstor_root_url, dstor_pkgrepo_path=dstor_pkgrepo_path ) except cr_exc.RCError as e: err_msg = (f'Execute: Add package:' f' {pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) try: package = Package( pkg_id=pkg_id, pkgrepo_dpath=self.config.inst_storage.pkgrepo_dpath, pkgactive_dpath=self.config.inst_storage.pkgactive_dpath, cluster_conf=self.config.cluster_conf ) except cr_exc.RCError as e: err_msg = (f'Execute: Initialize package:' f' {pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) try: ret_code, stdout, stderr = package.svc_manager.status() except svcm_exc.ServiceManagerCommandError as e: LOG.debug( f'{msg_src}: Execute: Get service status (initial):' f' {pkg_id.pkg_name}: {e}' ) # Try to setup, as a service (expectedly) doesn't exist and # checking it's status naturally would yield an error. package.svc_manager.setup() else: LOG.debug( f'{msg_src}: Execute: Get service status (initial):' f' {pkg_id.pkg_name}: stdout[{stdout}]' f' stderr[{stderr}]' ) svc_status = str(stdout).strip().rstrip('\n') # Try to remove existing service try: if svc_status == SVC_STATUS.RUNNING: package.svc_manager.stop() package.svc_manager.remove() LOG.debug(f'{msg_src}: Execute: Remove existing' f' service: {pkg_id.pkg_name}: OK') except svcm_exc.ServiceManagerCommandError as e: err_msg = (f'Execute: Remove existing service:' f' {pkg_id.pkg_name}: {e}') raise cr_exc.SetupCommandError(err_msg) # Setup a replacement service try: package.svc_manager.setup() ret_code, stdout, stderr = package.svc_manager.status() svc_status = str(stdout).strip().rstrip('\n') except svcm_exc.ServiceManagerCommandError as e: err_msg = (f'Execute: Setup replacement service:' f' {pkg_id.pkg_name}: {e}') raise cr_exc.SetupCommandError(err_msg) else: if svc_status != SVC_STATUS.STOPPED: err_msg = ( f'Execute: Setup service: {pkg_id.pkg_name}' f' Invalid status: {svc_status}' ) raise cr_exc.SetupCommandError(err_msg) LOG.debug(f'{msg_src}: Setup service: {pkg_id.pkg_name}: OK') try: package.manifest.save() except cr_exc.RCError as e: err_msg = (f'Execute: Register package:' f' {pkg_id.pkg_id}: {e}') raise cr_exc.SetupCommandError(err_msg) LOG.info(f'{msg_src}: Setup package: {pkg_id.pkg_id}: OK')