def _issue_ipmi_chassis_config_command(command, power_change, power_address, power_boot_type=None): with NamedTemporaryFile("w+", encoding="utf-8") as tmp_config: # Write out the chassis configuration. if (power_boot_type is None or power_boot_type == IPMI_BOOT_TYPE.DEFAULT): tmp_config.write(IPMI_CONFIG) else: tmp_config.write(IPMI_CONFIG_WITH_BOOT_TYPE % IPMI_BOOT_TYPE_MAPPING[power_boot_type]) tmp_config.flush() # Use it when running the chassis config command. # XXX: Not using call_and_check here because we # need to check stderr. command = tuple(command) + ("--filename", tmp_config.name) result = shell.run_command(*command) # XXX newell 2016-11-21 bug=1516065: Some IPMI hardware have timeout # issues when trying to set the boot order to PXE. We want to # continue and not raise an error here. ipmi_errors = { key: IPMI_ERRORS[key] for key in IPMI_ERRORS if IPMI_ERRORS[key]["exception"] == PowerAuthError } for error, error_info in ipmi_errors.items(): if error in result.stderr: raise error_info.get("exception")(error_info.get("message")) if result.returncode != 0: maaslog.warning("Failed to change the boot order to PXE %s: %s" % (power_address, result.stderr))
def _issue_ipmipower_command(command, power_change, power_address): result = shell.run_command(*command) for error, error_info in IPMI_ERRORS.items(): # ipmipower dumps errors to stdout if error in result.stdout: raise error_info.get("exception")(error_info.get("message")) if result.returncode != 0: raise PowerError("Failed to power %s %s: %s" % (power_change, power_address, result.stdout)) match = re.search(r":\s*(on|off)", result.stdout) return result.stdout if match is None else match.group(1)
def run_process(self, *command): """Run SNMP command in subprocess.""" result = shell.run_command(*command) if result.returncode != 0: raise PowerActionError( "APC Power Driver external process error for command %s: %s" % ("".join(command), result.stderr)) match = re.search(r"INTEGER:\s*([1-2])", result.stdout) if match is None: raise PowerActionError( "APC Power Driver unable to extract outlet power state" " from: %s" % result.stdout) else: return match.group(1)
def test_no_decode(self): with NamedTemporaryFile("w", encoding="utf-8", delete=False) as executable: executable.write( dedent("""\ #!/bin/sh echo "$@" echo stderr >&2 """)) executable.close() os.chmod(executable.name, 0o755) result = run_command(executable.name, "some", "args", decode=False) self.assertEqual(result.stdout, b"some args") self.assertEqual(result.stderr, b"stderr")
def _run(self, command: tuple, power_pass: str, stdin: bytes = None) -> bytes: """Run a subprocess with stdin.""" result = shell.run_command( *command, stdin=stdin, extra_environ={"AMT_PASSWORD": power_pass}, decode=False, ) if result.returncode != 0: raise PowerActionError( "Failed to run command: %s with error: %s" % (command, result.stderr.decode("utf-8", "replace"))) return result.stdout
def _get_amt_command(self, ip_address, power_pass): """Retrieve AMT command to use, either amttool or wsman (if AMT version > 8), for the given system. """ # XXX bug=1331214 # Check if the AMT ver > 8 # If so, we need wsman, not amttool result = shell.run_command( "wsman", "identify", "--port", "16992", "--hostname", ip_address, "--username", "admin", "--password", power_pass, ) if not result.stdout: for error, error_info in AMT_ERRORS.items(): if error in result.stderr: raise error_info.get("exception")( error_info.get("message")) raise PowerConnError( f"Unable to retrieve AMT version: {result.stderr}") else: match = re.search(r"ProductVersion>AMT\s*([0-9]+)", result.stdout) if match is None: raise PowerActionError("Unable to extract AMT version from " f"amttool output: {result.stdout}") else: version = match.group(1) if int(version) > 8: return "wsman" else: return "amttool"
def test_stdin(self): # The timeout here is to prevent hanging of the test suite # should it fail (since failure scenario is inheriting stdin # from parent process, i.e. this one!) result = run_command("cat", stdin=b"foo", decode=False, timeout=0.2) self.assertEqual(result.stdout, b"foo")
def test_environ(self): result = run_command("env", extra_environ={"FOO": "bar"}) self.assertIn("FOO=bar", result.stdout)