Пример #1
0
    def get_pkgactive(self, manifest_loader: Callable) -> Set:
        """Retrieve set of manifests of active packages.

        :param manifest_loader: callable, package manifest loader
        :return:                set, set of package manifest objects
        """
        assert callable(manifest_loader), (
            f'Argument: manifest_loader:'
            f' Got {type(manifest_loader).__name__} instead of callable'
        )

        pkg_manifests = set()

        # Path('/path/does/not/exist').glob('*') yields []
        for path in self.pkgactive_dpath.glob('*.json'):
            abs_path = self.pkgactive_dpath.joinpath(path)

            if abs_path.is_file():
                try:
                    pkg_manifests.add(manifest_loader(path))
                except cr_exc.RCError as e:
                    raise cr_exc.InstallationStorageError(
                        f'Get active package manifest:'
                        f' {path}: {type(e).__name__}: {e}'
                    ) from e

        return pkg_manifests
Пример #2
0
    def setup_conf(self):
        """Setup configuration objects for a DC/OS package."""
        pkg_id = self._pkg_manifest.pkg_id
        pkg_cfg_dpath = getattr(self._pkg_manifest.istor_nodes,
                                ISTOR_NODE.PKGREPO).joinpath(
                                    pkg_id.pkg_id, cr_const.PKG_CFG_DNAME)
        LOG.debug(f'{self.msg_src}: Setup configuration: {pkg_id.pkg_name}:'
                  f' Source directory path: {pkg_cfg_dpath}')

        config_dir = getattr(self._pkg_manifest.istor_nodes, ISTOR_NODE.CFG)
        pkg_shrcfg_dpath = config_dir.joinpath(pkg_id.pkg_name)
        LOG.debug(f'{self.msg_src}: Setup configuration: {pkg_id.pkg_name}:'
                  f' Destination directory path: {pkg_shrcfg_dpath}')

        pkg_context = self._pkg_manifest.context

        if pkg_cfg_dpath.exists():
            # Check source is a directory
            if pkg_cfg_dpath.is_symlink():
                err_msg = (f'Source directory: Symlink conflict:'
                           f' {pkg_cfg_dpath}')
                raise cfgm_exc.PkgConfInvalidError(err_msg)
            elif pkg_cfg_dpath.is_reserved():
                err_msg = (f'Source directory: Reserved name conflict:'
                           f' {pkg_cfg_dpath}')
                raise cfgm_exc.PkgConfInvalidError(err_msg)
            elif not pkg_cfg_dpath.is_dir():
                err_msg = (f'Source directory: Not a directory:'
                           f' {pkg_cfg_dpath}')
                raise cfgm_exc.PkgConfInvalidError(err_msg)

            # Ensure destination exists and is a directory
            try:
                pkg_shrcfg_dpath.mkdir(parents=True, exist_ok=True)
            except FileExistsError:
                raise cr_exc.InstallationStorageError(
                    f'Setup configuration: {pkg_id.pkg_name}:'
                    f' {pkg_shrcfg_dpath} exists but is not a directory')

            try:
                with tf.TemporaryDirectory(dir=str(config_dir)) as tdp:

                    self._process_pkgconf_srcdir(src_dpath=pkg_cfg_dpath,
                                                 tmp_dpath=Path(tdp),
                                                 context=pkg_context)
                    transfer_files(tdp, str(pkg_shrcfg_dpath))
                    LOG.debug(
                        f'{self.msg_src}: Setup configuration:'
                        f' {pkg_id.pkg_name}: Save: {pkg_shrcfg_dpath}: OK')
            except (OSError, RuntimeError) as e:
                err_msg = (f'Setup configuration: {pkg_id.pkg_name}:'
                           f' Process configuration sources:'
                           f' {pkg_cfg_dpath}: {type(e).__name__}: {e}')
                raise cfgm_exc.PkgConfManagerError(err_msg)
        else:
            err_msg = f'Source directory: Not found: {pkg_cfg_dpath}'
            raise cfgm_exc.PkgConfNotFoundError(err_msg)
Пример #3
0
 def destruct(self) -> None:
     """Remove entire existing DC/OS installation storage."""
     for path in self.istor_nodes[1:]:  # type: Path
         if path.is_absolute() and path.is_dir():
             try:
                 cm_utl.rmdir(path=str(path), recursive=True)
                 LOG.debug(f'{self.__class__.__name__}: Destruction:'
                           f' Remove directory: {path}')
             except (OSError, RuntimeError) as e:
                 raise cr_exc.InstallationStorageError(
                     f'Destruction: Remove directory: {path}:'
                     f' {type(e).__name__}: {e}')
Пример #4
0
    def get_pkgactive(self):
        """Retrieve set of manifests of active packages."""
        pkg_manifests = set()

        # Path('/path/does/not/exist').glob('*') yields []
        for path in self.pkgactive_dpath.glob('*.json'):
            abs_path = self.pkgactive_dpath.joinpath(path)

            if abs_path.is_file():
                try:
                    pkg_manifests.add(PackageManifest.load(path))
                except cr_exc.RCError as e:
                    raise cr_exc.InstallationStorageError(
                        f'Get active package manifest:'
                        f' {path}: {type(e).__name__}: {e}') from e

        return pkg_manifests
Пример #5
0
    def add_package(self, pkg_id: PackageId, dstor_root_url: str,
                    dstor_pkgrepo_path: str) -> None:
        """Add a package to the local package repository.

        :param pkg_id:             PackageId, package ID
        :param dstor_root_url:     str, DC/OS distribution storage root URL
        :param dstor_pkgrepo_path: str, DC/OS distribution storage package
                                   repository root path
        """
        msg_src = self.__class__.__name__
        # Download a package tarball
        pkg_url = self._make_pkg_url(pkg_id=pkg_id,
                                     dstor_root_url=dstor_root_url,
                                     dstor_pkgrepo_path=dstor_pkgrepo_path)
        try:
            pkgtarball_fpath = cm_utl.download(pkg_url, self.tmp_dpath)
            LOG.debug(f'{msg_src}: Add package: Download: {pkg_id}: {pkg_url}')
        except Exception as e:
            raise cr_exc.RCDownloadError(
                f'Add package: {pkg_id}: {pkg_url}: {type(e).__name__}: {e}'
            ) from e
        # Unpack a package tarball
        try:
            # Try to cleanup local package repository before trying to
            # create a package installation directory there
            pkg_inst_dpath = self.pkgrepo_dpath.joinpath(pkg_id.pkg_id)
            try:
                if pkg_inst_dpath.exists():
                    if pkg_inst_dpath.is_dir():
                        shutil.rmtree(str(pkg_inst_dpath))
                    elif pkg_inst_dpath.is_file and (
                        not pkg_inst_dpath.is_symlink()
                    ):
                        pkg_inst_dpath.unlink()
                    else:
                        raise cr_exc.InstallationStorageError(
                            f'Add package: {pkg_id}: Auto-cleanup'
                            f' package repository: Removing objects other than'
                            f' regular directories and files is not supported'
                        )
                    LOG.debug(f'{msg_src}: Add package: {pkg_id}: Auto-cleanup:'
                              f' {pkg_inst_dpath}')
            except (OSError, RuntimeError) as e:
                raise cr_exc.InstallationStorageError(
                    f'Add package: {pkg_id}: Auto-cleanup: {pkg_inst_dpath}:'
                    f' {type(e).__name__}: {e}'
                ) from e

            with tf.TemporaryDirectory(dir=str(self.tmp_dpath)) as temp_dpath:
                cm_utl.unpack(pkgtarball_fpath, temp_dpath)

                try:
                    # Lookup for a directory named after the package ID
                    src_dpath = [
                        path for path in Path(temp_dpath).iterdir() if (
                            path.name == pkg_id.pkg_id
                        )
                    ][0]
                    if src_dpath.is_dir():
                        shutil.copytree(
                            str(src_dpath), str(pkg_inst_dpath)
                        )
                    else:
                        # Only a directory may be named after the package ID,
                        # otherwise a package structure is broken
                        raise cr_exc.RCExtractError(
                            f'Add package: {pkg_id}: Broken package structure'
                        )
                except IndexError:
                    # Use the temporary directory as package's container
                    shutil.copytree(
                        temp_dpath, str(pkg_inst_dpath)
                    )

            LOG.debug(f'{msg_src}: Add package: Extract: {pkg_id}')
        except Exception as e:
            if not isinstance(e, cr_exc.RCExtractError):
                raise cr_exc.RCExtractError(
                    f'Add package: {pkg_id}: {type(e).__name__}: {e}'
                )
            else:
                raise
        finally:
            pkgtarball_fpath.unlink()
        # Create a work, runtime and log data directories for a package.
        for host_dpath in self.work_dpath, self.run_dpath, self.log_dpath:
            path = host_dpath.joinpath(pkg_id.pkg_name)

            if not path.exists():
                try:
                    path.mkdir(parents=True)
                    LOG.debug(f'{msg_src}: Add package: {pkg_id}:'
                              f' Create data directory: {path}')
                except (OSError, RuntimeError) as e:
                    raise cr_exc.InstallationStorageError(
                        f'Add package: {pkg_id}: Create data directory:'
                        f' {path}: {type(e).__name__}: {e}'
                    ) from e
            elif path.is_symlink():
                raise cr_exc.InstallationStorageError(
                        f'Add package: {pkg_id}: Create data directory:'
                        f' {path}: Symlink conflict'
                    )
            elif path.is_reserved():
                raise cr_exc.InstallationStorageError(
                    f'Add package: {pkg_id}: Create data directory:'
                    f' {path}: Reserved name conflict'
                )
            elif not path.is_dir():
                # Attempt to auto-clean garbage
                try:
                    path.unlink()
                    LOG.debug(f'{msg_src}: Add package: {pkg_id}: Auto-cleanup:'
                              f' File: {path}')
                except (OSError, RuntimeError) as e:
                    raise cr_exc.InstallationStorageError(
                        f'Add package: {pkg_id}: Auto-cleanup: File: {path}:'
                        f' {type(e).__name__}: {e}'
                    ) from e
                # Attempt to create data dir
                try:
                    path.mkdir(parents=True)
                    LOG.debug(f'{msg_src}: Add package: {pkg_id}:'
                              f' Create data directory: {path}')
                except (OSError, RuntimeError) as e:
                    raise cr_exc.InstallationStorageError(
                        f'Add package: {pkg_id}: Create data directory:'
                        f' {path}: {type(e).__name__}: {e}'
                    ) from e
            else:
                # Leave existing directories intact
                pass

        # Workaround for dcos-diagnostics to be able to start
        # TODO: Remove this code after correct dcos-diagnostics configuration
        #       is figured out and all its config files are arranged properly
        #       to support DC/OS installation storage FS layout.
        if pkg_id.pkg_name == 'dcos-diagnostics':
            # Move binary and config-files to DC/OS installation storage root
            src_dpath = self.pkgrepo_dpath.joinpath(pkg_id.pkg_id, 'bin')
            try:
                LOG.debug(
                    f'{msg_src}: Add package: Workaround: Copy list: '
                    f' {list(src_dpath.glob("*.*"))}'
                )
                for src_fpath in src_dpath.glob('*.*'):
                    if not self.root_dpath.joinpath(src_fpath.name).exists():
                        shutil.copy(str(src_fpath), str(self.root_dpath))
                        LOG.debug(
                            f'{msg_src}: Add package: Workaround: Copy file: '
                            f' {str(src_fpath)} -> {str(self.root_dpath)}'
                        )
                # Create a folder for logs
                log_dpath = self.root_dpath.joinpath('mesos-logs')
                if not log_dpath.exists():
                    log_dpath.mkdir()
            except Exception as e:
                raise cr_exc.RCExtractError(
                    f'Add package: {pkg_id}: {type(e).__name__}: {e}'
                )
