1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
# Copyright (c) 2012 Red Hat, Inc.
5
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6
# not use this file except in compliance with the License. You may obtain
7
# a copy of the License at
9
# http://www.apache.org/licenses/LICENSE-2.0
11
# Unless required by applicable law or agreed to in writing, software
12
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
# License for the specific language governing permissions and limitations
18
Configuration for libvirt objects.
20
Classes to represent the configuration of various libvirt objects
21
and support conversion to/from XML
24
from nova import log as logging
26
from lxml import etree
29
LOG = logging.getLogger(__name__)
32
class LibvirtConfigObject(object):
34
def __init__(self, **kwargs):
35
super(LibvirtConfigObject, self).__init__()
37
self.root_name = kwargs.get("root_name")
38
self.ns_prefix = kwargs.get('ns_prefix')
39
self.ns_uri = kwargs.get('ns_uri')
41
if "xml_str" in kwargs:
42
self.parse_dom(kwargs.get("xml_str"))
44
def _text_node(self, name, value):
45
child = etree.Element(name)
46
child.text = str(value)
50
if self.ns_uri is None:
51
return etree.Element(self.root_name)
53
return etree.Element("{" + self.ns_uri + "}" + self.root_name,
54
nsmap={self.ns_prefix: self.ns_uri})
56
def parse_dom(xmldoc):
57
raise NotImplementedError()
59
def to_xml(self, pretty_print=True):
60
root = self.format_dom()
61
xml_str = etree.tostring(root, pretty_print=pretty_print)
62
LOG.debug("Generated XML %s " % (xml_str,))
66
class LibvirtConfigGuestDevice(LibvirtConfigObject):
68
def __init__(self, **kwargs):
69
super(LibvirtConfigGuestDevice, self).__init__(**kwargs)
72
class LibvirtConfigGuestDisk(LibvirtConfigGuestDevice):
74
def __init__(self, **kwargs):
75
super(LibvirtConfigGuestDisk, self).__init__(root_name="disk",
78
self.source_type = "file"
79
self.source_device = "disk"
80
self.driver_name = None
81
self.driver_format = None
82
self.driver_cache = None
83
self.source_path = None
84
self.source_protocol = None
85
self.source_host = None
86
self.target_dev = None
87
self.target_path = None
88
self.target_bus = None
89
self.auth_username = None
90
self.auth_secret_type = None
91
self.auth_secret_uuid = None
94
dev = super(LibvirtConfigGuestDisk, self).format_dom()
96
dev.set("type", self.source_type)
97
dev.set("device", self.source_device)
98
if self.driver_name is not None or \
99
self.driver_format is not None or \
100
self.driver_cache is not None:
101
drv = etree.Element("driver")
102
if self.driver_name is not None:
103
drv.set("name", self.driver_name)
104
if self.driver_format is not None:
105
drv.set("type", self.driver_format)
106
if self.driver_cache is not None:
107
drv.set("cache", self.driver_cache)
110
if self.source_type == "file":
111
dev.append(etree.Element("source", file=self.source_path))
112
elif self.source_type == "block":
113
dev.append(etree.Element("source", dev=self.source_path))
114
elif self.source_type == "mount":
115
dev.append(etree.Element("source", dir=self.source_path))
116
elif self.source_type == "network":
117
dev.append(etree.Element("source", protocol=self.source_protocol,
118
name=self.source_host))
120
if self.auth_secret_type is not None:
121
auth = etree.Element("auth")
122
auth.set("username", self.auth_username)
123
auth.append(etree.Element("secret", type=self.auth_secret_type,
124
uuid=self.auth_secret_uuid))
127
if self.source_type == "mount":
128
dev.append(etree.Element("target", dir=self.target_path))
130
dev.append(etree.Element("target", dev=self.target_dev,
131
bus=self.target_bus))
136
class LibvirtConfigGuestFilesys(LibvirtConfigGuestDevice):
138
def __init__(self, **kwargs):
139
super(LibvirtConfigGuestFilesys, self).__init__(root_name="filesystem",
142
self.source_type = "mount"
143
self.source_dir = None
144
self.target_dir = "/"
146
def format_dom(self):
147
dev = super(LibvirtConfigGuestFilesys, self).format_dom()
149
dev.set("type", self.source_type)
151
dev.append(etree.Element("source", dir=self.source_dir))
152
dev.append(etree.Element("target", dir=self.target_dir))
157
class LibvirtConfigGuestInterface(LibvirtConfigGuestDevice):
159
def __init__(self, **kwargs):
160
super(LibvirtConfigGuestInterface, self).__init__(
161
root_name="interface",
165
self.target_dev = None
169
self.source_dev = None
170
self.vporttype = None
171
self.vportparams = []
172
self.filtername = None
173
self.filterparams = []
175
def format_dom(self):
176
dev = super(LibvirtConfigGuestInterface, self).format_dom()
178
dev.set("type", self.net_type)
179
dev.append(etree.Element("mac", address=self.mac_addr))
181
dev.append(etree.Element("model", type=self.model))
182
if self.net_type == "ethernet":
183
if self.script is not None:
184
dev.append(etree.Element("script", path=self.script))
185
dev.append(etree.Element("target", dev=self.target_dev))
186
elif self.net_type == "direct":
187
dev.append(etree.Element("source", dev=self.source_dev,
190
dev.append(etree.Element("source", bridge=self.source_dev))
192
if self.vporttype is not None:
193
vport = etree.Element("virtualport", type=self.vporttype)
194
for p in self.vportparams:
195
param = etree.Element("parameters")
196
param.set(p['key'], p['value'])
200
if self.filtername is not None:
201
filter = etree.Element("filterref", filter=self.filtername)
202
for p in self.filterparams:
203
filter.append(etree.Element("parameter",
210
def add_filter_param(self, key, value):
211
self.filterparams.append({'key': key, 'value': value})
213
def add_vport_param(self, key, value):
214
self.vportparams.append({'key': key, 'value': value})
217
class LibvirtConfigGuestInput(LibvirtConfigGuestDevice):
219
def __init__(self, **kwargs):
220
super(LibvirtConfigGuestInput, self).__init__(root_name="input",
226
def format_dom(self):
227
dev = super(LibvirtConfigGuestInput, self).format_dom()
229
dev.set("type", self.type)
230
dev.set("bus", self.bus)
235
class LibvirtConfigGuestGraphics(LibvirtConfigGuestDevice):
237
def __init__(self, **kwargs):
238
super(LibvirtConfigGuestGraphics, self).__init__(root_name="graphics",
246
def format_dom(self):
247
dev = super(LibvirtConfigGuestGraphics, self).format_dom()
249
dev.set("type", self.type)
251
dev.set("autoport", "yes")
253
dev.set("autoport", "no")
255
dev.set("keymap", self.keymap)
257
dev.set("listen", self.listen)
262
class LibvirtConfigGuestChar(LibvirtConfigGuestDevice):
264
def __init__(self, **kwargs):
265
super(LibvirtConfigGuestChar, self).__init__(**kwargs)
268
self.source_path = None
269
self.target_port = None
271
def format_dom(self):
272
dev = super(LibvirtConfigGuestChar, self).format_dom()
274
dev.set("type", self.type)
275
if self.type == "file":
276
dev.append(etree.Element("source", path=self.source_path))
277
if self.target_port is not None:
278
dev.append(etree.Element("target", port=str(self.target_port)))
283
class LibvirtConfigGuestSerial(LibvirtConfigGuestChar):
285
def __init__(self, **kwargs):
286
super(LibvirtConfigGuestSerial, self).__init__(root_name="serial",
290
class LibvirtConfigGuestConsole(LibvirtConfigGuestChar):
292
def __init__(self, **kwargs):
293
super(LibvirtConfigGuestConsole, self).__init__(root_name="console",
297
class LibvirtConfigGuest(LibvirtConfigObject):
299
def __init__(self, **kwargs):
300
super(LibvirtConfigGuest, self).__init__(root_name="domain",
303
self.virt_type = None
306
self.memory = 1024 * 1024 * 500
310
self.os_kernel = None
311
self.os_initrd = None
312
self.os_cmdline = None
314
self.os_init_path = None
315
self.os_boot_dev = None
318
def _format_basic_props(self, root):
319
root.append(self._text_node("uuid", self.uuid))
320
root.append(self._text_node("name", self.name))
321
root.append(self._text_node("memory", self.memory))
322
root.append(self._text_node("vcpu", self.vcpus))
324
def _format_os(self, root):
325
os = etree.Element("os")
326
os.append(self._text_node("type", self.os_type))
327
if self.os_kernel is not None:
328
os.append(self._text_node("kernel", self.os_kernel))
329
if self.os_initrd is not None:
330
os.append(self._text_node("initrd", self.os_initrd))
331
if self.os_cmdline is not None:
332
os.append(self._text_node("cmdline", self.os_cmdline))
333
if self.os_root is not None:
334
os.append(self._text_node("root", self.os_root))
335
if self.os_init_path is not None:
336
os.append(self._text_node("init", self.os_init_path))
337
if self.os_boot_dev is not None:
338
os.append(etree.Element("boot", dev=self.os_boot_dev))
341
def _format_features(self, root):
343
features = etree.Element("features")
344
features.append(etree.Element("acpi"))
345
root.append(features)
347
def _format_devices(self, root):
348
if len(self.devices) == 0:
350
devices = etree.Element("devices")
351
for dev in self.devices:
352
devices.append(dev.format_dom())
355
def format_dom(self):
356
root = super(LibvirtConfigGuest, self).format_dom()
358
root.set("type", self.virt_type)
360
self._format_basic_props(root)
361
self._format_os(root)
362
self._format_features(root)
363
self._format_devices(root)
367
def add_device(self, dev):
368
self.devices.append(dev)
371
class LibvirtConfigCPU(LibvirtConfigObject):
373
def __init__(self, **kwargs):
374
super(LibvirtConfigCPU, self).__init__(root_name="cpu",
385
def add_feature(self, name):
386
self.features.append(name)
388
def format_dom(self):
389
cpu = super(LibvirtConfigCPU, self).format_dom()
391
cpu.append(self._text_node("arch", self.arch))
393
cpu.append(self._text_node("model", self.model))
395
cpu.append(self._text_node("vendor", self.vendor))
396
if (self.sockets is not None and
397
self.cores is not None and
398
self.threads is not None):
399
cpu.append(etree.Element("topology",
400
sockets=str(self.sockets),
401
cores=str(self.cores),
402
threads=str(self.threads)))
404
for f in self.features:
405
cpu.append(etree.Element("feature",
411
class LibvirtConfigGuestSnapshot(LibvirtConfigObject):
413
def __init__(self, **kwargs):
414
super(LibvirtConfigGuestSnapshot, self).__init__(
415
root_name="domainsnapshot",
420
def format_dom(self):
421
ss = super(LibvirtConfigGuestSnapshot, self).format_dom()
422
ss.append(self._text_node("name", self.name))