Skip to content

Commit d04f97a

Browse files
authored
Merge pull request saltstack#54335 from cbosdo/virt-full-info-fix
virt.full_info fixes
2 parents b47787b + f4ffd37 commit d04f97a

File tree

2 files changed

+137
-119
lines changed

2 files changed

+137
-119
lines changed

salt/modules/virt.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ def _get_disks(dom):
458458
if driver is not None and driver.get('type') == 'qcow2':
459459
try:
460460
stdout = subprocess.Popen(
461-
['qemu-img', 'info', '--output', 'json', '--backing-chain', disk['file']],
461+
['qemu-img', 'info', '-U', '--output', 'json', '--backing-chain', disk['file']],
462462
shell=False,
463463
stdout=subprocess.PIPE).communicate()[0]
464464
qemu_output = salt.utils.stringutils.to_str(stdout)

tests/unit/modules/test_virt.py

+136-118
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,16 @@ def setup_loader_modules(self):
6262
self.addCleanup(delattr, self, 'mock_libvirt')
6363
self.addCleanup(delattr, self, 'mock_conn')
6464
self.addCleanup(delattr, self, 'mock_popen')
65-
mock_subprocess = MagicMock()
66-
mock_subprocess.Popen.return_value = self.mock_popen # pylint: disable=no-member
65+
self.mock_subprocess = MagicMock()
66+
self.mock_subprocess.return_value = self.mock_subprocess # pylint: disable=no-member
67+
self.mock_subprocess.Popen.return_value = self.mock_popen # pylint: disable=no-member
6768
loader_globals = {
6869
'__salt__': {
6970
'config.get': config.get,
7071
'config.option': config.option,
7172
},
7273
'libvirt': self.mock_libvirt,
73-
'subprocess': mock_subprocess
74+
'subprocess': self.mock_subprocess
7475
}
7576
return {virt: loader_globals, config: loader_globals}
7677

@@ -84,7 +85,9 @@ def set_mock_vm(self, name, xml):
8485
mock_domain.XMLDesc.return_value = xml # pylint: disable=no-member
8586

8687
# Return state as shutdown
87-
mock_domain.info.return_value = [4, 0, 0, 0] # pylint: disable=no-member
88+
mock_domain.info.return_value = [4, 2048 * 1024, 1024 * 1024, 2, 1234] # pylint: disable=no-member
89+
mock_domain.ID.return_value = 1
90+
mock_domain.name.return_value = name
8891
return mock_domain
8992

9093
def test_disk_profile_merge(self):
@@ -1397,49 +1400,6 @@ def test_mixed_dict_and_list_as_profile_objects(self):
13971400
re.match('^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$',
13981401
interface_attrs['mac'], re.I))
13991402