Пример #6
0
    def construct(self, clean: bool = False) -> None:
        """Construct DC/OS installation storage.

        :param clean: boolean, create a clean FS folder structure, wiping
                      out any possible leftovers, if True. Otherwise repair FS
                      directory structure, creating any missed pieces, as
                      required.
        """
        clean_ready = self._inst_stor_is_clean_ready(clean=clean)
        LOG.debug(f'{self.__class__.__name__}:'
                  f' Construction: Clean ready: {clean_ready}')
        rollback_path_list = []  # type: List

        def rollback() -> None:
            """"""
            for path in rollback_path_list:  # type: Path
                # Remove an existing DC/OS installation storage element
                try:
                    cm_utl.rmdir(path=str(path), recursive=True)
                except (OSError, RuntimeError) as e:
                    LOG.error(f'{self.__class__.__name__}: Construction:'
                              f' Rollback: {path}: {type(e).__name__}: {e}')

        for path in self.istor_nodes:  # type: Path
            if path.exists():
                if path.is_symlink():
                    rollback()
                    raise cr_exc.InstallationStorageError(
                        f'Construction: Symlink conflict: {path}'
                    )
                elif path.is_reserved():
                    rollback()
                    raise cr_exc.InstallationStorageError(
                        f'Construction: Reserved name conflict: {path}'
                    )
                elif not path.is_dir():
                    # Remove a file
                    try:
                        path.unlink()
                        LOG.debug(f'{self.__class__.__name__}:'
                                  f' Construction: Auto-cleanup: File: {path}')
                    except (OSError, RuntimeError) as e:
                        rollback()
                        raise cr_exc.InstallationStorageError(
                            f'Construction: Auto-cleanup: File: {path}:'
                            f' {type(e).__name__}: {e}'
                        ) from e
                    # Create a fresh DC/OS installation storage element
                    try:
                        path.mkdir(parents=True, exist_ok=True)
                        LOG.debug(f'{self.__class__.__name__}: Construction:'
                                  f' Create directory: {path}')
                    except (OSError, RuntimeError) as e:
                        rollback()
                        raise cr_exc.InstallationStorageError(
                            f'Construction: Create directory: {path}:'
                            f' {type(e).__name__}: {e}'
                        ) from e
                elif clean is True:
                    if clean_ready is True:
                        # Remove an existing DC/OS installation storage element
                        try:
                            cm_utl.rmdir(path=str(path), recursive=True)
                            LOG.debug(f'{self.__class__.__name__}:'
                                      f' Construction: Cleanup: {path}')
                        except (OSError, RuntimeError) as e:
                            rollback()
                            raise cr_exc.InstallationStorageError(
                                f'Construction: Cleanup: {path}:'
                                f' {type(e).__name__}: {e}'
                            ) from e
                        # Create a fresh DC/OS installation storage element
                        try:
                            path.mkdir(parents=True, exist_ok=True)
                            LOG.debug(f'{self.__class__.__name__}:'
                                      f' Construction: Create directory:'
                                      f' {path}')
                        except (OSError, RuntimeError) as e:
                            rollback()
                            raise cr_exc.InstallationStorageError(
                                f'Construction: Create directory: {path}:'
                                f' {type(e).__name__}: {e}'
                            ) from e
                    else:
                        rollback()
                        raise cr_exc.InstallationStorageError(
                            f'Construction:  Not ready for cleanup : {path}'
                        )
            else:
                # Create a fresh DC/OS installation storage element
                try:
                    path.mkdir(parents=True, exist_ok=True)
                    rollback_path_list.append(path)
                    LOG.debug(f'{self.__class__.__name__}: Construction:'
                              f' Create directory: {path}')
                except (OSError, RuntimeError) as e:
                    rollback()
                    raise cr_exc.InstallationStorageError(
                        f'Construction: Create directory: {path}:'
                        f' {type(e).__name__}: {e}'
                    ) from e
