forked from kimchi-project/kimchi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.py
155 lines (123 loc) · 4.51 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#
# Project Kimchi
#
# Copyright IBM Corp, 2015-2016
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import base64
import libvirt
from lxml import etree
from lxml.builder import E
from wok.exception import OperationFailed
KIMCHI_META_URL = 'https://github.com/kimchi-project/kimchi'
KIMCHI_NAMESPACE = 'kimchi'
def get_vm_name(vm_name, t_name, name_list):
if vm_name:
return vm_name
for i in range(1, 1000):
# VM will have templace name, but without slashes
vm_name = '%s-vm-%i' % (t_name.replace('/', '-'), i)
if vm_name not in name_list:
return vm_name
raise OperationFailed('KCHUTILS0003E')
def get_ascii_nonascii_name(name):
nonascii_name = None
if name.encode('ascii', 'ignore').decode('utf-8') != name:
nonascii_name = name
name = base64.urlsafe_b64encode(
nonascii_name.encode('utf-8')).decode('utf-8')
name = name.rstrip('=')
return name, nonascii_name
def get_vm_config_flag(dom, mode='persistent'):
# libvirt.VIR_DOMAIN_AFFECT_CURRENT is 0
# VIR_DOMAIN_AFFECT_LIVE is 1, VIR_DOMAIN_AFFECT_CONFIG is 2
flag = {
'live': libvirt.VIR_DOMAIN_AFFECT_LIVE,
'persistent': libvirt.VIR_DOMAIN_AFFECT_CONFIG,
'current': libvirt.VIR_DOMAIN_AFFECT_CURRENT,
'all': libvirt.VIR_DOMAIN_AFFECT_CONFIG + libvirt.VIR_DOMAIN_AFFECT_LIVE
if dom.isActive() and dom.isPersistent()
else libvirt.VIR_DOMAIN_AFFECT_CURRENT,
}
return flag[mode]
# avoid duplicate codes
def update_node(root, node):
old_node = root.find(node.tag)
(root.replace(old_node, node) if old_node is not None else root.append(node))
return root
def get_kimchi_metadata_node(dom, mode='current'):
if not metadata_exists(dom):
return None
try:
xml = dom.metadata(
libvirt.VIR_DOMAIN_METADATA_ELEMENT,
KIMCHI_META_URL,
flags=get_vm_config_flag(dom, mode),
)
return etree.fromstring(xml)
except libvirt.libvirtError:
return None
def set_kimchi_metadata_node(dom, metadata, mode='all'):
metadata_xml = etree.tostring(metadata).decode('utf-8')
# From libvirt doc, Passing None for @metadata says to remove that
# element from the domain XML (passing the empty string leaves the
# element present). Do not support remove the old metadata.
dom.setMetadata(
libvirt.VIR_DOMAIN_METADATA_ELEMENT,
metadata_xml,
KIMCHI_NAMESPACE,
KIMCHI_META_URL,
flags=get_vm_config_flag(dom, mode),
)
def set_metadata_node(dom, nodes, mode='all'):
kimchi = get_kimchi_metadata_node(dom, mode)
kimchi = E.metadata() if kimchi is None else kimchi
for n in nodes:
update_node(kimchi, n)
set_kimchi_metadata_node(dom, kimchi, mode)
def remove_metadata_node(dom, tag, mode='all'):
kimchi = get_kimchi_metadata_node(dom, mode)
if kimchi is not None:
node = kimchi.find(tag)
if node is not None:
kimchi.remove(node)
set_kimchi_metadata_node(dom, kimchi, mode)
def get_metadata_node(dom, tag, mode='current'):
kimchi = get_kimchi_metadata_node(dom, mode)
if kimchi is not None:
node = kimchi.find(tag)
if node is not None:
return etree.tostring(node)
return ''
def metadata_exists(dom):
xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE)
root = etree.fromstring(xml)
if root.find('metadata') is None:
return False
return True
def has_cpu_numa(dom):
"""
Verify if domain has NUMA configuration
Returns: True or False
"""
root = etree.fromstring(dom.XMLDesc(0))
return root.find('./cpu/numa') is not None
def set_numa_memory(mem, root):
"""
Set new NUMA memory value
Returns: etree element updated
"""
root.find('./cpu/numa/cell').set('memory', str(mem))
return root