From e012acf7fd7c7430d3cddef7853292e83c7a574a Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Fri, 22 Sep 2023 12:23:47 +0200 Subject: [PATCH] Separating definition of CobblerDistroInfo into a separate module --- lib/cr_vmware_tpl/config/__init__.py | 386 +------------------------ lib/cr_vmware_tpl/config/distro.py | 416 +++++++++++++++++++++++++++ 2 files changed, 421 insertions(+), 381 deletions(-) create mode 100644 lib/cr_vmware_tpl/config/distro.py diff --git a/lib/cr_vmware_tpl/config/__init__.py b/lib/cr_vmware_tpl/config/__init__.py index c195dee..92f7313 100644 --- a/lib/cr_vmware_tpl/config/__init__.py +++ b/lib/cr_vmware_tpl/config/__init__.py @@ -3,7 +3,7 @@ """ @author: Frank Brehm @contact: frank.brehm@pixelpark.com -@copyright: © 2018 by Frank Brehm, Berlin +@copyright: © 2023 by Frank Brehm, Berlin @summary: A module for providing a configuration """ from __future__ import absolute_import @@ -19,9 +19,7 @@ import ipaddress # Third party modules from pathlib import Path -from fb_tools.common import is_sequence, pp, to_bool -from fb_tools.obj import FbGenericBaseObject -from fb_tools.collections import CIStringSet +from fb_tools.common import is_sequence, pp from fb_tools.multi_config import BaseMultiConfig from fb_tools.multi_config import DEFAULT_ENCODING from fb_tools.xlate import format_list @@ -29,397 +27,23 @@ from fb_tools.xlate import format_list from fb_vmware.config import VSPhereConfigInfo # Own modules -from .. import DEFAULT_CONFIG_DIR, DEFAULT_DISTRO_ARCH +from .. import DEFAULT_CONFIG_DIR from .. import DEFAULT_PORT_LDAPS, DEFAULT_TIMEOUT, MAX_TIMEOUT from ..errors import CrTplConfigError from ..xlate import XLATOR +from .distro import CobblerDistroInfo from .ldap import LdapConnectionInfo, LdapConnectionDict -__version__ = '3.0.1' +__version__ = '3.0.2' LOG = logging.getLogger(__name__) _ = XLATOR.gettext ngettext = XLATOR.ngettext -# ============================================================================= -class CobblerDistroInfo(FbGenericBaseObject): - """Class for encapsulation all necessary data of a Repo definition in Cobbler.""" - - re_dashes = re.compile(r'[_-]') - valid_arch = ( - 'i386', 'x86_64', 'ia64', 'ppc', 'ppc64', 'ppc64el', 'ppc64le', - 's390', 's390x', 'arm', 'aarch64') - - # ------------------------------------------------------------------------- - def __init__( - self, name, shortname=None, distro=None, description=None, arch=DEFAULT_DISTRO_ARCH, - ks_repo_url=None, packages=None, repos=None, snippets=None): - - self._name = None - self._shortname = None - self._distro = None - self._description = None - self._arch = DEFAULT_DISTRO_ARCH - self._ks_repo_url = None - self._is_rhel = False - self._ks_template = 'el8-standard.ks' - self.packages = [] - self.repos = CIStringSet() - self.snippets = CIStringSet() - - self.name = name - self.shortname = shortname - self.distro = distro - self.description = description - self.arch = arch - - if packages: - if is_sequence(packages): - for pkg in packages: - if pkg not in packages: - self.packages.append(pkg) - else: - msg = _("The given parameter {p!r} must be sequential type (given: {v!r}).") - raise TypeError(msg.format(p='packages', v=repos)) - - if repos: - if is_sequence(repos): - for repo in repos: - self.repos.add(repo) - else: - msg = _("The given parameter {p!r} must be sequential type (given: {v!r}).") - raise TypeError(msg.format(p='repos', v=repos)) - - if snippets: - if is_sequence(repos): - self.snippets = copy.copy(snippets) - for snippet in snippets: - self.snippets.add(snippet) - else: - msg = _("The given parameter {p!r} must be sequential type (given: {v!r}).") - raise TypeError(msg.format(p='snippets', v=snippets)) - - # ------------------------------------------------------------------------- - @property - def name(self): - """The canonical name of the distribution.""" - return getattr(self, '_name', None) - - @name.setter - def name(self, value): - - name = value.strip() - if name == '': - msg = _("The name of a Cobbler distro may not be empty.") - raise ValueError(msg) - - self._name = name - - # ------------------------------------------------------------------------- - @property - def shortname(self): - """The short name of the distro, how to be used e.g. as part of the template name.""" - - shortname = getattr(self, '_shortname', None) - if shortname is None: - name = self.name - if name is None: - return None - shortname = self.re_dashes.sub('', name) - return shortname - - @shortname.setter - def shortname(self, value): - if value is None: - self._shortname = None - return - shortname = value.strip() - if shortname == '': - self._shortname = None - return - self._shortname = shortname - - # ------------------------------------------------------------------------- - @property - def distro(self): - """The name of the underlaying (real) cobbler distro.""" - return getattr(self, '_distro', None) - - @distro.setter - def distro(self, value): - if value is None: - self._distro = None - return - - dis = value.strip() - if dis == '': - self._distro = None - return - - self._distro = dis - - # ------------------------------------------------------------------------- - @property - def arch(self): - """The name of the underlaying (real) cobbler distro.""" - return getattr(self, '_arch', DEFAULT_DISTRO_ARCH) - - @arch.setter - def arch(self, value): - - arch = value.strip().lower() - if arch not in self.valid_arch: - msg = _( - "Invalid architecture {a!r} for distro {n!r} given. Valid architectures are {v}.") - msg = msg.format(a=value, n=self.name, v=format_list(self.valid_arch, do_repr=True)) - raise ValueError(msg) - - self._arch = arch - - # ------------------------------------------------------------------------- - @property - def description(self): - """The name of the underlaying (real) cobbler distro.""" - return getattr(self, '_description', None) - - @description.setter - def description(self, value): - if value is None: - self._description = None - return - - desc = value.strip() - if desc == '': - self._description = None - return - - self._description = desc - - # ------------------------------------------------------------------------- - @property - def ks_repo_url(self): - """The URL for the base installation repository.""" - return getattr(self, '_ks_repo_url', None) - - @ks_repo_url.setter - def ks_repo_url(self, value): - if value is None: - self._ks_repo_url = None - return - - ks_repo_url = value.strip() - if ks_repo_url == '': - self._ks_repo_url = None - return - - self._ks_repo_url = ks_repo_url - - # ------------------------------------------------------------------------- - @property - def is_rhel(self): - """Is the currwnt distro a RHEL distro?""" - return self._is_rhel - - @is_rhel.setter - def is_rhel(self, value): - self._is_rhel = to_bool(value) - - # ------------------------------------------------------------------------- - @property - def ks_template(self): - """The filename below templates for generating the final kickstart file.""" - - return getattr(self, '_ks_template', 'el8-standard.ks') - - @ks_template.setter - def ks_template(self, value): - if value is None: - return - template = value.strip() - if template == '': - return - self._ks_template = template - - # ------------------------------------------------------------------------- - @property - def repos_string(self): - """Returns all repos as a string of their space concatinated names.""" - if self.repos: - return ' '.join(self.repos.as_list()) - return '' - - # ------------------------------------------------------------------------- - def __repr__(self): - """Typecasting into a string for reproduction.""" - - out = "<%s()" % (self.__class__.__name__) - - fields = [] - fields.append("name={!r}".format(self.name)) - fields.append("shortname={!r}".format(self._shortname)) - fields.append("distro={!r}".format(self.distro)) - fields.append("arch={!r}".format(self.arch)) - fields.append("is_rhel={!r}".format(self.is_rhel)) - fields.append("ks_template={!r}".format(self.ks_template)) - fields.append("description={!r}".format(self.description)) - fields.append("ks_repo_url={!r}".format(self.ks_repo_url)) - - out += ", ".join(fields) + ")>" - - return out - - # ------------------------------------------------------------------------- - def as_dict(self, short=True): - """ - Transforms the elements of the object into a dict - - @param short: don't include local properties in resulting dict. - @type short: bool - - @return: structure as dict - @rtype: dict - """ - - res = super(CobblerDistroInfo, self).as_dict(short=short) - res['arch'] = self.arch - res['description'] = self.description - res['distro'] = self.distro - res['is_rhel'] = self.is_rhel - res['ks_repo_url'] = self.ks_repo_url - res['ks_template'] = self.ks_template - res['name'] = self.name - res['repos_string'] = self.repos_string - res['shortname'] = self.shortname - - return res - - # ------------------------------------------------------------------------- - def __eq__(self, other): - - if not isinstance(other, CobblerDistroInfo): - return False - - return self.name == other.name - - # ------------------------------------------------------------------------- - def __copy__(self): - - new = self.__class__( - self.name, shortname=self.shortname, distro=self.distro, arch=self.arch, - ks_repo_url=self.ks_repo_url, description=self.description) - - for package in self.packages: - new.packages.append(package) - - for repo in self.repos: - new.repos.add(repo) - - for snippet in self.snippets: - new.snippets.add(snippet) - - return new - - # ------------------------------------------------------------------------- - @classmethod - def init_from_config(cls, name, data, verbose=0): - - new = cls(name) - - for key in data.keys(): - value = data[key] - - if key.lower() == 'shortname' and value.strip() != '': - new.shortname = value.strip() - continue - - if key.lower() == 'distro' and value.strip() != '': - new.distro = value.strip() - continue - - if key.lower() == 'description' and value.strip() != '': - new.description = value.strip() - continue - - if key.lower() == 'arch' and value.strip() != '': - new.arch = value.strip() - continue - - if key.lower() == 'is_rhel': - new.is_rhel = value - continue - - if key.lower() == 'ks_repo_url' and value.strip() != '': - new.ks_repo_url = value.strip() - continue - - if key.lower() == 'ks_template' and value.strip() != '': - new._ks_template = value.strip() - continue - - if key.lower() == 'repos': - cls._update_repos(new, value) - continue - - if key.lower() == 'packages': - cls._update_packages(new, value) - continue - - if key.lower() == 'snippets': - cls._update_snippets(new, value) - continue - - if verbose: - LOG.warn(_( - "Found unknown config parameter {p!r} with value {v!r} in configuration " - "of the Cobbler repository {r!r}.").format(p=key, v=value, r=name)) - - if verbose > 2: - msg = _("Found Cobbler repository configuration:") + '\n' + pp(new.as_dict()) - LOG.debug(msg) - - return new - - # ------------------------------------------------------------------------- - @classmethod - def _update_repos(cls, new, value): - - if is_sequence(value): - for repo in value: - repo = repo.strip() - if repo != '': - new.repos.add(repo) - elif value.strip() != '': - new.repos.add(value.strip()) - - # ------------------------------------------------------------------------- - @classmethod - def _update_packages(cls, new, value): - - if is_sequence(value): - for pkg in value: - pkg = pkg.strip() - if pkg != '' and pkg not in new.packages: - new.packages.append(pkg) - elif value.strip() != '': - new.packages.add(value.strip()) - - # ------------------------------------------------------------------------- - @classmethod - def _update_snippets(cls, new, value): - - if is_sequence(value): - for snippet in value: - snippet = snippet.strip() - if snippet != '': - new.snippets.add(snippet) - elif value.strip() != '': - new.snippets.add(value.strip()) - - # ============================================================================= class CrTplConfiguration(BaseMultiConfig): """ diff --git a/lib/cr_vmware_tpl/config/distro.py b/lib/cr_vmware_tpl/config/distro.py new file mode 100644 index 0000000..bac9bf4 --- /dev/null +++ b/lib/cr_vmware_tpl/config/distro.py @@ -0,0 +1,416 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +@author: Frank Brehm +@contact: frank.brehm@pixelpark.com +@copyright: © 20123by Frank Brehm, Berlin +@summary: A module for providing a configuration for cobbler distros +""" +from __future__ import absolute_import + +# Standard module +import logging +import re +import copy + +# Third party modules +from fb_tools.common import is_sequence, pp, to_bool +from fb_tools.obj import FbGenericBaseObject +from fb_tools.collections import CIStringSet +from fb_tools.xlate import format_list + +# Own modules +from .. import DEFAULT_DISTRO_ARCH + +from ..xlate import XLATOR + +__version__ = '0.1.0' +LOG = logging.getLogger(__name__) + +_ = XLATOR.gettext +ngettext = XLATOR.ngettext + + +# ============================================================================= +class CobblerDistroInfo(FbGenericBaseObject): + """Class for encapsulation all necessary data of a Repo definition in Cobbler.""" + + re_dashes = re.compile(r'[_-]') + valid_arch = ( + 'i386', 'x86_64', 'ia64', 'ppc', 'ppc64', 'ppc64el', 'ppc64le', + 's390', 's390x', 'arm', 'aarch64') + + # ------------------------------------------------------------------------- + def __init__( + self, name, shortname=None, distro=None, description=None, arch=DEFAULT_DISTRO_ARCH, + ks_repo_url=None, packages=None, repos=None, snippets=None): + + self._name = None + self._shortname = None + self._distro = None + self._description = None + self._arch = DEFAULT_DISTRO_ARCH + self._ks_repo_url = None + self._is_rhel = False + self._ks_template = 'el8-standard.ks' + self.packages = [] + self.repos = CIStringSet() + self.snippets = CIStringSet() + + self.name = name + self.shortname = shortname + self.distro = distro + self.description = description + self.arch = arch + + if packages: + if is_sequence(packages): + for pkg in packages: + if pkg not in packages: + self.packages.append(pkg) + else: + msg = _("The given parameter {p!r} must be sequential type (given: {v!r}).") + raise TypeError(msg.format(p='packages', v=repos)) + + if repos: + if is_sequence(repos): + for repo in repos: + self.repos.add(repo) + else: + msg = _("The given parameter {p!r} must be sequential type (given: {v!r}).") + raise TypeError(msg.format(p='repos', v=repos)) + + if snippets: + if is_sequence(repos): + self.snippets = copy.copy(snippets) + for snippet in snippets: + self.snippets.add(snippet) + else: + msg = _("The given parameter {p!r} must be sequential type (given: {v!r}).") + raise TypeError(msg.format(p='snippets', v=snippets)) + + # ------------------------------------------------------------------------- + @property + def name(self): + """The canonical name of the distribution.""" + return getattr(self, '_name', None) + + @name.setter + def name(self, value): + + name = value.strip() + if name == '': + msg = _("The name of a Cobbler distro may not be empty.") + raise ValueError(msg) + + self._name = name + + # ------------------------------------------------------------------------- + @property + def shortname(self): + """The short name of the distro, how to be used e.g. as part of the template name.""" + + shortname = getattr(self, '_shortname', None) + if shortname is None: + name = self.name + if name is None: + return None + shortname = self.re_dashes.sub('', name) + return shortname + + @shortname.setter + def shortname(self, value): + if value is None: + self._shortname = None + return + shortname = value.strip() + if shortname == '': + self._shortname = None + return + self._shortname = shortname + + # ------------------------------------------------------------------------- + @property + def distro(self): + """The name of the underlaying (real) cobbler distro.""" + return getattr(self, '_distro', None) + + @distro.setter + def distro(self, value): + if value is None: + self._distro = None + return + + dis = value.strip() + if dis == '': + self._distro = None + return + + self._distro = dis + + # ------------------------------------------------------------------------- + @property + def arch(self): + """The name of the underlaying (real) cobbler distro.""" + return getattr(self, '_arch', DEFAULT_DISTRO_ARCH) + + @arch.setter + def arch(self, value): + + arch = value.strip().lower() + if arch not in self.valid_arch: + msg = _( + "Invalid architecture {a!r} for distro {n!r} given. Valid architectures are {v}.") + msg = msg.format(a=value, n=self.name, v=format_list(self.valid_arch, do_repr=True)) + raise ValueError(msg) + + self._arch = arch + + # ------------------------------------------------------------------------- + @property + def description(self): + """The name of the underlaying (real) cobbler distro.""" + return getattr(self, '_description', None) + + @description.setter + def description(self, value): + if value is None: + self._description = None + return + + desc = value.strip() + if desc == '': + self._description = None + return + + self._description = desc + + # ------------------------------------------------------------------------- + @property + def ks_repo_url(self): + """The URL for the base installation repository.""" + return getattr(self, '_ks_repo_url', None) + + @ks_repo_url.setter + def ks_repo_url(self, value): + if value is None: + self._ks_repo_url = None + return + + ks_repo_url = value.strip() + if ks_repo_url == '': + self._ks_repo_url = None + return + + self._ks_repo_url = ks_repo_url + + # ------------------------------------------------------------------------- + @property + def is_rhel(self): + """Is the currwnt distro a RHEL distro?""" + return self._is_rhel + + @is_rhel.setter + def is_rhel(self, value): + self._is_rhel = to_bool(value) + + # ------------------------------------------------------------------------- + @property + def ks_template(self): + """The filename below templates for generating the final kickstart file.""" + + return getattr(self, '_ks_template', 'el8-standard.ks') + + @ks_template.setter + def ks_template(self, value): + if value is None: + return + template = value.strip() + if template == '': + return + self._ks_template = template + + # ------------------------------------------------------------------------- + @property + def repos_string(self): + """Returns all repos as a string of their space concatinated names.""" + if self.repos: + return ' '.join(self.repos.as_list()) + return '' + + # ------------------------------------------------------------------------- + def __repr__(self): + """Typecasting into a string for reproduction.""" + + out = "<%s()" % (self.__class__.__name__) + + fields = [] + fields.append("name={!r}".format(self.name)) + fields.append("shortname={!r}".format(self._shortname)) + fields.append("distro={!r}".format(self.distro)) + fields.append("arch={!r}".format(self.arch)) + fields.append("is_rhel={!r}".format(self.is_rhel)) + fields.append("ks_template={!r}".format(self.ks_template)) + fields.append("description={!r}".format(self.description)) + fields.append("ks_repo_url={!r}".format(self.ks_repo_url)) + + out += ", ".join(fields) + ")>" + + return out + + # ------------------------------------------------------------------------- + def as_dict(self, short=True): + """ + Transforms the elements of the object into a dict + + @param short: don't include local properties in resulting dict. + @type short: bool + + @return: structure as dict + @rtype: dict + """ + + res = super(CobblerDistroInfo, self).as_dict(short=short) + res['arch'] = self.arch + res['description'] = self.description + res['distro'] = self.distro + res['is_rhel'] = self.is_rhel + res['ks_repo_url'] = self.ks_repo_url + res['ks_template'] = self.ks_template + res['name'] = self.name + res['repos_string'] = self.repos_string + res['shortname'] = self.shortname + + return res + + # ------------------------------------------------------------------------- + def __eq__(self, other): + + if not isinstance(other, CobblerDistroInfo): + return False + + return self.name == other.name + + # ------------------------------------------------------------------------- + def __copy__(self): + + new = self.__class__( + self.name, shortname=self.shortname, distro=self.distro, arch=self.arch, + ks_repo_url=self.ks_repo_url, description=self.description) + + for package in self.packages: + new.packages.append(package) + + for repo in self.repos: + new.repos.add(repo) + + for snippet in self.snippets: + new.snippets.add(snippet) + + return new + + # ------------------------------------------------------------------------- + @classmethod + def init_from_config(cls, name, data, verbose=0): + + new = cls(name) + + for key in data.keys(): + value = data[key] + + if key.lower() == 'shortname' and value.strip() != '': + new.shortname = value.strip() + continue + + if key.lower() == 'distro' and value.strip() != '': + new.distro = value.strip() + continue + + if key.lower() == 'description' and value.strip() != '': + new.description = value.strip() + continue + + if key.lower() == 'arch' and value.strip() != '': + new.arch = value.strip() + continue + + if key.lower() == 'is_rhel': + new.is_rhel = value + continue + + if key.lower() == 'ks_repo_url' and value.strip() != '': + new.ks_repo_url = value.strip() + continue + + if key.lower() == 'ks_template' and value.strip() != '': + new._ks_template = value.strip() + continue + + if key.lower() == 'repos': + cls._update_repos(new, value) + continue + + if key.lower() == 'packages': + cls._update_packages(new, value) + continue + + if key.lower() == 'snippets': + cls._update_snippets(new, value) + continue + + if verbose: + LOG.warn(_( + "Found unknown config parameter {p!r} with value {v!r} in configuration " + "of the Cobbler repository {r!r}.").format(p=key, v=value, r=name)) + + if verbose > 2: + msg = _("Found Cobbler repository configuration:") + '\n' + pp(new.as_dict()) + LOG.debug(msg) + + return new + + # ------------------------------------------------------------------------- + @classmethod + def _update_repos(cls, new, value): + + if is_sequence(value): + for repo in value: + repo = repo.strip() + if repo != '': + new.repos.add(repo) + elif value.strip() != '': + new.repos.add(value.strip()) + + # ------------------------------------------------------------------------- + @classmethod + def _update_packages(cls, new, value): + + if is_sequence(value): + for pkg in value: + pkg = pkg.strip() + if pkg != '' and pkg not in new.packages: + new.packages.append(pkg) + elif value.strip() != '': + new.packages.add(value.strip()) + + # ------------------------------------------------------------------------- + @classmethod + def _update_snippets(cls, new, value): + + if is_sequence(value): + for snippet in value: + snippet = snippet.strip() + if snippet != '': + new.snippets.add(snippet) + elif value.strip() != '': + new.snippets.add(value.strip()) + + +# ============================================================================= +if __name__ == "__main__": + + pass + +# ============================================================================= + +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list -- 2.39.5