diff options
Diffstat (limited to 'ironic/tests')
-rw-r--r-- | ironic/tests/api/v1/test_nodes.py | 17 | ||||
-rw-r--r-- | ironic/tests/db/test_conductor.py | 14 | ||||
-rw-r--r-- | ironic/tests/db/test_nodes.py | 10 | ||||
-rw-r--r-- | ironic/tests/drivers/ilo/test_deploy.py | 78 | ||||
-rw-r--r-- | ironic/tests/drivers/test_agent.py | 69 | ||||
-rw-r--r-- | ironic/tests/drivers/test_deploy_utils.py | 46 | ||||
-rw-r--r-- | ironic/tests/drivers/test_ipmitool.py | 80 | ||||
-rw-r--r-- | ironic/tests/drivers/test_iscsi_deploy.py | 19 | ||||
-rw-r--r-- | ironic/tests/drivers/test_seamicro.py | 3 | ||||
-rw-r--r-- | ironic/tests/drivers/test_utils.py | 35 | ||||
-rw-r--r-- | ironic/tests/stubs.py | 12 | ||||
-rw-r--r-- | ironic/tests/test_glance_service.py | 17 | ||||
-rw-r--r-- | ironic/tests/test_images.py | 11 | ||||
-rw-r--r-- | ironic/tests/test_pxe_utils.py | 37 |
14 files changed, 326 insertions, 122 deletions
diff --git a/ironic/tests/api/v1/test_nodes.py b/ironic/tests/api/v1/test_nodes.py index c2b510173..dbb95daaf 100644 --- a/ironic/tests/api/v1/test_nodes.py +++ b/ironic/tests/api/v1/test_nodes.py @@ -1813,17 +1813,14 @@ class TestPut(test_api_base.FunctionalTest): True, 'test-topic') def test_provision_node_in_maintenance_fail(self): - with mock.patch.object(rpcapi.ConductorAPI, 'do_node_deploy') as dnd: - self.node.maintenance = True - self.node.save() - dnd.side_effect = exception.NodeInMaintenance(op='provisioning', - node=self.node.uuid) + self.node.maintenance = True + self.node.save() - ret = self.put_json('/nodes/%s/states/provision' % self.node.uuid, - {'target': states.ACTIVE}, - expect_errors=True) - self.assertEqual(400, ret.status_code) - self.assertTrue(ret.json['error_message']) + ret = self.put_json('/nodes/%s/states/provision' % self.node.uuid, + {'target': states.ACTIVE}, + expect_errors=True) + self.assertEqual(400, ret.status_code) + self.assertTrue(ret.json['error_message']) @mock.patch.object(rpcapi.ConductorAPI, 'set_boot_device') def test_set_boot_device(self, mock_sbd): diff --git a/ironic/tests/db/test_conductor.py b/ironic/tests/db/test_conductor.py index d93aad120..1ff182615 100644 --- a/ironic/tests/db/test_conductor.py +++ b/ironic/tests/db/test_conductor.py @@ -64,7 +64,7 @@ class DbConductorTestCase(base.DbTestCase): self.dbapi.unregister_conductor, c.hostname) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_touch_conductor(self, mock_utcnow): test_time = datetime.datetime(2000, 1, 1, 0, 0) mock_utcnow.return_value = test_time @@ -110,7 +110,7 @@ class DbConductorTestCase(base.DbTestCase): self.assertEqual('hostname2', node2.reservation) self.assertIsNone(node3.reservation) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_get_active_driver_dict_one_host_no_driver(self, mock_utcnow): h = 'fake-host' expected = {} @@ -120,7 +120,7 @@ class DbConductorTestCase(base.DbTestCase): result = self.dbapi.get_active_driver_dict() self.assertEqual(expected, result) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_get_active_driver_dict_one_host_one_driver(self, mock_utcnow): h = 'fake-host' d = 'fake-driver' @@ -131,7 +131,7 @@ class DbConductorTestCase(base.DbTestCase): result = self.dbapi.get_active_driver_dict() self.assertEqual(expected, result) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_get_active_driver_dict_one_host_many_drivers(self, mock_utcnow): h = 'fake-host' d1 = 'driver-one' @@ -143,7 +143,7 @@ class DbConductorTestCase(base.DbTestCase): result = self.dbapi.get_active_driver_dict() self.assertEqual(expected, result) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_get_active_driver_dict_many_hosts_one_driver(self, mock_utcnow): h1 = 'host-one' h2 = 'host-two' @@ -156,7 +156,7 @@ class DbConductorTestCase(base.DbTestCase): result = self.dbapi.get_active_driver_dict() self.assertEqual(expected, result) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_get_active_driver_dict_many_hosts_and_drivers(self, mock_utcnow): h1 = 'host-one' h2 = 'host-two' @@ -172,7 +172,7 @@ class DbConductorTestCase(base.DbTestCase): result = self.dbapi.get_active_driver_dict() self.assertEqual(expected, result) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_get_active_driver_dict_with_old_conductor(self, mock_utcnow): past = datetime.datetime(2000, 1, 1, 0, 0) present = past + datetime.timedelta(minutes=2) diff --git a/ironic/tests/db/test_nodes.py b/ironic/tests/db/test_nodes.py index 7e3450345..be44943b4 100644 --- a/ironic/tests/db/test_nodes.py +++ b/ironic/tests/db/test_nodes.py @@ -136,7 +136,7 @@ class DbNodeTestCase(base.DbTestCase): res = self.dbapi.get_node_list(filters={'maintenance': False}) self.assertEqual([node1.id], [r.id for r in res]) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_get_nodeinfo_list_provision(self, mock_utcnow): past = datetime.datetime(2000, 1, 1, 0, 0) next = past + datetime.timedelta(minutes=8) @@ -161,7 +161,7 @@ class DbNodeTestCase(base.DbTestCase): states.DEPLOYWAIT}) self.assertEqual([node2.id], [r[0] for r in res]) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_get_nodeinfo_list_inspection(self, mock_utcnow): past = datetime.datetime(2000, 1, 1, 0, 0) next = past + datetime.timedelta(minutes=8) @@ -354,7 +354,7 @@ class DbNodeTestCase(base.DbTestCase): node2.id, {'instance_uuid': new_i_uuid}) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_update_node_provision(self, mock_utcnow): mocked_time = datetime.datetime(2000, 1, 1, 0, 0) mock_utcnow.return_value = mocked_time @@ -378,7 +378,7 @@ class DbNodeTestCase(base.DbTestCase): self.assertIsNone(res['provision_updated_at']) self.assertIsNone(res['inspection_started_at']) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_update_node_inspection_started_at(self, mock_utcnow): mocked_time = datetime.datetime(2000, 1, 1, 0, 0) mock_utcnow.return_value = mocked_time @@ -390,7 +390,7 @@ class DbNodeTestCase(base.DbTestCase): timeutils.normalize_time(result)) self.assertIsNone(res['inspection_finished_at']) - @mock.patch.object(timeutils, 'utcnow') + @mock.patch.object(timeutils, 'utcnow', autospec=True) def test_update_node_inspection_finished_at(self, mock_utcnow): mocked_time = datetime.datetime(2000, 1, 1, 0, 0) mock_utcnow.return_value = mocked_time diff --git a/ironic/tests/drivers/ilo/test_deploy.py b/ironic/tests/drivers/ilo/test_deploy.py index 8cc70cab4..f44e532b9 100644 --- a/ironic/tests/drivers/ilo/test_deploy.py +++ b/ironic/tests/drivers/ilo/test_deploy.py @@ -124,7 +124,7 @@ class IloDeployPrivateMethodsTestCase(db_base.DbTestCase): boot_iso_expected = 'boot-iso-uuid' self.assertEqual(boot_iso_expected, boot_iso_actual) - @mock.patch.object(driver_utils, 'get_boot_mode_for_deploy') + @mock.patch.object(deploy_utils, 'get_boot_mode_for_deploy') @mock.patch.object(images, 'get_image_properties') @mock.patch.object(ilo_deploy, '_parse_deploy_info') def test__get_boot_iso_uefi_no_glance_image(self, @@ -293,19 +293,6 @@ class IloDeployPrivateMethodsTestCase(db_base.DbTestCase): ilo_deploy._update_secure_boot_mode(task, False) self.assertFalse(func_set_secure_boot_mode.called) - @mock.patch.object(driver_utils, 'add_node_capability') - @mock.patch.object(driver_utils, 'rm_node_capability') - def test__enable_uefi_capability(self, func_rm_node_capability, - func_add_node_capability): - with task_manager.acquire(self.context, self.node.uuid, - shared=False) as task: - ilo_deploy._enable_uefi_capability(task) - func_rm_node_capability.assert_called_once_with(task, - 'boot_mode') - func_add_node_capability.assert_called_once_with(task, - 'boot_mode', - 'uefi') - @mock.patch.object(ilo_common, 'set_secure_boot_mode') @mock.patch.object(ilo_common, 'get_secure_boot_mode') def test__disable_secure_boot_false(self, @@ -349,67 +336,86 @@ class IloDeployPrivateMethodsTestCase(db_base.DbTestCase): self.assertFalse(returned_state) @mock.patch.object(ilo_common, 'update_boot_mode') - @mock.patch.object(deploy_utils, 'is_secure_boot_requested') @mock.patch.object(ilo_deploy, '_disable_secure_boot') @mock.patch.object(manager_utils, 'node_power_action') def test__prepare_node_for_deploy(self, func_node_power_action, func_disable_secure_boot, - func_is_secure_boot_requested, func_update_boot_mode): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: func_disable_secure_boot.return_value = False - func_is_secure_boot_requested.return_value = False ilo_deploy._prepare_node_for_deploy(task) func_node_power_action.assert_called_once_with(task, states.POWER_OFF) func_disable_secure_boot.assert_called_once_with(task) - func_is_secure_boot_requested.assert_called_once_with(task.node) func_update_boot_mode.assert_called_once_with(task) + bootmode = driver_utils.get_node_capability(task.node, "boot_mode") + self.assertIsNone(bootmode) @mock.patch.object(ilo_common, 'update_boot_mode') - @mock.patch.object(deploy_utils, 'is_secure_boot_requested') @mock.patch.object(ilo_deploy, '_disable_secure_boot') @mock.patch.object(manager_utils, 'node_power_action') def test__prepare_node_for_deploy_sec_boot_on(self, func_node_power_action, func_disable_secure_boot, - func_is_secure_boot_req, func_update_boot_mode): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: func_disable_secure_boot.return_value = True - func_is_secure_boot_req.return_value = False ilo_deploy._prepare_node_for_deploy(task) func_node_power_action.assert_called_once_with(task, states.POWER_OFF) func_disable_secure_boot.assert_called_once_with(task) - func_is_secure_boot_req.assert_called_once_with(task.node) self.assertFalse(func_update_boot_mode.called) + ret_boot_mode = task.node.instance_info['deploy_boot_mode'] + self.assertEqual('uefi', ret_boot_mode) + bootmode = driver_utils.get_node_capability(task.node, "boot_mode") + self.assertIsNone(bootmode) + + @mock.patch.object(ilo_common, 'update_boot_mode') + @mock.patch.object(ilo_deploy, '_disable_secure_boot') + @mock.patch.object(manager_utils, 'node_power_action') + def test__prepare_node_for_deploy_inst_info(self, + func_node_power_action, + func_disable_secure_boot, + func_update_boot_mode): + instance_info = {'capabilities': '{"secure_boot": "true"}'} + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + func_disable_secure_boot.return_value = False + task.node.instance_info = instance_info + ilo_deploy._prepare_node_for_deploy(task) + func_node_power_action.assert_called_once_with(task, + states.POWER_OFF) + func_disable_secure_boot.assert_called_once_with(task) + func_update_boot_mode.assert_called_once_with(task) + bootmode = driver_utils.get_node_capability(task.node, "boot_mode") + self.assertIsNone(bootmode) + deploy_boot_mode = task.node.instance_info.get('deploy_boot_mode') + self.assertIsNone(deploy_boot_mode) @mock.patch.object(ilo_common, 'update_boot_mode') - @mock.patch.object(ilo_deploy, '_enable_uefi_capability') - @mock.patch.object(deploy_utils, 'is_secure_boot_requested') @mock.patch.object(ilo_deploy, '_disable_secure_boot') @mock.patch.object(manager_utils, 'node_power_action') - def test__prepare_node_for_deploy_sec_boot_req(self, - func_node_power_action, - func_disable_secure_boot, - func_is_secure_boot_req, - func_enable_uefi_cap, - func_update_boot_mode): + def test__prepare_node_for_deploy_sec_boot_on_inst_info(self, + func_node_power_action, + func_disable_secure_boot, + func_update_boot_mode): + instance_info = {'capabilities': '{"secure_boot": "true"}'} with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: func_disable_secure_boot.return_value = True - func_is_secure_boot_req.return_value = True + task.node.instance_info = instance_info ilo_deploy._prepare_node_for_deploy(task) func_node_power_action.assert_called_once_with(task, states.POWER_OFF) func_disable_secure_boot.assert_called_once_with(task) - func_is_secure_boot_req.assert_called_once_with(task.node) - func_enable_uefi_cap.assert_called_once_with(task) self.assertFalse(func_update_boot_mode.called) + bootmode = driver_utils.get_node_capability(task.node, "boot_mode") + self.assertIsNone(bootmode) + deploy_boot_mode = task.node.instance_info.get('deploy_boot_mode') + self.assertIsNone(deploy_boot_mode) class IloVirtualMediaIscsiDeployTestCase(db_base.DbTestCase): @@ -1179,8 +1185,10 @@ class IloVirtualMediaAgentVendorInterfaceTestCase(db_base.DbTestCase): @mock.patch.object(agent.AgentVendorInterface, 'reboot_to_instance') @mock.patch.object(agent.AgentVendorInterface, 'check_deploy_success') + @mock.patch.object(ilo_common, 'update_boot_mode') @mock.patch.object(ilo_deploy, '_update_secure_boot_mode') def test_reboot_to_instance(self, func_update_secure_boot_mode, + func_update_boot_mode, check_deploy_success_mock, agent_reboot_to_instance_mock): kwargs = {'address': '123456'} @@ -1189,14 +1197,17 @@ class IloVirtualMediaAgentVendorInterfaceTestCase(db_base.DbTestCase): shared=False) as task: task.driver.vendor.reboot_to_instance(task, **kwargs) check_deploy_success_mock.called_once_with(task.node) + func_update_boot_mode.assert_called_once_with(task) func_update_secure_boot_mode.assert_called_once_with(task, True) agent_reboot_to_instance_mock.assert_called_once_with(task, **kwargs) @mock.patch.object(agent.AgentVendorInterface, 'reboot_to_instance') @mock.patch.object(agent.AgentVendorInterface, 'check_deploy_success') + @mock.patch.object(ilo_common, 'update_boot_mode') @mock.patch.object(ilo_deploy, '_update_secure_boot_mode') def test_reboot_to_instance_deploy_fail(self, func_update_secure_boot_mode, + func_update_boot_mode, check_deploy_success_mock, agent_reboot_to_instance_mock): kwargs = {'address': '123456'} @@ -1205,6 +1216,7 @@ class IloVirtualMediaAgentVendorInterfaceTestCase(db_base.DbTestCase): shared=False) as task: task.driver.vendor.reboot_to_instance(task, **kwargs) check_deploy_success_mock.called_once_with(task.node) + self.assertFalse(func_update_boot_mode.called) self.assertFalse(func_update_secure_boot_mode.called) agent_reboot_to_instance_mock.assert_called_once_with(task, **kwargs) diff --git a/ironic/tests/drivers/test_agent.py b/ironic/tests/drivers/test_agent.py index b9ea638e0..bb9675f3f 100644 --- a/ironic/tests/drivers/test_agent.py +++ b/ironic/tests/drivers/test_agent.py @@ -164,6 +164,14 @@ class TestAgentDeploy(db_base.DbTestCase): self.assertIn('driver_info.deploy_ramdisk', str(e)) self.assertIn('driver_info.deploy_kernel', str(e)) + def test_validate_driver_info_manage_tftp_false(self): + self.config(manage_tftp=False, group='agent') + self.node.driver_info = {} + self.node.save() + with task_manager.acquire( + self.context, self.node['uuid'], shared=False) as task: + self.driver.validate(task) + def test_validate_instance_info_missing_params(self): self.node.instance_info = {} self.node.save() @@ -199,6 +207,37 @@ class TestAgentDeploy(db_base.DbTestCase): self.assertRaises(exception.InvalidParameterValue, task.driver.deploy.validate, task) + @mock.patch.object(agent, '_cache_tftp_images') + @mock.patch.object(pxe_utils, 'create_pxe_config') + @mock.patch.object(agent, '_build_pxe_config_options') + @mock.patch.object(agent, '_get_tftp_image_info') + def test__prepare_pxe_boot(self, pxe_info_mock, options_mock, + create_mock, cache_mock): + with task_manager.acquire( + self.context, self.node['uuid'], shared=False) as task: + agent._prepare_pxe_boot(task) + pxe_info_mock.assert_called_once_with(task.node) + options_mock.assert_called_once_with(task.node, mock.ANY) + create_mock.assert_called_once_with( + task, mock.ANY, CONF.agent.agent_pxe_config_template) + cache_mock.assert_called_once_with(task.context, task.node, + mock.ANY) + + @mock.patch.object(agent, '_cache_tftp_images') + @mock.patch.object(pxe_utils, 'create_pxe_config') + @mock.patch.object(agent, '_build_pxe_config_options') + @mock.patch.object(agent, '_get_tftp_image_info') + def test__prepare_pxe_boot_manage_tftp_false( + self, pxe_info_mock, options_mock, create_mock, cache_mock): + self.config(manage_tftp=False, group='agent') + with task_manager.acquire( + self.context, self.node['uuid'], shared=False) as task: + agent._prepare_pxe_boot(task) + self.assertFalse(pxe_info_mock.called) + self.assertFalse(options_mock.called) + self.assertFalse(create_mock.called) + self.assertFalse(cache_mock.called) + @mock.patch.object(dhcp_factory.DHCPFactory, 'update_dhcp') @mock.patch('ironic.conductor.utils.node_set_boot_device') @mock.patch('ironic.conductor.utils.node_power_action') @@ -221,6 +260,36 @@ class TestAgentDeploy(db_base.DbTestCase): power_mock.assert_called_once_with(task, states.POWER_OFF) self.assertEqual(driver_return, states.DELETED) + @mock.patch.object(pxe_utils, 'clean_up_pxe_config') + @mock.patch.object(agent, 'AgentTFTPImageCache') + @mock.patch('ironic.common.utils.unlink_without_raise') + @mock.patch.object(agent, '_get_tftp_image_info') + def test__clean_up_pxe(self, info_mock, unlink_mock, cache_mock, + clean_mock): + info_mock.return_value = {'label': ['fake1', 'fake2']} + with task_manager.acquire( + self.context, self.node['uuid'], shared=False) as task: + agent._clean_up_pxe(task) + info_mock.assert_called_once_with(task.node) + unlink_mock.assert_called_once_with('fake2') + clean_mock.assert_called_once_with(task) + + @mock.patch.object(pxe_utils, 'clean_up_pxe_config') + @mock.patch.object(agent.AgentTFTPImageCache, 'clean_up') + @mock.patch('ironic.common.utils.unlink_without_raise') + @mock.patch.object(agent, '_get_tftp_image_info') + def test__clean_up_pxe_manage_tftp_false( + self, info_mock, unlink_mock, cache_mock, clean_mock): + self.config(manage_tftp=False, group='agent') + info_mock.return_value = {'label': ['fake1', 'fake2']} + with task_manager.acquire( + self.context, self.node['uuid'], shared=False) as task: + agent._clean_up_pxe(task) + self.assertFalse(info_mock.called) + self.assertFalse(unlink_mock.called) + self.assertFalse(cache_mock.called) + self.assertFalse(clean_mock.called) + @mock.patch('ironic.dhcp.neutron.NeutronDHCPApi.delete_cleaning_ports') @mock.patch('ironic.dhcp.neutron.NeutronDHCPApi.create_cleaning_ports') @mock.patch('ironic.drivers.modules.agent._do_pxe_boot') diff --git a/ironic/tests/drivers/test_deploy_utils.py b/ironic/tests/drivers/test_deploy_utils.py index 033bd89d5..fdb6653a3 100644 --- a/ironic/tests/drivers/test_deploy_utils.py +++ b/ironic/tests/drivers/test_deploy_utils.py @@ -1020,13 +1020,18 @@ class WorkOnDiskTestCase(tests_base.TestCase): self.swap_part = '/dev/fake-part1' self.root_part = '/dev/fake-part2' - self.mock_ibd = mock.patch.object(utils, 'is_block_device').start() - self.mock_mp = mock.patch.object(utils, 'make_partitions').start() - self.addCleanup(self.mock_ibd.stop) - self.addCleanup(self.mock_mp.stop) - self.mock_remlbl = mock.patch.object(utils, - 'destroy_disk_metadata').start() - self.addCleanup(self.mock_remlbl.stop) + self.mock_ibd_obj = mock.patch.object( + utils, 'is_block_device', autospec=True) + self.mock_ibd = self.mock_ibd_obj.start() + self.addCleanup(self.mock_ibd_obj.stop) + self.mock_mp_obj = mock.patch.object( + utils, 'make_partitions', autospec=True) + self.mock_mp = self.mock_mp_obj.start() + self.addCleanup(self.mock_mp_obj.stop) + self.mock_remlbl_obj = mock.patch.object( + utils, 'destroy_disk_metadata', autospec=True) + self.mock_remlbl = self.mock_remlbl_obj.start() + self.addCleanup(self.mock_remlbl_obj.stop) self.mock_mp.return_value = {'swap': self.swap_part, 'root': self.root_part} @@ -1044,7 +1049,7 @@ class WorkOnDiskTestCase(tests_base.TestCase): boot_mode="bios") def test_no_swap_partition(self): - self.mock_ibd.side_effect = [True, False] + self.mock_ibd.side_effect = iter([True, False]) calls = [mock.call(self.root_part), mock.call(self.swap_part)] self.assertRaises(exception.InstanceDeployFailure, @@ -1068,7 +1073,7 @@ class WorkOnDiskTestCase(tests_base.TestCase): self.mock_mp.return_value = {'ephemeral': ephemeral_part, 'swap': swap_part, 'root': root_part} - self.mock_ibd.side_effect = [True, True, False] + self.mock_ibd.side_effect = iter([True, True, False]) calls = [mock.call(root_part), mock.call(swap_part), mock.call(ephemeral_part)] @@ -1096,7 +1101,7 @@ class WorkOnDiskTestCase(tests_base.TestCase): self.mock_mp.return_value = {'swap': swap_part, 'configdrive': configdrive_part, 'root': root_part} - self.mock_ibd.side_effect = [True, True, False] + self.mock_ibd.side_effect = iter([True, True, False]) calls = [mock.call(root_part), mock.call(swap_part), mock.call(configdrive_part)] @@ -1465,6 +1470,27 @@ class ParseInstanceInfoCapabilitiesTestCase(tests_base.TestCase): self.node.instance_info = {'capabilities': {"secure_boot": "invalid"}} self.assertFalse(utils.is_secure_boot_requested(self.node)) + def test_get_boot_mode_for_deploy_using_capabilities(self): + properties = {'capabilities': 'boot_mode:uefi,cap2:value2'} + self.node.properties = properties + + result = utils.get_boot_mode_for_deploy(self.node) + self.assertEqual('uefi', result) + + def test_get_boot_mode_for_deploy_using_instance_info_cap(self): + instance_info = {'capabilities': {'secure_boot': 'True'}} + self.node.instance_info = instance_info + + result = utils.get_boot_mode_for_deploy(self.node) + self.assertEqual('uefi', result) + + def test_get_boot_mode_for_deploy_using_instance_info(self): + instance_info = {'deploy_boot_mode': 'bios'} + self.node.instance_info = instance_info + + result = utils.get_boot_mode_for_deploy(self.node) + self.assertEqual('bios', result) + class TrySetBootDeviceTestCase(db_base.DbTestCase): diff --git a/ironic/tests/drivers/test_ipmitool.py b/ironic/tests/drivers/test_ipmitool.py index a27060d0f..2e0097fba 100644 --- a/ironic/tests/drivers/test_ipmitool.py +++ b/ironic/tests/drivers/test_ipmitool.py @@ -840,6 +840,86 @@ class IPMIToolPrivateMethodTestCase(db_base.DbTestCase): mock_support.assert_called_once_with('timing') mock_pwf.assert_called_once_with(self.info['password']) mock_exec.assert_called_once_with(*args) + self.assertEqual(1, mock_exec.call_count) + + @mock.patch.object(ipmi, '_is_option_supported', autospec=True) + @mock.patch.object(utils, 'execute', autospec=True) + def test__exec_ipmitool_exception_retry(self, + mock_exec, mock_support, mock_sleep): + + ipmi.LAST_CMD_TIME = {} + mock_support.return_value = False + mock_exec.side_effect = iter([ + processutils.ProcessExecutionError( + stderr="insufficient resources for session" + ), + (None, None) + ]) + + # Directly set the configuration values such that + # the logic will cause _exec_ipmitool to retry twice. + self.config(min_command_interval=1, group='ipmi') + self.config(retry_timeout=2, group='ipmi') + + ipmi._exec_ipmitool(self.info, 'A B C') + + mock_support.assert_called_once_with('timing') + self.assertEqual(2, mock_exec.call_count) + + @mock.patch.object(ipmi, '_is_option_supported', autospec=True) + @mock.patch.object(utils, 'execute', autospec=True) + def test__exec_ipmitool_exception_retries_exceeded(self, + mock_exec, mock_support, mock_sleep): + + ipmi.LAST_CMD_TIME = {} + mock_support.return_value = False + + mock_exec.side_effect = processutils.ProcessExecutionError( + stderr="insufficient resources for session" + ) + + # Directly set the configuration values such that + # the logic will cause _exec_ipmitool to timeout. + self.config(min_command_interval=1, group='ipmi') + self.config(retry_timeout=1, group='ipmi') + + self.assertRaises(processutils.ProcessExecutionError, + ipmi._exec_ipmitool, + self.info, 'A B C') + mock_support.assert_called_once_with('timing') + self.assertEqual(1, mock_exec.call_count) + + @mock.patch.object(ipmi, '_is_option_supported', autospec=True) + @mock.patch.object(utils, 'execute', autospec=True) + def test__exec_ipmitool_exception_non_retryable_failure(self, + mock_exec, mock_support, mock_sleep): + + ipmi.LAST_CMD_TIME = {} + mock_support.return_value = False + + # Return a retryable error, then an error that cannot + # be retried thus resulting in a single retry + # attempt by _exec_ipmitool. + mock_exec.side_effect = iter([ + processutils.ProcessExecutionError( + stderr="insufficient resources for session" + ), + processutils.ProcessExecutionError( + stderr="Unknown" + ), + ]) + + # Directly set the configuration values such that + # the logic will cause _exec_ipmitool to retry up + # to 3 times. + self.config(min_command_interval=1, group='ipmi') + self.config(retry_timeout=3, group='ipmi') + + self.assertRaises(processutils.ProcessExecutionError, + ipmi._exec_ipmitool, + self.info, 'A B C') + mock_support.assert_called_once_with('timing') + self.assertEqual(2, mock_exec.call_count) @mock.patch.object(ipmi, '_exec_ipmitool', autospec=True) def test__power_status_on(self, mock_exec, mock_sleep): diff --git a/ironic/tests/drivers/test_iscsi_deploy.py b/ironic/tests/drivers/test_iscsi_deploy.py index a0b1f40ba..4d3803542 100644 --- a/ironic/tests/drivers/test_iscsi_deploy.py +++ b/ironic/tests/drivers/test_iscsi_deploy.py @@ -487,6 +487,25 @@ class IscsiDeployMethodsTestCase(db_base.DbTestCase): self._test_build_deploy_ramdisk_options(mock_alnum, fake_api_url, expected_boot_option=expected) + @mock.patch.object(keystone, 'get_service_url', autospec=True) + @mock.patch.object(utils, 'random_alnum', autospec=True) + def test_build_deploy_ramdisk_options_whole_disk_image(self, mock_alnum, + mock_get_url): + """Tests a hack to boot_option for whole disk images. + + This hack is in place to fix bug #1441556. + """ + self.node.instance_info = {'capabilities': '{"boot_option": "local"}'} + dii = self.node.driver_internal_info + dii['is_whole_disk_image'] = True + self.node.driver_internal_info = dii + self.node.save() + expected = 'netboot' + fake_api_url = 'http://127.0.0.1:6385' + self.config(api_url=fake_api_url, group='conductor') + self._test_build_deploy_ramdisk_options(mock_alnum, fake_api_url, + expected_boot_option=expected) + def test_get_boot_option(self): self.node.instance_info = {'capabilities': '{"boot_option": "local"}'} result = iscsi_deploy.get_boot_option(self.node) diff --git a/ironic/tests/drivers/test_seamicro.py b/ironic/tests/drivers/test_seamicro.py index ad4586828..e477cddd4 100644 --- a/ironic/tests/drivers/test_seamicro.py +++ b/ironic/tests/drivers/test_seamicro.py @@ -129,6 +129,7 @@ class SeaMicroValidateParametersTestCase(db_base.DbTestCase): node) +@mock.patch('eventlet.greenthread.sleep', lambda n: None) class SeaMicroPrivateMethodsTestCase(db_base.DbTestCase): def setUp(self): @@ -144,8 +145,6 @@ class SeaMicroPrivateMethodsTestCase(db_base.DbTestCase): self.config(action_timeout=0, group='seamicro') self.config(max_retry=2, group='seamicro') - self.patcher = mock.patch('eventlet.greenthread.sleep') - self.mock_sleep = self.patcher.start() self.info = seamicro._parse_driver_info(self.node) @mock.patch.object(seamicro_client, "Client") diff --git a/ironic/tests/drivers/test_utils.py b/ironic/tests/drivers/test_utils.py index 5eb9b5ace..cd14b464f 100644 --- a/ironic/tests/drivers/test_utils.py +++ b/ironic/tests/drivers/test_utils.py @@ -112,27 +112,6 @@ class UtilsTestCase(db_base.DbTestCase): self.assertEqual('a:b,c:d,a:b', task.node.properties['capabilities']) - def test_rm_node_capability(self): - with task_manager.acquire(self.context, self.node.uuid, - shared=False) as task: - task.node.properties['capabilities'] = 'a:b' - driver_utils.rm_node_capability(task, 'a') - self.assertIsNone(task.node.properties['capabilities']) - - def test_rm_node_capability_exists(self): - with task_manager.acquire(self.context, self.node.uuid, - shared=False) as task: - task.node.properties['capabilities'] = 'a:b,c:d,x:y' - self.assertIsNone(driver_utils.rm_node_capability(task, 'c')) - self.assertEqual('a:b,x:y', task.node.properties['capabilities']) - - def test_rm_node_capability_non_existent(self): - with task_manager.acquire(self.context, self.node.uuid, - shared=False) as task: - task.node.properties['capabilities'] = 'a:b' - self.assertIsNone(driver_utils.rm_node_capability(task, 'x')) - self.assertEqual('a:b', task.node.properties['capabilities']) - def test_validate_capability(self): properties = {'capabilities': 'cat:meow,cap2:value2'} self.node.properties = properties @@ -191,17 +170,3 @@ class UtilsTestCase(db_base.DbTestCase): self.assertRaises(exception.InvalidParameterValue, driver_utils.validate_secure_boot_capability, self.node) - - def test_get_boot_mode_for_deploy_using_capabilities(self): - properties = {'capabilities': 'boot_mode:uefi,cap2:value2'} - self.node.properties = properties - - result = driver_utils.get_boot_mode_for_deploy(self.node) - self.assertEqual('uefi', result) - - def test_get_boot_mode_for_deploy_using_instance_info(self): - instance_info = {'deploy_boot_mode': 'uefi'} - self.node.instance_info = instance_info - - result = driver_utils.get_boot_mode_for_deploy(self.node) - self.assertEqual('uefi', result) diff --git a/ironic/tests/stubs.py b/ironic/tests/stubs.py index 7d43d2676..d20c1fd8a 100644 --- a/ironic/tests/stubs.py +++ b/ironic/tests/stubs.py @@ -12,7 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. -from ironic.common import exception +from glanceclient import exc as glance_exc NOW_GLANCE_FORMAT = "2010-10-11T10:30:22" @@ -40,7 +40,7 @@ class StubGlanceClient(object): index += 1 break else: - raise exception.BadRequest('Marker not found') + raise glance_exc.BadRequest('Marker not found') return self._images[index:index + limit] @@ -48,7 +48,7 @@ class StubGlanceClient(object): for image in self._images: if image.id == str(image_id): return image - raise exception.ImageNotFound(image_id) + raise glance_exc.NotFound(image_id) def data(self, image_id): self.get(image_id) @@ -76,7 +76,7 @@ class StubGlanceClient(object): for k, v in metadata.items(): setattr(self._images[i], k, v) return self._images[i] - raise exception.NotFound(image_id) + raise glance_exc.NotFound(image_id) def delete(self, image_id): for i, image in enumerate(self._images): @@ -86,10 +86,10 @@ class StubGlanceClient(object): # HTTPForbidden. image_data = self._images[i] if image_data.deleted: - raise exception.Forbidden() + raise glance_exc.Forbidden() image_data.deleted = True return - raise exception.NotFound(image_id) + raise glance_exc.NotFound(image_id) class FakeImage(object): diff --git a/ironic/tests/test_glance_service.py b/ironic/tests/test_glance_service.py index 8482ed751..6c3276da6 100644 --- a/ironic/tests/test_glance_service.py +++ b/ironic/tests/test_glance_service.py @@ -20,8 +20,11 @@ import os import tempfile import time +from glanceclient import exc as glance_exc import mock +from oslo_config import cfg from oslo_context import context +from oslo_serialization import jsonutils import testtools @@ -33,8 +36,6 @@ from ironic.tests import base from ironic.tests import matchers from ironic.tests import stubs -from oslo_config import cfg -from oslo_serialization import jsonutils CONF = cfg.CONF @@ -468,7 +469,7 @@ class TestGlanceImageService(base.TestCase): def get(self, image_id): if tries[0] == 0: tries[0] = 1 - raise exception.ServiceUnavailable('') + raise glance_exc.ServiceUnavailable('') else: return {} @@ -536,7 +537,7 @@ class TestGlanceImageService(base.TestCase): class MyGlanceStubClient(stubs.StubGlanceClient): """A client that raises a Forbidden exception.""" def get(self, image_id): - raise exception.Forbidden(image_id) + raise glance_exc.Forbidden(image_id) stub_client = MyGlanceStubClient() stub_context = context.RequestContext(auth_token=True) @@ -552,7 +553,7 @@ class TestGlanceImageService(base.TestCase): class MyGlanceStubClient(stubs.StubGlanceClient): """A client that raises a HTTPForbidden exception.""" def get(self, image_id): - raise exception.HTTPForbidden(image_id) + raise glance_exc.HTTPForbidden(image_id) stub_client = MyGlanceStubClient() stub_context = context.RequestContext(auth_token=True) @@ -568,7 +569,7 @@ class TestGlanceImageService(base.TestCase): class MyGlanceStubClient(stubs.StubGlanceClient): """A client that raises a NotFound exception.""" def get(self, image_id): - raise exception.NotFound(image_id) + raise glance_exc.NotFound(image_id) stub_client = MyGlanceStubClient() stub_context = context.RequestContext(auth_token=True) @@ -584,7 +585,7 @@ class TestGlanceImageService(base.TestCase): class MyGlanceStubClient(stubs.StubGlanceClient): """A client that raises a HTTPNotFound exception.""" def get(self, image_id): - raise exception.HTTPNotFound(image_id) + raise glance_exc.HTTPNotFound(image_id) stub_client = MyGlanceStubClient() stub_context = context.RequestContext(auth_token=True) @@ -635,7 +636,7 @@ def _create_failing_glance_client(info): def get(self, image_id): info['num_calls'] += 1 if info['num_calls'] == 1: - raise exception.ServiceUnavailable('') + raise glance_exc.ServiceUnavailable('') return {} return MyGlanceStubClient() diff --git a/ironic/tests/test_images.py b/ironic/tests/test_images.py index fb1da9dbc..b610d4b0a 100644 --- a/ironic/tests/test_images.py +++ b/ironic/tests/test_images.py @@ -424,12 +424,15 @@ class FsImageTestCase(base.TestCase): self.assertEqual(expected_cfg, cfg) def test__generate_grub_cfg(self): - kernel_params = ['key1=value1', 'key2'] options = {'linux': '/vmlinuz', 'initrd': '/initrd'} - expected_cfg = ("menuentry \"install\" {\n" - "linux /vmlinuz key1=value1 key2 --\n" - "initrd /initrd\n" + expected_cfg = ("set default=0\n" + "set timeout=5\n" + "set hidden_timeout_quiet=false\n" + "\n" + "menuentry \"boot_partition\" {\n" + "linuxefi /vmlinuz key1=value1 key2 --\n" + "initrdefi /initrd\n" "}") cfg = images._generate_cfg(kernel_params, diff --git a/ironic/tests/test_pxe_utils.py b/ironic/tests/test_pxe_utils.py index f16cd3e1b..1792d840a 100644 --- a/ironic/tests/test_pxe_utils.py +++ b/ironic/tests/test_pxe_utils.py @@ -144,7 +144,40 @@ class TestPXEUtils(db_base.DbTestCase): ] unlink_calls = [ mock.call('/tftpboot/pxelinux.cfg/01-00-11-22-33-44-55-66'), - mock.call('/tftpboot/pxelinux.cfg/01-00-11-22-33-44-55-67') + mock.call('/tftpboot/pxelinux.cfg/01-00-11-22-33-44-55-67'), + ] + with task_manager.acquire(self.context, self.node.uuid) as task: + pxe_utils._link_mac_pxe_configs(task) + + unlink_mock.assert_has_calls(unlink_calls) + create_link_mock.assert_has_calls(create_link_calls) + + @mock.patch('ironic.common.utils.create_link_without_raise', autospec=True) + @mock.patch('ironic.common.utils.unlink_without_raise', autospec=True) + @mock.patch('ironic.drivers.utils.get_node_mac_addresses', autospec=True) + def test__write_mac_ipxe_configs(self, get_macs_mock, unlink_mock, + create_link_mock): + self.config(ipxe_enabled=True, group='pxe') + macs = [ + '00:11:22:33:44:55:66', + '00:11:22:33:44:55:67' + ] + get_macs_mock.return_value = macs + create_link_calls = [ + mock.call(u'/httpboot/1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config', + '/httpboot/pxelinux.cfg/00-11-22-33-44-55-66'), + mock.call(u'/httpboot/1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config', + '/httpboot/pxelinux.cfg/00112233445566'), + mock.call(u'/httpboot/1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config', + '/httpboot/pxelinux.cfg/00-11-22-33-44-55-67'), + mock.call(u'/httpboot/1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config', + '/httpboot/pxelinux.cfg/00112233445567'), + ] + unlink_calls = [ + mock.call('/httpboot/pxelinux.cfg/00-11-22-33-44-55-66'), + mock.call('/httpboot/pxelinux.cfg/00112233445566'), + mock.call('/httpboot/pxelinux.cfg/00-11-22-33-44-55-67'), + mock.call('/httpboot/pxelinux.cfg/00112233445567'), ] with task_manager.acquire(self.context, self.node.uuid) as task: pxe_utils._link_mac_pxe_configs(task) @@ -218,7 +251,7 @@ class TestPXEUtils(db_base.DbTestCase): self.config(ipxe_enabled=True, group='pxe') self.config(http_root='/httpboot', group='pxe') mac = '00:11:22:33:AA:BB:CC' - self.assertEqual('/httpboot/pxelinux.cfg/00112233aabbcc', + self.assertEqual('/httpboot/pxelinux.cfg/00-11-22-33-aa-bb-cc', pxe_utils._get_pxe_mac_path(mac)) def test__get_pxe_ip_address_path(self): |