def _compress(self): methods = [] # Make sure that valid compression commands exist. for method in ['xz', 'gzip']: if is_executable(method): methods.append(method) else: self.log_info("\"%s\" compression method unavailable" % method) if self.method in methods: methods = [self.method] exp_msg = "No compression utilities found." last_error = Exception(exp_msg) for cmd in methods: suffix = "." + cmd.replace('ip', '') cmd = self._policy.get_cmd_for_compress_method(cmd, self._threads) try: exec_cmd = "%s %s" % (cmd, self.name()) r = sos_get_command_output(exec_cmd, stderr=True, timeout=0) if r['status']: self.log_error(r['output']) raise Exception("%s exited with %s" % (exec_cmd, r['status'])) self._suffix += suffix return self.name() except Exception as e: last_error = e raise last_error
def get_command_output(self, prog, timeout=300): (status, output, runtime) = sos_get_command_output(prog, timeout) if status == 124: self.soslog.warning("command '%s' timed out after %ds" % (prog, timeout)) if status == 127: self.soslog.info("could not run '%s': command not found" % prog) return (status, output, runtime)
def get_command_output(self, prog, timeout=300, stderr=True, chroot=True, runat=None): if chroot or self.commons['cmdlineopts'].chroot == 'always': root = self.sysroot else: root = None result = sos_get_command_output(prog, timeout=timeout, stderr=stderr, chroot=root, chdir=runat) if result['status'] == 124: self._log_warn("command '%s' timed out after %ds" % (prog, timeout)) # command not found or not runnable if result['status'] == 126 or result['status'] == 127: # automatically retry chroot'ed commands in the host namespace if chroot and self.commons['cmdlineopts'].chroot != 'always': self._log_info("command '%s' not found in %s - " "re-trying in host root" % (prog.split()[0], root)) return self.get_command_output(prog, timeout=timeout, chroot=False, runat=runat) self._log_debug("could not run '%s': command not found" % prog) return result
def _compress(self): methods = [] # Make sure that valid compression commands exist. for method in ['xz', 'bzip2', 'gzip']: if is_executable(method): methods.append(method) else: self.log_error("\"%s\" command not found." % method) if self.method in methods: methods = [self.method] exp_msg = "No compression utilities found." last_error = Exception(exp_msg) for cmd in methods: suffix = "." + cmd.replace('ip', '') # use fast compression if using xz or bz2 if cmd != "gzip": cmd = "%s -1" % cmd try: r = sos_get_command_output("%s %s" % (cmd, self.name())) if r['status']: self.log_info(r['output']) self._suffix += suffix return self.name() except Exception as e: last_error = e raise last_error
def _compress(self): methods = [] # Make sure that valid compression commands exist. for method in ['xz', 'bzip2', 'gzip']: if is_executable(method): methods.append(method) else: self.log_error("\"%s\" command not found." % method) if self.method in methods: methods = [self.method] exp_msg = "No compression utilities found." last_error = Exception(exp_msg) for cmd in methods: suffix = "." + cmd.replace('ip', '') # use fast compression if using xz or bz2 if cmd != "gzip": cmd = "%s -1" % cmd try: r = sos_get_command_output("%s %s" % (cmd, self.name()), timeout=0) if r['status']: self.log_info(r['output']) self._suffix += suffix return self.name() except Exception as e: last_error = e raise last_error
def get_cmd_output_now(self, exe, suggest_filename=None, root_symlink=False, timeout=300): """Execute a command and save the output to a file for inclusion in the report. """ if self.commons['cmdlineopts'].profiler: start_time = time() # pylint: disable-msg = W0612 status, shout, runtime = sos_get_command_output(exe, timeout=timeout) if (status == 127): self.soslog.debug("could not run '%s': command not found" % exe) return None if suggest_filename: outfn = self.make_command_filename(suggest_filename) else: outfn = self.make_command_filename(exe) outfn_strip = outfn[len(self.commons['cmddir'])+1:] self.archive.add_string(shout, outfn) if root_symlink: self.archive.add_link(outfn, root_symlink) # save info for later self.executed_commands.append({'exe': exe, 'file':outfn_strip}) # save in our list self.commons['xmlreport'].add_command(cmdline=exe,exitcode=status,f_stdout=outfn_strip,runtime=runtime) if self.commons['cmdlineopts'].profiler: time_passed = time() - start_time self.proflog.debug("output: %-75s time: %f" % (exe, time_passed)) return outfn
def get_command_output(self, prog, timeout=300, runat=None): result = sos_get_command_output(prog, timeout=timeout, runat=runat) if result['status'] == 124: self.log_warn("command '%s' timed out after %ds" % (prog, timeout)) if result['status'] == 127: self.log_debug("could not run '%s': command not found" % prog) return result
def _compress(self): methods = [] # Make sure that valid compression commands exist. for method in ['xz', 'bzip2', 'gzip']: if is_executable(method): methods.append(method) else: self.log_info("\"%s\" compression method unavailable" % method) if self.method in methods: methods = [self.method] exp_msg = "No compression utilities found." last_error = Exception(exp_msg) for cmd in methods: suffix = "." + cmd.replace('ip', '') cmd = self._policy.get_cmd_for_compress_method(cmd, self._threads) try: exec_cmd = "%s %s" % (cmd, self.name()) r = sos_get_command_output(exec_cmd, stderr=True, timeout=0) if r['status']: self.log_error(r['output']) raise Exception("%s exited with %s" % (exec_cmd, r['status'])) self._suffix += suffix return self.name() except Exception as e: last_error = e raise last_error
def run_oc(self, cmd, **kwargs): """Format and run a command with `oc` in the project defined for our execution """ return sos_get_command_output( "oc -n %s %s" % (self.project, cmd), **kwargs )
def get_command_output(self, prog, timeout=300, runat=None, stderr=True): result = sos_get_command_output(prog, timeout=timeout, runat=runat, stderr=stderr) if result["status"] == 124: self._log_warn("command '%s' timed out after %ds" % (prog, timeout)) # 126 means 'found but not executable' if result["status"] == 126 or result["status"] == 127: self._log_debug("could not run '%s': command not found" % prog) return result
def _query_service(self, name): """Query an individual service""" if self.query_cmd: try: return sos_get_command_output("%s %s" % (self.query_cmd, name)) except Exception: return None return None
def _query_service(self, name): """Query an individual service""" if self.query_cmd: res = sos_get_command_output("%s %s" % (self.query_cmd, name)) if res['status'] == 0: return res else: return None return None
def get_volumes(self): """Get a list of container volumes present on the system """ 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 get_command_output(self, prog, timeout=300, runat=None, stderr=True): result = sos_get_command_output(prog, timeout=timeout, runat=runat, stderr=stderr) if result['status'] == 124: self._log_warn("command '%s' timed out after %ds" % (prog, timeout)) # 126 means 'found but not executable' if result['status'] == 126 or result['status'] == 127: self._log_debug("could not run '%s': command not found" % prog) return result
def get_images(self): """Get a list of images present on the system """ 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_containers(self, get_all=False): """Get a list of containers present on the system. If `get_all` is `True`, also include non-running containers """ 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_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, chroot=self.policy.sysroot) if out['status'] == 0: for ent in out['output'].splitlines()[1:]: ent = ent.split() vols.append(ent[-1]) return vols
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 = [] if self.active: out = sos_get_command_output("%s images" % self.binary, chroot=self.policy.sysroot) 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], ent[2])) return images
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, chroot=self.policy.sysroot) 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_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 -o json" % (self.binary, '-a' if get_all else '') if self.active: out = sos_get_command_output(_cmd, chroot=self.policy.sysroot) if out["status"] == 0: out_json = json.loads(out["output"]) for container in out_json["containers"]: # takes the form (container_id, container_name) containers.append( (container["id"], container["metadata"]["name"])) return containers
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), chroot=self.policy.sysroot) 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 _encrypt(self, archive): """Encrypts the compressed archive using GPG. If encryption fails for any reason, it should be logged by sos but not cause execution to stop. The assumption is that the unencrypted archive would still be of use to the user, and/or that the end user has another means of securing the archive. Returns the name of the encrypted archive, or raises an exception to signal that encryption failed and the unencrypted archive name should be used. """ arc_name = archive.replace("sosreport-", "secured-sosreport-") arc_name += ".gpg" enc_cmd = "gpg --batch -o %s " % arc_name env = None if self.enc_opts["key"]: # need to assume a trusted key here to be able to encrypt the # archive non-interactively enc_cmd += "--trust-model always -e -r %s " % self.enc_opts["key"] enc_cmd += archive if self.enc_opts["password"]: # prevent change of gpg options using a long password, but also # prevent the addition of quote characters to the passphrase passwd = "%s" % self.enc_opts["password"].replace('\'"', '') env = {"sos_gpg": passwd} enc_cmd += "-c --passphrase-fd 0 " enc_cmd = "/bin/bash -c \"echo $sos_gpg | %s\"" % enc_cmd enc_cmd += archive r = sos_get_command_output(enc_cmd, timeout=0, env=env) if r["status"] == 0: return arc_name elif r["status"] == 2: if self.enc_opts["key"]: msg = "Specified key not in keyring" else: msg = "Could not read passphrase" else: # TODO: report the actual error from gpg. Currently, we cannot as # sos_get_command_output() does not capture stderr msg = "gpg exited with code %s" % r["status"] raise Exception(msg)
def setup(self): self.check_rmq_embedded() if self.rmq_embedded: original_env = os.environ envopts = { # 'HOME': '/opt/morpheus/embedded/rabbitmq', 'PREPATH': '/opt/morpheus/bin:/opt/morpheus/embedded/bin:/opt/morpheus/embedded/sbin', 'ERL_EPMD_ADDRESS': '127.0.0.1', 'RABBITMQ_CONF_ENV_FILE': '/opt/morpheus/embedded/rabbitmq/etc/rabbitmq-env.conf', 'RABBITMQ_SYS_PREFIX': '/opt/morpheus/embedded/rabbitmq', 'RABBITMQ_CONFIG_FILE': '/opt/morpheus/embedded/rabbitmq/etc/rabbit', 'RABBITMQ_MNESIA_BASE': '/var/opt/morpheus/rabbitmq/db', 'RABBITMQ_SCHEMA_DIR': '/opt/morpheus/embedded/rabbitmq/priv/schema', 'RABBITMQ_ENABLED_PLUGINS_FILE': '/opt/morpheus/embedded/rabbitmq/etc/enabled_plugins', 'RABBITMQ_LOG_BASE': '/var/log/morpheus/rabbitmq', 'RABBITMQ_NODE_IP_ADDRESS': '127.0.0.1', 'RABBITMQ_NODE_PORT': '5672', 'RABBITMQ_PID_FILE': '/var/run/morpheus/rabbitmq/[email protected]', 'RABBITMQ_NODENAME': 'rabbit@localhost' } envopts['PATH'] = envopts['PREPATH'] + ":" + os.environ['PATH'] os.environ.update(envopts) #envopts = {'HOME': '/opt/morpheus/embedded/rabbitmq'} #self.add_cmd_output("rabbitmqctl report") out = utilities.sos_get_command_output("rabbitmqctl report") self.add_string_as_file(out['output'], "rabbitmqctl_report_out") os.environ = original_env self.add_copy_spec([ "/opt/morpheus/embedded/rabbitmq/etc/*", "/etc/security/limits.d/", "/etc/systemd/" ]) self.add_copy_spec([ "/var/log/morpheus/rabbitmq/*", ])
def _connect(self, password): # the oc binary must be _locally_ available for this to work if not is_executable('oc'): return False # deploy the debug container we'll exec into podconf = self.get_node_pod_config() self.pod_name = podconf['metadata']['name'] fd, self.pod_tmp_conf = tempfile.mkstemp(dir=self.tmpdir) with open(fd, 'w') as cfile: json.dump(podconf, cfile) self.log_debug("Starting sos collector container '%s'" % self.pod_name) # this specifically does not need to run with a project definition out = sos_get_command_output( "oc create -f %s" % self.pod_tmp_conf ) if (out['status'] != 0 or "pod/%s created" % self.pod_name not in out['output']): self.log_error("Unable to deploy sos collect pod") self.log_debug("Debug pod deployment failed: %s" % out['output']) return False self.log_debug("Pod '%s' successfully deployed, waiting for pod to " "enter ready state" % self.pod_name) # wait for the pod to report as running try: up = self.run_oc("wait --for=condition=Ready pod/%s --timeout=30s" % self.pod_name, # timeout is for local safety, not oc timeout=40) if not up['status'] == 0: self.log_error("Pod not available after 30 seconds") return False except SoSTimeoutError: self.log_error("Timeout while polling for pod readiness") return False except Exception as err: self.log_error("Error while waiting for pod to be ready: %s" % err) return False return True
def compress(self, cmd): """Execute the compression command, and set the appropriate final archive path for later reference by SoSCleaner on a per-archive basis """ self.build_tar_file() exec_cmd = "%s %s" % (cmd, self.tarpath) res = sos_get_command_output(exec_cmd, timeout=0, stderr=True) if res['status'] == 0: self.final_archive_path = self.tarpath + '.' + exec_cmd[0:2] self.log_debug("Compressed to %s" % self.final_archive_path) try: self.remove_extracted_path() except Exception as err: self.log_debug("Failed to remove extraction directory: %s" % err) self.report_msg('Failed to remove temporary extraction ' 'directory') else: err = res['output'].split(':')[-1] self.log_debug("Exception while compressing archive: %s" % err) raise Exception(err)
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 = [] if self.active: out = sos_get_command_output("%s images -o json" % self.binary, chroot=self.policy.sysroot) if out['status'] == 0: out_json = json.loads(out["output"]) for image in out_json["images"]: # takes the form (repository:tag, image_id) if len(image["repoTags"]) > 0: for repo_tag in image["repoTags"]: images.append((repo_tag, image["id"])) else: if len(image["repoDigests"]) == 0: image_name = "<none>" else: image_name = image["repoDigests"][0].split("@")[0] images.append((image_name + ":<none>", image["id"])) return images
def _compress(self): methods = ['xz', 'bzip2', 'gzip'] if self.method in methods: methods = [self.method] last_error = Exception("compression failed") for cmd in methods: suffix = "." + cmd.replace('ip', '') # use fast compression if using xz or bz2 if cmd != "gzip": cmd = "%s -1" % cmd try: r = sos_get_command_output("%s %s" % (cmd, self.name())) if r['status']: self.log_info(r['output']) self._suffix += suffix return self.name() except Exception as e: last_error = e raise last_error
def _get_scls(self): output = sos_get_command_output("scl -l")["output"] return [scl.strip() for scl in output.splitlines()]
def test_output(self): path = os.path.join(TEST_DIR, 'test_exe.py') ret, out, junk = sos_get_command_output(path) self.assertEquals(ret, 0) self.assertEquals(out, "executed\n")
def test_output_non_exe(self): path = os.path.join(TEST_DIR, 'utility_tests.py') ret, out, junk = sos_get_command_output(path) self.assertEquals(ret, 127) self.assertEquals(out, "")
def call_ext_prog(self, prog, timeout=300): """Execute a command independantly of the output gathering part of sosreport. """ # pylint: disable-msg = W0612 return sos_get_command_output(prog, timeout)
def test_output_non_exe(self): path = os.path.join(TEST_DIR, 'utility_tests.py') result = sos_get_command_output(path) self.assertEquals(result['status'], 127) self.assertEquals(result['output'], "")
def test_output(self): path = os.path.join(TEST_DIR, 'test_exe.py') result = sos_get_command_output(path) self.assertEquals(result['status'], 0) self.assertEquals(result['output'], "executed\n")
def test_output(self): path = os.path.join(TEST_DIR, "test_exe.py") result = sos_get_command_output(path) self.assertEquals(result["status"], 0) self.assertEquals(result["output"], "executed\n")
def test_output_non_exe(self): path = os.path.join(TEST_DIR, "utility_tests.py") result = sos_get_command_output(path) self.assertEquals(result["status"], 127) self.assertEquals(result["output"], "")
def test_output_chdir(self): cmd = "/bin/bash -c 'echo $PWD'" result = sos_get_command_output(cmd, chdir=TEST_DIR) print(result) self.assertEquals(result['status'], 0) self.assertEquals(result['output'].strip(), TEST_DIR)