from fb_tools.xlate import format_list
from .distro import CobblerDistro
+from .files import CobblerFiles
from .. import print_section_start, print_section_end
from ..xlate import XLATOR
-__version__ = '0.11.0'
+__version__ = '0.11.1'
LOG = logging.getLogger(__name__)
# =============================================================================
-class Cobbler(BaseHandler, CobblerDistro):
+class Cobbler(BaseHandler, CobblerDistro, CobblerFiles):
"""
A handler class for executing cobbler actions.
"""
LOG.debug(_("Completed SSH process:") + "\n{}".format(proc))
return proc
- # -------------------------------------------------------------------------
- def scp_to(self, local_file, remote_file):
-
- ssh = None
-
- try:
-
- if self.verbose > 2:
- LOG.debug(_("Initializing {} ...").format('paramiko SSHClient'))
- ssh = paramiko.SSHClient()
- if self.verbose > 2:
- LOG.debug(_("Loading SSH system host keys."))
- ssh.load_system_host_keys()
- if self.verbose > 2:
- LOG.debug(_("Setting SSH missing host key policy to {}.").format('AutoAddPolicy'))
- ssh.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
-
- if self.verbose > 1:
- LOG.debug(_("Connecting to {h!r}, port {p} as {u!r} per SSH ...").format(
- h=self.host, p=self.ssh_port, u=self.ssh_user))
-
- if self.simulate:
- LOG.debug(_(
- "Simulating SCP of {local!r} to {user}@{host}:{remote} ...").format(
- local=str(local_file), user=self.ssh_user,
- host=self.host, remote=str(remote_file)))
-
- else:
- ssh.connect(
- self.host, port=self.ssh_port, timeout=self.ssh_timeout,
- username=self.ssh_user, key_filename=self.private_ssh_key)
-
- sftp = ssh.open_sftp()
-
- LOG.debug(_("SCP of {local!r} to {user}@{host}:{remote} ...").format(
- local=str(local_file), user=self.ssh_user,
- host=self.host, remote=str(remote_file)))
-
- sftp.put(str(local_file), str(remote_file))
-
- except SSHException as e:
- msg = _("Could not connect via {w} to {user}@{host}: {e}").format(
- w='SCP', user=self.ssh_user, host=self.host, e=e)
- raise ExpectedCobblerError(msg)
-
- finally:
- sftp = None
- if ssh:
- if self.verbose > 2:
- LOG.debug(_("Closing SSH connection."))
- ssh.close()
-
# -------------------------------------------------------------------------
def get_cobbler_version(self):
"""Trying to evaluate the version of Cobbler on the cobbler host."""
return cobbler_version
- # -------------------------------------------------------------------------
- def check_remote_directory(self, rdir, desc=None):
-
- if self.verbose > 1:
- msg = _("Checking existence of remote directory {!r} ...").format(str(rdir))
- LOG.debug(msg)
-
- cmd = textwrap.dedent("""\
- if [ -d {rdir!r} ] ; then
- exit 0
- fi
- exit 7
- """).format(rdir=str(rdir))
-
- proc = self.exec_ssh(cmd)
- if proc.returncode != 0:
- dsc = _('Remote directory')
- if desc:
- dsc = desc
- msg = _(
- "{dsc} {rdir!r} on host {host!r} does not exists or is not a directory.").format(
- dsc=dsc, rdir=str(rdir), host=self.host)
- raise ExpectedCobblerError(msg)
-
- # -------------------------------------------------------------------------
- def ensure_remote_directory(self, rdir, desc=None):
-
- if self.verbose:
- msg = _("Ensuring existence of remote directory {!r} ...").format(str(rdir))
- LOG.debug(msg)
-
- verb = ''
- if self.verbose:
- verb = " --verbose"
-
- cmd = textwrap.dedent("""\
- if [ -d {rdir!r} ] ; then
- exit 0
- fi
- if [ -e {rdir!r} ] ; then
- echo "Path {rdir!r} exists, but is not a directory." >&2
- exit 7
- fi
- mkdir --parents{verb} {rdir!r}
- """).format(rdir=str(rdir), verb=verb)
-
- proc = self.exec_ssh(cmd)
- if proc.returncode == 0:
- if proc.stdout:
- LOG.debug(_("Output:") + "\n{}".format(proc.stdout))
- else:
- dsc = _('Remote directory')
- if desc:
- dsc = desc
- err = _('No error message')
- if proc.stderr:
- err = proc.stderr
- elif proc.stdout:
- err = proc.stdout
- msg = _(
- "{dsc} {rdir!r} on host {host!r} could not be created: {err}").format(
- dsc=dsc, rdir=str(rdir), host=self.host, err=err)
- raise ExpectedCobblerError(msg)
-
# -------------------------------------------------------------------------
def get_profile_list(self):
"""Trying to get a list of all configured cobbler profiles."""
LOG.debug(_("Sorted list of found profiles:") + "\n{}".format(pp(profile_list)))
return profile_list
- # -------------------------------------------------------------------------
- def ensure_remote_file(self, local_file, remote_file, check_parent=True):
-
- if check_parent:
- self.check_remote_directory(remote_file.parent)
-
- msg = _("Checking remote file {rfile!r} based on local {lfile!r} ...").format(
- rfile=str(remote_file), lfile=str(local_file))
- LOG.debug(msg)
-
- if not local_file.exists() or not local_file.is_file():
- msg = _("Local file {!r} either not exists or is not a regular file.").format(
- str(local_file))
- raise ExpectedCobblerError(msg)
- local_file_content = local_file.read_bytes()
- digest = hashlib.sha256(local_file_content).hexdigest()
- if self.verbose > 1:
- LOG.debug(_('{typ} sum of {ks!r} is: {dig}').format(
- typ='SHA256', ks=str(local_file), dig=digest))
-
- cmd = textwrap.dedent("""\
- if [ -f {rfile!r} ] ; then
- digest=$(sha256sum {rfile!r} | awk '{{print $1}}')
- echo "Digest: ${{digest}}"
- if [ "${{digest}}" != {dig!r} ] ; then
- echo "SHA256 sum does not match." >&2
- exit 4
- fi
- exit 0
- else
- exit 3
- fi
- """).format(rfile=str(remote_file), dig=digest)
-
- proc = self.exec_ssh(cmd)
- if proc.returncode == 0:
- LOG.debug(_("Remote file {!r} has the correct content.").format(
- str(remote_file)))
- return
-
- msg = _("File {!r} has to be copied.").format(str(local_file))
- LOG.warn(msg)
-
- 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, tmp_auth_keys_file=None):
-
- bname = 'auth_keys_pp_betrieb'
- if tmp_auth_keys_file:
- local_file = tmp_auth_keys_file
- else:
- local_file = self.base_dir / 'keys' / bname
- remote_file = self.cfg.cobbler_ws_docroot / self.cfg.cobbler_ws_rel_filesdir / bname
-
- self.ensure_remote_file(local_file, remote_file)
-
- # -------------------------------------------------------------------------
- def ensure_rsyslog_cfg_files(self):
-
- files_dir = self.base_dir / 'files'
- docroot = self.cfg.cobbler_ws_docroot / self.cfg.cobbler_ws_rel_filesdir
- remote_dir = docroot / self.cfg.system_status
-
- LOG.info(_("Ensuring currentness of rsyslog config files ..."))
- print_section_start(
- 'ensure_rsyslog_cfg_files', 'Ensuring rsyslog config files.', collapsed=True)
-
- for local_cfg_file in files_dir.glob('*rsyslog.conf*'):
- remote_cfg_file = remote_dir / local_cfg_file.name
- LOG.debug(_("Ensuring {loc!r} => {rem!r}.").format(
- loc=str(local_cfg_file), rem=str(remote_cfg_file)))
- self.ensure_remote_file(local_cfg_file, remote_cfg_file, check_parent=False)
-
- print_section_end('ensure_rsyslog_cfg_files')
-
# -------------------------------------------------------------------------
def ensure_profile_ks(self):