Merge "Smaller non-HA virtual deployment template"
[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
14 from common import (
15     log,
16     exec_cmd,
17     err,
18     delete,
19 )
20
21 DEV = {'pxe': 'network',
22        'disk': 'hd',
23        'iso': 'cdrom'}
24
25
26 class LibvirtAdapter(HardwareAdapter):
27
28     def __init__(self, yaml_path):
29         super(LibvirtAdapter, self).__init__(yaml_path)
30         self.parser = etree.XMLParser(remove_blank_text=True)
31
32     def node_power_off(self, node_id):
33         vm_name = self.get_node_property(node_id, 'libvirtName')
34         log('Power OFF Node %s' % vm_name)
35         state = exec_cmd('virsh domstate %s' % vm_name)
36         if state == 'running':
37             exec_cmd('virsh destroy %s' % vm_name, False)
38
39     def node_power_on(self, node_id):
40         vm_name = self.get_node_property(node_id, 'libvirtName')
41         log('Power ON Node %s' % vm_name)
42         state = exec_cmd('virsh domstate %s' % vm_name)
43         if state == 'shut off':
44             exec_cmd('virsh start %s' % vm_name)
45
46     def node_reset(self, node_id):
47         vm_name = self.get_node_property(node_id, 'libvirtName')
48         log('Reset Node %s' % vm_name)
49         exec_cmd('virsh reset %s' % vm_name)
50
51     def translate(self, boot_order_list):
52         translated = []
53         for boot_dev in boot_order_list:
54             if boot_dev in DEV:
55                 translated.append(DEV[boot_dev])
56             else:
57                 err('Boot device %s not recognized' % boot_dev)
58         return translated
59
60     def node_set_boot_order(self, node_id, boot_order_list):
61         boot_order_list = self.translate(boot_order_list)
62         vm_name = self.get_node_property(node_id, 'libvirtName')
63         temp_dir = exec_cmd('mktemp -d')
64         log('Set boot order %s on Node %s' % (boot_order_list, vm_name))
65         resp = exec_cmd('virsh dumpxml %s' % vm_name)
66         xml_dump = etree.fromstring(resp, self.parser)
67         os = xml_dump.xpath('/domain/os')
68         for o in os:
69             for bootelem in ['boot', 'bootmenu']:
70                 boot = o.xpath(bootelem)
71                 for b in boot:
72                     o.remove(b)
73             for dev in boot_order_list:
74                 b = etree.Element('boot')
75                 b.set('dev', dev)
76                 o.append(b)
77             bmenu = etree.Element('bootmenu')
78             bmenu.set('enable', 'no')
79             o.append(bmenu)
80         tree = etree.ElementTree(xml_dump)
81         xml_file = temp_dir + '/%s.xml' % vm_name
82         with open(xml_file, 'w') as f:
83             tree.write(f, pretty_print=True, xml_declaration=True)
84         exec_cmd('virsh define %s' % xml_file)
85         delete(temp_dir)
86
87     def node_zero_mbr(self, node_id):
88         vm_name = self.get_node_property(node_id, 'libvirtName')
89         resp = exec_cmd('virsh dumpxml %s' % vm_name)
90         xml_dump = etree.fromstring(resp)
91         disks = xml_dump.xpath('/domain/devices/disk')
92         for disk in disks:
93             if disk.get('device') == 'disk':
94                 sources = disk.xpath('source')
95                 for source in sources:
96                     disk_file = source.get('file')
97                     disk_size = exec_cmd('ls -l %s' % disk_file).split()[4]
98                     delete(disk_file)
99                     exec_cmd('fallocate -l %s %s' % (disk_size, disk_file))
100
101     def node_eject_iso(self, node_id):
102         vm_name = self.get_node_property(node_id, 'libvirtName')
103         device = self.get_name_of_device(vm_name, 'cdrom')
104         exec_cmd('virsh change-media %s --eject %s --config --live'
105                  % (vm_name, device), False)
106
107     def node_insert_iso(self, node_id, iso_file):
108         vm_name = self.get_node_property(node_id, 'libvirtName')
109         device = self.get_name_of_device(vm_name, 'cdrom')
110         exec_cmd('virsh change-media %s --insert %s %s'
111                  % (vm_name, device, iso_file))
112
113     def get_node_pxe_mac(self, node_id):
114         mac_list = []
115         vm_name = self.get_node_property(node_id, 'libvirtName')
116         resp = exec_cmd('virsh dumpxml %s' % vm_name)
117         xml_dump = etree.fromstring(resp)
118         interfaces = xml_dump.xpath('/domain/devices/interface')
119         for interface in interfaces:
120             macs = interface.xpath('mac')
121             for mac in macs:
122                 mac_list.append(mac.get('address').lower())
123         return mac_list
124
125     def get_name_of_device(self, vm_name, device_type):
126         resp = exec_cmd('virsh dumpxml %s' % vm_name)
127         xml_dump = etree.fromstring(resp)
128         disks = xml_dump.xpath('/domain/devices/disk')
129         for disk in disks:
130             if disk.get('device') == device_type:
131                 targets = disk.xpath('target')
132                 for target in targets:
133                     device = target.get('dev')
134                     if device:
135                         return device
136
137     def get_virt_net_conf_dir(self):
138         return self.dha_struct['virtNetConfDir']