# 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. import libvirt from oslotest import base from six.moves import mock from sushy_tools.emulator.drivers.libvirtdriver import LibvirtDriver from sushy_tools.emulator import main from sushy_tools.error import FishyError @mock.patch.object(main, 'driver', None) # This enables libvirt driver class EmulatorTestCase(base.BaseTestCase): def setUp(self): self.app = main.app.test_client() self.test_driver = LibvirtDriver() super(EmulatorTestCase, self).setUp() def test_root_resource(self): response = self.app.get('/redfish/v1/') self.assertEqual(200, response.status_code) self.assertTrue(response.json) @mock.patch('libvirt.openReadOnly', autospec=True) def test_collection_resource(self, libvirt_mock): conn_mock = libvirt_mock.return_value conn_mock.listDefinedDomains.return_value = ['host0', 'host1'] response = self.app.get('/redfish/v1/Systems') self.assertEqual(200, response.status_code) self.assertEqual({'@odata.id': '/redfish/v1/Systems/host0'}, response.json['Members'][0]) self.assertEqual({'@odata.id': '/redfish/v1/Systems/host1'}, response.json['Members'][1]) @mock.patch('libvirt.openReadOnly', autospec=True) def test_system_resource_get(self, libvirt_mock): with open('sushy_tools/tests/unit/emulator/domain.xml', 'r') as f: data = f.read() domain_mock = mock.Mock() domain_mock.XMLDesc.return_value = data domain_mock.isActive.return_value = True domain_mock.maxMemory.return_value = 1024 * 1024 domain_mock.UUIDString.return_value = 'zzzz-yyyy-xxxx' domain_mock.maxVcpus.return_value = 2 conn_mock = libvirt_mock.return_value conn_mock.lookupByName.return_value = domain_mock response = self.app.get('/redfish/v1/Systems/xxxx-yyyy-zzzz') self.assertEqual(200, response.status_code) self.assertEqual('xxxx-yyyy-zzzz', response.json['Id']) self.assertEqual('zzzz-yyyy-xxxx', response.json['UUID']) self.assertEqual('On', response.json['PowerState']) self.assertEqual( 1, response.json['MemorySummary']['TotalSystemMemoryGiB']) self.assertEqual(2, response.json['ProcessorSummary']['Count']) self.assertEqual( 'Cd', response.json['Boot']['BootSourceOverrideTarget']) self.assertEqual( 'Legacy', response.json['Boot']['BootSourceOverrideMode']) @mock.patch('libvirt.open', autospec=True) def test_system_resource_patch(self, libvirt_mock): with open('sushy_tools/tests/unit/emulator/domain.xml', 'r') as f: data = f.read() domain_mock = mock.Mock() domain_mock.XMLDesc.return_value = data conn_mock = libvirt_mock.return_value conn_mock.lookupByName.return_value = domain_mock conn_mock.defineXML = mock.Mock() data = {'Boot': {'BootSourceOverrideTarget': 'Cd'}} response = self.app.patch('/redfish/v1/Systems/xxxx-yyyy-zzzz', json=data) self.assertEqual(204, response.status_code) @mock.patch('libvirt.open', autospec=True) def test_system_reset_action_on(self, libvirt_mock): domain_mock = mock.Mock() domain_mock.isActive.return_value = True conn_mock = libvirt_mock.return_value conn_mock.lookupByName.return_value = domain_mock data = {'ResetType': 'On'} response = self.app.post( '/redfish/v1/Systems/xxxx-yyyy-zzzz/Actions/ComputerSystem.Reset', json=data) self.assertEqual(204, response.status_code) domain_mock.create.assert_not_called() @mock.patch('libvirt.open', autospec=True) def test_system_reset_action_forceon(self, libvirt_mock): domain_mock = mock.Mock() domain_mock.isActive.return_value = True conn_mock = libvirt_mock.return_value conn_mock.lookupByName.return_value = domain_mock data = {'ResetType': 'ForceOn'} response = self.app.post( '/redfish/v1/Systems/xxxx-yyyy-zzzz/Actions/ComputerSystem.Reset', json=data) self.assertEqual(204, response.status_code) domain_mock.create.assert_not_called() @mock.patch('libvirt.open', autospec=True) def test_system_reset_action_forceoff(self, libvirt_mock): domain_mock = mock.Mock() domain_mock.isActive.return_value = True conn_mock = libvirt_mock.return_value conn_mock.lookupByName.return_value = domain_mock data = {'ResetType': 'ForceOff'} response = self.app.post( '/redfish/v1/Systems/xxxx-yyyy-zzzz/Actions/ComputerSystem.Reset', json=data) self.assertEqual(204, response.status_code) domain_mock.destroy.assert_called_once_with() @mock.patch('libvirt.open', autospec=True) def test_system_reset_action_shutdown(self, libvirt_mock): domain_mock = mock.Mock() domain_mock.isActive.return_value = True conn_mock = libvirt_mock.return_value conn_mock.lookupByName.return_value = domain_mock data = {'ResetType': 'GracefulShutdown'} response = self.app.post( '/redfish/v1/Systems/xxxx-yyyy-zzzz/Actions/ComputerSystem.Reset', json=data) self.assertEqual(204, response.status_code) domain_mock.shutdown.assert_called_once_with() @mock.patch('libvirt.open', autospec=True) def test_system_reset_action_restart(self, libvirt_mock): domain_mock = mock.Mock() domain_mock.isActive.return_value = True conn_mock = libvirt_mock.return_value conn_mock.lookupByName.return_value = domain_mock data = {'ResetType': 'GracefulRestart'} response = self.app.post( '/redfish/v1/Systems/xxxx-yyyy-zzzz/Actions/ComputerSystem.Reset', json=data) self.assertEqual(204, response.status_code) domain_mock.reboot.assert_called_once_with() @mock.patch('libvirt.open', autospec=True) def test_system_reset_action_forcerestart(self, libvirt_mock): domain_mock = mock.Mock() domain_mock.isActive.return_value = True conn_mock = libvirt_mock.return_value conn_mock.lookupByName.return_value = domain_mock data = {'ResetType': 'ForceRestart'} response = self.app.post( '/redfish/v1/Systems/xxxx-yyyy-zzzz/Actions/ComputerSystem.Reset', json=data) self.assertEqual(204, response.status_code) domain_mock.reset.assert_called_once_with() @mock.patch('libvirt.open', autospec=True) def test_system_reset_action_nmi(self, libvirt_mock): domain_mock = mock.Mock() domain_mock.isActive.return_value = True conn_mock = libvirt_mock.return_value conn_mock.lookupByName.return_value = domain_mock data = {'ResetType': 'Nmi'} response = self.app.post( '/redfish/v1/Systems/xxxx-yyyy-zzzz/Actions/ComputerSystem.Reset', json=data) self.assertEqual(204, response.status_code) domain_mock.injectNMI.assert_called_once_with() @mock.patch('libvirt.open', autospec=True) def test_get_bios(self, libvirt_mock): with open('sushy_tools/tests/unit/emulator/domain.xml') as f: domain_xml = f.read() conn_mock = libvirt_mock.return_value domain_mock = conn_mock.lookupByName.return_value domain_mock.XMLDesc.return_value = domain_xml bios_attributes = self.test_driver.get_bios('xxx-yyy-zzz') self.assertEqual(LibvirtDriver.DEFAULT_BIOS_ATTRIBUTES, bios_attributes) self.assertEqual(1, conn_mock.defineXML.call_count) @mock.patch('libvirt.open', autospec=True) def test_get_bios_existing(self, libvirt_mock): with open('sushy_tools/tests/unit/emulator/domain_bios.xml') as f: domain_xml = f.read() conn_mock = libvirt_mock.return_value domain_mock = conn_mock.lookupByName.return_value domain_mock.XMLDesc.return_value = domain_xml bios_attributes = self.test_driver.get_bios('xxx-yyy-zzz') self.assertEqual({"BootMode": "Bios", "EmbeddedSata": "Raid", "NicBoot1": "NetworkBoot", "ProcTurboMode": "Disabled"}, bios_attributes) conn_mock.defineXML.assert_not_called() @mock.patch('libvirt.open', autospec=True) def test_set_bios(self, libvirt_mock): with open('sushy_tools/tests/unit/emulator/domain_bios.xml') as f: domain_xml = f.read() conn_mock = libvirt_mock.return_value domain_mock = conn_mock.lookupByName.return_value domain_mock.XMLDesc.return_value = domain_xml self.test_driver.set_bios('xxx-yyy-zzz', {"BootMode": "Uefi", "ProcTurboMode": "Enabled"}) self.assertEqual(1, conn_mock.defineXML.call_count) @mock.patch('libvirt.open', autospec=True) def test_reset_bios(self, libvirt_mock): with open('sushy_tools/tests/unit/emulator/domain_bios.xml') as f: domain_xml = f.read() conn_mock = libvirt_mock.return_value domain_mock = conn_mock.lookupByName.return_value domain_mock.XMLDesc.return_value = domain_xml self.test_driver.reset_bios('xxx-yyy-zzz') self.assertEqual(1, conn_mock.defineXML.call_count) def test__process_bios_attributes_get_default(self): with open('sushy_tools/tests/unit/emulator/domain.xml') as f: domain_xml = f.read() result = self.test_driver._process_bios_attributes(domain_xml) self.assertTrue(result.attributes_written) self.assertEqual(LibvirtDriver.DEFAULT_BIOS_ATTRIBUTES, result.bios_attributes) self._assert_bios_xml(result.tree) def test__process_bios_attributes_get_default_metadata_exists(self): with open('sushy_tools/tests/unit/emulator/' 'domain_metadata.xml') as f: domain_xml = f.read() result = self.test_driver._process_bios_attributes(domain_xml) self.assertTrue(result.attributes_written) self.assertEqual(LibvirtDriver.DEFAULT_BIOS_ATTRIBUTES, result.bios_attributes) self._assert_bios_xml(result.tree) def test__process_bios_attributes_get_existing(self): with open('sushy_tools/tests/unit/emulator/domain_bios.xml') as f: domain_xml = f.read() result = self.test_driver._process_bios_attributes(domain_xml) self.assertFalse(result.attributes_written) self.assertEqual({"BootMode": "Bios", "EmbeddedSata": "Raid", "NicBoot1": "NetworkBoot", "ProcTurboMode": "Disabled"}, result.bios_attributes) self._assert_bios_xml(result.tree) def test__process_bios_attributes_update(self): with open('sushy_tools/tests/unit/emulator/domain_bios.xml') as f: domain_xml = f.read() result = self.test_driver._process_bios_attributes( domain_xml, {"BootMode": "Uefi", "ProcTurboMode": "Enabled"}, True) self.assertTrue(result.attributes_written) self.assertEqual({"BootMode": "Uefi", "ProcTurboMode": "Enabled"}, result.bios_attributes) self._assert_bios_xml(result.tree) def _assert_bios_xml(self, tree): ns = {'sushy': 'http://openstack.org/xmlns/libvirt/sushy'} self.assertIsNotNone(tree.find('metadata') .find('sushy:bios', ns) .find('sushy:attributes', ns)) @mock.patch('libvirt.open', autospec=True) def test__process_bios_error(self, libvirt_mock): with open('sushy_tools/tests/unit/emulator/domain.xml') as f: domain_xml = f.read() conn_mock = libvirt_mock.return_value domain_mock = conn_mock.lookupByName.return_value domain_mock.XMLDesc.return_value = domain_xml conn_mock.defineXML.side_effect = libvirt.libvirtError( 'because I can') self.assertRaises(FishyError, self.test_driver._process_bios, 'xxx-yyy-zzz', {"BootMode": "Uefi", "ProcTurboMode": "Enabled"}) @mock.patch('libvirt.openReadOnly', autospec=True) def test_get_nics(self, libvirt_mock): with open('sushy_tools/tests/unit/emulator/domain_nics.xml') as f: domain_xml = f.read() conn_mock = libvirt_mock.return_value domain_mock = conn_mock.lookupByName.return_value domain_mock.XMLDesc.return_value = domain_xml nics = self.test_driver.get_nics('xxx-yyy-zzz') self.assertEqual([{'id': '00:11:22:33:44:55', 'mac': '00:11:22:33:44:55'}, {'id': '52:54:00:4e:5d:37', 'mac': '52:54:00:4e:5d:37'}], sorted(nics, key=lambda k: k['id'])) @mock.patch('libvirt.openReadOnly', autospec=True) def test_get_nics_empty(self, libvirt_mock): with open('sushy_tools/tests/unit/emulator/domain.xml') as f: domain_xml = f.read() conn_mock = libvirt_mock.return_value domain_mock = conn_mock.lookupByName.return_value domain_mock.XMLDesc.return_value = domain_xml nics = self.test_driver.get_nics('xxx-yyy-zzz') self.assertEqual([], nics)