def test__finds_power_address_from_mac_address(self): context = make_context() driver = IPMIPowerDriver() ip_address = factory.make_ipv4_address() find_ip_via_arp = self.patch(ipmi_module, 'find_ip_via_arp') find_ip_via_arp.return_value = ip_address power_change = random.choice(("on", "off")) context['mac_address'] = factory.make_mac_address() context['power_address'] = random.choice((None, "", " ")) self.patch_autospec(driver, "_issue_ipmi_chassis_config_command") self.patch_autospec(driver, "_issue_ipmipower_command") driver._issue_ipmi_command(power_change, **context) # The IP address is passed to _issue_ipmi_chassis_config_command. self.assertThat( driver._issue_ipmi_chassis_config_command, MockCalledOnceWith(ANY, power_change, ip_address, power_boot_type=None)) # The IP address is also within the command passed to # _issue_ipmi_chassis_config_command. self.assertThat(driver._issue_ipmi_chassis_config_command.call_args[0], Contains(ip_address)) # The IP address is passed to _issue_ipmipower_command. self.assertThat(driver._issue_ipmipower_command, MockCalledOnceWith(ANY, power_change, ip_address)) # The IP address is also within the command passed to # _issue_ipmipower_command. self.assertThat(driver._issue_ipmipower_command.call_args[0], Contains(ip_address))
def test_power_query_retires_on_kg_error(self): context = make_context() k_g = context.pop("k_g", factory.make_name("k_g")) ipmi_power_driver = IPMIPowerDriver() mock_issue_ipmi_command = self.patch(ipmi_power_driver, "_issue_ipmi_command") k_g_error = IPMI_ERRORS["k_g invalid"] mock_issue_ipmi_command.side_effect = ( k_g_error["exception"](k_g_error["message"]), None, ) system_id = factory.make_name("system_id") ipmi_power_driver.power_query(system_id, {"k_g": k_g, **context}) self.assertThat( mock_issue_ipmi_command, MockCallsMatch( call("query", **{ "k_g": k_g, **context }), call("query", **context), ), )
def test__issue_ipmi_command_issues_power_on(self): context = make_context() ipmi_chassis_config_command = make_ipmi_chassis_config_command( **context, tmp_config_name=ANY) ipmipower_command = make_ipmipower_command(**context) ipmipower_command += ("--cycle", "--on-if-off") ipmi_power_driver = IPMIPowerDriver() env = get_env_with_locale() popen_mock = self.patch(ipmi_module, "Popen") process = popen_mock.return_value process.communicate.side_effect = [(b"", b""), (b"on", b"")] process.returncode = 0 result = ipmi_power_driver._issue_ipmi_command("on", **context) self.expectThat( popen_mock, MockCallsMatch( call( ipmi_chassis_config_command, stdout=PIPE, stderr=PIPE, env=env, ), call(ipmipower_command, stdout=PIPE, stderr=PIPE, env=env), ), ) self.expectThat(result, Equals("on"))
def test__issue_ipmi_command_issues_power_off_soft_mode(self): context = make_context() context['power_off_mode'] = 'soft' ipmi_chassis_config_command = make_ipmi_chassis_config_command( **context, tmp_config_name=ANY) ipmipower_command = make_ipmipower_command(**context) ipmipower_command += ('--soft', ) ipmi_power_driver = IPMIPowerDriver() env = get_env_with_locale() popen_mock = self.patch(ipmi_module, 'Popen') process = popen_mock.return_value process.communicate.side_effect = [(b'', b''), (b'off', b'')] process.returncode = 0 result = ipmi_power_driver._issue_ipmi_command('off', **context) self.expectThat( popen_mock, MockCallsMatch( call(ipmi_chassis_config_command, stdout=PIPE, stderr=PIPE, env=env), call(ipmipower_command, stdout=PIPE, stderr=PIPE, env=env))) self.expectThat(result, Equals('off'))
def test__chassis_config_written_to_temporary_file_with_boot_type(self): boot_type = self.patch(ipmi_module, "power_boot_type") boot_type.return_value = IPMI_BOOT_TYPE.EFI NamedTemporaryFile = self.patch(ipmi_module, "NamedTemporaryFile") tmpfile = NamedTemporaryFile.return_value tmpfile.__enter__.return_value = tmpfile tmpfile.name = factory.make_name("filename") IPMIPowerDriver._issue_ipmi_chassis_config_command( ["true"], sentinel.change, sentinel.addr, power_boot_type=IPMI_BOOT_TYPE.EFI, ) self.assertThat(NamedTemporaryFile, MockCalledOnceWith("w+", encoding="utf-8")) self.assertThat(tmpfile.__enter__, MockCalledOnceWith()) self.assertThat( tmpfile.write, MockCalledOnceWith(IPMI_CONFIG_WITH_BOOT_TYPE % IPMI_BOOT_TYPE_MAPPING[IPMI_BOOT_TYPE.EFI]), ) self.assertThat(tmpfile.flush, MockCalledOnceWith()) self.assertThat(tmpfile.__exit__, MockCalledOnceWith(None, None, None))
def test_issue_ipmi_command_issues_power_query(self): context = make_context() ipmipower_command = make_ipmipower_command(**context) ipmipower_command += ("--stat", ) ipmi_power_driver = IPMIPowerDriver() run_command_mock = self.patch(ipmi_module.shell, "run_command") run_command_mock.return_value = ProcessResult(stdout="other") result = ipmi_power_driver._issue_ipmi_command("query", **context) run_command_mock.assert_called_once_with(*ipmipower_command) self.expectThat(result, Equals("other"))
def test_power_off_calls__issue_ipmi_command(self): context = make_context() ipmi_power_driver = IPMIPowerDriver() _issue_ipmi_command_mock = self.patch(ipmi_power_driver, '_issue_ipmi_command') system_id = factory.make_name('system_id') ipmi_power_driver.power_off(system_id, context) self.assertThat(_issue_ipmi_command_mock, MockCalledOnceWith('off', **context))
def test_power_query_calls__issue_ipmi_command(self): context = make_context() ipmi_power_driver = IPMIPowerDriver() _issue_ipmi_command_mock = self.patch(ipmi_power_driver, "_issue_ipmi_command") system_id = factory.make_name("system_id") ipmi_power_driver.power_query(system_id, context) self.assertThat(_issue_ipmi_command_mock, MockCalledOnceWith("query", **context))
def test__issue_ipmi_chassis_config_command_logs_maaslog_warning(self): power_address = factory.make_name('power_address') stderr = factory.make_name('stderr') popen_mock = self.patch(ipmi_module, 'Popen') process = popen_mock.return_value process.communicate.return_value = (b'', stderr.encode('utf-8')) maaslog = self.patch(ipmi_module, 'maaslog') IPMIPowerDriver._issue_ipmi_chassis_config_command( factory.make_name('command'), factory.make_name('power_change'), power_address) self.assertThat( maaslog.warning, MockCalledOnceWith( "Failed to change the boot order to PXE %s: %s" % ( power_address, stderr)))
def test__chassis_config_written_to_temporary_file(self): NamedTemporaryFile = self.patch(ipmi_module, "NamedTemporaryFile") tmpfile = NamedTemporaryFile.return_value tmpfile.__enter__.return_value = tmpfile tmpfile.name = factory.make_name("filename") IPMIPowerDriver._issue_ipmi_chassis_config_command( ["true"], sentinel.change, sentinel.addr) self.assertThat( NamedTemporaryFile, MockCalledOnceWith("w+", encoding="utf-8")) self.assertThat(tmpfile.__enter__, MockCalledOnceWith()) self.assertThat(tmpfile.write, MockCalledOnceWith(IPMI_CONFIG)) self.assertThat(tmpfile.flush, MockCalledOnceWith()) self.assertThat(tmpfile.__exit__, MockCalledOnceWith(None, None, None))
def test_issue_ipmi_command_issues_power_on(self): context = make_context() ipmi_chassis_config_command = make_ipmi_chassis_config_command( **context, tmp_config_name=ANY) ipmipower_command = make_ipmipower_command(**context) ipmipower_command += ("--cycle", "--on-if-off") ipmi_power_driver = IPMIPowerDriver() run_command_mock = self.patch(ipmi_module.shell, "run_command") run_command_mock.side_effect = [ ProcessResult(), ProcessResult(stdout="on"), ] result = ipmi_power_driver._issue_ipmi_command("on", **context) run_command_mock.assert_has_calls( [call(*ipmi_chassis_config_command), call(*ipmipower_command)]) self.expectThat(result, Equals("on"))
def test_issue_ipmi_chassis_config_command_logs_maaslog_warning(self): power_address = factory.make_name("power_address") stderr = factory.make_name("stderr") run_command_mock = self.patch(ipmi_module.shell, "run_command") run_command_mock.return_value = ProcessResult(stderr=stderr, returncode=1) maaslog = self.patch(ipmi_module, "maaslog") IPMIPowerDriver._issue_ipmi_chassis_config_command( [factory.make_name("command")], factory.make_name("power_change"), power_address, ) self.assertThat( maaslog.warning, MockCalledOnceWith( "Failed to change the boot order to PXE %s: %s" % (power_address, stderr)), )
def test__issue_ipmi_chassis_config_command_logs_maaslog_warning(self): power_address = factory.make_name("power_address") stderr = factory.make_name("stderr") popen_mock = self.patch(ipmi_module, "Popen") process = popen_mock.return_value process.communicate.return_value = (b"", stderr.encode("utf-8")) maaslog = self.patch(ipmi_module, "maaslog") IPMIPowerDriver._issue_ipmi_chassis_config_command( factory.make_name("command"), factory.make_name("power_change"), power_address, ) self.assertThat( maaslog.warning, MockCalledOnceWith( "Failed to change the boot order to PXE %s: %s" % (power_address, stderr)), )
def test__issue_ipmi_command_issues_power_query(self): context = make_context() ipmipower_command = make_ipmipower_command(**context) ipmipower_command += ('--stat', ) ipmi_power_driver = IPMIPowerDriver() env = select_c_utf8_locale() popen_mock = self.patch(ipmi_module, 'Popen') process = popen_mock.return_value process.communicate.return_value = (b'other', b'') process.returncode = 0 result = ipmi_power_driver._issue_ipmi_command('query', **context) self.expectThat( popen_mock, MockCalledOnceWith( ipmipower_command, stdout=PIPE, stderr=PIPE, env=env)) self.expectThat(result, Equals('other'))
def test__issue_ipmipower_command_does_not_mistake_host_for_status(self): popen_mock = self.patch(ipmi_module, 'Popen') process = popen_mock.return_value # "cameron" contains the string "on", but the machine is off. process.communicate.return_value = (b'cameron: off', b'') process.returncode = 0 self.assertThat( IPMIPowerDriver._issue_ipmipower_command( factory.make_name('command'), 'query', factory.make_name('address')), Equals("off"))
def test__issue_ipmi_command_issues_power_off_soft_mode(self): context = make_context() context["power_off_mode"] = "soft" ipmipower_command = make_ipmipower_command(**context) ipmipower_command += ("--soft", ) ipmi_power_driver = IPMIPowerDriver() env = get_env_with_locale() popen_mock = self.patch(ipmi_module, "Popen") process = popen_mock.return_value process.communicate.side_effect = [(b"off", b"")] process.returncode = 0 result = ipmi_power_driver._issue_ipmi_command("off", **context) self.expectThat( popen_mock, MockCallsMatch( call(ipmipower_command, stdout=PIPE, stderr=PIPE, env=env)), ) self.expectThat(result, Equals("off"))
def test__issue_ipmi_command_issues_power_query(self): context = make_context() ipmipower_command = make_ipmipower_command(**context) ipmipower_command += ("--stat", ) ipmi_power_driver = IPMIPowerDriver() env = get_env_with_locale() popen_mock = self.patch(ipmi_module, "Popen") process = popen_mock.return_value process.communicate.return_value = (b"other", b"") process.returncode = 0 result = ipmi_power_driver._issue_ipmi_command("query", **context) self.expectThat( popen_mock, MockCalledOnceWith(ipmipower_command, stdout=PIPE, stderr=PIPE, env=env), ) self.expectThat(result, Equals("other"))
def test_issue_ipmipower_command_does_not_mistake_host_for_status(self): run_command_mock = self.patch(ipmi_module.shell, "run_command") # "cameron" contains the string "on", but the machine is off. run_command_mock.return_value = ProcessResult(stdout="cameron: off") self.assertThat( IPMIPowerDriver._issue_ipmipower_command( factory.make_name("command"), "query", factory.make_name("address"), ), Equals("off"), )
def test__issue_ipmi_chassis_config_with_power_boot_type(self): context = make_context() driver = IPMIPowerDriver() ip_address = factory.make_ipv4_address() find_ip_via_arp = self.patch(ipmi_module, "find_ip_via_arp") find_ip_via_arp.return_value = ip_address power_change = "on" context["mac_address"] = factory.make_mac_address() context["power_address"] = random.choice((None, "", " ")) context["power_boot_type"] = IPMI_BOOT_TYPE.EFI self.patch_autospec(driver, "_issue_ipmi_chassis_config_command") self.patch_autospec(driver, "_issue_ipmipower_command") driver._issue_ipmi_command(power_change, **context) # The IP address is passed to _issue_ipmi_chassis_config_command. self.assertThat( driver._issue_ipmi_chassis_config_command, MockCalledOnceWith( ANY, power_change, ip_address, power_boot_type=IPMI_BOOT_TYPE.EFI, ), ) # The IP address is also within the command passed to # _issue_ipmi_chassis_config_command. self.assertThat( driver._issue_ipmi_chassis_config_command.call_args[0], Contains(ip_address), ) # The IP address is passed to _issue_ipmipower_command. self.assertThat( driver._issue_ipmipower_command, MockCalledOnceWith(ANY, power_change, ip_address), )
# is to be performed. schemas = [ driver.get_schema(detect_missing_packages=detect_missing_packages) for _, driver in cls ] validate(schemas, JSON_POWER_DRIVERS_SCHEMA) return schemas # Register all the power drivers. power_drivers = [ AMTPowerDriver(), APCPowerDriver(), DLIPowerDriver(), HMCPowerDriver(), IPMIPowerDriver(), LXDPowerDriver(), ManualPowerDriver(), MoonshotIPMIPowerDriver(), MSCMPowerDriver(), MicrosoftOCSPowerDriver(), NovaPowerDriver(), OpenBMCPowerDriver(), RECSPowerDriver(), RedfishPowerDriver(), SeaMicroPowerDriver(), UCSMPowerDriver(), VirshPowerDriver(), VMwarePowerDriver(), WedgePowerDriver(), ]