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
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()
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
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()