aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJake Hunsaker <jhunsake@redhat.com>2020-12-17 16:08:54 -0500
committerJake Hunsaker <jhunsake@redhat.com>2021-01-04 11:55:11 -0500
commitd48660eef94d906831a38fd16e7a0f3791228242 (patch)
tree982734d18d13d05efcc6d2f3c458df7703c0ed99
parentdb398cc11daa7d3d06f245162787a3982323f573 (diff)
downloadsos-d48660eef94d906831a38fd16e7a0f3791228242.tar.gz
[ContainerRuntime] Separate runtimes from policies
Moves `ContainerRuntime` and the related subclasses out from `sos/policies/__init__.py` into a new `sos/policies/runtimes` subdir. Related: #2349 Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
-rw-r--r--sos/policies/__init__.py182
-rw-r--r--sos/policies/runtimes/__init__.py173
-rw-r--r--sos/policies/runtimes/docker.py30
-rw-r--r--sos/policies/runtimes/podman.py21
4 files changed, 226 insertions, 180 deletions
diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py
index 7f140613..ee466c95 100644
--- a/sos/policies/__init__.py
+++ b/sos/policies/__init__.py
@@ -12,12 +12,13 @@ from getpass import getpass
from pwd import getpwuid
from sos.utilities import (ImporterHelper,
import_module,
- is_executable,
shell_out,
sos_get_command_output,
get_human_readable)
from sos.report.plugins import IndependentPlugin, ExperimentalPlugin
from sos.options import SoSOptions
+from sos.policies.runtimes.docker import DockerContainerRuntime
+from sos.policies.runtimes.podman import PodmanContainerRuntime
from sos import _sos as _
from textwrap import fill
from pipes import quote
@@ -59,185 +60,6 @@ def load(cache={}, sysroot=None, init=None, probe_runtime=True,
return cache['policy']
-class ContainerRuntime(object):
- """Encapsulates a container runtime that provides the ability to plugins to
- check runtime status, check for the presence of specific containers, and
- to format commands to run in those containers
-
- :param policy: The loaded policy for the system
- :type policy: ``Policy()``
-
- :cvar name: The name of the container runtime, e.g. 'podman'
- :vartype name: ``str``
-
- :cvar containers: A list of containers known to the runtime
- :vartype containers: ``list``
-
- :cvar images: A list of images known to the runtime
- :vartype images: ``list``
-
- :cvar binary: The binary command to run for the runtime, must exit within
- $PATH
- :vartype binary: ``str``
- """
-
- name = 'Undefined'
- containers = []
- images = []
- volumes = []
- binary = ''
- active = False
-
- def __init__(self, policy=None):
- self.policy = policy
- self.run_cmd = "%s exec " % self.binary
-
- def load_container_info(self):
- """If this runtime is found to be active, attempt to load information
- on the objects existing in the runtime.
- """
- self.containers = self.get_containers()
- self.images = self.get_images()
- self.volumes = self.get_volumes()
-
- def check_is_active(self):
- """Check to see if the container runtime is both present AND active.
-
- Active in this sense means that the runtime can be used to glean
- information about the runtime itself and containers that are running.
-
- :returns: ``True`` if the runtime is active, else ``False``
- :rtype: ``bool``
- """
- if is_executable(self.binary):
- self.active = True
- return True
- return False
-
- def get_containers(self, get_all=False):
- """Get a list of containers present on the system.
-
- :param get_all: If set, include stopped containers as well
- :type get_all: ``bool``
- """
- containers = []
- _cmd = "%s ps %s" % (self.binary, '-a' if get_all else '')
- if self.active:
- out = sos_get_command_output(_cmd)
- if out['status'] == 0:
- for ent in out['output'].splitlines()[1:]:
- ent = ent.split()
- # takes the form (container_id, container_name)
- containers.append((ent[0], ent[-1]))
- return containers
-
- def get_container_by_name(self, name):
- """Get the container ID for the container matching the provided
- name
-
- :param name: The name of the container, note this can be a regex
- :type name: ``str``
-
- :returns: The id of the first container to match `name`, else ``None``
- :rtype: ``str``
- """
- if not self.active or name is None:
- return None
- for c in self.containers:
- if re.match(name, c[1]):
- return c[1]
- return None
-
- def get_images(self):
- """Get a list of images present on the system
-
- :returns: A list of 2-tuples containing (image_name, image_id)
- :rtype: ``list``
- """
- images = []
- fmt = '{{lower .Repository}}:{{lower .Tag}} {{lower .ID}}'
- if self.active:
- out = sos_get_command_output("%s images --format '%s'"
- % (self.binary, fmt))
- if out['status'] == 0:
- for ent in out['output'].splitlines():
- ent = ent.split()
- # takes the form (image_name, image_id)
- images.append((ent[0], ent[1]))
- return images
-
- def get_volumes(self):
- """Get a list of container volumes present on the system
-
- :returns: A list of volume IDs on the system
- :rtype: ``list``
- """
- vols = []
- if self.active:
- out = sos_get_command_output("%s volume ls" % self.binary)
- if out['status'] == 0:
- for ent in out['output'].splitlines()[1:]:
- ent = ent.split()
- vols.append(ent[-1])
- return vols
-
- def fmt_container_cmd(self, container, cmd, quotecmd):
- """Format a command to run inside a container using the runtime
-
- :param container: The name or ID of the container in which to run
- :type container: ``str``
-
- :param cmd: The command to run inside `container`
- :type cmd: ``str``
-
- :param quotecmd: Whether the cmd should be quoted.
- :type quotecmd: ``bool``
-
- :returns: Formatted string to run `cmd` inside `container`
- :rtype: ``str``
- """
- if quotecmd:
- quoted_cmd = quote(cmd)
- else:
- quoted_cmd = cmd
- return "%s %s %s" % (self.run_cmd, container, quoted_cmd)
-
- def get_logs_command(self, container):
- """Get the command string used to dump container logs from the
- runtime
-
- :param container: The name or ID of the container to get logs for
- :type container: ``str``
-
- :returns: Formatted runtime command to get logs from `container`
- :type: ``str``
- """
- return "%s logs -t %s" % (self.binary, container)
-
-
-class DockerContainerRuntime(ContainerRuntime):
- """Runtime class to use for systems running Docker"""
-
- name = 'docker'
- binary = 'docker'
-
- def check_is_active(self):
- # the daemon must be running
- if (is_executable('docker') and
- (self.policy.init_system.is_running('docker') or
- self.policy.init_system.is_running('snap.docker.dockerd'))):
- self.active = True
- return True
- return False
-
-
-class PodmanContainerRuntime(ContainerRuntime):
- """Runtime class to use for systems running Podman"""
-
- name = 'podman'
- binary = 'podman'
-
-
class InitSystem(object):
"""Encapsulates an init system to provide service-oriented functions to
sos.
diff --git a/sos/policies/runtimes/__init__.py b/sos/policies/runtimes/__init__.py
new file mode 100644
index 00000000..1a61b644
--- /dev/null
+++ b/sos/policies/runtimes/__init__.py
@@ -0,0 +1,173 @@
+# Copyright (C) 2020 Red Hat, Inc., Jake Hunsaker <jhunsake@redhat.com>
+
+# This file is part of the sos project: https://github.com/sosreport/sos
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# version 2 of the GNU General Public License.
+#
+# See the LICENSE file in the source distribution for further information.
+
+import re
+
+from pipes import quote
+from sos.utilities import sos_get_command_output, is_executable
+
+
+class ContainerRuntime():
+ """Encapsulates a container runtime that provides the ability to plugins to
+ check runtime status, check for the presence of specific containers, and
+ to format commands to run in those containers
+
+ :param policy: The loaded policy for the system
+ :type policy: ``Policy()``
+
+ :cvar name: The name of the container runtime, e.g. 'podman'
+ :vartype name: ``str``
+
+ :cvar containers: A list of containers known to the runtime
+ :vartype containers: ``list``
+
+ :cvar images: A list of images known to the runtime
+ :vartype images: ``list``
+
+ :cvar binary: The binary command to run for the runtime, must exit within
+ $PATH
+ :vartype binary: ``str``
+ """
+
+ name = 'Undefined'
+ containers = []
+ images = []
+ volumes = []
+ binary = ''
+ active = False
+
+ def __init__(self, policy=None):
+ self.policy = policy
+ self.run_cmd = "%s exec " % self.binary
+
+ def load_container_info(self):
+ """If this runtime is found to be active, attempt to load information
+ on the objects existing in the runtime.
+ """
+ self.containers = self.get_containers()
+ self.images = self.get_images()
+ self.volumes = self.get_volumes()
+
+ def check_is_active(self):
+ """Check to see if the container runtime is both present AND active.
+
+ Active in this sense means that the runtime can be used to glean
+ information about the runtime itself and containers that are running.
+
+ :returns: ``True`` if the runtime is active, else ``False``
+ :rtype: ``bool``
+ """
+ if is_executable(self.binary):
+ self.active = True
+ return True
+ return False
+
+ def get_containers(self, get_all=False):
+ """Get a list of containers present on the system.
+
+ :param get_all: If set, include stopped containers as well
+ :type get_all: ``bool``
+ """
+ containers = []
+ _cmd = "%s ps %s" % (self.binary, '-a' if get_all else '')
+ if self.active:
+ out = sos_get_command_output(_cmd)
+ if out['status'] == 0:
+ for ent in out['output'].splitlines()[1:]:
+ ent = ent.split()
+ # takes the form (container_id, container_name)
+ containers.append((ent[0], ent[-1]))
+ return containers
+
+ def get_container_by_name(self, name):
+ """Get the container ID for the container matching the provided
+ name
+
+ :param name: The name of the container, note this can be a regex
+ :type name: ``str``
+
+ :returns: The id of the first container to match `name`, else ``None``
+ :rtype: ``str``
+ """
+ if not self.active or name is None:
+ return None
+ for c in self.containers:
+ if re.match(name, c[1]):
+ return c[1]
+ return None
+
+ def get_images(self):
+ """Get a list of images present on the system
+
+ :returns: A list of 2-tuples containing (image_name, image_id)
+ :rtype: ``list``
+ """
+ images = []
+ fmt = '{{lower .Repository}}:{{lower .Tag}} {{lower .ID}}'
+ if self.active:
+ out = sos_get_command_output("%s images --format '%s'"
+ % (self.binary, fmt))
+ if out['status'] == 0:
+ for ent in out['output'].splitlines():
+ ent = ent.split()
+ # takes the form (image_name, image_id)
+ images.append((ent[0], ent[1]))
+ return images
+
+ def get_volumes(self):
+ """Get a list of container volumes present on the system
+
+ :returns: A list of volume IDs on the system
+ :rtype: ``list``
+ """
+ vols = []
+ if self.active:
+ out = sos_get_command_output("%s volume ls" % self.binary)
+ if out['status'] == 0:
+ for ent in out['output'].splitlines()[1:]:
+ ent = ent.split()
+ vols.append(ent[-1])
+ return vols
+
+ def fmt_container_cmd(self, container, cmd, quotecmd):
+ """Format a command to run inside a container using the runtime
+
+ :param container: The name or ID of the container in which to run
+ :type container: ``str``
+
+ :param cmd: The command to run inside `container`
+ :type cmd: ``str``
+
+ :param quotecmd: Whether the cmd should be quoted.
+ :type quotecmd: ``bool``
+
+ :returns: Formatted string to run `cmd` inside `container`
+ :rtype: ``str``
+ """
+ if quotecmd:
+ quoted_cmd = quote(cmd)
+ else:
+ quoted_cmd = cmd
+ return "%s %s %s" % (self.run_cmd, container, quoted_cmd)
+
+ def get_logs_command(self, container):
+ """Get the command string used to dump container logs from the
+ runtime
+
+ :param container: The name or ID of the container to get logs for
+ :type container: ``str``
+
+ :returns: Formatted runtime command to get logs from `container`
+ :type: ``str``
+ """
+ return "%s logs -t %s" % (self.binary, container)
+
+
+# vim: set et ts=4 sw=4 :
diff --git a/sos/policies/runtimes/docker.py b/sos/policies/runtimes/docker.py
new file mode 100644
index 00000000..759dfaf6
--- /dev/null
+++ b/sos/policies/runtimes/docker.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2020 Red Hat, Inc., Jake Hunsaker <jhunsake@redhat.com>
+
+# This file is part of the sos project: https://github.com/sosreport/sos
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# version 2 of the GNU General Public License.
+#
+# See the LICENSE file in the source distribution for further information.
+
+from sos.policies.runtimes import ContainerRuntime
+from sos.utilities import is_executable
+
+
+class DockerContainerRuntime(ContainerRuntime):
+ """Runtime class to use for systems running Docker"""
+
+ name = 'docker'
+ binary = 'docker'
+
+ def check_is_active(self):
+ # the daemon must be running
+ if (is_executable('docker') and
+ (self.policy.init_system.is_running('docker') or
+ self.policy.init_system.is_running('snap.docker.dockerd'))):
+ self.active = True
+ return True
+ return False
+
+# vim: set et ts=4 sw=4 :
diff --git a/sos/policies/runtimes/podman.py b/sos/policies/runtimes/podman.py
new file mode 100644
index 00000000..ef53ce2e
--- /dev/null
+++ b/sos/policies/runtimes/podman.py
@@ -0,0 +1,21 @@
+# Copyright (C) 2020 Red Hat, Inc., Jake Hunsaker <jhunsake@redhat.com>
+
+# This file is part of the sos project: https://github.com/sosreport/sos
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# version 2 of the GNU General Public License.
+#
+# See the LICENSE file in the source distribution for further information.
+
+from sos.policies.runtimes import ContainerRuntime
+
+
+class PodmanContainerRuntime(ContainerRuntime):
+ """Runtime class to use for systems running Podman"""
+
+ name = 'podman'
+ binary = 'podman'
+
+
+# vim: set et ts=4 sw=4 :