Ejemplo n.º 1
0
    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')
Ejemplo n.º 2
0
    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')
Ejemplo n.º 3
0
    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')
Ejemplo n.º 4
0
    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')
Ejemplo n.º 5
0
 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}')
Ejemplo n.º 6
0
    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')
Ejemplo n.º 7
0
    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')
Ejemplo n.º 8
0
    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')
Ejemplo n.º 9
0
    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')
Ejemplo n.º 10
0
    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')
Ejemplo n.º 11
0
    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')