Provide access to mgmt network from host level
[fuel.git] / deploy / dha_adapters / libvirt_adapter.py
1 ###############################################################################
2 # Copyright (c) 2015 Ericsson AB and others.
3 # szilard.cserey@ericsson.com
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ###############################################################################
9
10
11 from lxml import etree
12 from hardware_adapter import HardwareAdapter
13 import tempfile
14 import os
15
16 from common import (
17     log,
18     exec_cmd,
19     err,
20     delete,
21 )
22
23 DEV = {'pxe': 'network',
24        'disk': 'hd',
25        'iso': 'cdrom'}
26
27 VOL_XML_TEMPLATE = '''<volume type='file'>
28   <name>{name}</name>
29   <capacity unit='{unit}'>{size!s}</capacity>
30   <target>
31     <format type='{format_type}'/>
32   </target>
33 </volume>'''
34
35 DEFAULT_POOL = 'jenkins'
36
37 class LibvirtAdapter(HardwareAdapter):
38
39     def __init__(self, yaml_path):
40         super(LibvirtAdapter, self).__init__(yaml_path)
41         self.parser = etree.XMLParser(remove_blank_text=True)
42
43     def node_power_off(self, node_id):
44         vm_name = self.get_node_property(node_id, 'libvirtName')
45         log('Power OFF Node %s' % vm_name)
46         state = exec_cmd('virsh domstate %s' % vm_name)
47         if state == 'running':
48             exec_cmd('virsh destroy %s' % vm_name, False)
49
50     def node_power_on(self, node_id):
51         vm_name = self.get_node_property(node_id, 'libvirtName')
52         log('Power ON Node %s' % vm_name)
53         state = exec_cmd('virsh domstate %s' % vm_name)
54         if state == 'shut off':
55             exec_cmd('virsh start %s' % vm_name)
56
57     def node_reset(self, node_id):
58         vm_name = self.get_node_property(node_id, 'libvirtName')
59         log('Reset Node %s' % vm_name)
60         exec_cmd('virsh reset %s' % vm_name)
61
62     def translate(self, boot_order_list):
63         translated = []
64         for boot_dev in boot_order_list:
65             if boot_dev in DEV:
66                 translated.append(DEV[boot_dev])
67             else:
68                 err('Boot device %s not recognized' % boot_dev)
69         return translated
70
71     def node_set_boot_order(self, node_id, boot_order_list):
72         boot_order_list = self.translate(boot_order_list)
73         vm_name = self.get_node_property(node_id, 'libvirtName')
74         temp_dir = tempfile.mkdtemp()
75         log('Set boot order %s on Node %s' % (boot_order_list, vm_name))
76         resp = exec_cmd('virsh dumpxml %s' % vm_name)
77         xml_dump = etree.fromstring(resp, self.parser)
78         os = xml_dump.xpath('/domain/os')
79         for o in os:
80             for bootelem in ['boot', 'bootmenu']:
81                 boot = o.xpath(bootelem)
82                 for b in boot:
83                     o.remove(b)
84             for dev in boot_order_list:
85                 b = etree.Element('boot')
86                 b.set('dev', dev)
87                 o.append(b)
88             bmenu = etree.Element('bootmenu')
89             bmenu.set('enable', 'no')
90             o.append(bmenu)
91         tree = etree.ElementTree(xml_dump)
92         xml_file = temp_dir + '/%s.xml' % vm_name
93         with open(xml_file, 'w') as f:
94             tree.write(f, pretty_print=True, xml_declaration=True)
95         exec_cmd('virsh define %s' % xml_file)
96         delete(temp_dir)
97
98     def node_zero_mbr(self, node_id):
99         vm_name = self.get_node_property(node_id, 'libvirtName')
100         resp = exec_cmd('virsh dumpxml %s' % vm_name)
101         xml_dump = etree.fromstring(resp)
102         disks = xml_dump.xpath('/domain/devices/disk')
103         for disk in disks:
104             if disk.get('device') == 'disk':
105                 sources = disk.xpath('source')
106                 for source in sources:
107                     disk_file = source.get('file')
108                     disk_size = exec_cmd('qemu-img info '
109                                          '%s |grep \"virtual size:\"'
110                                          % disk_file).split()[2]
111                     delete(disk_file)
112                     exec_cmd('qemu-img create -f qcow2 %s %s' % (disk_file,
113                                                                  disk_size))
114
115     def node_eject_iso(self, node_id):
116         vm_name = self.get_node_property(node_id, 'libvirtName')
117         device = self.get_name_of_device(vm_name, 'cdrom')
118         exec_cmd('virsh change-media %s --eject %s --config --live'
119                  % (vm_name, device), False)
120
121     def node_insert_iso(self, node_id, iso_file):
122         vm_name = self.get_node_property(node_id, 'libvirtName')
123         device = self.get_name_of_device(vm_name, 'cdrom')
124         exec_cmd('virsh change-media %s --insert %s %s'
125                  % (vm_name, device, iso_file))
126
127     def get_node_pxe_mac(self, node_id):
128         mac_list = []
129         vm_name = self.get_node_property(node_id, 'libvirtName')
130         resp = exec_cmd('virsh dumpxml %s' % vm_name)
131         xml_dump = etree.fromstring(resp)
132         interfaces = xml_dump.xpath('/domain/devices/interface')
133         for interface in interfaces:
134             macs = interface.xpath('mac')
135             for mac in macs:
136                 mac_list.append(mac.get('address').lower())
137         return mac_list
138
139     def get_name_of_device(self, vm_name, device_type):
140         resp = exec_cmd('virsh dumpxml %s' % vm_name)
141         xml_dump = etree.fromstring(resp)
142         disks = xml_dump.xpath('/domain/devices/disk')
143         for disk in disks:
144             if disk.get('device') == device_type:
145                 targets = disk.xpath('target')
146                 for target in targets:
147                     device = target.get('dev')
148                     if device:
149                         return device
150
151     def get_virt_net_conf_dir(self):
152         return self.dha_struct['virtNetConfDir']
153
154     def upload_iso(self, iso_file):
155         size = os.path.getsize(iso_file)
156         vol_name = os.path.basename(iso_file)
157         vol_xml = VOL_XML_TEMPLATE.format(name=vol_name, unit='bytes',
158                                           size=size, format_type='raw')
159         fd, fname = tempfile.mkstemp(text=True, suffix='deploy')
160         os.write(fd, vol_xml)
161         os.close(fd)
162
163         log(vol_xml)
164         pool = DEFAULT_POOL # FIXME
165         exec_cmd('virsh vol-create --pool %s %s' % (pool, fname))
166         vol_path = exec_cmd('virsh vol-path --pool %s %s' % (pool, vol_name))
167
168         exec_cmd('virsh vol-upload %s %s' % (vol_path, iso_file),
169                  attempts=5, delay=10, verbose=True)
170
171         delete(fname)
172
173         return vol_path