Example #1
0
def get_dstor_dcoscfgpkg_path(dstor_root_url: str, dstor_lpi_path: str,
                              tmp_dpath: str):
    """Retrieve the Linux Package Index (LPI) object from the DC/OS
    distribution storage and discover a relative URL to the DC/OS
    aggregated configuration package.
    LPI is expected to be a JSON-formatted file containing descriptors for
    DC/OS distribution packages:

    {
        "<pkg-name>":{
            "filename":"<base-path>/<pkg-name>--<pkg-version>.tar.xz",
            "id":"<pkg-name>--<pkg-version>"
        },
        ...
    }

    :param dstor_root_url:         str, DC/OS distribution storage root URL
    :param dstor_lpi_path:         str, URL path to the DC/OS Linux package
                                   index object at the DC/OS distribution
                                   storage
    :return tmp_dpath:             str, URL path to the DC/OS aggregated
                                   config package at the DC/OS distribution
                                   storage
    """
    dcos_conf_pkg_name = 'dcos-config-win'

    # Linux package index direct URL
    lpi_url = posixpath.join(dstor_root_url, dstor_lpi_path)
    try:
        lpi_fpath = cm_utl.download(lpi_url, tmp_dpath)
        LOG.debug(f'DC/OS Linux package index: Download: {lpi_url}')
    except Exception as e:
        raise cr_exc.RCDownloadError(
            f'DC/OS Linux package index: {lpi_url}: {type(e).__name__}: {e}'
        ) from e

    try:
        lpi = cr_utl.rc_load_json(lpi_fpath,
                                  emheading='DC/OS Linux package index')

        if not isinstance(lpi, dict):
            raise cr_exc.RCInvalidError(
                f'DC/OS Linux package index: {lpi_url}: Invalid structure')

        dcos_conf_pkg_desc = lpi.get(dcos_conf_pkg_name)

        if dcos_conf_pkg_desc is None:
            raise cr_exc.RCElementError(
                f'DC/OS Linux package index: {lpi_url}: DC/OS aggregated'
                f' config package descriptor is missed:'
                f' {dcos_conf_pkg_name}')

        if not isinstance(dcos_conf_pkg_desc, dict):
            raise cr_exc.RCElementError(
                f'DC/OS Linux package index: {lpi_url}: Invalid DC/OS'
                f' aggregated config package descriptor:'
                f' {dcos_conf_pkg_desc}')

        dstor_dcoscfgpkg_path = dcos_conf_pkg_desc.get('filename')
        if dstor_dcoscfgpkg_path is None:
            raise cr_exc.RCElementError(
                f'DC/OS Linux package index: {lpi_url}: DC/OS aggregated'
                f' config package descriptor: Distribution storage path is'
                f' missed: {dcos_conf_pkg_desc}')
        if not isinstance(dstor_dcoscfgpkg_path, str):
            raise cr_exc.RCElementError(
                f'DC/OS Linux package index: {lpi_url}: DC/OS aggregated'
                f' config package descriptor: Distribution storage path:'
                f' Invalid type: {dstor_dcoscfgpkg_path}')
    finally:
        lpi_fpath.unlink()

    return dstor_dcoscfgpkg_path
Example #2
0
    def get_dcos_conf(self):
        """Get the DC/OS aggregated configuration object.

        :return: dict, set of DC/OS shared and package specific configuration
                 objects:
                     {
                         'package': {[
                             {'path': <str>, 'content': <str>},
                             ...
                         ]}
                     }
        """

        dstor_root_url = (self.cluster_conf.get('distribution-storage',
                                                {}).get('rooturl', ''))
        dstor_dcoscfg_path = (self.cluster_conf.get('distribution-storage',
                                                    {}).get('dcoscfgpath', ''))
        # Unblock irrelevant local operations
        if self.cluster_conf_nop or dstor_dcoscfg_path == 'NOP':
            LOG.info(f'{self.msg_src}: dcos_conf: NOP')
            return {}

        dcoscfg_url = posixpath.join(dstor_root_url, dstor_dcoscfg_path)
        dcoscfg_fname = Path(dstor_dcoscfg_path).name

        try:
            cm_utl.download(dcoscfg_url, str(self.inst_storage.tmp_dpath))
            LOG.debug(f'{self.msg_src}: DC/OS aggregated config: Download:'
                      f' {dcoscfg_fname}: {dcoscfg_url}')
        except Exception as e:
            raise cr_exc.RCDownloadError(
                f'DC/OS aggregated config: Download: {dcoscfg_fname}:'
                f' {dcoscfg_url}: {type(e).__name__}: {e}') from e

        dcoscfg_fpath = self.inst_storage.tmp_dpath.joinpath(dcoscfg_fname)

        try:
            dcos_conf = cr_utl.rc_load_yaml(
                dcoscfg_fpath,
                emheading=f'DC/OS aggregated config: {dcoscfg_fname}',
                render=True,
                context=ResourceContext(
                    istor_nodes=self.inst_storage.istor_nodes,
                    cluster_conf=self.cluster_conf))

            if (not isinstance(dcos_conf, dict)
                    or not isinstance(dcos_conf.get('package'), list)):
                raise cr_exc.RCInvalidError(
                    f'DC/OS aggregated config: {dcos_conf}')

            for element in dcos_conf.get('package'):
                if (not isinstance(element, dict)
                        or not isinstance(element.get('path'), str)
                        or not isinstance(element.get('content'), str)):
                    raise cr_exc.RCElementError(
                        f'DC/OS aggregated config: {element}')

            return dcos_conf

        except cr_exc.RCError as e:
            raise e
        finally:
            dcoscfg_fpath.unlink()
