Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:15-SP2
salt.12957
fix-virt.full_info-176.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File fix-virt.full_info-176.patch of Package salt.12957
From 4ce0bc544174fdb00482db4653fb4b0ef411e78b Mon Sep 17 00:00:00 2001 From: Cedric Bosdonnat <cbosdonnat@suse.com> Date: Tue, 3 Sep 2019 15:18:04 +0200 Subject: [PATCH] Fix virt.full_info (#176) * virt.get_xml doesn't take a domain object In some places in the virt module, the get_xml function was called with a domain object, leading to runtime errors like the following one: 'ERROR: The VM "<libvirt.virDomain object at 0x7fad04208650>" is not present' * qemu-img info needs -U flag on running VMs When getting VM disks informations on a running VM, the following error occured: The minion function caused an exception: Traceback (most recent call last): File "/usr/lib/python3.6/site-packages/salt/minion.py", line 1673, in _thread_return return_data = minion_instance.executors[fname](opts, data, func, args, kwargs) File "/usr/lib/python3.6/site-packages/salt/executors/direct_call.py", line 12, in execute return func(*args, **kwargs) File "/usr/lib/python3.6/site-packages/salt/modules/virt.py", line 2411, in full_info 'vm_info': vm_info()} File "/usr/lib/python3.6/site-packages/salt/modules/virt.py", line 2020, in vm_info info[domain.name()] = _info(domain) File "/usr/lib/python3.6/site-packages/salt/modules/virt.py", line 2004, in _info 'disks': _get_disks(dom), File "/usr/lib/python3.6/site-packages/salt/modules/virt.py", line 465, in _get_disks output = _parse_qemu_img_info(qemu_output) File "/usr/lib/python3.6/site-packages/salt/modules/virt.py", line 287, in _parse_qemu_img_info raw_infos = salt.utils.json.loads(info) File "/usr/lib/python3.6/site-packages/salt/utils/json.py", line 92, in loads return json_module.loads(s, **kwargs) File "/usr/lib64/python3.6/json/__init__.py", line 354, in loads return _default_decoder.decode(s) File "/usr/lib64/python3.6/json/decoder.py", line 339, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/lib64/python3.6/json/decoder.py", line 357, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) This is due to the fact that qemu-img can't get infos on a disk that is already used like by a running VM. Using the qemu-img -U flag gets it running in all cases. --- salt/modules/virt.py | 10 +- tests/unit/modules/test_virt.py | 242 +++++++++++++++++--------------- 2 files changed, 132 insertions(+), 120 deletions(-) diff --git a/salt/modules/virt.py b/salt/modules/virt.py index 96c17bd60b..d01b6c3f1e 100644 --- a/salt/modules/virt.py +++ b/salt/modules/virt.py @@ -331,7 +331,7 @@ def _get_uuid(dom): salt '*' virt.get_uuid <domain> ''' - return ElementTree.fromstring(get_xml(dom)).find('uuid').text + return ElementTree.fromstring(dom.XMLDesc(0)).find('uuid').text def _get_on_poweroff(dom): @@ -344,7 +344,7 @@ def _get_on_poweroff(dom): salt '*' virt.get_on_restart <domain> ''' - node = ElementTree.fromstring(get_xml(dom)).find('on_poweroff') + node = ElementTree.fromstring(dom.XMLDesc(0)).find('on_poweroff') return node.text if node is not None else '' @@ -358,7 +358,7 @@ def _get_on_reboot(dom): salt '*' virt.get_on_reboot <domain> ''' - node = ElementTree.fromstring(get_xml(dom)).find('on_reboot') + node = ElementTree.fromstring(dom.XMLDesc(0)).find('on_reboot') return node.text if node is not None else '' @@ -372,7 +372,7 @@ def _get_on_crash(dom): salt '*' virt.get_on_crash <domain> ''' - node = ElementTree.fromstring(get_xml(dom)).find('on_crash') + node = ElementTree.fromstring(dom.XMLDesc(0)).find('on_crash') return node.text if node is not None else '' @@ -458,7 +458,7 @@ def _get_disks(dom): if driver is not None and driver.get('type') == 'qcow2': try: stdout = subprocess.Popen( - ['qemu-img', 'info', '--output', 'json', '--backing-chain', disk['file']], + ['qemu-img', 'info', '-U', '--output', 'json', '--backing-chain', disk['file']], shell=False, stdout=subprocess.PIPE).communicate()[0] qemu_output = salt.utils.stringutils.to_str(stdout) diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py index e644e62452..4d20e998d8 100644 --- a/tests/unit/modules/test_virt.py +++ b/tests/unit/modules/test_virt.py @@ -81,7 +81,9 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin): mock_domain.XMLDesc.return_value = xml # pylint: disable=no-member # Return state as shutdown - mock_domain.info.return_value = [4, 0, 0, 0] # pylint: disable=no-member + mock_domain.info.return_value = [4, 2048 * 1024, 1024 * 1024, 2, 1234] # pylint: disable=no-member + mock_domain.ID.return_value = 1 + mock_domain.name.return_value = name return mock_domain def test_disk_profile_merge(self): @@ -1394,49 +1396,6 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin): re.match('^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$', interface_attrs['mac'], re.I)) - def test_get_graphics(self): - ''' - Test virt.get_graphics() - ''' - xml = '''<domain type='kvm' id='7'> - <name>test-vm</name> - <devices> - <graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'> - <listen type='address' address='0.0.0.0'/> - </graphics> - </devices> - </domain> - ''' - self.set_mock_vm("test-vm", xml) - - graphics = virt.get_graphics('test-vm') - self.assertEqual('vnc', graphics['type']) - self.assertEqual('5900', graphics['port']) - self.assertEqual('0.0.0.0', graphics['listen']) - - def test_get_nics(self): - ''' - Test virt.get_nics() - ''' - xml = '''<domain type='kvm' id='7'> - <name>test-vm</name> - <devices> - <interface type='bridge'> - <mac address='ac:de:48:b6:8b:59'/> - <source bridge='br0'/> - <model type='virtio'/> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> - </interface> - </devices> - </domain> - ''' - self.set_mock_vm("test-vm", xml) - - nics = virt.get_nics('test-vm') - nic = nics[list(nics)[0]] - self.assertEqual('bridge', nic['type']) - self.assertEqual('ac:de:48:b6:8b:59', nic['mac']) - def test_parse_qemu_img_info(self): ''' Make sure that qemu-img info output is properly parsed @@ -1558,77 +1517,6 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin): ], }, virt._parse_qemu_img_info(qemu_infos)) - def test_get_disks(self): - ''' - Test virt.get_disks() - ''' - xml = '''<domain type='kvm' id='7'> - <name>test-vm</name> - <devices> - <disk type='file' device='disk'> - <driver name='qemu' type='qcow2'/> - <source file='/disks/test.qcow2'/> - <target dev='vda' bus='virtio'/> - </disk> - <disk type='file' device='cdrom'> - <driver name='qemu' type='raw'/> - <source file='/disks/test-cdrom.iso'/> - <target dev='hda' bus='ide'/> - <readonly/> - </disk> - </devices> - </domain> - ''' - self.set_mock_vm("test-vm", xml) - - qemu_infos = '''[{ - "virtual-size": 25769803776, - "filename": "/disks/test.qcow2", - "cluster-size": 65536, - "format": "qcow2", - "actual-size": 217088, - "format-specific": { - "type": "qcow2", - "data": { - "compat": "1.1", - "lazy-refcounts": false, - "refcount-bits": 16, - "corrupt": false - } - }, - "full-backing-filename": "/disks/mybacking.qcow2", - "backing-filename": "mybacking.qcow2", - "dirty-flag": false - }, - { - "virtual-size": 25769803776, - "filename": "/disks/mybacking.qcow2", - "cluster-size": 65536, - "format": "qcow2", - "actual-size": 393744384, - "format-specific": { - "type": "qcow2", - "data": { - "compat": "1.1", - "lazy-refcounts": false, - "refcount-bits": 16, - "corrupt": false - } - }, - "dirty-flag": false - }]''' - - self.mock_popen.communicate.return_value = [qemu_infos] # pylint: disable=no-member - disks = virt.get_disks('test-vm') - disk = disks.get('vda') - self.assertEqual('/disks/test.qcow2', disk['file']) - self.assertEqual('disk', disk['type']) - self.assertEqual('/disks/mybacking.qcow2', disk['backing file']['file']) - cdrom = disks.get('hda') - self.assertEqual('/disks/test-cdrom.iso', cdrom['file']) - self.assertEqual('cdrom', cdrom['type']) - self.assertFalse('backing file' in cdrom.keys()) - @patch('salt.modules.virt.stop', return_value=True) @patch('salt.modules.virt.undefine') @patch('os.remove') @@ -2994,3 +2882,127 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin): virt.volume_delete('default', 'missing') virt.volume_delete('missing', 'test_volume') self.assertEqual(mock_delete.call_count, 2) + + def test_full_info(self): + ''' + Test virt.full_info + ''' + xml = '''<domain type='kvm' id='7'> + <uuid>28deee33-4859-4f23-891c-ee239cffec94</uuid> + <name>test-vm</name> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/disks/test.qcow2'/> + <target dev='vda' bus='virtio'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/disks/test-cdrom.iso'/> + <target dev='hda' bus='ide'/> + <readonly/> + </disk> + <interface type='bridge'> + <mac address='ac:de:48:b6:8b:59'/> + <source bridge='br0'/> + <model type='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </interface> + <graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'> + <listen type='address' address='0.0.0.0'/> + </graphics> + </devices> + </domain> + ''' + self.set_mock_vm("test-vm", xml) + + qemu_infos = '''[{ + "virtual-size": 25769803776, + "filename": "/disks/test.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": 217088, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "refcount-bits": 16, + "corrupt": false + } + }, + "full-backing-filename": "/disks/mybacking.qcow2", + "backing-filename": "mybacking.qcow2", + "dirty-flag": false + }, + { + "virtual-size": 25769803776, + "filename": "/disks/mybacking.qcow2", + "cluster-size": 65536, + "format": "qcow2", + "actual-size": 393744384, + "format-specific": { + "type": "qcow2", + "data": { + "compat": "1.1", + "lazy-refcounts": false, + "refcount-bits": 16, + "corrupt": false + } + }, + "dirty-flag": false + }]''' + + self.mock_popen.communicate.return_value = [qemu_infos] # pylint: disable=no-member + + self.mock_conn.getInfo = MagicMock(return_value=['x86_64', 4096, 8, 2712, 1, 2, 4, 2]) + + actual = virt.full_info() + + # Test the hypervisor infos + self.assertEqual(2816, actual['freemem']) + self.assertEqual(6, actual['freecpu']) + self.assertEqual(4, actual['node_info']['cpucores']) + self.assertEqual(2712, actual['node_info']['cpumhz']) + self.assertEqual('x86_64', actual['node_info']['cpumodel']) + self.assertEqual(8, actual['node_info']['cpus']) + self.assertEqual(2, actual['node_info']['cputhreads']) + self.assertEqual(1, actual['node_info']['numanodes']) + self.assertEqual(4096, actual['node_info']['phymemory']) + self.assertEqual(2, actual['node_info']['sockets']) + + # Test the vm_info output: + self.assertEqual(2, actual['vm_info']['test-vm']['cpu']) + self.assertEqual(1234, actual['vm_info']['test-vm']['cputime']) + self.assertEqual(1024 * 1024, actual['vm_info']['test-vm']['mem']) + self.assertEqual(2048 * 1024, actual['vm_info']['test-vm']['maxMem']) + self.assertEqual('shutdown', actual['vm_info']['test-vm']['state']) + self.assertEqual('28deee33-4859-4f23-891c-ee239cffec94', actual['vm_info']['test-vm']['uuid']) + self.assertEqual('destroy', actual['vm_info']['test-vm']['on_crash']) + self.assertEqual('restart', actual['vm_info']['test-vm']['on_reboot']) + self.assertEqual('destroy', actual['vm_info']['test-vm']['on_poweroff']) + + # Test the nics + nic = actual['vm_info']['test-vm']['nics']['ac:de:48:b6:8b:59'] + self.assertEqual('bridge', nic['type']) + self.assertEqual('ac:de:48:b6:8b:59', nic['mac']) + + # Test the disks + disks = actual['vm_info']['test-vm']['disks'] + disk = disks.get('vda') + self.assertEqual('/disks/test.qcow2', disk['file']) + self.assertEqual('disk', disk['type']) + self.assertEqual('/disks/mybacking.qcow2', disk['backing file']['file']) + cdrom = disks.get('hda') + self.assertEqual('/disks/test-cdrom.iso', cdrom['file']) + self.assertEqual('cdrom', cdrom['type']) + self.assertFalse('backing file' in cdrom.keys()) + + # Test the graphics + graphics = actual['vm_info']['test-vm']['graphics'] + self.assertEqual('vnc', graphics['type']) + self.assertEqual('5900', graphics['port']) + self.assertEqual('0.0.0.0', graphics['listen']) -- 2.20.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor