# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Test class for Management Interface used by iLO modules.""" import mock from ironic.common import exception from ironic.common import states from ironic.common import utils from ironic.conductor import task_manager from ironic.conductor import utils as conductor_utils from ironic.drivers.modules.ilo import common as ilo_common from ironic.drivers.modules.ilo import inspect as ilo_inspect from ironic.drivers.modules.ilo import power as ilo_power from ironic.drivers.modules import inspect_utils from ironic.tests.unit.drivers.modules.ilo import test_common class IloInspectTestCase(test_common.BaseIloTest): def test_get_properties(self): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: properties = ilo_common.REQUIRED_PROPERTIES.copy() properties.update(ilo_common.SNMP_PROPERTIES) properties.update(ilo_common.SNMP_OPTIONAL_PROPERTIES) self.assertEqual(properties, task.driver.inspect.get_properties()) @mock.patch.object(ilo_common, 'parse_driver_info', spec_set=True, autospec=True) def test_validate(self, driver_info_mock): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: task.driver.inspect.validate(task) driver_info_mock.assert_called_once_with(task.node) @mock.patch.object(ilo_inspect, '_get_capabilities', spec_set=True, autospec=True) @mock.patch.object(inspect_utils, 'create_ports_if_not_exist', spec_set=True, autospec=True) @mock.patch.object(ilo_inspect, '_get_essential_properties', spec_set=True, autospec=True) @mock.patch.object(ilo_power.IloPower, 'get_power_state', spec_set=True, autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, autospec=True) def test_inspect_essential_ok(self, get_ilo_object_mock, power_mock, get_essential_mock, create_port_mock, get_capabilities_mock): ilo_object_mock = get_ilo_object_mock.return_value properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1', 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} capabilities = {} result = {'properties': properties, 'macs': macs} get_essential_mock.return_value = result get_capabilities_mock.return_value = capabilities power_mock.return_value = states.POWER_ON with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: task.driver.inspect.inspect_hardware(task) self.assertEqual(properties, task.node.properties) power_mock.assert_called_once_with(mock.ANY, task) get_essential_mock.assert_called_once_with(task.node, ilo_object_mock) get_capabilities_mock.assert_called_once_with(task.node, ilo_object_mock) create_port_mock.assert_called_once_with(task, macs) @mock.patch.object(ilo_inspect.LOG, 'warning', spec_set=True, autospec=True) @mock.patch.object(ilo_inspect, '_get_capabilities', spec_set=True, autospec=True) @mock.patch.object(inspect_utils, 'create_ports_if_not_exist', spec_set=True, autospec=True) @mock.patch.object(ilo_inspect, '_get_essential_properties', spec_set=True, autospec=True) @mock.patch.object(ilo_power.IloPower, 'get_power_state', spec_set=True, autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, autospec=True) def test_inspect_essential_ok_local_gb_zero(self, get_ilo_object_mock, power_mock, get_essential_mock, create_port_mock, get_capabilities_mock, log_mock): ilo_object_mock = get_ilo_object_mock.return_value properties = {'memory_mb': '512', 'local_gb': 0, 'cpus': '1', 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} capabilities = {} result = {'properties': properties, 'macs': macs} get_essential_mock.return_value = result get_capabilities_mock.return_value = capabilities power_mock.return_value = states.POWER_ON with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: properties = task.node.properties properties['local_gb'] = 10 task.node.properties = properties task.node.save() expected_properties = {'memory_mb': '512', 'local_gb': 10, 'cpus': '1', 'cpu_arch': 'x86_64'} task.driver.inspect.inspect_hardware(task) self.assertEqual(expected_properties, task.node.properties) power_mock.assert_called_once_with(mock.ANY, task) get_essential_mock.assert_called_once_with(task.node, ilo_object_mock) self.assertTrue(log_mock.called) get_capabilities_mock.assert_called_once_with(task.node, ilo_object_mock) create_port_mock.assert_called_once_with(task, macs) @mock.patch.object(ilo_inspect.LOG, 'warning', spec_set=True, autospec=True) @mock.patch.object(ilo_inspect, '_get_capabilities', spec_set=True, autospec=True) @mock.patch.object(inspect_utils, 'create_ports_if_not_exist', spec_set=True, autospec=True) @mock.patch.object(ilo_inspect, '_get_essential_properties', spec_set=True, autospec=True) @mock.patch.object(ilo_power.IloPower, 'get_power_state', spec_set=True, autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, autospec=True) def test_inspect_ok_gen8(self, get_ilo_object_mock, power_mock, get_essential_mock, create_port_mock, get_capabilities_mock, log_mock): ilo_object_mock = get_ilo_object_mock.return_value properties = {'memory_mb': '512', 'local_gb': 10, 'cpus': '1', 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} capabilities = {'server_model': 'Gen8'} result = {'properties': properties, 'macs': macs} get_essential_mock.return_value = result get_capabilities_mock.return_value = capabilities power_mock.return_value = states.POWER_ON with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: expected_properties = {'memory_mb': '512', 'local_gb': 10, 'cpus': '1', 'cpu_arch': 'x86_64', 'capabilities': 'server_model:Gen8'} task.driver.inspect.inspect_hardware(task) self.assertEqual(expected_properties, task.node.properties) power_mock.assert_called_once_with(mock.ANY, task) get_essential_mock.assert_called_once_with(task.node, ilo_object_mock) self.assertTrue(log_mock.called) get_capabilities_mock.assert_called_once_with(task.node, ilo_object_mock) create_port_mock.assert_called_once_with(task, macs) @mock.patch.object(ilo_inspect.LOG, 'warning', spec_set=True, autospec=True) @mock.patch.object(ilo_inspect, '_get_capabilities', spec_set=True, autospec=True) @mock.patch.object(inspect_utils, 'create_ports_if_not_exist', spec_set=True, autospec=True) @mock.patch.object(ilo_inspect, '_get_essential_properties', spec_set=True, autospec=True) @mock.patch.object(ilo_power.IloPower, 'get_power_state', spec_set=True, autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, autospec=True) def test_inspect_ok_gen10(self, get_ilo_object_mock, power_mock, get_essential_mock, create_port_mock, get_capabilities_mock, log_mock): ilo_object_mock = get_ilo_object_mock.return_value properties = {'memory_mb': '512', 'local_gb': 10, 'cpus': '1', 'cpu_arch': 'x86_64'} macs = {'NIC.LOM.1.1': 'aa:aa:aa:aa:aa:aa'} capabilities = {'server_model': 'Gen10'} result = {'properties': properties, 'macs': macs} get_essential_mock.return_value = result get_capabilities_mock.return_value = capabilities power_mock.return_value = states.POWER_ON with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: expected_properties = {'memory_mb': '512', 'local_gb': 10, 'cpus': '1', 'cpu_arch': 'x86_64', 'capabilities': 'server_model:Gen10'} task.driver.inspect.inspect_hardware(task) self.assertEqual(expected_properties, task.node.properties) power_mock.assert_called_once_with(mock.ANY, task) get_essential_mock.assert_called_once_with(task.node, ilo_object_mock) self.assertFalse(log_mock.called) get_capabilities_mock.assert_called_once_with(task.node, ilo_object_mock) create_port_mock.assert_called_once_with(task, macs) @mock.patch.object(ilo_inspect, '_get_capabilities', spec_set=True, autospec=True) @mock.patch.object(inspect_utils, 'create_ports_if_not_exist', spec_set=True, autospec=True) @mock.patch.object(ilo_inspect, '_get_essential_properties', spec_set=True, autospec=True) @mock.patch.object(conductor_utils, 'node_power_action', spec_set=True, autospec=True) @mock.patch.object(ilo_power.IloPower, 'get_power_state', spec_set=True, autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, autospec=True) def test_inspect_essential_ok_power_off(self, get_ilo_object_mock, power_mock, set_power_mock, get_essential_mock, create_port_mock, get_capabilities_mock): ilo_object_mock = get_ilo_object_mock.return_value properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1', 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} capabilities = {} result = {'properties': properties, 'macs': macs} get_essential_mock.return_value = result get_capabilities_mock.return_value = capabilities power_mock.return_value = states.POWER_OFF with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: task.driver.inspect.inspect_hardware(task) self.assertEqual(properties, task.node.properties) power_mock.assert_called_once_with(mock.ANY, task) set_power_mock.assert_any_call(task, states.POWER_ON) get_essential_mock.assert_called_once_with(task.node, ilo_object_mock) get_capabilities_mock.assert_called_once_with(task.node, ilo_object_mock) create_port_mock.assert_called_once_with(task, macs) @mock.patch.object(ilo_inspect, '_get_capabilities', spec_set=True, autospec=True) @mock.patch.object(inspect_utils, 'create_ports_if_not_exist', spec_set=True, autospec=True) @mock.patch.object(ilo_inspect, '_get_essential_properties', spec_set=True, autospec=True) @mock.patch.object(ilo_power.IloPower, 'get_power_state', spec_set=True, autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, autospec=True) def test_inspect_essential_capabilities_ok(self, get_ilo_object_mock, power_mock, get_essential_mock, create_port_mock, get_capabilities_mock): ilo_object_mock = get_ilo_object_mock.return_value properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1', 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} capability_str = 'sriov_enabled:true' capabilities = {'sriov_enabled': 'true'} result = {'properties': properties, 'macs': macs} get_essential_mock.return_value = result get_capabilities_mock.return_value = capabilities power_mock.return_value = states.POWER_ON with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: task.driver.inspect.inspect_hardware(task) expected_properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1', 'cpu_arch': 'x86_64', 'capabilities': capability_str} self.assertEqual(expected_properties, task.node.properties) power_mock.assert_called_once_with(mock.ANY, task) get_essential_mock.assert_called_once_with(task.node, ilo_object_mock) get_capabilities_mock.assert_called_once_with(task.node, ilo_object_mock) create_port_mock.assert_called_once_with(task, macs) @mock.patch.object(ilo_inspect, '_get_capabilities', spec_set=True, autospec=True) @mock.patch.object(inspect_utils, 'create_ports_if_not_exist', spec_set=True, autospec=True) @mock.patch.object(ilo_inspect, '_get_essential_properties', spec_set=True, autospec=True) @mock.patch.object(ilo_power.IloPower, 'get_power_state', spec_set=True, autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, autospec=True) def test_inspect_essential_capabilities_exist_ok(self, get_ilo_object_mock, power_mock, get_essential_mock, create_port_mock, get_capabilities_mock): ilo_object_mock = get_ilo_object_mock.return_value properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1', 'cpu_arch': 'x86_64', 'somekey': 'somevalue'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} result = {'properties': properties, 'macs': macs} capabilities = {'sriov_enabled': 'true'} get_essential_mock.return_value = result get_capabilities_mock.return_value = capabilities power_mock.return_value = states.POWER_ON with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: task.node.properties = {'capabilities': 'boot_mode:uefi'} expected_capabilities = ('sriov_enabled:true,' 'boot_mode:uefi') set1 = set(expected_capabilities.split(',')) task.driver.inspect.inspect_hardware(task) end_capabilities = task.node.properties['capabilities'] set2 = set(end_capabilities.split(',')) self.assertEqual(set1, set2) expected_properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1', 'cpu_arch': 'x86_64', 'capabilities': end_capabilities} power_mock.assert_called_once_with(mock.ANY, task) self.assertEqual(task.node.properties, expected_properties) get_essential_mock.assert_called_once_with(task.node, ilo_object_mock) get_capabilities_mock.assert_called_once_with(task.node, ilo_object_mock) create_port_mock.assert_called_once_with(task, macs) class TestInspectPrivateMethods(test_common.BaseIloTest): def test__get_essential_properties_ok(self): ilo_mock = mock.MagicMock(spec=['get_essential_properties']) properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1', 'cpu_arch': 'x86_64'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} result = {'properties': properties, 'macs': macs} ilo_mock.get_essential_properties.return_value = result actual_result = ilo_inspect._get_essential_properties(self.node, ilo_mock) self.assertEqual(result, actual_result) def test__get_essential_properties_fail(self): ilo_mock = mock.MagicMock( spec=['get_additional_capabilities', 'get_essential_properties']) # Missing key: cpu_arch properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa', 'Port 2': 'bb:bb:bb:bb:bb:bb'} result = {'properties': properties, 'macs': macs} ilo_mock.get_essential_properties.return_value = result result = self.assertRaises(exception.HardwareInspectionFailure, ilo_inspect._get_essential_properties, self.node, ilo_mock) self.assertEqual( str(result), ("Failed to inspect hardware. Reason: Server didn't return the " "key(s): cpu_arch")) def test__get_essential_properties_fail_invalid_format(self): ilo_mock = mock.MagicMock( spec=['get_additional_capabilities', 'get_essential_properties']) # Not a dict properties = ['memory_mb', '512', 'local_gb', '10', 'cpus', '1'] macs = ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb'] capabilities = '' result = {'properties': properties, 'macs': macs} ilo_mock.get_essential_properties.return_value = result ilo_mock.get_additional_capabilities.return_value = capabilities self.assertRaises(exception.HardwareInspectionFailure, ilo_inspect._get_essential_properties, self.node, ilo_mock) def test__get_essential_properties_fail_mac_invalid_format(self): ilo_mock = mock.MagicMock(spec=['get_essential_properties']) properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1', 'cpu_arch': 'x86_64'} # Not a dict macs = 'aa:aa:aa:aa:aa:aa' result = {'properties': properties, 'macs': macs} ilo_mock.get_essential_properties.return_value = result self.assertRaises(exception.HardwareInspectionFailure, ilo_inspect._get_essential_properties, self.node, ilo_mock) def test__get_essential_properties_hardware_port_empty(self): ilo_mock = mock.MagicMock( spec=['get_additional_capabilities', 'get_essential_properties']) properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1', 'cpu_arch': 'x86_64'} # Not a dictionary macs = None result = {'properties': properties, 'macs': macs} capabilities = '' ilo_mock.get_essential_properties.return_value = result ilo_mock.get_additional_capabilities.return_value = capabilities self.assertRaises(exception.HardwareInspectionFailure, ilo_inspect._get_essential_properties, self.node, ilo_mock) def test__get_essential_properties_hardware_port_not_dict(self): ilo_mock = mock.MagicMock(spec=['get_essential_properties']) properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1', 'cpu_arch': 'x86_64'} # Not a dict macs = 'aa:bb:cc:dd:ee:ff' result = {'properties': properties, 'macs': macs} ilo_mock.get_essential_properties.return_value = result result = self.assertRaises( exception.HardwareInspectionFailure, ilo_inspect._get_essential_properties, self.node, ilo_mock) @mock.patch.object(utils, 'get_updated_capabilities', spec_set=True, autospec=True) def test__get_capabilities_ok(self, capability_mock): ilo_mock = mock.MagicMock(spec=['get_server_capabilities']) capabilities = {'ilo_firmware_version': 'xyz'} ilo_mock.get_server_capabilities.return_value = capabilities cap = ilo_inspect._get_capabilities(self.node, ilo_mock) self.assertEqual(cap, capabilities) def test__validate_ok(self): properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '2', 'cpu_arch': 'x86_arch'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa'} data = {'properties': properties, 'macs': macs} valid_keys = ilo_inspect.IloInspect.ESSENTIAL_PROPERTIES ilo_inspect._validate(self.node, data) self.assertEqual(sorted(set(properties)), sorted(valid_keys)) def test__validate_essential_keys_fail_missing_key(self): properties = {'memory_mb': '512', 'local_gb': '10', 'cpus': '1'} macs = {'Port 1': 'aa:aa:aa:aa:aa:aa'} data = {'properties': properties, 'macs': macs} self.assertRaises(exception.HardwareInspectionFailure, ilo_inspect._validate, self.node, data) def test___create_supported_capabilities_dict(self): capabilities = {} expected = {} for key in ilo_inspect.CAPABILITIES_KEYS: capabilities.update({key: 'true'}) expected.update({key: 'true'}) capabilities.update({'unknown_property': 'true'}) cap = ilo_inspect._create_supported_capabilities_dict(capabilities) self.assertEqual(expected, cap) def test___create_supported_capabilities_dict_excluded_capability(self): capabilities = {} expected = {} for key in ilo_inspect.CAPABILITIES_KEYS - {'has_ssd'}: capabilities.update({key: 'true'}) expected.update({key: 'true'}) cap = ilo_inspect._create_supported_capabilities_dict(capabilities) self.assertEqual(expected, cap)