mirror of
https://github.com/valitydev/salt.git
synced 2024-11-06 16:45:27 +00:00
virt module: extract get_nics, get_disks and get_graphics
Extract the code of get_nics, get_disks and get_graphics into private functions providing the same feature with a libvirt domain as parameter. The rationale behind this change is to allow reducing the number of libvirt connections opened during some calls.
This commit is contained in:
parent
2dfdc4eb4b
commit
627b2e2594
@ -278,6 +278,114 @@ def _parse_qemu_img_info(info):
|
||||
return '\n'.join(output)
|
||||
|
||||
|
||||
def _get_nics(dom):
|
||||
'''
|
||||
Get domain network interfaces from a libvirt domain object.
|
||||
'''
|
||||
nics = {}
|
||||
doc = minidom.parse(_StringIO(dom.getXMLDesc(0)))
|
||||
for node in doc.getElementsByTagName('devices'):
|
||||
i_nodes = node.getElementsByTagName('interface')
|
||||
for i_node in i_nodes:
|
||||
nic = {}
|
||||
nic['type'] = i_node.getAttribute('type')
|
||||
for v_node in i_node.getElementsByTagName('*'):
|
||||
if v_node.tagName == 'mac':
|
||||
nic['mac'] = v_node.getAttribute('address')
|
||||
if v_node.tagName == 'model':
|
||||
nic['model'] = v_node.getAttribute('type')
|
||||
if v_node.tagName == 'target':
|
||||
nic['target'] = v_node.getAttribute('dev')
|
||||
# driver, source, and match can all have optional attributes
|
||||
if re.match('(driver|source|address)', v_node.tagName):
|
||||
temp = {}
|
||||
for key, value in v_node.attributes.items():
|
||||
temp[key] = value
|
||||
nic[six.text_type(v_node.tagName)] = temp
|
||||
# virtualport needs to be handled separately, to pick up the
|
||||
# type attribute of the virtualport itself
|
||||
if v_node.tagName == 'virtualport':
|
||||
temp = {}
|
||||
temp['type'] = v_node.getAttribute('type')
|
||||
for key, value in v_node.attributes.items():
|
||||
temp[key] = value
|
||||
nic['virtualport'] = temp
|
||||
if 'mac' not in nic:
|
||||
continue
|
||||
nics[nic['mac']] = nic
|
||||
return nics
|
||||
|
||||
|
||||
def _get_graphics(dom):
|
||||
'''
|
||||
Get domain graphics from a libvirt domain object.
|
||||
'''
|
||||
out = {'autoport': 'None',
|
||||
'keymap': 'None',
|
||||
'listen': 'None',
|
||||
'port': 'None',
|
||||
'type': 'None'}
|
||||
xml = dom.getXMLDesc(0)
|
||||
ssock = _StringIO(xml)
|
||||
doc = minidom.parse(ssock)
|
||||
for node in doc.getElementsByTagName('domain'):
|
||||
g_nodes = node.getElementsByTagName('graphics')
|
||||
for g_node in g_nodes:
|
||||
for key, value in g_node.attributes.items():
|
||||
out[key] = value
|
||||
return out
|
||||
|
||||
|
||||
def _get_disks(dom):
|
||||
'''
|
||||
Get domain disks from a libvirt domain object.
|
||||
'''
|
||||
disks = {}
|
||||
doc = minidom.parse(_StringIO(dom.getXMLDesc(0)))
|
||||
for elem in doc.getElementsByTagName('disk'):
|
||||
sources = elem.getElementsByTagName('source')
|
||||
targets = elem.getElementsByTagName('target')
|
||||
if sources:
|
||||
source = sources[0]
|
||||
else:
|
||||
continue
|
||||
if targets:
|
||||
target = targets[0]
|
||||
else:
|
||||
continue
|
||||
if target.hasAttribute('dev'):
|
||||
qemu_target = ''
|
||||
if source.hasAttribute('file'):
|
||||
qemu_target = source.getAttribute('file')
|
||||
elif source.hasAttribute('dev'):
|
||||
qemu_target = source.getAttribute('dev')
|
||||
elif source.hasAttribute('protocol') and \
|
||||
source.hasAttribute('name'): # For rbd network
|
||||
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
|
||||
|
||||
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'})
|
||||
return disks
|
||||
|
||||
|
||||
def _libvirt_creds():
|
||||
'''
|
||||
Returns the user and group that the disk images should be owned by
|
||||
@ -1106,38 +1214,7 @@ def get_nics(vm_):
|
||||
|
||||
salt '*' virt.get_nics <domain>
|
||||
'''
|
||||
nics = {}
|
||||
doc = minidom.parse(_StringIO(get_xml(vm_)))
|
||||
for node in doc.getElementsByTagName('devices'):
|
||||
i_nodes = node.getElementsByTagName('interface')
|
||||
for i_node in i_nodes:
|
||||
nic = {}
|
||||
nic['type'] = i_node.getAttribute('type')
|
||||
for v_node in i_node.getElementsByTagName('*'):
|
||||
if v_node.tagName == 'mac':
|
||||
nic['mac'] = v_node.getAttribute('address')
|
||||
if v_node.tagName == 'model':
|
||||
nic['model'] = v_node.getAttribute('type')
|
||||
if v_node.tagName == 'target':
|
||||
nic['target'] = v_node.getAttribute('dev')
|
||||
# driver, source, and match can all have optional attributes
|
||||
if re.match('(driver|source|address)', v_node.tagName):
|
||||
temp = {}
|
||||
for key, value in v_node.attributes.items():
|
||||
temp[key] = value
|
||||
nic[six.text_type(v_node.tagName)] = temp
|
||||
# virtualport needs to be handled separately, to pick up the
|
||||
# type attribute of the virtualport itself
|
||||
if v_node.tagName == 'virtualport':
|
||||
temp = {}
|
||||
temp['type'] = v_node.getAttribute('type')
|
||||
for key, value in v_node.attributes.items():
|
||||
temp[key] = value
|
||||
nic['virtualport'] = temp
|
||||
if 'mac' not in nic:
|
||||
continue
|
||||
nics[nic['mac']] = nic
|
||||
return nics
|
||||
return _get_nics(_get_domain(vm_))
|
||||
|
||||
|
||||
def get_macs(vm_):
|
||||
@ -1170,20 +1247,7 @@ def get_graphics(vm_):
|
||||
|
||||
salt '*' virt.get_graphics <domain>
|
||||
'''
|
||||
out = {'autoport': 'None',
|
||||
'keymap': 'None',
|
||||
'listen': 'None',
|
||||
'port': 'None',
|
||||
'type': 'None'}
|
||||
xml = get_xml(vm_)
|
||||
ssock = _StringIO(xml)
|
||||
doc = minidom.parse(ssock)
|
||||
for node in doc.getElementsByTagName('domain'):
|
||||
g_nodes = node.getElementsByTagName('graphics')
|
||||
for g_node in g_nodes:
|
||||
for key, value in g_node.attributes.items():
|
||||
out[key] = value
|
||||
return out
|
||||
return _get_graphics(_get_domain(vm_))
|
||||
|
||||
|
||||
def get_disks(vm_):
|
||||
@ -1196,50 +1260,7 @@ def get_disks(vm_):
|
||||
|
||||
salt '*' virt.get_disks <domain>
|
||||
'''
|
||||
disks = {}
|
||||
doc = minidom.parse(_StringIO(get_xml(vm_)))
|
||||
for elem in doc.getElementsByTagName('disk'):
|
||||
sources = elem.getElementsByTagName('source')
|
||||
targets = elem.getElementsByTagName('target')
|
||||
if sources:
|
||||
source = sources[0]
|
||||
else:
|
||||
continue
|
||||
if targets:
|
||||
target = targets[0]
|
||||
else:
|
||||
continue
|
||||
if target.hasAttribute('dev'):
|
||||
qemu_target = ''
|
||||
if source.hasAttribute('file'):
|
||||
qemu_target = source.getAttribute('file')
|
||||
elif source.hasAttribute('dev'):
|
||||
qemu_target = source.getAttribute('dev')
|
||||
elif source.hasAttribute('protocol') and \
|
||||
source.hasAttribute('name'): # For rbd network
|
||||
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
|
||||
|
||||
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'})
|
||||
return disks
|
||||
return _get_disks(_get_domain(vm_))
|
||||
|
||||
|
||||
def setmem(vm_, memory, config=False):
|
||||
|
@ -31,15 +31,26 @@ class LibvirtMock(MagicMock):
|
||||
class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
|
||||
def setup_loader_modules(self):
|
||||
self.mock_libvirt = LibvirtMock()
|
||||
self.mock_conn = MagicMock()
|
||||
self.mock_libvirt.openAuth.return_value = self.mock_conn
|
||||
self.addCleanup(delattr, self, 'mock_libvirt')
|
||||
self.addCleanup(delattr, self, 'mock_conn')
|
||||
loader_globals = {
|
||||
'__salt__': {
|
||||
'config.get': config.get,
|
||||
'config.option': config.option,
|
||||
},
|
||||
'libvirt': LibvirtMock()
|
||||
'libvirt': self.mock_libvirt
|
||||
}
|
||||
return {virt: loader_globals, config: loader_globals}
|
||||
|
||||
def set_mock_vm(self, name, xml):
|
||||
self.mock_conn.listDefinedDomains.return_value = [name]
|
||||
mock_domain = MagicMock()
|
||||
self.mock_conn.lookupByName.return_value = mock_domain
|
||||
mock_domain.getXMLDesc.return_value = xml
|
||||
|
||||
def test_boot_default_dev(self):
|
||||
diskp = virt._disk_profile('default', 'kvm')
|
||||
nicp = virt._nic_profile('default', 'kvm')
|
||||
@ -481,7 +492,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
interface_attrs['mac'], re.I))
|
||||
|
||||
def test_get_graphics(self):
|
||||
get_xml_mock = MagicMock(return_value='''<domain type='kvm' id='7'>
|
||||
xml = '''<domain type='kvm' id='7'>
|
||||
<name>test-vm</name>
|
||||
<devices>
|
||||
<graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'>
|
||||
@ -489,15 +500,16 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
</graphics>
|
||||
</devices>
|
||||
</domain>
|
||||
''')
|
||||
with patch.object(virt, 'get_xml', get_xml_mock):
|
||||
graphics = virt.get_graphics('test-vm')
|
||||
self.assertEqual('vnc', graphics['type'])
|
||||
self.assertEqual('5900', graphics['port'])
|
||||
self.assertEqual('0.0.0.0', graphics['listen'])
|
||||
'''
|
||||
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):
|
||||
get_xml_mock = MagicMock(return_value='''<domain type='kvm' id='7'>
|
||||
xml = '''<domain type='kvm' id='7'>
|
||||
<name>test-vm</name>
|
||||
<devices>
|
||||
<interface type='bridge'>
|
||||
@ -508,17 +520,18 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
</interface>
|
||||
</devices>
|
||||
</domain>
|
||||
''')
|
||||
with patch.object(virt, 'get_xml', get_xml_mock):
|
||||
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'])
|
||||
'''
|
||||
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'])
|
||||
|
||||
@patch('subprocess.Popen')
|
||||
@patch('subprocess.Popen.communicate', return_value="")
|
||||
def test_get_disks(self, mock_communicate, mock_popen):
|
||||
get_xml_mock = MagicMock(return_value='''<domain type='kvm' id='7'>
|
||||
xml = '''<domain type='kvm' id='7'>
|
||||
<name>test-vm</name>
|
||||
<devices>
|
||||
<disk type='file' device='disk'>
|
||||
@ -534,15 +547,16 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
</disk>
|
||||
</devices>
|
||||
</domain>
|
||||
''')
|
||||
with patch.object(virt, 'get_xml', get_xml_mock):
|
||||
disks = virt.get_disks('test-vm')
|
||||
disk = disks[list(disks)[0]]
|
||||
self.assertEqual('/disks/test.qcow2', disk['file'])
|
||||
self.assertEqual('disk', disk['type'])
|
||||
cdrom = disks[list(disks)[1]]
|
||||
self.assertEqual('/disks/test-cdrom.iso', cdrom['file'])
|
||||
self.assertEqual('cdrom', cdrom['type'])
|
||||
'''
|
||||
self.set_mock_vm("test-vm", xml)
|
||||
|
||||
disks = virt.get_disks('test-vm')
|
||||
disk = disks[list(disks)[0]]
|
||||
self.assertEqual('/disks/test.qcow2', disk['file'])
|
||||
self.assertEqual('disk', disk['type'])
|
||||
cdrom = disks[list(disks)[1]]
|
||||
self.assertEqual('/disks/test-cdrom.iso', cdrom['file'])
|
||||
self.assertEqual('cdrom', cdrom['type'])
|
||||
|
||||
@patch('subprocess.Popen')
|
||||
@patch('subprocess.Popen.communicate', return_value="")
|
||||
@ -550,7 +564,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
@patch('salt.modules.virt.undefine')
|
||||
@patch('os.remove')
|
||||
def test_purge_default(self, mock_remove, mock_undefine, mock_stop, mock_communicate, mock_popen):
|
||||
get_xml_mock = MagicMock(return_value='''<domain type='kvm' id='7'>
|
||||
xml = '''<domain type='kvm' id='7'>
|
||||
<name>test-vm</name>
|
||||
<devices>
|
||||
<disk type='file' device='disk'>
|
||||
@ -566,13 +580,13 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
</disk>
|
||||
</devices>
|
||||
</domain>
|
||||
''')
|
||||
mock = MagicMock(return_value={})
|
||||
with patch.object(virt, 'get_xml', get_xml_mock):
|
||||
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')
|
||||
'''
|
||||
self.set_mock_vm("test-vm", xml)
|
||||
|
||||
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="")
|
||||
@ -580,7 +594,8 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
@patch('salt.modules.virt.undefine')
|
||||
@patch('os.remove')
|
||||
def test_purge_noremovable(self, mock_remove, mock_undefine, mock_stop, mock_communicate, mock_popen):
|
||||
get_xml_mock = MagicMock(return_value='''<domain type='kvm' id='7'>
|
||||
|
||||
xml = '''<domain type='kvm' id='7'>
|
||||
<name>test-vm</name>
|
||||
<devices>
|
||||
<disk type='file' device='disk'>
|
||||
@ -602,13 +617,13 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||
</disk>
|
||||
</devices>
|
||||
</domain>
|
||||
''')
|
||||
mock = MagicMock(return_value={})
|
||||
with patch.object(virt, 'get_xml', get_xml_mock):
|
||||
res = virt.purge('test-vm', removables=False)
|
||||
self.assertTrue(res)
|
||||
mock_remove.assert_called_once()
|
||||
mock_remove.assert_any_call('/disks/test.qcow2')
|
||||
'''
|
||||
self.set_mock_vm("test-vm", xml)
|
||||
|
||||
res = virt.purge('test-vm', removables=False)
|
||||
self.assertTrue(res)
|
||||
mock_remove.assert_called_once()
|
||||
mock_remove.assert_any_call('/disks/test.qcow2')
|
||||
|
||||
def test_network(self):
|
||||
xml_data = virt._gen_net_xml('network', 'main', 'bridge', 'openvswitch')
|
||||
|
Loading…
Reference in New Issue
Block a user