Example #3
0
    def get_dstor_dcoscfgpkg_path(self, dstor_root_url: str,
                                  dstor_lpi_path: str):
        """Retrieve the Linux Package Index (LPI) object from the DC/OS
        distribution storage and discover a relative URL to the DC/OS
        aggregated configuration package.
        LPI is expected to be a JSON-formatted file containing descriptors for
        DC/OS distribution packages:

        {
            "<pkg-name>":{
                "filename":"<base-path>/<pkg-name>--<pkg-version>.tar.xz",
                "id":"<pkg-name>--<pkg-version>"
            },
            ...
        }

        :param dstor_root_url:         str, DC/OS distribution storage root URL
        :param dstor_lpi_path:         str, URL path to the DC/OS Linux package
                                       index object at the DC/OS distribution
                                       storage
        :return dstor_dcoscfgpkg_path: str, URL path to the DC/OS aggregated
                                       config package at the DC/OS distribution
                                       storage
        """
        # TODO: Functionality implemented in this method needs to be reused
        #       in other application parts (e.g. CmdConfigUpgrade) and so, it
        #       has been arranged as a standalone function
        #       get_dstor_dcoscfgpkg_path().
        #       Thus the CmdConfigSetup is to be moved to use that standalone
        #       function instead of this method to avoid massive code
        #       duplication.
        dcos_conf_pkg_name = 'dcos-config-win'

        # Linux package index direct URL
        lpi_url = posixpath.join(dstor_root_url, dstor_lpi_path)

        try:
            lpi_fpath = cm_utl.download(lpi_url, self.inst_storage.tmp_dpath)
            LOG.debug(f'{self.msg_src}: DC/OS Linux package index: Download:'
                      f' {lpi_url}')
        except Exception as e:
            raise cr_exc.RCDownloadError(
                f'DC/OS Linux package index: {lpi_url}: {type(e).__name__}:'
                f' {e}') from e

        try:
            lpi = cr_utl.rc_load_json(lpi_fpath,
                                      emheading='DC/OS Linux package index')

            if not isinstance(lpi, dict):
                raise cr_exc.RCInvalidError(
                    f'DC/OS Linux package index: {lpi_url}: Invalid structure')

            dcos_conf_pkg_desc = lpi.get(dcos_conf_pkg_name)

            if dcos_conf_pkg_desc is None:
                raise cr_exc.RCElementError(
                    f'DC/OS Linux package index: {lpi_url}: DC/OS aggregated'
                    f' config package descriptor is missed:'
                    f' {dcos_conf_pkg_name}')

            if not isinstance(dcos_conf_pkg_desc, dict):
                raise cr_exc.RCElementError(
                    f'DC/OS Linux package index: {lpi_url}: Invalid DC/OS'
                    f' aggregated config package descriptor:'
                    f' {dcos_conf_pkg_desc}')

            dstor_dcoscfgpkg_path = dcos_conf_pkg_desc.get('filename')
            if dstor_dcoscfgpkg_path is None:
                raise cr_exc.RCElementError(
                    f'DC/OS Linux package index: {lpi_url}: DC/OS aggregated'
                    f' config package descriptor: Distribution storage path is'
                    f' missed: {dcos_conf_pkg_desc}')
            if not isinstance(dstor_dcoscfgpkg_path, str):
                raise cr_exc.RCElementError(
                    f'DC/OS Linux package index: {lpi_url}: DC/OS aggregated'
                    f' config package descriptor: Distribution storage path:'
                    f' Invalid type: {dstor_dcoscfgpkg_path}')
        finally:
            lpi_fpath.unlink()

        return dstor_dcoscfgpkg_path