Пример #7
0
    def __init__(self,
                 root_dpath: str=DCOS_INST_ROOT_DPATH_DFT,
                 cfg_dpath: str=DCOS_INST_CFG_DPATH_DFT,
                 pkgrepo_dpath: str=DCOS_INST_PKGREPO_DPATH_DFT,
                 state_dpath: str=DCOS_INST_STATE_DPATH_DFT,
                 pkgactive_dpath: str=DCOS_PKGACTIVE_DPATH_DFT,
                 var_dpath: str=DCOS_INST_VAR_DPATH_DFT,
                 work_dpath: str=DCOS_INST_WORK_DPATH_DFT,
                 run_dpath: str=DCOS_INST_RUN_DPATH_DFT,
                 log_dpath: str=DCOS_INST_LOG_DPATH_DFT,
                 tmp_dpath: str=DCOS_INST_TMP_DPATH_DFT,
                 bin_dpath: str=DCOS_INST_BIN_DPATH_DFT,
                 lib_dpath: str=DCOS_INST_LIB_DPATH_DFT):
        """Constructor.

        :param root_dpath:      str, DC/OS installation root dir path
        :param cfg_dpath:       str, DC/OS installation configs root dir path
        :param pkgrepo_dpath:   str, local package repository root dir path
        :param state_dpath:     str, DC/OS installation state root dir path
        :param pkgactive_dpath: str, DC/OS active packages index dir path
        :param var_dpath:       str, DC/OS installation variable data root
                                dir path
        :param work_dpath:      str, package-specific work dirs root dir path
        :param run_dpath:       str, package-specific runtime data dirs root
                                dir path
        :param log_dpath:       str, package-specific/common log files root
                                dir path
        :param tmp_dpath:       str, package-specific/common temporary data
                                root dir path
        :param bin_dpath:       str, shared executables root dir path
        :param lib_dpath:       str, shared libraries root dir path
        """
        self.root_dpath = Path(root_dpath)
        if not self.root_dpath.is_absolute():
            raise cr_exc.InstallationStorageError(
                f'Require absolute root path: {root_dpath}'
            )
        self.cfg_dpath = self.root_dpath.joinpath(cfg_dpath)
        self.pkgrepo_dpath = self.root_dpath.joinpath(pkgrepo_dpath)
        self.state_dpath = self.root_dpath.joinpath(state_dpath)
        self.pkgactive_dpath = self.state_dpath.joinpath(pkgactive_dpath)
        self.var_dpath = self.root_dpath.joinpath(var_dpath)
        self.work_dpath = self.var_dpath.joinpath(work_dpath)
        self.run_dpath = self.var_dpath.joinpath(run_dpath)
        self.log_dpath = self.var_dpath.joinpath(log_dpath)
        self.tmp_dpath = self.var_dpath.joinpath(tmp_dpath)
        self.bin_dpath = self.root_dpath.joinpath(bin_dpath)
        self.lib_dpath = self.root_dpath.joinpath(lib_dpath)

        # TODO Fix Too many arguments for "IStorNodes"
        self.istor_nodes = IStorNodes(**{  # type: ignore
            ISTOR_NODE.ROOT: self.root_dpath,
            ISTOR_NODE.CFG: self.cfg_dpath,
            ISTOR_NODE.PKGREPO: self.pkgrepo_dpath,
            ISTOR_NODE.STATE: self.state_dpath,
            ISTOR_NODE.PKGACTIVE: self.pkgactive_dpath,
            ISTOR_NODE.VAR: self.var_dpath,
            ISTOR_NODE.WORK: self.work_dpath,
            ISTOR_NODE.RUN: self.run_dpath,
            ISTOR_NODE.LOG: self.log_dpath,
            ISTOR_NODE.TMP: self.tmp_dpath,
            ISTOR_NODE.BIN: self.bin_dpath,
            ISTOR_NODE.LIB: self.lib_dpath,
        })
