aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--man/en/sos-collect.130
-rw-r--r--sos/collector/__init__.py17
-rw-r--r--sos/collector/sosnode.py40
-rw-r--r--sos/policies/distros/__init__.py16
-rw-r--r--sos/policies/distros/redhat.py25
-rw-r--r--sos/policies/runtimes/__init__.py25
6 files changed, 140 insertions, 13 deletions
diff --git a/man/en/sos-collect.1 b/man/en/sos-collect.1
index 286bfe71..cdbc3257 100644
--- a/man/en/sos-collect.1
+++ b/man/en/sos-collect.1
@@ -26,6 +26,11 @@ sos collect \- Collect sosreports from multiple (cluster) nodes
[\-\-no\-pkg\-check]
[\-\-no\-local]
[\-\-master MASTER]
+ [\-\-image IMAGE]
+ [\-\-force-pull-image]
+ [\-\-registry-user USER]
+ [\-\-registry-password PASSWORD]
+ [\-\-registry-authfile FILE]
[\-o ONLY_PLUGINS]
[\-p SSH_PORT]
[\-\-password]
@@ -245,6 +250,31 @@ Specify a master node for the cluster.
If provided, then sos collect will check the master node, not localhost, for determining
the type of cluster in use.
.TP
+\fB\-\-image IMAGE\fR
+Specify an image to use for the temporary container created for collections on
+containerized host, if you do not want to use the default image specifed by the
+host's policy. Note that this should include the registry.
+.TP
+\fB\-\-force-pull-image\fR
+Use this option to force the container runtime to pull the specified image (even
+if it is the policy default image) even if the image already exists on the host.
+This may be useful to update an older container image on containerized hosts.
+.TP
+\fB\-\-registry-user USER\fR
+Specify the username to authenticate to the registry with in order to pull the container
+image
+.TP
+\fB\-\-registry-password PASSWORD\fR
+Specify the password to authenticate to the registry with in order to pull the container
+image. If no password is required, leave this blank.
+.TP
+\fB\-\-registry-authfile FILE\fR
+Specify the filename to use for providing authentication credentials to the registry
+to pull the container image.
+
+Note that this file must exist on the node(s) performing the pull operations, not the
+node from which \fBsos collect\fR was run.
+.TP
\fB\-o\fR ONLY_PLUGINS, \fB\-\-only\-plugins\fR ONLY_PLUGINS
Sosreport option. Run ONLY the plugins listed.
diff --git a/sos/collector/__init__.py b/sos/collector/__init__.py
index 1c742cf5..0624caad 100644
--- a/sos/collector/__init__.py
+++ b/sos/collector/__init__.py
@@ -63,6 +63,7 @@ class SoSCollector(SoSComponent):
'encrypt_pass': '',
'group': None,
'image': '',
+ 'force_pull_image': False,
'jobs': 4,
'keywords': [],
'keyword_file': None,
@@ -84,6 +85,9 @@ class SoSCollector(SoSComponent):
'plugin_timeout': None,
'cmd_timeout': None,
'preset': '',
+ 'registry_user': None,
+ 'registry_password': None,
+ 'registry_authfile': None,
'save_group': '',
'since': '',
'skip_commands': [],
@@ -319,6 +323,19 @@ class SoSCollector(SoSComponent):
collect_grp.add_argument('--image',
help=('Specify the container image to use for'
' containerized hosts.'))
+ collect_grp.add_argument('--force-pull-image', '--pull', default=False,
+ action='store_true',
+ help='Force pull the container image even if '
+ 'it already exists on the host')
+ collect_grp.add_argument('--registry-user', default=None,
+ help='Username to authenticate to the '
+ 'registry with for pulling an image')
+ collect_grp.add_argument('--registry-password', default=None,
+ help='Password to authenticate to the '
+ 'registry with for pulling an image')
+ collect_grp.add_argument('--registry-authfile', default=None,
+ help='Use this authfile to provide registry '
+ 'authentication when pulling an image')
collect_grp.add_argument('-i', '--ssh-key', help='Specify an ssh key')
collect_grp.add_argument('-j', '--jobs', default=4, type=int,
help='Number of concurrent nodes to collect')
diff --git a/sos/collector/sosnode.py b/sos/collector/sosnode.py
index 48693342..d1c11824 100644
--- a/sos/collector/sosnode.py
+++ b/sos/collector/sosnode.py
@@ -134,9 +134,27 @@ class SosNode():
"""If the host is containerized, create the container we'll be using
"""
if self.host.containerized:
- res = self.run_command(self.host.create_sos_container(),
- need_root=True)
- if res['status'] in [0, 125]: # 125 means container exists
+ cmd = self.host.create_sos_container(
+ image=self.opts.image,
+ auth=self.get_container_auth(),
+ force_pull=self.opts.force_pull_image
+ )
+ res = self.run_command(cmd, need_root=True)
+ if res['status'] in [0, 125]:
+ if res['status'] == 125:
+ if 'unable to retrieve auth token' in res['stdout']:
+ self.log_error(
+ "Could not pull image. Provide either a username "
+ "and password or authfile"
+ )
+ raise Exception
+ elif 'unknown: Not found' in res['stdout']:
+ self.log_error('Specified image not found on registry')
+ raise Exception
+ # 'name exists' with code 125 means the container was
+ # created successfully, so ignore it.
+ # initial creations leads to an exited container, restarting it
+ # here will keep it alive for us to exec through
ret = self.run_command(self.host.restart_sos_container(),
need_root=True)
if ret['status'] == 0:
@@ -152,6 +170,20 @@ class SosNode():
% res['stdout'])
raise Exception
+ def get_container_auth(self):
+ """Determine what the auth string should be to pull the image used to
+ deploy our temporary container
+ """
+ if self.opts.registry_user:
+ return self.host.runtimes['default'].fmt_registry_credentials(
+ self.opts.registry_user,
+ self.opts.registry_password
+ )
+ else:
+ return self.host.runtimes['default'].fmt_registry_authfile(
+ self.opts.registry_authfile or self.host.container_authfile
+ )
+
def file_exists(self, fname):
"""Checks for the presence of fname on the remote node"""
if not self.local:
@@ -343,7 +375,7 @@ class SosNode():
% self.commons['policy'].distro)
return self.commons['policy']
host = load(cache={}, sysroot=self.opts.sysroot, init=InitSystem(),
- probe_runtime=False, remote_exec=self.ssh_cmd,
+ probe_runtime=True, remote_exec=self.ssh_cmd,
remote_check=self.read_file('/etc/os-release'))
if host:
self.log_info("loaded policy %s for host" % host.distro)
diff --git a/sos/policies/distros/__init__.py b/sos/policies/distros/__init__.py
index 9fe31513..f5b9fd5b 100644
--- a/sos/policies/distros/__init__.py
+++ b/sos/policies/distros/__init__.py
@@ -62,6 +62,7 @@ class LinuxPolicy(Policy):
sos_bin_path = '/usr/bin'
sos_container_name = 'sos-collector-tmp'
container_version_command = None
+ container_authfile = None
def __init__(self, sysroot=None, init=None, probe_runtime=True):
super(LinuxPolicy, self).__init__(sysroot=sysroot,
@@ -626,13 +627,26 @@ class LinuxPolicy(Policy):
"""
return ''
- def create_sos_container(self):
+ def create_sos_container(self, image=None, auth=None, force_pull=False):
"""Returns the command that will create the container that will be
used for running commands inside a container on hosts that require it.
This will use the container runtime defined for the host type to
launch a container. From there, we use the defined runtime to exec into
the container's namespace.
+
+ :param image: The name of the image if not using the policy default
+ :type image: ``str`` or ``None``
+
+ :param auth: The auth string required by the runtime to pull an
+ image from the registry
+ :type auth: ``str`` or ``None``
+
+ :param force_pull: Should the runtime forcibly pull the image
+ :type force_pull: ``bool``
+
+ :returns: The command to execute to launch the temp container
+ :rtype: ``str``
"""
return ''
diff --git a/sos/policies/distros/redhat.py b/sos/policies/distros/redhat.py
index 241d3f13..20afbcc4 100644
--- a/sos/policies/distros/redhat.py
+++ b/sos/policies/distros/redhat.py
@@ -452,15 +452,19 @@ support representative.
return self.find_preset(ATOMIC)
- def create_sos_container(self):
+ def create_sos_container(self, image=None, auth=None, force_pull=False):
_cmd = ("{runtime} run -di --name {name} --privileged --ipc=host"
" --net=host --pid=host -e HOST=/host -e NAME={name} -e "
- "IMAGE={image} -v /run:/run -v /var/log:/var/log -v "
+ "IMAGE={image} {pull} -v /run:/run -v /var/log:/var/log -v "
"/etc/machine-id:/etc/machine-id -v "
- "/etc/localtime:/etc/localtime -v /:/host {image}")
+ "/etc/localtime:/etc/localtime -v /:/host {auth} {image}")
+ _image = image or self.container_image
+ _pull = '--pull=always' if force_pull else ''
return _cmd.format(runtime=self.container_runtime,
name=self.sos_container_name,
- image=self.container_image)
+ image=_image,
+ pull=_pull,
+ auth=auth or '')
def set_cleanup_cmd(self):
return 'docker rm --force sos-collector-tmp'
@@ -482,6 +486,7 @@ support representative.
container_image = 'registry.redhat.io/rhel8/support-tools'
sos_path_strip = '/host'
container_version_command = 'rpm -q sos'
+ container_authfile = '/var/lib/kubelet/config.json'
def __init__(self, sysroot=None, init=None, probe_runtime=True,
remote_exec=None):
@@ -511,15 +516,19 @@ support representative.
# RH OCP environments.
return self.find_preset(RHOCP)
- def create_sos_container(self):
+ def create_sos_container(self, image=None, auth=None, force_pull=False):
_cmd = ("{runtime} run -di --name {name} --privileged --ipc=host"
" --net=host --pid=host -e HOST=/host -e NAME={name} -e "
- "IMAGE={image} -v /run:/run -v /var/log:/var/log -v "
+ "IMAGE={image} {pull} -v /run:/run -v /var/log:/var/log -v "
"/etc/machine-id:/etc/machine-id -v "
- "/etc/localtime:/etc/localtime -v /:/host {image}")
+ "/etc/localtime:/etc/localtime -v /:/host {auth} {image}")
+ _image = image or self.container_image
+ _pull = '--pull=always' if force_pull else ''
return _cmd.format(runtime=self.container_runtime,
name=self.sos_container_name,
- image=self.container_image)
+ image=_image,
+ pull=_pull,
+ auth=auth or '')
def set_cleanup_cmd(self):
return 'podman rm --force %s' % self.sos_container_name
diff --git a/sos/policies/runtimes/__init__.py b/sos/policies/runtimes/__init__.py
index 1a61b644..f28d6a1d 100644
--- a/sos/policies/runtimes/__init__.py
+++ b/sos/policies/runtimes/__init__.py
@@ -157,6 +157,31 @@ class ContainerRuntime():
quoted_cmd = cmd
return "%s %s %s" % (self.run_cmd, container, quoted_cmd)
+ def fmt_registry_credentials(self, username, password):
+ """Format a string to pass to the 'run' command of the runtime to
+ enable authorization for pulling the image during `sos collect`, if
+ needed using username and optional password creds
+
+ :param username: The name of the registry user
+ :type username: ``str``
+
+ :param password: The password of the registry user
+ :type password: ``str`` or ``None``
+
+ :returns: The string to use to enable a run command to pull the image
+ :rtype: ``str``
+ """
+ return "--creds=%s%s" % (username, ':' + password if password else '')
+
+ def fmt_registry_authfile(self, authfile):
+ """Format a string to pass to the 'run' command of the runtime to
+ enable authorization for pulling the image during `sos collect`, if
+ needed using an authfile.
+ """
+ if authfile:
+ return "--authfile %s" % authfile
+ return ''
+
def get_logs_command(self, container):
"""Get the command string used to dump container logs from the
runtime