Example #4
0
    def get_dcos_conf(self):
        """Get the DC/OS aggregated configuration object.

        :return: dict, set of DC/OS shared and package specific configuration
                 templates coupled with 'key=value' substitution data
                 container:
                 {
                    'template': {
                        'package': [
                            {'path': <str>, 'content': <str>},
                             ...
                        ]
                    },
                    'values': {
                        key: value,
                        ...
                    }
                 }
        """

        dstor_root_url = (self.cluster_conf.get('distribution-storage',
                                                {}).get('rooturl', ''))
        dstor_linux_pkg_index_path = (self.cluster_conf.get(
            'distribution-storage', {}).get('dcosclusterpkginfopath', ''))
        dcos_conf_pkg_name = 'dcos-config-win'
        template_fname = 'dcos-config-windows.yaml'
        values_fname = 'expanded.config.full.json'

        # Unblock irrelevant local operations
        if self.cluster_conf_nop or dstor_linux_pkg_index_path == 'NOP':
            LOG.info(f'{self.msg_src}: dcos_conf: NOP')
            return {}

        # Linux package index direct URL
        lpi_url = posixpath.join(dstor_root_url, dstor_linux_pkg_index_path)
        lpi_fname = Path(dstor_linux_pkg_index_path).name

        try:
            cm_utl.download(lpi_url, str(self.inst_storage.tmp_dpath))
            LOG.debug(f'{self.msg_src}: DC/OS Linux package index: Download:'
                      f' {lpi_fname}: {lpi_url}')
        except Exception as e:
            raise cr_exc.RCDownloadError(
                f'DC/OS Linux package index: Download: {lpi_fname}:'
                f' {lpi_url}: {type(e).__name__}: {e}') from e

        lpi_fpath = self.inst_storage.tmp_dpath.joinpath(lpi_fname)

        try:
            lpi = cr_utl.rc_load_json(
                lpi_fpath, emheading=f'DC/OS Linux package index: {lpi_fname}')

            if (not isinstance(lpi, dict)
                    or not isinstance(lpi.get(dcos_conf_pkg_name), dict)):
                raise cr_exc.RCInvalidError(
                    f'DC/OS Linux package index: {lpi}')

            dstor_dcoscfg_pkg_path = lpi.get(dcos_conf_pkg_name).get(
                'filename')
            if not isinstance(dstor_dcoscfg_pkg_path, str):
                raise cr_exc.RCElementError(
                    f'DC/OS Linux package index: DC/OS config package'
                    f' distribution storage path: {dstor_dcoscfg_pkg_path}')
        except cr_exc.RCError as e:
            raise e
        finally:
            lpi_fpath.unlink()

        dcoscfg_pkg_url = posixpath.join(dstor_root_url,
                                         dstor_dcoscfg_pkg_path)
        dcoscfg_pkg_fname = Path(dstor_dcoscfg_pkg_path).name

        # Download DC/OS aggregated configuration package ...
        try:
            cm_utl.download(dcoscfg_pkg_url, str(self.inst_storage.tmp_dpath))
            LOG.debug(f'{self.msg_src}: DC/OS aggregated config: Download:'
                      f' {dcoscfg_pkg_fname}: {dcoscfg_pkg_url}')
        except Exception as e:
            raise cr_exc.RCDownloadError(
                f'DC/OS aggregated config: Download: {dcoscfg_pkg_fname}:'
                f' {dcoscfg_pkg_url}: {type(e).__name__}: {e}') from e

        dcoscfg_pkg_fpath = self.inst_storage.tmp_dpath.joinpath(
            dcoscfg_pkg_fname)

        try:
            with tf.TemporaryDirectory(
                    dir=str(self.inst_storage.tmp_dpath)) as tmp_dpath:
                cm_utl.unpack(str(dcoscfg_pkg_fpath), tmp_dpath)
                LOG.debug(f'{self.msg_src}: DC/OS aggregated config: Extract:'
                          f' OK')

                values_fpath = Path(tmp_dpath).joinpath(values_fname)
                values = cr_utl.rc_load_json(
                    values_fpath,
                    emheading=f'DC/OS aggregated config: Values: {values_fname}'
                )
                template_fpath = Path(tmp_dpath).joinpath(template_fname)
                template = self.load_dcos_conf_templete(template_fpath)
        except Exception as e:
            if not isinstance(e, cr_exc.RCError):
                raise cr_exc.RCExtractError(
                    f'DC/OS aggregated config: {type(e).__name__}: {e}')
            else:
                raise
        else:
            return {'template': template, 'values': values}
        finally:
            dcoscfg_pkg_fpath.unlink()