From 32b7007fa0210b2d7e6969f1fad46af71dc9b6c2 Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Fri, 29 May 2020 15:13:00 +0200 Subject: [PATCH] Implementing changing of an existing profile --- lib/cr_vmware_tpl/cobbler.py | 118 ++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 3 deletions(-) diff --git a/lib/cr_vmware_tpl/cobbler.py b/lib/cr_vmware_tpl/cobbler.py index efbe9f9..7328e30 100644 --- a/lib/cr_vmware_tpl/cobbler.py +++ b/lib/cr_vmware_tpl/cobbler.py @@ -17,6 +17,8 @@ import json import hashlib import textwrap +from json import JSONDecodeError + # Third party modules import paramiko from paramiko.ssh_exception import SSHException @@ -35,7 +37,7 @@ from .config import CrTplConfiguration from .xlate import XLATOR -__version__ = '0.3.10' +__version__ = '0.4.0' LOG = logging.getLogger(__name__) @@ -270,8 +272,6 @@ class Cobbler(BaseHandler): dsc=dsc, rdir=str(rdir), host=self.host) raise ExpectedCobblerError(msg) - - # ------------------------------------------------------------------------- def get_distro_list(self): """Trying to get a list of all configured distros.""" @@ -349,6 +349,35 @@ class Cobbler(BaseHandler): self.scp_to(local_file, remote_file) + # ------------------------------------------------------------------------- + def get_remote_filecontent(self, remote_file): + + LOG.debug(_("Getting content of remote file {!r} ...").format(str(remote_file))) + + cmd = textwrap.dedent("""\ + if [ -f {rfile!r} ] ; then + cat {rfile!r} + else + echo "Remote file does not exists." >&2 + exit 7 + fi + """).format(rfile=str(remote_file)) + + proc = self.exec_ssh(cmd) + if proc.returncode: + err = _('No error message') + if proc.stderr: + err = proc.stderr + elif proc.stdout: + err = proc.stdout + msg = _( + "Error getting content of {rfile!r} on host {host!r} - " + "returncode was {rc}: {err}").format( + rfile=str(remote_file), host=self.host, rc=proc.returncode, err=err) + raise ExpectedCobblerError(msg) + + return proc.stdout + # ------------------------------------------------------------------------- def ensure_root_authkeys(self): @@ -390,6 +419,89 @@ class Cobbler(BaseHandler): distro = self.config.cobbler_distro LOG.debug(_("Checking existing profile {!r} ...").format(profile)) + remote_file = ( + self.config.cobbler_rootdir / 'config' / 'profiles.d' / ( + self.config.cobbler_profile + '.json')) + + fcontent = self.get_remote_filecontent(remote_file) + if self.verbose > 2: + LOG.debug(_("Got content of remote {rfile!r}:\n{cont}").format( + rfile=str(remote_file), cont=fcontent)) + + try: + js = json.loads(fcontent) + except JSONDecodeError as e: + msg = _("Error interpreting JS: {}").format(e) + raise ExpectedCobblerError(msg) + + if self.verbose > 1: + LOG.debug(_("Got json object for profile {name!r}:\n{obj}").format( + name=profile, obj=pp(js))) + + self._change_profile(js) + + # ------------------------------------------------------------------------- + def _change_profile(self, js): + + profile = self.config.cobbler_profile + distro = self.config.cobbler_distro + + args = [] + + if js['distro'] != distro: + args.append('--distro') + args.append(distro) + + if not js['enable_menu']: + args.append('--enable-menu') + args.append('1') + + if js['kickstart'] != str(self.config.cobbler_profile_ks): + args.append('--kickstart') + args.append(str(self.config.cobbler_profile_ks)) + + if 'inst.sshd' not in js['kernel_options']: + args.append('--kopts') + args.append('inst.sshd') + + if js['repos'] != self.config.cobbler_profile_repos: + args.append('--repos') + args.append(' '.join(self.config.cobbler_profile_repos)) + + os_id = self.config.os_id + comment = "Profile for creating a {} profile.".format(os_id) + if js['comment'] != comment: + args.append('--comment') + args.append(comment) + + if js['name_servers'] != self.config.cobbler_nameservers: + args.append('--name-servers') + args.append(' '.join(self.config.cobbler_nameservers)) + + if js['name_servers_search'] != self.config.cobbler_dns_search: + args.append('--name-servers-search') + args.append(' '.join(self.config.cobbler_dns_search)) + + if self.verbose: + LOG.debug("Args for 'profile edit:\n{}".format(pp(args))) + + if not args: + LOG.debug(_("No need for changing profile {!r}").format(profile)) + return + + args = ['profile', 'edit', '--name', profile] + args + + proc = self.exec_cobbler(args) + + if proc.returncode: + err = _('No error message') + if proc.stderr: + err = proc.stderr + elif proc.stdout: + err = proc.stdout + msg = _("Error editing a cobbler profile - returncode was {rc}: {err}").format( + rc=proc.returncode, err=err) + raise ExpectedCobblerError(msg) # ------------------------------------------------------------------------- def add_profile(self): -- 2.39.5