Пример #8
0
    def add_package(self, pkg_id, dstor_root_url, dstor_pkgrepo_path):
        """Add a package to the local package repository.

        :param pkg_id:             PackageId, package ID
        :param dstor_root_url:     str, DC/OS distribution storage root URL
        :param dstor_pkgrepo_path: str, DC/OS distribution storage package
                                   repository root path
        """
        msg_src = self.__class__.__name__
        # Download a package tarball
        try:
            cm_utl.download(
                self._make_pkg_url(pkg_id=pkg_id,
                                   dstor_root_url=dstor_root_url,
                                   dstor_pkgrepo_path=dstor_pkgrepo_path),
                str(self.tmp_dpath))
            LOG.debug(f'{msg_src}: Add package: Download: {pkg_id}')
        except Exception as e:
            raise cr_exc.RCDownloadError(
                f'Add package: {pkg_id}: {type(e).__name__}: {e}')
        # Unpack a package tarball
        pkgtarball_fpath = (self.tmp_dpath.joinpath(
            pkg_id.pkg_id).with_suffix('.tar.xz'))
        try:
            cm_utl.unpack(str(pkgtarball_fpath), self.pkgrepo_dpath)
            LOG.debug(f'{msg_src}: Add package: Extract: {pkg_id}')
        except Exception as e:
            raise cr_exc.RCExtractError(
                f'Add package: {pkg_id}: {type(e).__name__}: {e}')
        finally:
            pkgtarball_fpath.unlink()
        # Create a work, runtime and log data directories for a package.
        for host_dpath in self.work_dpath, self.run_dpath, self.log_dpath:
            path = host_dpath.joinpath(pkg_id.pkg_name)

            if not path.exists():
                try:
                    path.mkdir(parents=True)
                    LOG.debug(f'{msg_src}: Add package: {pkg_id}:'
                              f' Create data directory: {path}')
                except (OSError, RuntimeError) as e:
                    raise cr_exc.InstallationStorageError(
                        f'Add package: {pkg_id}: Create data directory:'
                        f' {path}: {type(e).__name__}: {e}') from e
            elif path.is_symlink():
                raise cr_exc.InstallationStorageError(
                    f'Add package: {pkg_id}: Create data directory:'
                    f' {path}: Symlink conflict')
            elif path.is_reserved():
                raise cr_exc.InstallationStorageError(
                    f'Add package: {pkg_id}: Create data directory:'
                    f' {path}: Reserved name conflict')
            elif not path.is_dir():
                # Attempt to auto-clean garbage
                try:
                    path.unlink()
                    LOG.debug(
                        f'{msg_src}: Add package: {pkg_id}: Auto-cleanup:'
                        f' File: {path}')
                except (OSError, RuntimeError) as e:
                    raise cr_exc.InstallationStorageError(
                        f'Add package: {pkg_id}: Auto-cleanup: File: {path}:'
                        f' {type(e).__name__}: {e}') from e
                # Attempt to create data dir
                try:
                    path.mkdir(parents=True)
                    LOG.debug(f'{msg_src}: Add package: {pkg_id}:'
                              f' Create data directory: {path}')
                except (OSError, RuntimeError) as e:
                    raise cr_exc.InstallationStorageError(
                        f'Add package: {pkg_id}: Create data directory:'
                        f' {path}: {type(e).__name__}: {e}') from e
            else:
                # Leave existing directories intact
                pass

        # Workaround for dcos-diagnostics to be able to start
        # TODO: Remove this code after correct dcos-diagnostics configuration
        #       is figured out and all its config files are arranged properly
        #       to support DC/OS installation storage FS layout.
        if pkg_id.pkg_name == 'dcos-diagnostics':
            # Move binary and config-files to DC/OS installation storage root
            src_dpath = self.pkgrepo_dpath.joinpath(pkg_id.pkg_id, 'bin')
            try:
                LOG.debug(f'{msg_src}: Add package: Workaround: Copy list: '
                          f' {list(src_dpath.glob("*.*"))}')
                for src_fpath in src_dpath.glob('*.*'):
                    if not self.root_dpath.joinpath(src_fpath.name).exists():
                        shutil.copy(str(src_fpath), str(self.root_dpath))
                        LOG.debug(
                            f'{msg_src}: Add package: Workaround: Copy file: '
                            f' {str(src_fpath)} -> {str(self.root_dpath)}')
                # Create a folder for logs
                log_dpath = self.root_dpath.joinpath('mesos-logs')
                if not log_dpath.exists():
                    log_dpath.mkdir()
            except Exception as e:
                raise cr_exc.RCExtractError(
                    f'Add package: {pkg_id}: {type(e).__name__}: {e}')
