Refactoring virt.get_disks

virt.get_disks does not need to depend on libvirt:hypervisor value to
decice whether to extract data using qemu-img info on a disk image.
This needs to be run on all qemu images... and those can be also used
by a Xen VM nowadays.

The refactoring removes that dependency on the deprecated configuration
libvirt:hypervisor and uses the value for the <driver> type attribute
in the disk XML configuration.

Enhance the get_disk unit test to make sure that the qemu-img info is
parsed for a qemu image and not for others
This commit is contained in:
Cédric Bosdonnat 2018-06-13 10:53:20 +02:00
parent 1cee5ec014
commit 256a123108
No known key found for this signature in database
GPG Key ID: 743CCED3EDD1578D
2 changed files with 70 additions and 29 deletions

View File

@ -485,25 +485,26 @@ def _get_disks(dom):
qemu_target = '{0}:{1}'.format(
source.getAttribute('protocol'),
source.getAttribute('name'))
if qemu_target:
disks[target.getAttribute('dev')] = {
'file': qemu_target,
'type': elem.getAttribute('device')}
for dev in disks:
try:
hypervisor = __salt__['config.get']('libvirt:hypervisor', 'kvm')
if hypervisor not in ['qemu', 'kvm']:
break
if not qemu_target:
continue
stdout = subprocess.Popen(
['qemu-img', 'info', disks[dev]['file']],
shell=False,
stdout=subprocess.PIPE).communicate()[0]
qemu_output = salt.utils.stringutils.to_str(stdout)
output = _parse_qemu_img_info(qemu_output)
disks[dev].update(salt.utils.yaml.safe_load(output))
except TypeError:
disks[dev].update({'image': 'Does not exist'})
disk = {'file': qemu_target,
'type': elem.getAttribute('device')}
driver = _get_xml_first_element_by_tag_name(elem, 'driver')
if driver and driver.getAttribute('type') == 'qcow2':
try:
stdout = subprocess.Popen(
['qemu-img', 'info', disk['file']],
shell=False,
stdout=subprocess.PIPE).communicate()[0]
qemu_output = salt.utils.stringutils.to_str(stdout)
output = _parse_qemu_img_info(qemu_output)
disk.update(salt.utils.yaml.safe_load(output))
except TypeError:
disk.update({'image': 'Does not exist'})
disks[target.getAttribute('dev')] = disk
return disks

View File

@ -50,14 +50,19 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
self.mock_libvirt = LibvirtMock()
self.mock_conn = MagicMock()
self.mock_libvirt.openAuth.return_value = self.mock_conn
self.mock_popen = MagicMock()
self.addCleanup(delattr, self, 'mock_libvirt')
self.addCleanup(delattr, self, 'mock_conn')
self.addCleanup(delattr, self, 'mock_popen')
mock_subprocess = MagicMock()
mock_subprocess.Popen.return_value = self.mock_popen # pylint: disable=no-member
loader_globals = {
'__salt__': {
'config.get': config.get,
'config.option': config.option,
},
'libvirt': self.mock_libvirt
'libvirt': self.mock_libvirt,
'subprocess': mock_subprocess
}
return {virt: loader_globals, config: loader_globals}
@ -608,11 +613,9 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
self.assertEqual('bridge', nic['type'])
self.assertEqual('ac:de:48:b6:8b:59', nic['mac'])
@patch('subprocess.Popen')
@patch('subprocess.Popen.communicate', return_value="")
def test_get_disks(self, mock_communicate, mock_popen):
def test_get_disks(self):
'''
Test virt.get_discs()
Test virt.get_disks()
'''
xml = '''<domain type='kvm' id='7'>
<name>test-vm</name>
@ -633,20 +636,33 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
'''
self.set_mock_vm("test-vm", xml)
qemu_infos = '''image: test.qcow2
file format: qcow2
virtual size: 15G (16106127360 bytes)
disk size: 196K
cluster_size: 65536
backing file: mybacking.qcow2 (actual path: /disks/mybacking.qcow2)
Format specific information:
compat: 1.1
lazy refcounts: false
refcount bits: 16
corrupt: 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'])
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('subprocess.Popen')
@patch('subprocess.Popen.communicate', return_value="")
@patch('salt.modules.virt.stop', return_value=True)
@patch('salt.modules.virt.undefine')
@patch('os.remove')
def test_purge_default(self, mock_remove, mock_undefine, mock_stop, mock_communicate, mock_popen):
def test_purge_default(self, mock_remove, mock_undefine, mock_stop):
'''
Test virt.purge() with default parameters
'''
@ -669,17 +685,28 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
'''
self.set_mock_vm("test-vm", xml)
qemu_infos = '''image: test.qcow2
file format: qcow2
virtual size: 15G (16106127360 bytes)
disk size: 196K
cluster_size: 65536
Format specific information:
compat: 1.1
lazy refcounts: false
refcount bits: 16
corrupt: false'''
self.mock_popen.communicate.return_value = [qemu_infos] # pylint: disable=no-member
res = virt.purge('test-vm')
self.assertTrue(res)
mock_remove.assert_any_call('/disks/test.qcow2')
mock_remove.assert_any_call('/disks/test-cdrom.iso')
@patch('subprocess.Popen')
@patch('subprocess.Popen.communicate', return_value="")
@patch('salt.modules.virt.stop', return_value=True)
@patch('salt.modules.virt.undefine')
@patch('os.remove')
def test_purge_noremovable(self, mock_remove, mock_undefine, mock_stop, mock_communicate, mock_popen):
def test_purge_noremovable(self, mock_remove, mock_undefine, mock_stop):
'''
Test virt.purge(removables=False)
'''
@ -708,6 +735,19 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
'''
self.set_mock_vm("test-vm", xml)
qemu_infos = '''image: test.qcow2
file format: qcow2
virtual size: 15G (16106127360 bytes)
disk size: 196K
cluster_size: 65536
Format specific information:
compat: 1.1
lazy refcounts: false
refcount bits: 16
corrupt: false'''
self.mock_popen.communicate.return_value = [qemu_infos] # pylint: disable=no-member
res = virt.purge('test-vm', removables=False)
self.assertTrue(res)
mock_remove.assert_called_once()