# 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.""" from unittest 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, ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']) @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, ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']) @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, ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']) @mock.patch.object(ilo_inspect.LOG, 'warning', spec_set=True, autospec=True) @mock.patch.object(ilo_inspect, '_get_security_parameters', 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, get_security_params_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'} security_params = ( {'security_parameters': {'Password Complexity': 'ok'}}) result = {'properties': properties, 'macs': macs} get_essential_mock.return_value = result get_capabilities_mock.return_value = capabilities get_security_params_mock.return_value = security_params 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', 'security_parameters': {'Password Complexity': 'ok'}} 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, ['aa:aa:aa:aa:aa:aa']) @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, ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']) @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, ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']) @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, ['aa:aa:aa:aa:aa:aa', 'bb:bb:bb:bb:bb:bb']) 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) def test___create_supported_capabilities_dict_gpu_capabilities(self): capabilities = {'gpu_Nvidia_count': 1, 'gpu_Nvidia_Tesla_M10_count': 1, 'gpu_Nvidia_Tesla_M10': True} expected = {} expected.update(capabilities) 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)