3
# Some code for parsing libvirt's capabilities XML
5
# Copyright 2007 Red Hat, Inc.
6
# Mark McLoughlin <markmc@redhat.com>
8
# This program is free software; you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation; either version 2 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program; if not, write to the Free Software
20
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24
from virtinst import _virtinst as _
26
class CapabilitiesParserException(Exception):
27
def __init__(self, msg):
28
Exception.__init__(self, msg)
30
# Whether a guest can be created with a certain feature on resp. off
34
class Features(object):
35
"""Represent a set of features. For each feature, store a bit mask of
36
FEATURE_ON and FEATURE_OFF to indicate whether the feature can
37
be turned on or off. For features for which toggling doesn't make sense
38
(e.g., 'vmx') store FEATURE_ON when the feature is present."""
40
def __init__(self, node = None):
45
def __getitem__(self, feature):
46
if self.features.has_key(feature):
47
return self.features[feature]
51
return self.features.keys()
53
def parseXML(self, node):
55
for n in node.xpathEval("*"):
57
if not d.has_key(feature):
60
self._extractFeature(feature, d, n)
62
def _extractFeature(self, feature, dict, node):
63
"""Extract the value of FEATURE from NODE and set DICT[FEATURE] to
64
its value. Abstract method, must be overridden"""
65
raise NotImplementedError("Abstract base class")
67
class CapabilityFeatures(Features):
68
def __init__(self, node = None):
69
Features.__init__(self, node)
71
def _extractFeature(self, feature, d, n):
72
default = xpathString(n, "@default")
73
toggle = xpathString(n, "@toggle")
75
if default is not None:
77
d[feature] = FEATURE_ON
78
elif default == "off":
79
d[feature] = FEATURE_OFF
81
raise CapabilitiesParserException("Feature %s: value of default must be 'on' or 'off', but is '%s'" % (feature, default))
83
d[feature] |= d[feature] ^ (FEATURE_ON|FEATURE_OFF)
85
if feature == "nonpae":
86
d["pae"] |= FEATURE_OFF
88
d[feature] |= FEATURE_ON
91
def __init__(self, node = None):
92
# e.g. "i686" or "x86_64"
95
self.features = CapabilityFeatures()
100
def parseXML(self, node):
101
child = node.children
103
if child.name != "cpu":
110
self.arch = n.content
111
elif n.name == "features":
112
self.features = CapabilityFeatures(n)
118
def __init__(self, node = None):
119
# e.g. "xen" or "hvm"
122
# e.g. "xen", "qemu", "kqemu" or "kvm"
123
self.hypervisor_type = None
125
# e.g. "i686" or "x86_64"
128
self.features = CapabilityFeatures()
133
def parseXML(self, node):
134
child = node.children
136
if child.name == "os_type":
137
self.os_type = child.content
138
elif child.name == "features":
139
self.features = CapabilityFeatures(child)
140
elif child.name == "arch":
141
self.arch = child.prop("name")
144
# NB. for now, ignoring the rest of arch e.g. wordsize etc.
145
if n.name == "domain":
146
self.hypervisor_type = n.prop("type")
151
class Capabilities(object):
152
def __init__(self, node = None):
159
def parseXML(self, node):
160
child = node.children
162
if child.name == "host":
163
self.host = Host(child)
164
elif child.name == "guest":
165
self.guests.append(Guest(child))
172
def handler(self, ctx, str):
174
error = ErrorHandler()
175
libxml2.registerErrorHandler(error.handler, None)
178
# try/except/finally is only available in python-2.5
180
doc = libxml2.readMemory(xml, len(xml),
182
libxml2.XML_PARSE_NOBLANKS)
183
except (libxml2.parserError, libxml2.treeError), e:
184
raise CapabilitiesParserException("%s\n%s" % (e, error.msg))
186
libxml2.registerErrorHandler(None, None)
189
root = doc.getRootElement()
190
if root.name != "capabilities":
191
raise CapabilitiesParserException("Root element is not 'capabilities'")
193
capabilities = Capabilities(root)
199
def xpathString(node, path, default = None):
200
result = node.xpathEval("string(%s)" % path)