]> Frank Brehm's Git Trees - pixelpark/create-vmware-tpl.git/commitdiff
Adding class CobblerDistroInfo to module cr_vmware_tpl.config.
authorFrank Brehm <frank@brehm-online.com>
Thu, 23 Jun 2022 10:51:05 +0000 (12:51 +0200)
committerFrank Brehm <frank@brehm-online.com>
Thu, 23 Jun 2022 10:51:05 +0000 (12:51 +0200)
lib/cr_vmware_tpl/config.py

index a979ac5395bd51c113ef7f5a495fefb7ab60553b..1a66e2dcebbb715896b0316bc8d785b196752a48 100644 (file)
@@ -19,6 +19,8 @@ from pathlib import Path
 
 # Own modules
 from fb_tools.common import is_sequence
+from fb_tools.obj import FbGenericBaseObject
+from fb_tools.collections import CIStringSet
 from fb_tools.multi_config import MultiConfigError, BaseMultiConfig
 from fb_tools.multi_config import DEFAULT_ENCODING
 from fb_tools.xlate import format_list
@@ -29,7 +31,7 @@ from . import DEFAULT_CONFIG_DIR
 
 from .xlate import XLATOR
 
-__version__ = '1.8.1'
+__version__ = '1.9.1'
 LOG = logging.getLogger(__name__)
 
 _ = XLATOR.gettext
@@ -44,6 +46,222 @@ class CrTplConfigError(MultiConfigError):
     pass
 
 
+# =============================================================================
+class CobblerDistroInfo(FbGenericBaseObject):
+    """Class for encapsulation all necessary data of a Repo definition in Cobbler."""
+
+    re_dashes = re.compile(r'[_-]')
+
+    # -------------------------------------------------------------------------
+    def __init__(
+            self, name, shortname=None, distro=None, description=None, repos=None, snippets=None):
+
+        self._name = None
+        self._shortname = None
+        self._distro = None
+        self._description = None
+        self.repos = CIStringSet()
+        self.snippets = CIStringSet()
+
+        self.name = name
+        self.shortname = shortname
+        self.distro = distro
+        self.description = description
+
+        if repos:
+            if is_sequence(repos):
+                self.repos = copy.copy(repos)
+            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)
+            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 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
+
+    # -------------------------------------------------------------------------
+    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("description={!r}".format(self.description))
+
+        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['name'] = self.name
+        res['shortname'] = self.shortname
+        res['distro'] = self.distro
+        res['description'] = self.description
+
+        return res
+
+    # -------------------------------------------------------------------------
+    def __copy__(self):
+
+        new = self.__class__(
+            self.name, shortname=self.shortname, distro=self.distro, description=self.description)
+
+        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
+                continue
+
+            if key.lower() == 'distro' and value.strip() != '':
+                new.distro = value
+                continue
+
+            if key.lower() == 'description' and value.strip() != '':
+                new.description = value
+                continue
+
+            if key.lower() == 'repos':
+                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())
+
+                continue
+
+            if key.lower() == 'snippets':
+                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())
+
+                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))
+
+        return new
+
+
 # =============================================================================
 class CrTplConfiguration(BaseMultiConfig):
     """
@@ -334,6 +552,11 @@ class CrTplConfiguration(BaseMultiConfig):
         res['system_ks'] = self.system_ks
         res['snippets_dir'] = self.snippets_dir
 
+        res['cobbler_distros'] = {}
+        for distro in self.cobbler_distros.keys():
+            res['cobbler_distros'][distro] = self.cobbler_distros[distro].as_dict(short=short)
+
+
         res['root_password'] = None
         if self.root_password:
             if self.verbose > 4:
@@ -379,27 +602,27 @@ class CrTplConfiguration(BaseMultiConfig):
             raise CrTplConfigError(msg)
 
         for distro_id in self.cobbler_distros.keys():
-            distro_info = self.cobbler_distros[distro_id]
+            distro = self.cobbler_distros[distro_id]
 
-            if 'distro' not in distro_info:
+            if not distro.distro:
                 msg = _("Did not found distro of configured Cobbler distro {!r}.").format(
                     distro_id)
                 raise CrTplConfigError(msg)
 
-            if not len(distro_info['repos']):
+            if not len(distro.repos):
                 msg = _(
                     "Did not found repo definitions for configured Cobbler "
                     "distro {!r}.").format(distro_id)
                 LOG.warn(msg)
 
-            if 'description' not in distro_info:
-                distro_info['description'] = distro_id
+            if not distro.description:
+                distro.description = distro_id
 
         if self.os_id not in self.cobbler_distros:
             msg = _("Did not found distro {!r} in configured Cobbler distros.").format(self.os_id)
             raise CrTplConfigError(msg)
 
-        self.cobbler_distro = self.cobbler_distros[self.os_id]['distro']
+        self.cobbler_distro = self.cobbler_distros[self.os_id].distro
 
         LOG.info(_("Using OS {os!r} with cobbler distro {di!r}.").format(
             os=self.os_id, di=self.cobbler_distro))
@@ -751,40 +974,9 @@ class CrTplConfiguration(BaseMultiConfig):
         for distro_id in section.keys():
             distro_info = section[distro_id]
             distro_id = distro_id.lower()
-            if distro_id not in self.cobbler_distros:
-                self.cobbler_distros[distro_id] = {}
-
-            self._eval_cobbler_distro(distro_id, distro_info)
-
-    # -------------------------------------------------------------------------
-    def _eval_cobbler_distro(self, distro_id, distro_info):
-
-        if self.verbose > 2:
-            LOG.debug(_("Evaluating Cobbler distro {!r} ...").format(distro_id))
-
-        distro = self.cobbler_distros[distro_id]
-
-        if 'repos' not in distro:
-            distro['repos'] = []
-
-        for key in distro_info.keys():
-            value = distro_info[key]
-
-            if key.lower() == 'distro' and value.strip() != '':
-                distro['distro'] = value.strip()
-                continue
-            if key.lower() == 'description' and value.strip() != '':
-                distro['description'] = value.strip()
-                continue
-            if key.lower() == 'repos':
-                if is_sequence(value):
-                    for repo in value:
-                        repo = repo.strip()
-                        if repo != '':
-                            distro['repos'].append(repo)
-                elif value.strip() != '':
-                    distro['repos'].append(value.strip())
-                continue
+            distro = CobblerDistroInfo.init_from_config(
+                distro_id, distro_info, verbose=self.verbose)
+            self.cobbler_distros[distro_id] = distro
 
     # -------------------------------------------------------------------------
     def get_root_pwd_hash(self, method='sha256'):