Пример #9
0
    def __init__(self,
                 drive=DCOS_INST_DRIVE_DFT,
                 root_dpath=DCOS_INST_ROOT_DPATH_DFT,
                 cfg_dpath=DCOS_INST_CFG_DPATH_DFT,
                 pkgrepo_dpath=DCOS_INST_PKGREPO_DPATH_DFT,
                 state_dpath=DCOS_INST_STATE_DPATH_DFT,
                 pkgactive_dpath=DCOS_PKGACTIVE_DPATH_DFT,
                 var_dpath=DCOS_INST_VAR_DPATH_DFT,
                 work_dpath=DCOS_INST_WORK_DPATH_DFT,
                 run_dpath=DCOS_INST_RUN_DPATH_DFT,
                 log_dpath=DCOS_INST_LOG_DPATH_DFT,
                 tmp_dpath=DCOS_INST_TMP_DPATH_DFT):
        """DC/OS installation storage manager.

        :param drive:           str, DC/OS installation drive spec (ex. 'c:')
        :param root_dpath:      str, DC/OS installation root dir path
        :param cfg_dpath:       str, DC/OS installation configs root dir path
        :param pkgrepo_dpath:   str, local package repository root dir path
        :param state_dpath:     str, DC/OS installation state root dir path
        :param pkgactive_dpath: str, DC/OS active packages index dir path
        :param var_dpath:       str, DC/OS installation variable data root
                                dir path
        :param work_dpath:      str, package-specific work dirs root dir path
        :param run_dpath:       str, package-specific runtime data dirs root
                                dir path
        :param log_dpath:       str, package-specific/common log files root
                                dir path
        :param tmp_dpath:       str, package-specific/common temporary data
                                root dir path
        """
        # Refine/verify drive specification
        drive_ = Path(f'{drive.strip(":")}:').drive
        LOG.debug(f'InstallationStorage: drive_: {drive_}')
        if drive_:
            self.drive = Path(drive_, '/')
        else:
            raise cr_exc.InstallationStorageError(
                f'Invalid drive specification: {drive}')
        # Construct DC/OS installation root dir path
        root_dpath_ = Path(str(root_dpath))
        self.root_dpath = (root_dpath_ if root_dpath_.is_absolute() else Path(
            self.drive).joinpath(root_dpath_))
        # Construct DC/OS installation configuration dir path
        cfg_dpath_ = Path(str(cfg_dpath))
        self.cfg_dpath = (cfg_dpath_ if cfg_dpath_.is_absolute() else
                          self.root_dpath.joinpath(cfg_dpath_))
        # Construct DC/OS installation local package repository dir path
        pkgrepo_dpath_ = Path(str(pkgrepo_dpath))
        self.pkgrepo_dpath = (pkgrepo_dpath_ if pkgrepo_dpath_.is_absolute()
                              else self.root_dpath.joinpath(pkgrepo_dpath_))
        # Construct DC/OS installation state dir path
        state_dpath_ = Path(str(state_dpath))
        self.state_dpath = (state_dpath_ if state_dpath_.is_absolute() else
                            self.root_dpath.joinpath(state_dpath_))
        # Construct DC/OS installation active packages index dir path
        pkgactive_dpath_ = Path(str(pkgactive_dpath))
        self.pkgactive_dpath = (pkgactive_dpath_
                                if pkgactive_dpath_.is_absolute() else
                                self.state_dpath.joinpath(pkgactive_dpath_))
        # Construct DC/OS installation variable data root dir path
        var_dpath_ = Path(str(var_dpath))
        self.var_dpath = (var_dpath_ if var_dpath_.is_absolute() else
                          self.root_dpath.joinpath(var_dpath_))
        # Construct DC/OS installation package-specific work dirs root dir path
        work_dpath_ = Path(str(work_dpath))
        self.work_dpath = (work_dpath_ if work_dpath_.is_absolute() else
                           self.var_dpath.joinpath(work_dpath_))
        # Construct DC/OS installation runtime data root dir path
        run_dpath_ = Path(str(run_dpath))
        self.run_dpath = (run_dpath_ if run_dpath_.is_absolute() else
                          self.var_dpath.joinpath(run_dpath_))
        # Construct DC/OS installation logging data root dir path
        log_dpath_ = Path(str(log_dpath))
        self.log_dpath = (log_dpath_ if log_dpath_.is_absolute() else
                          self.var_dpath.joinpath(log_dpath_))
        # Construct DC/OS installation temporary data root dir path
        tmp_dpath_ = Path(str(tmp_dpath))
        self.tmp_dpath = (tmp_dpath_ if tmp_dpath_.is_absolute() else
                          self.var_dpath.joinpath(tmp_dpath_))

        self.istor_nodes = IStorNodes(
            **{
                ISTOR_NODE.DRIVE: self.drive,
                ISTOR_NODE.ROOT: self.root_dpath,
                ISTOR_NODE.CFG: self.cfg_dpath,
                ISTOR_NODE.PKGREPO: self.pkgrepo_dpath,
                ISTOR_NODE.STATE: self.state_dpath,
                ISTOR_NODE.PKGACTIVE: self.pkgactive_dpath,
                ISTOR_NODE.VAR: self.var_dpath,
                ISTOR_NODE.WORK: self.work_dpath,
                ISTOR_NODE.RUN: self.run_dpath,
                ISTOR_NODE.LOG: self.log_dpath,
                ISTOR_NODE.TMP: self.tmp_dpath
            })