1400-
def test_get_graphics(self):
1401-
'''
1402-
Test virt.get_graphics()
1403-
'''
1404-
xml = '''<domain type='kvm' id='7'>
1405-
<name>test-vm</name>
1406-
<devices>
1407-
<graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'>
1408-
<listen type='address' address='0.0.0.0'/>
1409-
</graphics>
1410-
</devices>
1411-
</domain>
1412-
'''
1413-
self.set_mock_vm("test-vm", xml)
1414-
1415-
graphics = virt.get_graphics('test-vm')
1416-
self.assertEqual('vnc', graphics['type'])
1417-
self.assertEqual('5900', graphics['port'])
1418-
self.assertEqual('0.0.0.0', graphics['listen'])
1419-
1420-
def test_get_nics(self):
1421-
'''
1422-
Test virt.get_nics()
1423-
'''
1424-
xml = '''<domain type='kvm' id='7'>
1425-
<name>test-vm</name>
1426-
<devices>
1427-
<interface type='bridge'>
1428-
<mac address='ac:de:48:b6:8b:59'/>
1429-
<source bridge='br0'/>
1430-
<model type='virtio'/>
1431-
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
1432-
</interface>
1433-
</devices>
1434-
</domain>
1435-
'''
1436-
self.set_mock_vm("test-vm", xml)
1437-
1438-
nics = virt.get_nics('test-vm')
1439-
nic = nics[list(nics)[0]]
1440-
self.assertEqual('bridge', nic['type'])
1441-
self.assertEqual('ac:de:48:b6:8b:59', nic['mac'])
1442-
14431403
def test_get_xml(self):
14441404
'''
14451405
Test virt.get_xml()
@@ -1578,77 +1538,6 @@ def test_parse_qemu_img_info(self):
15781538
],
15791539
}, virt._parse_qemu_img_info(qemu_infos))
15801540

1581-
def test_get_disks(self):
1582-
'''
1583-
Test virt.get_disks()
1584-
'''
1585-
xml = '''<domain type='kvm' id='7'>
1586-
<name>test-vm</name>
1587-
<devices>
1588-
<disk type='file' device='disk'>
1589-
<driver name='qemu' type='qcow2'/>
1590-
<source file='/disks/test.qcow2'/>
1591-
<target dev='vda' bus='virtio'/>
1592-
</disk>
1593-
<disk type='file' device='cdrom'>
1594-
<driver name='qemu' type='raw'/>
1595-
<source file='/disks/test-cdrom.iso'/>
1596-
<target dev='hda' bus='ide'/>
1597-
<readonly/>
1598-
</disk>
1599-
</devices>
1600-
</domain>
1601-
'''
1602-
self.set_mock_vm("test-vm", xml)
1603-
1604-
qemu_infos = '''[{
1605-
"virtual-size": 25769803776,
1606-
"filename": "/disks/test.qcow2",
1607-
"cluster-size": 65536,
1608-
"format": "qcow2",
1609-
"actual-size": 217088,
1610-
"format-specific": {
1611-
"type": "qcow2",
1612-
"data": {
1613-
"compat": "1.1",
1614-
"lazy-refcounts": false,
1615-
"refcount-bits": 16,
1616-
"corrupt": false
1617-
}
1618-
},
1619-
"full-backing-filename": "/disks/mybacking.qcow2",
1620-
"backing-filename": "mybacking.qcow2",
1621-
"dirty-flag": false
1622-
},
1623-
{
1624-
"virtual-size": 25769803776,
1625-
"filename": "/disks/mybacking.qcow2",
1626-
"cluster-size": 65536,
1627-
"format": "qcow2",
1628-
"actual-size": 393744384,
1629-
"format-specific": {
1630-
"type": "qcow2",
1631-
"data": {
1632-
"compat": "1.1",
1633-
"lazy-refcounts": false,
1634-
"refcount-bits": 16,
1635-
"corrupt": false
1636-
}
1637-
},
1638-
"dirty-flag": false
1639-
}]'''
1640-
1641-
self.mock_popen.communicate.return_value = [qemu_infos] # pylint: disable=no-member
1642-
disks = virt.get_disks('test-vm')
1643-
disk = disks.get('vda')
1644-
self.assertEqual('/disks/test.qcow2', disk['file'])
1645-
self.assertEqual('disk', disk['type'])
1646-
self.assertEqual('/disks/mybacking.qcow2', disk['backing file']['file'])
1647-
cdrom = disks.get('hda')
1648-
self.assertEqual('/disks/test-cdrom.iso', cdrom['file'])
1649-
self.assertEqual('cdrom', cdrom['type'])
1650-
self.assertFalse('backing file' in cdrom.keys())
1651-
16521541
@patch('salt.modules.virt.stop', return_value=True)
16531542
@patch('salt.modules.virt.undefine')
16541543
@patch('os.remove')
@@ -2693,3 +2582,132 @@ def test_pool_delete(self):
26932582
# Shouldn't be called with another parameter so far since those are not implemented
26942583
# and thus throwing exceptions.
26952584
mock_pool.delete.assert_called_once_with(self.mock_libvirt.VIR_STORAGE_POOL_DELETE_NORMAL)
2585+
2586+
def test_full_info(self):
2587+
'''
2588+
Test virt.full_info
2589+
'''
2590+
xml = '''<domain type='kvm' id='7'>
2591+
<uuid>28deee33-4859-4f23-891c-ee239cffec94</uuid>
2592+
<name>test-vm</name>
2593+
<on_poweroff>destroy</on_poweroff>
2594+
<on_reboot>restart</on_reboot>
2595+
<on_crash>destroy</on_crash>
2596+
<devices>
2597+
<disk type='file' device='disk'>
2598+
<driver name='qemu' type='qcow2'/>
2599+
<source file='/disks/test.qcow2'/>
2600+
<target dev='vda' bus='virtio'/>
2601+
</disk>
2602+
<disk type='file' device='cdrom'>
2603+
<driver name='qemu' type='raw'/>
2604+
<source file='/disks/test-cdrom.iso'/>
2605+
<target dev='hda' bus='ide'/>
2606+
<readonly/>
2607+
</disk>
2608+
<interface type='bridge'>
2609+
<mac address='ac:de:48:b6:8b:59'/>
2610+
<source bridge='br0'/>
2611+
<model type='virtio'/>
2612+
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
2613+
</interface>
2614+
<graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'>
2615+
<listen type='address' address='0.0.0.0'/>
2616+
</graphics>
2617+
</devices>
2618+
</domain>
2619+
'''
2620+
self.set_mock_vm("test-vm", xml)
2621+
2622+
qemu_infos = '''[{
2623+
"virtual-size": 25769803776,
2624+
"filename": "/disks/test.qcow2",
2625+
"cluster-size": 65536,
2626+
"format": "qcow2",
2627+
"actual-size": 217088,
2628+
"format-specific": {
2629+
"type": "qcow2",
2630+
"data": {
2631+
"compat": "1.1",
2632+
"lazy-refcounts": false,
2633+
"refcount-bits": 16,
2634+
"corrupt": false
2635+
}
2636+
},
2637+
"full-backing-filename": "/disks/mybacking.qcow2",
2638+
"backing-filename": "mybacking.qcow2",
2639+
"dirty-flag": false
2640+
},
2641+
{
2642+
"virtual-size": 25769803776,
2643+
"filename": "/disks/mybacking.qcow2",
2644+
"cluster-size": 65536,
2645+
"format": "qcow2",
2646+
"actual-size": 393744384,
2647+
"format-specific": {
2648+
"type": "qcow2",
2649+
"data": {
2650+
"compat": "1.1",
2651+
"lazy-refcounts": false,
2652+
"refcount-bits": 16,
2653+
"corrupt": false
2654+
}
2655+
},
2656+
"dirty-flag": false
2657+
}]'''
2658+
2659+
self.mock_popen.communicate.return_value = [qemu_infos] # pylint: disable=no-member
2660+
2661+
self.mock_conn.getInfo = MagicMock(return_value=['x86_64', 4096, 8, 2712, 1, 2, 4, 2])
2662+
2663+
actual = virt.full_info()
2664+
2665+
# Check that qemu-img was called with the proper parameters
2666+
qemu_img_call = [call for call in self.mock_subprocess.Popen.call_args_list if 'qemu-img' in call[0][0]][0]
2667+
self.assertIn('info', qemu_img_call[0][0])
2668+
self.assertIn('-U', qemu_img_call[0][0])
2669+
2670+
# Test the hypervisor infos
2671+
self.assertEqual(2816, actual['freemem'])
2672+
self.assertEqual(6, actual['freecpu'])
2673+
self.assertEqual(4, actual['node_info']['cpucores'])
2674+
self.assertEqual(2712, actual['node_info']['cpumhz'])
2675+
self.assertEqual('x86_64', actual['node_info']['cpumodel'])
2676+
self.assertEqual(8, actual['node_info']['cpus'])
2677+
self.assertEqual(2, actual['node_info']['cputhreads'])
2678+
self.assertEqual(1, actual['node_info']['numanodes'])
2679+
self.assertEqual(4096, actual['node_info']['phymemory'])
2680+
self.assertEqual(2, actual['node_info']['sockets'])
2681+
2682+
# Test the vm_info output:
2683+
self.assertEqual(2, actual['vm_info']['test-vm']['cpu'])
2684+
self.assertEqual(1234, actual['vm_info']['test-vm']['cputime'])
2685+
self.assertEqual(1024 * 1024, actual['vm_info']['test-vm']['mem'])
2686+
self.assertEqual(2048 * 1024, actual['vm_info']['test-vm']['maxMem'])
2687+
self.assertEqual('shutdown', actual['vm_info']['test-vm']['state'])
2688+
self.assertEqual('28deee33-4859-4f23-891c-ee239cffec94', actual['vm_info']['test-vm']['uuid'])
2689+
self.assertEqual('destroy', actual['vm_info']['test-vm']['on_crash'])
2690+
self.assertEqual('restart', actual['vm_info']['test-vm']['on_reboot'])
2691+
self.assertEqual('destroy', actual['vm_info']['test-vm']['on_poweroff'])
2692+
2693+
# Test the nics
2694+
nic = actual['vm_info']['test-vm']['nics']['ac:de:48:b6:8b:59']
2695+
self.assertEqual('bridge', nic['type'])
2696+
self.assertEqual('ac:de:48:b6:8b:59', nic['mac'])
2697+
2698+
# Test the disks
2699+
disks = actual['vm_info']['test-vm']['disks']
2700+
disk = disks.get('vda')
2701+
self.assertEqual('/disks/test.qcow2', disk['file'])
2702+
self.assertEqual('disk', disk['type'])
2703+
self.assertEqual('/disks/mybacking.qcow2', disk['backing file']['file'])
2704+
cdrom = disks.get('hda')
2705+
self.assertEqual('/disks/test-cdrom.iso', cdrom['file'])
2706+
self.assertEqual('cdrom', cdrom['type'])
2707+
self.assertFalse('backing file' in cdrom.keys())
2708+
2709+
# Test the graphics
2710+
graphics = actual['vm_info']['test-vm']['graphics']
2711+
self.assertEqual('vnc', graphics['type'])
2712+
self.assertEqual('5900', graphics['port'])
2713+
self.assertEqual('0.0.0.0', graphics['listen'])

0 commit comments

Comments
 (0)