Пример #10
0
    def setup_conf(self):
        """Setup configuration objects for a DC/OS package."""
        pkg_id = self._pkg_manifest.pkg_id
        pkg_cfg_dpath = getattr(self._pkg_manifest.istor_nodes,
                                ISTOR_NODE.PKGREPO).joinpath(
                                    pkg_id.pkg_id, cr_const.PKG_CFG_DNAME)
        LOG.debug(f'{self.msg_src}: Setup configuration: {pkg_id.pkg_name}:'
                  f' Source directory path: {pkg_cfg_dpath}')

        pkg_shrcfg_dpath = getattr(self._pkg_manifest.istor_nodes,
                                   ISTOR_NODE.CFG).joinpath(pkg_id.pkg_name)
        LOG.debug(f'{self.msg_src}: Setup configuration: {pkg_id.pkg_name}:'
                  f' Destination directory path: {pkg_shrcfg_dpath}')

        inst_tmp_dpath = getattr(self._pkg_manifest.istor_nodes,
                                 ISTOR_NODE.TMP)
        pkg_context = self._pkg_manifest.context

        if pkg_cfg_dpath.exists():
            if pkg_cfg_dpath.is_symlink():
                err_msg = (f'Source directory: Symlink conflict:'
                           f' {pkg_cfg_dpath}')
                raise cfgm_exc.PkgConfInvalidError(err_msg)
            elif pkg_cfg_dpath.is_reserved():
                err_msg = (f'Source directory: Reserved name conflict:'
                           f' {pkg_cfg_dpath}')
                raise cfgm_exc.PkgConfInvalidError(err_msg)
            elif not pkg_cfg_dpath.is_dir():
                err_msg = (f'Source directory: Not a directory:'
                           f' {pkg_cfg_dpath}')
                raise cfgm_exc.PkgConfInvalidError(err_msg)
            else:
                # Try to cleanup DC/OS shared configuration directory before
                # trying to create a package-specific configuration directory
                # there
                try:
                    if pkg_shrcfg_dpath.exists():
                        if pkg_shrcfg_dpath.is_dir():
                            shutil.rmtree(str(pkg_shrcfg_dpath))
                        elif pkg_shrcfg_dpath.is_file and (
                                not pkg_shrcfg_dpath.is_symlink()):
                            pkg_shrcfg_dpath.unlink()
                        else:
                            raise cr_exc.InstallationStorageError(
                                f'Setup configuration: {pkg_id.pkg_name}:'
                                f' Auto-cleanup: Removing objects other than'
                                f' regular directories and files is not'
                                f' supported: {pkg_shrcfg_dpath}')
                        LOG.debug(f'{self.msg_src}: Setup configuration:'
                                  f' {pkg_id.pkg_name}: Auto-cleanup:'
                                  f' {pkg_shrcfg_dpath}')
                except (OSError, RuntimeError) as e:
                    raise cr_exc.InstallationStorageError(
                        f'Setup configuration: {pkg_id.pkg_name}:'
                        f' Auto-cleanup: {pkg_shrcfg_dpath}:'
                        f' {type(e).__name__}: {e}') from e

                try:
                    with tf.TemporaryDirectory(dir=str(inst_tmp_dpath)) as tdp:

                        self._process_pkgconf_srcdir(src_dpath=pkg_cfg_dpath,
                                                     tmp_dpath=Path(tdp),
                                                     context=pkg_context)
                        shutil.copytree(tdp, str(pkg_shrcfg_dpath))
                        LOG.debug(
                            f'{self.msg_src}: Setup configuration:'
                            f' {pkg_id.pkg_name}: Save: {pkg_shrcfg_dpath}: OK'
                        )
                except (OSError, RuntimeError) as e:
                    err_msg = (f'Setup configuration: {pkg_id.pkg_name}:'
                               f' Process configuration sources:'
                               f' {pkg_cfg_dpath}: {type(e).__name__}: {e}')
                    raise cfgm_exc.PkgConfManagerError(err_msg)
        else:
            err_msg = f'Source directory: Not found: {pkg_cfg_dpath}'
            raise cfgm_exc.PkgConfNotFoundError(err_msg)
Пример #11
0
    def __init__(self,
                 drive=DCOS_INST_DRIVE_DFT,
                 root_dpath=DCOS_INST_ROOT_DPATH_DFT,
                 cfg_dpath=DCOS_INST_CFG_DPATH_DFT,
                 pkgrepo_dpath=DCOS_INST_PKGREPO_DPATH_DFT,
                 state_dpath=DCOS_INST_STATE_DPATH_DFT,
                 pkgactive_dpath=DCOS_PKGACTIVE_DPATH_DFT,
                 var_dpath=DCOS_INST_VAR_DPATH_DFT,
                 work_dpath=DCOS_INST_WORK_DPATH_DFT,
                 run_dpath=DCOS_INST_RUN_DPATH_DFT,
                 log_dpath=DCOS_INST_LOG_DPATH_DFT,
                 tmp_dpath=DCOS_INST_TMP_DPATH_DFT,
                 bin_dpath=DCOS_INST_BIN_DPATH_DFT,
                 lib_dpath=DCOS_INST_LIB_DPATH_DFT):
        """Constructor.

        :param drive:           str, DC/OS installation drive spec (ex. 'c:')
        :param root_dpath:      str, DC/OS installation root dir path
        :param cfg_dpath:       str, DC/OS installation configs root dir path
        :param pkgrepo_dpath:   str, local package repository root dir path
        :param state_dpath:     str, DC/OS installation state root dir path
        :param pkgactive_dpath: str, DC/OS active packages index dir path
        :param var_dpath:       str, DC/OS installation variable data root
                                dir path
        :param work_dpath:      str, package-specific work dirs root dir path
        :param run_dpath:       str, package-specific runtime data dirs root
                                dir path
        :param log_dpath:       str, package-specific/common log files root
                                dir path
        :param tmp_dpath:       str, package-specific/common temporary data
                                root dir path
        :param bin_dpath:       str, shared executables root dir path
        :param lib_dpath:       str, shared libraries root dir path
        """
        # Refine/verify drive specification
        drive_ = Path(f'{drive.strip(":")}:').drive
        LOG.debug(f'InstallationStorage: drive_: {drive_}')
        if drive_:
            self.drive = Path(drive_, '/')
        else:
            raise cr_exc.InstallationStorageError(
                f'Invalid drive specification: {drive}'
            )
        self.root_dpath = self.drive.joinpath(root_dpath)
        self.cfg_dpath = self.root_dpath.joinpath(cfg_dpath)
        self.pkgrepo_dpath = self.root_dpath.joinpath(pkgrepo_dpath)
        self.state_dpath = self.root_dpath.joinpath(state_dpath)
        self.pkgactive_dpath = self.state_dpath.joinpath(pkgactive_dpath)
        self.var_dpath = self.root_dpath.joinpath(var_dpath)
        self.work_dpath = self.var_dpath.joinpath(work_dpath)
        self.run_dpath = self.var_dpath.joinpath(run_dpath)
        self.log_dpath = self.var_dpath.joinpath(log_dpath)
        self.tmp_dpath = self.var_dpath.joinpath(tmp_dpath)
        self.bin_dpath = self.root_dpath.joinpath(bin_dpath)
        self.lib_dpath = self.root_dpath.joinpath(lib_dpath)

        self.istor_nodes = IStorNodes(**{
            ISTOR_NODE.DRIVE: self.drive,
            ISTOR_NODE.ROOT: self.root_dpath,
            ISTOR_NODE.CFG: self.cfg_dpath,
            ISTOR_NODE.PKGREPO: self.pkgrepo_dpath,
            ISTOR_NODE.STATE: self.state_dpath,
            ISTOR_NODE.PKGACTIVE: self.pkgactive_dpath,
            ISTOR_NODE.VAR: self.var_dpath,
            ISTOR_NODE.WORK: self.work_dpath,
            ISTOR_NODE.RUN: self.run_dpath,
            ISTOR_NODE.LOG: self.log_dpath,
            ISTOR_NODE.TMP: self.tmp_dpath,
            ISTOR_NODE.BIN: self.bin_dpath,
            ISTOR_NODE.LIB: self.lib_dpath,
        })