"Fossies" - the Fresh Open Source Software Archive

Member "nova-22.0.1/nova/virt/libvirt/config.py" (19 Nov 2020, 117722 Bytes) of package /linux/misc/openstack/nova-22.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "config.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 22.0.0_vs_22.0.1.

    1 # Copyright (C) 2012-2013 Red Hat, Inc.
    2 #
    3 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
    4 #    not use this file except in compliance with the License. You may obtain
    5 #    a copy of the License at
    6 #
    7 #         http://www.apache.org/licenses/LICENSE-2.0
    8 #
    9 #    Unless required by applicable law or agreed to in writing, software
   10 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   11 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   12 #    License for the specific language governing permissions and limitations
   13 #    under the License.
   14 
   15 """
   16 Configuration for libvirt objects.
   17 
   18 Classes to represent the configuration of various libvirt objects
   19 and support conversion to/from XML. These classes are solely concerned
   20 by providing direct Object <-> XML document conversions. No policy or
   21 operational decisions should be made by code in these classes. Such
   22 policy belongs in the 'designer.py' module which provides simplified
   23 helpers for populating up config object instances.
   24 """
   25 
   26 import time
   27 
   28 from collections import OrderedDict
   29 from lxml import etree
   30 from oslo_utils import strutils
   31 from oslo_utils import units
   32 import six
   33 
   34 from nova import exception
   35 from nova.i18n import _
   36 from nova.pci import utils as pci_utils
   37 from nova.virt import hardware
   38 
   39 
   40 # Namespace to use for Nova specific metadata items in XML
   41 NOVA_NS = "http://openstack.org/xmlns/libvirt/nova/1.0"
   42 
   43 
   44 class LibvirtConfigObject(object):
   45 
   46     def __init__(self, **kwargs):
   47         super(LibvirtConfigObject, self).__init__()
   48 
   49         self.root_name = kwargs.get("root_name")
   50         self.ns_prefix = kwargs.get('ns_prefix')
   51         self.ns_uri = kwargs.get('ns_uri')
   52 
   53     def _new_node(self, node_name, **kwargs):
   54         if self.ns_uri is None:
   55             return etree.Element(node_name, **kwargs)
   56         else:
   57             return etree.Element("{" + self.ns_uri + "}" + node_name,
   58                                  nsmap={self.ns_prefix: self.ns_uri},
   59                                  **kwargs)
   60 
   61     def _text_node(self, node_name, value, **kwargs):
   62         child = self._new_node(node_name, **kwargs)
   63         child.text = six.text_type(value)
   64         return child
   65 
   66     def format_dom(self):
   67         return self._new_node(self.root_name)
   68 
   69     def parse_str(self, xmlstr):
   70         self.parse_dom(etree.fromstring(xmlstr))
   71 
   72     def parse_dom(self, xmldoc):
   73         if self.root_name != xmldoc.tag:
   74             msg = (_("Root element name should be '%(name)s' not '%(tag)s'") %
   75                    {'name': self.root_name, 'tag': xmldoc.tag})
   76             raise exception.InvalidInput(msg)
   77 
   78     def to_xml(self, pretty_print=True):
   79         root = self.format_dom()
   80         xml_str = etree.tostring(root, encoding='unicode',
   81                                  pretty_print=pretty_print)
   82         return xml_str
   83 
   84 
   85 class LibvirtConfigCaps(LibvirtConfigObject):
   86 
   87     def __init__(self, **kwargs):
   88         super(LibvirtConfigCaps, self).__init__(root_name="capabilities",
   89                                                 **kwargs)
   90         self.host = None
   91         self.guests = []
   92 
   93     def parse_dom(self, xmldoc):
   94         super(LibvirtConfigCaps, self).parse_dom(xmldoc)
   95 
   96         for c in xmldoc:
   97             if c.tag == "host":
   98                 host = LibvirtConfigCapsHost()
   99                 host.parse_dom(c)
  100                 self.host = host
  101             elif c.tag == "guest":
  102                 guest = LibvirtConfigCapsGuest()
  103                 guest.parse_dom(c)
  104                 self.guests.append(guest)
  105 
  106     def format_dom(self):
  107         caps = super(LibvirtConfigCaps, self).format_dom()
  108 
  109         if self.host:
  110             caps.append(self.host.format_dom())
  111         for g in self.guests:
  112             caps.append(g.format_dom())
  113 
  114         return caps
  115 
  116 
  117 class LibvirtConfigDomainCaps(LibvirtConfigObject):
  118 
  119     def __init__(self, **kwargs):
  120         super(LibvirtConfigDomainCaps, self).__init__(
  121             root_name="domainCapabilities", **kwargs)
  122         self._features = None
  123         self._machine = None
  124         self._alias = None
  125         self._devices = None
  126 
  127     def parse_dom(self, xmldoc):
  128         super(LibvirtConfigDomainCaps, self).parse_dom(xmldoc)
  129 
  130         for c in xmldoc:
  131             if c.tag == "features":
  132                 features = LibvirtConfigDomainCapsFeatures()
  133                 features.parse_dom(c)
  134                 self._features = features
  135             elif c.tag == "machine":
  136                 self._machine = c.text
  137             elif c.tag == "devices":
  138                 devices = LibvirtConfigDomainCapsDevices()
  139                 devices.parse_dom(c)
  140                 self._devices = devices
  141 
  142     @property
  143     def features(self):
  144         if self._features is None:
  145             return []
  146         return self._features.features
  147 
  148     @property
  149     def machine_type(self):
  150         if self._machine is None:
  151             return ""
  152         return self._machine
  153 
  154     @property
  155     def machine_type_alias(self):
  156         if self._alias is None:
  157             return self._machine
  158         return self._alias
  159 
  160     @machine_type_alias.setter
  161     def machine_type_alias(self, alias):
  162         self._alias = alias
  163 
  164     @property
  165     def devices(self):
  166         if self._devices is None:
  167             return []
  168         return self._devices
  169 
  170 
  171 class LibvirtConfigDomainCapsVideoModels(LibvirtConfigObject):
  172 
  173     def __init__(self, **kwargs):
  174         super().__init__(root_name='video', **kwargs)
  175         self.supported = False
  176         self.models = set()
  177 
  178     def parse_dom(self, xmldoc):
  179         super().parse_dom(xmldoc)
  180 
  181         if xmldoc.get('supported') == 'yes':
  182             self.supported = True
  183         self.models = {str(node) for node in
  184                        xmldoc.xpath("//enum[@name='modelType']/value/text()")}
  185 
  186 
  187 class LibvirtConfigDomainCapsDiskBuses(LibvirtConfigObject):
  188 
  189     def __init__(self, **kwargs):
  190         super().__init__(root_name='disk', **kwargs)
  191         self.supported = False
  192         self.buses = set()
  193 
  194     def parse_dom(self, xmldoc):
  195         super(LibvirtConfigDomainCapsDiskBuses, self).parse_dom(xmldoc)
  196 
  197         if xmldoc.get('supported') == 'yes':
  198             self.supported = True
  199         self.buses = {str(node) for node in
  200                       xmldoc.xpath("//enum[@name='bus']/value/text()")}
  201 
  202 
  203 class LibvirtConfigDomainCapsDevices(LibvirtConfigObject):
  204     DEVICE_PARSERS = {
  205         'video': LibvirtConfigDomainCapsVideoModels,
  206         'disk': LibvirtConfigDomainCapsDiskBuses,
  207     }
  208 
  209     def __init__(self, **kwargs):
  210         super().__init__(root_name='devices', **kwargs)
  211         self.devices = set()
  212 
  213     def parse_dom(self, xmldoc):
  214         super().parse_dom(xmldoc)
  215 
  216         for c in list(xmldoc):
  217             device = self.DEVICE_PARSERS.get(c.tag)
  218             if device:
  219                 device = device()
  220                 device.parse_dom(c)
  221                 self.devices.add(device)
  222 
  223     def _get_device(self, device_type):
  224         for device in self.devices:
  225             if type(device) == self.DEVICE_PARSERS.get(device_type):
  226                 return device
  227         return None
  228 
  229     @property
  230     def disk(self):
  231         return self._get_device('disk')
  232 
  233     @property
  234     def video(self):
  235         return self._get_device('video')
  236 
  237 
  238 class LibvirtConfigDomainCapsFeatures(LibvirtConfigObject):
  239 
  240     def __init__(self, **kwargs):
  241         super(LibvirtConfigDomainCapsFeatures, self).__init__(
  242             root_name="features", **kwargs)
  243         self.features = []
  244 
  245     def parse_dom(self, xmldoc):
  246         super(LibvirtConfigDomainCapsFeatures, self).parse_dom(xmldoc)
  247 
  248         for c in xmldoc:
  249             feature = None
  250             if c.tag == "sev":
  251                 feature = LibvirtConfigDomainCapsFeatureSev()
  252             if feature:
  253                 feature.parse_dom(c)
  254                 self.features.append(feature)
  255 
  256             # There are many other features and domain capabilities,
  257             # but we don't need to regenerate the XML (it's read-only
  258             # data provided by libvirtd), so there's no point parsing
  259             # them until we actually need their values.
  260 
  261     # For the same reason, we do not need a format_dom() method, but
  262     # it's a bug if this ever gets called and we inherited one from
  263     # the base class, so override that to watch out for accidental
  264     # calls.
  265     def format_dom(self):
  266         raise RuntimeError(_('BUG: tried to generate domainCapabilities XML'))
  267 
  268 
  269 class LibvirtConfigDomainCapsFeatureSev(LibvirtConfigObject):
  270 
  271     def __init__(self, **kwargs):
  272         super(LibvirtConfigDomainCapsFeatureSev, self).__init__(
  273             root_name='sev', **kwargs)
  274         self.supported = False
  275         self.cbitpos = None
  276         self.reduced_phys_bits = None
  277 
  278     def parse_dom(self, xmldoc):
  279         super(LibvirtConfigDomainCapsFeatureSev, self).parse_dom(xmldoc)
  280 
  281         if xmldoc.get('supported') == 'yes':
  282             self.supported = True
  283 
  284         for c in list(xmldoc):
  285             if c.tag == 'reducedPhysBits':
  286                 self.reduced_phys_bits = int(c.text)
  287             elif c.tag == 'cbitpos':
  288                 self.cbitpos = int(c.text)
  289 
  290 
  291 class LibvirtConfigCapsNUMATopology(LibvirtConfigObject):
  292 
  293     def __init__(self, **kwargs):
  294         super(LibvirtConfigCapsNUMATopology, self).__init__(
  295             root_name="topology",
  296             **kwargs)
  297 
  298         self.cells = []
  299 
  300     def parse_dom(self, xmldoc):
  301         super(LibvirtConfigCapsNUMATopology, self).parse_dom(xmldoc)
  302 
  303         xmlcells = xmldoc[0]
  304         for xmlcell in xmlcells:
  305             cell = LibvirtConfigCapsNUMACell()
  306             cell.parse_dom(xmlcell)
  307             self.cells.append(cell)
  308 
  309     def format_dom(self):
  310         topo = super(LibvirtConfigCapsNUMATopology, self).format_dom()
  311 
  312         cells = etree.Element("cells")
  313         cells.set("num", str(len(self.cells)))
  314         topo.append(cells)
  315 
  316         for cell in self.cells:
  317             cells.append(cell.format_dom())
  318 
  319         return topo
  320 
  321 
  322 class LibvirtConfigCapsNUMACell(LibvirtConfigObject):
  323 
  324     def __init__(self, **kwargs):
  325         super(LibvirtConfigCapsNUMACell, self).__init__(root_name="cell",
  326                                                         **kwargs)
  327 
  328         self.id = None
  329         self.memory = 0
  330         self.mempages = []
  331         self.cpus = []
  332 
  333     def parse_dom(self, xmldoc):
  334         super(LibvirtConfigCapsNUMACell, self).parse_dom(xmldoc)
  335 
  336         self.id = int(xmldoc.get("id"))
  337         for c in xmldoc:
  338             if c.tag == "memory":
  339                 self.memory = int(c.text)
  340             elif c.tag == "pages":
  341                 pages = LibvirtConfigCapsNUMAPages()
  342                 pages.parse_dom(c)
  343                 self.mempages.append(pages)
  344             elif c.tag == "cpus":
  345                 for c2 in c:
  346                     cpu = LibvirtConfigCapsNUMACPU()
  347                     cpu.parse_dom(c2)
  348                     self.cpus.append(cpu)
  349 
  350     def format_dom(self):
  351         cell = super(LibvirtConfigCapsNUMACell, self).format_dom()
  352 
  353         cell.set("id", str(self.id))
  354 
  355         mem = etree.Element("memory")
  356         mem.set("unit", "KiB")
  357         mem.text = str(self.memory)
  358         cell.append(mem)
  359 
  360         for pages in self.mempages:
  361             cell.append(pages.format_dom())
  362 
  363         cpus = etree.Element("cpus")
  364         cpus.set("num", str(len(self.cpus)))
  365         for cpu in self.cpus:
  366             cpus.append(cpu.format_dom())
  367         cell.append(cpus)
  368 
  369         return cell
  370 
  371 
  372 class LibvirtConfigCapsNUMACPU(LibvirtConfigObject):
  373 
  374     def __init__(self, **kwargs):
  375         super(LibvirtConfigCapsNUMACPU, self).__init__(root_name="cpu",
  376                                                        **kwargs)
  377 
  378         self.id = None
  379         self.socket_id = None
  380         self.core_id = None
  381         self.siblings = None
  382 
  383     def parse_dom(self, xmldoc):
  384         super(LibvirtConfigCapsNUMACPU, self).parse_dom(xmldoc)
  385 
  386         self.id = int(xmldoc.get("id"))
  387         if xmldoc.get("socket_id") is not None:
  388             self.socket_id = int(xmldoc.get("socket_id"))
  389         if xmldoc.get("core_id") is not None:
  390             self.core_id = int(xmldoc.get("core_id"))
  391 
  392         if xmldoc.get("siblings") is not None:
  393             self.siblings = hardware.parse_cpu_spec(
  394                 xmldoc.get("siblings"))
  395 
  396     def format_dom(self):
  397         cpu = super(LibvirtConfigCapsNUMACPU, self).format_dom()
  398 
  399         cpu.set("id", str(self.id))
  400         if self.socket_id is not None:
  401             cpu.set("socket_id", str(self.socket_id))
  402         if self.core_id is not None:
  403             cpu.set("core_id", str(self.core_id))
  404         if self.siblings is not None:
  405             cpu.set("siblings",
  406                     hardware.format_cpu_spec(self.siblings))
  407 
  408         return cpu
  409 
  410 
  411 class LibvirtConfigCapsNUMAPages(LibvirtConfigObject):
  412 
  413     def __init__(self, **kwargs):
  414         super(LibvirtConfigCapsNUMAPages, self).__init__(
  415             root_name="pages", **kwargs)
  416 
  417         self.size = None
  418         self.total = None
  419 
  420     def parse_dom(self, xmldoc):
  421         super(LibvirtConfigCapsNUMAPages, self).parse_dom(xmldoc)
  422 
  423         self.size = int(xmldoc.get("size"))
  424         self.total = int(xmldoc.text)
  425 
  426     def format_dom(self):
  427         pages = super(LibvirtConfigCapsNUMAPages, self).format_dom()
  428 
  429         pages.text = str(self.total)
  430         pages.set("size", str(self.size))
  431         pages.set("unit", "KiB")
  432 
  433         return pages
  434 
  435 
  436 class LibvirtConfigCapsHost(LibvirtConfigObject):
  437 
  438     def __init__(self, **kwargs):
  439         super(LibvirtConfigCapsHost, self).__init__(root_name="host",
  440                                                     **kwargs)
  441 
  442         self.cpu = None
  443         self.uuid = None
  444         self.topology = None
  445 
  446     def parse_dom(self, xmldoc):
  447         super(LibvirtConfigCapsHost, self).parse_dom(xmldoc)
  448 
  449         for c in xmldoc:
  450             if c.tag == "cpu":
  451                 cpu = LibvirtConfigCPU()
  452                 cpu.parse_dom(c)
  453                 self.cpu = cpu
  454             elif c.tag == "uuid":
  455                 self.uuid = c.text
  456             elif c.tag == "topology":
  457                 self.topology = LibvirtConfigCapsNUMATopology()
  458                 self.topology.parse_dom(c)
  459 
  460     def format_dom(self):
  461         caps = super(LibvirtConfigCapsHost, self).format_dom()
  462 
  463         if self.uuid:
  464             caps.append(self._text_node("uuid", self.uuid))
  465         if self.cpu:
  466             caps.append(self.cpu.format_dom())
  467         if self.topology:
  468             caps.append(self.topology.format_dom())
  469 
  470         return caps
  471 
  472 
  473 class LibvirtConfigCapsGuest(LibvirtConfigObject):
  474 
  475     def __init__(self, **kwargs):
  476         super(LibvirtConfigCapsGuest, self).__init__(root_name="guest",
  477                                                      **kwargs)
  478 
  479         self.arch = None
  480         self.ostype = None
  481         # Map domain types such as 'qemu' and 'kvm' to
  482         # LibvirtConfigCapsGuestDomain instances.
  483         self.domains = OrderedDict()
  484         self.default_domain = None
  485 
  486     def parse_dom(self, xmldoc):
  487         super(LibvirtConfigCapsGuest, self).parse_dom(xmldoc)
  488 
  489         for child in xmldoc:
  490             if child.tag == "os_type":
  491                 self.ostype = child.text
  492             elif child.tag == "arch":
  493                 self.parse_arch(child)
  494 
  495     def parse_arch(self, xmldoc):
  496         self.arch = xmldoc.get("name")
  497         # NOTE(aspiers): The data relating to each <domain> element
  498         # under <arch> (such as <emulator> and many <machine>
  499         # elements) is structured in a slightly odd way.  There is one
  500         # "default" domain such as
  501         #
  502         #   <domain type='qemu'/>
  503         #
  504         # which has no child elements, and all its data is provided in
  505         # sibling elements.  Then others such as
  506         #
  507         #   <domain type='kvm'>
  508         #
  509         # will have their <emulator> and <machine> elements as
  510         # children.  So we need to handle the two cases separately.
  511         self.default_domain = LibvirtConfigCapsGuestDomain()
  512         for child in xmldoc:
  513             if child.tag == "domain":
  514                 if list(child):
  515                     # This domain has children, so create a new instance,
  516                     # parse it, and register it in the dict of domains.
  517                     domain = LibvirtConfigCapsGuestDomain()
  518                     domain.parse_dom(child)
  519                     self.domains[domain.domtype] = domain
  520                 else:
  521                     # This is the childless <domain/> element for the
  522                     # default domain
  523                     self.default_domain.parse_domain(child)
  524                     self.domains[self.default_domain.domtype] = \
  525                         self.default_domain
  526             else:
  527                 # Sibling element of the default domain
  528                 self.default_domain.parse_child(child)
  529 
  530     def format_dom(self):
  531         caps = super(LibvirtConfigCapsGuest, self).format_dom()
  532 
  533         if self.ostype is not None:
  534             caps.append(self._text_node("os_type", self.ostype))
  535         if self.arch:
  536             arch = self.format_arch()
  537             caps.append(arch)
  538 
  539         return caps
  540 
  541     def format_arch(self):
  542         arch = etree.Element("arch", name=self.arch)
  543 
  544         for c in self.default_domain.format_dom():
  545             arch.append(c)
  546         arch.append(self._new_node("domain", type=self.default_domain.domtype))
  547 
  548         for domtype, domain in self.domains.items():
  549             if domtype == self.default_domain.domtype:
  550                 # We've already added this domain at the top level
  551                 continue
  552             arch.append(domain.format_dom())
  553 
  554         return arch
  555 
  556 
  557 class LibvirtConfigCapsGuestDomain(LibvirtConfigObject):
  558     def __init__(self, **kwargs):
  559         super(LibvirtConfigCapsGuestDomain, self).__init__(
  560             root_name="domain", **kwargs)
  561 
  562         self.domtype = None
  563 
  564         # Track <emulator> values, which we need in order to be able
  565         # to call virConnectGetDomainCapabilities() - typically
  566         # something like '/usr/bin/qemu-system-i386'.
  567         self.emulator = None
  568 
  569         self.machines = {}
  570         self.aliases = {}
  571 
  572     def parse_dom(self, xmldoc):
  573         super(LibvirtConfigCapsGuestDomain, self).parse_dom(xmldoc)
  574 
  575         self.parse_domain(xmldoc)
  576 
  577         for c in xmldoc:
  578             self.parse_child(c)
  579 
  580     def parse_child(self, xmldoc):
  581         if xmldoc.tag == "emulator":
  582             self.emulator = xmldoc.text
  583         elif xmldoc.tag == "machine":
  584             self.parse_machine(xmldoc)
  585 
  586     def parse_domain(self, xmldoc):
  587         self.domtype = xmldoc.get("type")
  588         if self.domtype is None:
  589             raise exception.InvalidInput(
  590                 "Didn't find domain type in %s", xmldoc)
  591 
  592     def parse_machine(self, xmldoc):
  593         if 'canonical' in xmldoc.attrib:
  594             self.aliases[xmldoc.text] = xmldoc.attrib
  595         else:
  596             self.machines[xmldoc.text] = xmldoc.attrib
  597 
  598     def format_dom(self):
  599         domain = super(LibvirtConfigCapsGuestDomain, self).format_dom()
  600 
  601         if self.domtype is not None:
  602             domain.set("type", self.domtype)
  603         if self.emulator is not None:
  604             domain.append(self._text_node("emulator", self.emulator))
  605         for mach_type, machine in self.machines.items():
  606             domain.append(self._text_node("machine", mach_type, **machine))
  607         for alias, machine in self.aliases.items():
  608             domain.append(self._text_node("machine", alias, **machine))
  609 
  610         return domain
  611 
  612 
  613 class LibvirtConfigGuestTimer(LibvirtConfigObject):
  614 
  615     def __init__(self, **kwargs):
  616         super(LibvirtConfigGuestTimer, self).__init__(root_name="timer",
  617                                                       **kwargs)
  618 
  619         self.name = "platform"
  620         self.track = None
  621         self.tickpolicy = None
  622         self.present = None
  623 
  624     def format_dom(self):
  625         tm = super(LibvirtConfigGuestTimer, self).format_dom()
  626 
  627         tm.set("name", self.name)
  628         if self.track is not None:
  629             tm.set("track", self.track)
  630         if self.tickpolicy is not None:
  631             tm.set("tickpolicy", self.tickpolicy)
  632         if self.present is not None:
  633             if self.present:
  634                 tm.set("present", "yes")
  635             else:
  636                 tm.set("present", "no")
  637 
  638         return tm
  639 
  640 
  641 class LibvirtConfigGuestClock(LibvirtConfigObject):
  642 
  643     def __init__(self, **kwargs):
  644         super(LibvirtConfigGuestClock, self).__init__(root_name="clock",
  645                                                       **kwargs)
  646 
  647         self.offset = "utc"
  648         self.adjustment = None
  649         self.timezone = None
  650         self.timers = []
  651 
  652     def format_dom(self):
  653         clk = super(LibvirtConfigGuestClock, self).format_dom()
  654 
  655         clk.set("offset", self.offset)
  656         if self.adjustment:
  657             clk.set("adjustment", self.adjustment)
  658         elif self.timezone:
  659             clk.set("timezone", self.timezone)
  660 
  661         for tm in self.timers:
  662             clk.append(tm.format_dom())
  663 
  664         return clk
  665 
  666     def add_timer(self, tm):
  667         self.timers.append(tm)
  668 
  669 
  670 class LibvirtConfigCPUFeature(LibvirtConfigObject):
  671 
  672     def __init__(self, name=None, **kwargs):
  673         super(LibvirtConfigCPUFeature, self).__init__(root_name='feature',
  674                                                       **kwargs)
  675 
  676         self.name = name
  677         self.policy = "require"
  678 
  679     def parse_dom(self, xmldoc):
  680         super(LibvirtConfigCPUFeature, self).parse_dom(xmldoc)
  681 
  682         self.name = xmldoc.get("name")
  683         self.policy = xmldoc.get("policy", "require")
  684 
  685     def format_dom(self):
  686         ft = super(LibvirtConfigCPUFeature, self).format_dom()
  687 
  688         ft.set("name", self.name)
  689 
  690         return ft
  691 
  692     def __eq__(self, obj):
  693         return obj.name == self.name
  694 
  695     def __ne__(self, obj):
  696         return obj.name != self.name
  697 
  698     def __hash__(self):
  699         return hash(self.name)
  700 
  701 
  702 class LibvirtConfigCPU(LibvirtConfigObject):
  703 
  704     def __init__(self, **kwargs):
  705         super(LibvirtConfigCPU, self).__init__(root_name='cpu',
  706                                                **kwargs)
  707 
  708         self.arch = None
  709         self.vendor = None
  710         self.model = None
  711 
  712         self.sockets = None
  713         self.cores = None
  714         self.threads = None
  715 
  716         self.features = set()
  717 
  718     def parse_dom(self, xmldoc):
  719         super(LibvirtConfigCPU, self).parse_dom(xmldoc)
  720 
  721         for c in xmldoc:
  722             if c.tag == "arch":
  723                 self.arch = c.text
  724             elif c.tag == "model":
  725                 self.model = c.text
  726             elif c.tag == "vendor":
  727                 self.vendor = c.text
  728             elif c.tag == "topology":
  729                 self.sockets = int(c.get("sockets"))
  730                 self.cores = int(c.get("cores"))
  731                 self.threads = int(c.get("threads"))
  732             elif c.tag == "feature":
  733                 f = LibvirtConfigCPUFeature()
  734                 f.parse_dom(c)
  735                 if f.policy != "disable":
  736                     self.add_feature(f)
  737 
  738     def format_dom(self):
  739         cpu = super(LibvirtConfigCPU, self).format_dom()
  740 
  741         if self.arch is not None:
  742             cpu.append(self._text_node("arch", self.arch))
  743         if self.model is not None:
  744             cpu.append(self._text_node("model", self.model))
  745         if self.vendor is not None:
  746             cpu.append(self._text_node("vendor", self.vendor))
  747 
  748         if (self.sockets is not None and
  749             self.cores is not None and
  750                 self.threads is not None):
  751             top = etree.Element("topology")
  752             top.set("sockets", str(self.sockets))
  753             top.set("cores", str(self.cores))
  754             top.set("threads", str(self.threads))
  755             cpu.append(top)
  756 
  757         # sorting the features to allow more predictable tests
  758         for f in sorted(self.features, key=lambda x: x.name):
  759             if f.policy != "disable":
  760                 cpu.append(f.format_dom())
  761 
  762         return cpu
  763 
  764     def add_feature(self, feat):
  765         self.features.add(feat)
  766 
  767 
  768 class LibvirtConfigGuestCPUFeature(LibvirtConfigCPUFeature):
  769 
  770     def __init__(self, name=None, **kwargs):
  771         super(LibvirtConfigGuestCPUFeature, self).__init__(name, **kwargs)
  772 
  773         self.policy = "require"
  774 
  775     def format_dom(self):
  776         ft = super(LibvirtConfigGuestCPUFeature, self).format_dom()
  777 
  778         ft.set("policy", self.policy)
  779 
  780         return ft
  781 
  782 
  783 class LibvirtConfigGuestCPUNUMACell(LibvirtConfigObject):
  784 
  785     def __init__(self, **kwargs):
  786         super(LibvirtConfigGuestCPUNUMACell, self).__init__(root_name="cell",
  787                                                             **kwargs)
  788         self.id = None
  789         self.cpus = None
  790         self.memory = None
  791         self.memAccess = None
  792 
  793     def parse_dom(self, xmldoc):
  794         if xmldoc.get("id") is not None:
  795             self.id = int(xmldoc.get("id"))
  796         if xmldoc.get("memory") is not None:
  797             self.memory = int(xmldoc.get("memory"))
  798         if xmldoc.get("cpus") is not None:
  799             self.cpus = hardware.parse_cpu_spec(xmldoc.get("cpus"))
  800         self.memAccess = xmldoc.get("memAccess")
  801 
  802     def format_dom(self):
  803         cell = super(LibvirtConfigGuestCPUNUMACell, self).format_dom()
  804 
  805         if self.id is not None:
  806             cell.set("id", str(self.id))
  807         if self.cpus is not None:
  808             cell.set("cpus",
  809                      hardware.format_cpu_spec(self.cpus))
  810         if self.memory is not None:
  811             cell.set("memory", str(self.memory))
  812         if self.memAccess is not None:
  813             cell.set("memAccess", self.memAccess)
  814 
  815         return cell
  816 
  817 
  818 class LibvirtConfigGuestCPUNUMA(LibvirtConfigObject):
  819 
  820     def __init__(self, **kwargs):
  821         super(LibvirtConfigGuestCPUNUMA, self).__init__(root_name="numa",
  822                                                         **kwargs)
  823 
  824         self.cells = []
  825 
  826     def parse_dom(self, xmldoc):
  827         super(LibvirtConfigGuestCPUNUMA, self).parse_dom(xmldoc)
  828 
  829         for child in xmldoc:
  830             if child.tag == "cell":
  831                 cell = LibvirtConfigGuestCPUNUMACell()
  832                 cell.parse_dom(child)
  833                 self.cells.append(cell)
  834 
  835     def format_dom(self):
  836         numa = super(LibvirtConfigGuestCPUNUMA, self).format_dom()
  837 
  838         for cell in self.cells:
  839             numa.append(cell.format_dom())
  840 
  841         return numa
  842 
  843 
  844 class LibvirtConfigGuestCPU(LibvirtConfigCPU):
  845 
  846     def __init__(self, **kwargs):
  847         super(LibvirtConfigGuestCPU, self).__init__(**kwargs)
  848 
  849         self.mode = None
  850         self.match = "exact"
  851         self.numa = None
  852 
  853     def parse_dom(self, xmldoc):
  854         super(LibvirtConfigGuestCPU, self).parse_dom(xmldoc)
  855         self.mode = xmldoc.get('mode')
  856         self.match = xmldoc.get('match')
  857         for child in xmldoc:
  858             if child.tag == "numa":
  859                 numa = LibvirtConfigGuestCPUNUMA()
  860                 numa.parse_dom(child)
  861                 self.numa = numa
  862 
  863     def format_dom(self):
  864         cpu = super(LibvirtConfigGuestCPU, self).format_dom()
  865 
  866         if self.mode:
  867             cpu.set("mode", self.mode)
  868         cpu.set("match", self.match)
  869         if self.numa is not None:
  870             cpu.append(self.numa.format_dom())
  871 
  872         return cpu
  873 
  874 
  875 class LibvirtConfigGuestSMBIOS(LibvirtConfigObject):
  876 
  877     def __init__(self, **kwargs):
  878         super(LibvirtConfigGuestSMBIOS, self).__init__(root_name="smbios",
  879                                                        **kwargs)
  880 
  881         self.mode = "sysinfo"
  882 
  883     def format_dom(self):
  884         smbios = super(LibvirtConfigGuestSMBIOS, self).format_dom()
  885         smbios.set("mode", self.mode)
  886 
  887         return smbios
  888 
  889 
  890 class LibvirtConfigGuestSysinfo(LibvirtConfigObject):
  891 
  892     def __init__(self, **kwargs):
  893         super(LibvirtConfigGuestSysinfo, self).__init__(root_name="sysinfo",
  894                                                         **kwargs)
  895 
  896         self.type = "smbios"
  897         self.bios_vendor = None
  898         self.bios_version = None
  899         self.system_manufacturer = None
  900         self.system_product = None
  901         self.system_version = None
  902         self.system_serial = None
  903         self.system_uuid = None
  904         self.system_family = None
  905 
  906     def format_dom(self):
  907         sysinfo = super(LibvirtConfigGuestSysinfo, self).format_dom()
  908 
  909         sysinfo.set("type", self.type)
  910 
  911         bios = etree.Element("bios")
  912         system = etree.Element("system")
  913 
  914         if self.bios_vendor is not None:
  915             bios.append(self._text_node("entry", self.bios_vendor,
  916                                         name="vendor"))
  917 
  918         if self.bios_version is not None:
  919             bios.append(self._text_node("entry", self.bios_version,
  920                                         name="version"))
  921 
  922         if self.system_manufacturer is not None:
  923             system.append(self._text_node("entry", self.system_manufacturer,
  924                                           name="manufacturer"))
  925 
  926         if self.system_product is not None:
  927             system.append(self._text_node("entry", self.system_product,
  928                                           name="product"))
  929 
  930         if self.system_version is not None:
  931             system.append(self._text_node("entry", self.system_version,
  932                                           name="version"))
  933 
  934         if self.system_serial is not None:
  935             system.append(self._text_node("entry", self.system_serial,
  936                                           name="serial"))
  937 
  938         if self.system_uuid is not None:
  939             system.append(self._text_node("entry", self.system_uuid,
  940                                           name="uuid"))
  941 
  942         if self.system_family is not None:
  943             system.append(self._text_node("entry", self.system_family,
  944                                           name="family"))
  945 
  946         if len(list(bios)) > 0:
  947             sysinfo.append(bios)
  948 
  949         if len(list(system)) > 0:
  950             sysinfo.append(system)
  951 
  952         return sysinfo
  953 
  954 
  955 class LibvirtConfigGuestDevice(LibvirtConfigObject):
  956 
  957     def __init__(self, **kwargs):
  958         super(LibvirtConfigGuestDevice, self).__init__(**kwargs)
  959 
  960     @property
  961     def uses_virtio(self):
  962         return False
  963 
  964 
  965 class LibvirtConfigGuestVTPM(LibvirtConfigGuestDevice):
  966 
  967     def __init__(self, vtpm_config, vtpm_secret_uuid, **kwargs):
  968         super(LibvirtConfigGuestVTPM, self).__init__(root_name="tpm", **kwargs)
  969 
  970         self.version = vtpm_config.version
  971         self.model = vtpm_config.model
  972         self.secret_uuid = vtpm_secret_uuid
  973 
  974     def format_dom(self):
  975         # <tpm model='$model'>
  976         dev = super(LibvirtConfigGuestVTPM, self).format_dom()
  977         dev.set("model", self.model)
  978         #     <backend type='emulator' version='$version'>
  979         back = etree.Element("backend")
  980         back.set("type", "emulator")
  981         back.set("version", self.version)
  982         #         <encryption secret='$secret_uuid'/>
  983         enc = etree.Element("encryption")
  984         enc.set("secret", self.secret_uuid)
  985 
  986         back.append(enc)
  987         dev.append(back)
  988 
  989         return dev
  990 
  991 
  992 class LibvirtConfigGuestDisk(LibvirtConfigGuestDevice):
  993 
  994     def __init__(self, **kwargs):
  995         super(LibvirtConfigGuestDisk, self).__init__(root_name="disk",
  996                                                      **kwargs)
  997 
  998         self.source_type = "file"
  999         self.source_device = "disk"
 1000         self.driver_name = None
 1001         self.driver_format = None
 1002         self.driver_cache = None
 1003         self.driver_discard = None
 1004         self.driver_io = None
 1005         self.driver_iommu = False
 1006         self.source_path = None
 1007         self.source_protocol = None
 1008         self.source_name = None
 1009         self.source_hosts = []
 1010         self.source_ports = []
 1011         self.target_dev = None
 1012         self.target_path = None
 1013         self.target_bus = None
 1014         self.auth_username = None
 1015         self.auth_secret_type = None
 1016         self.auth_secret_uuid = None
 1017         self.serial = None
 1018         self.disk_read_bytes_sec = None
 1019         self.disk_read_iops_sec = None
 1020         self.disk_write_bytes_sec = None
 1021         self.disk_write_iops_sec = None
 1022         self.disk_total_bytes_sec = None
 1023         self.disk_total_iops_sec = None
 1024         self.disk_read_bytes_sec_max = None
 1025         self.disk_write_bytes_sec_max = None
 1026         self.disk_total_bytes_sec_max = None
 1027         self.disk_read_iops_sec_max = None
 1028         self.disk_write_iops_sec_max = None
 1029         self.disk_total_iops_sec_max = None
 1030         self.disk_size_iops_sec = None
 1031         self.logical_block_size = None
 1032         self.physical_block_size = None
 1033         self.readonly = False
 1034         self.shareable = False
 1035         self.snapshot = None
 1036         self.backing_store = None
 1037         self.device_addr = None
 1038         self.boot_order = None
 1039         self.mirror = None
 1040         self.encryption = None
 1041 
 1042     def _format_iotune(self, dev):
 1043         iotune = etree.Element("iotune")
 1044 
 1045         if self.disk_read_bytes_sec is not None:
 1046             iotune.append(self._text_node("read_bytes_sec",
 1047                           self.disk_read_bytes_sec))
 1048 
 1049         if self.disk_read_iops_sec is not None:
 1050             iotune.append(self._text_node("read_iops_sec",
 1051                           self.disk_read_iops_sec))
 1052 
 1053         if self.disk_write_bytes_sec is not None:
 1054             iotune.append(self._text_node("write_bytes_sec",
 1055                           self.disk_write_bytes_sec))
 1056 
 1057         if self.disk_write_iops_sec is not None:
 1058             iotune.append(self._text_node("write_iops_sec",
 1059                           self.disk_write_iops_sec))
 1060 
 1061         if self.disk_total_bytes_sec is not None:
 1062             iotune.append(self._text_node("total_bytes_sec",
 1063                           self.disk_total_bytes_sec))
 1064 
 1065         if self.disk_total_iops_sec is not None:
 1066             iotune.append(self._text_node("total_iops_sec",
 1067                           self.disk_total_iops_sec))
 1068 
 1069         if self.disk_read_bytes_sec_max is not None:
 1070             iotune.append(self._text_node("read_bytes_sec_max",
 1071                           self.disk_read_bytes_sec_max))
 1072 
 1073         if self.disk_write_bytes_sec_max is not None:
 1074             iotune.append(self._text_node("write_bytes_sec_max",
 1075                           self.disk_write_bytes_sec_max))
 1076 
 1077         if self.disk_total_bytes_sec_max is not None:
 1078             iotune.append(self._text_node("total_bytes_sec_max",
 1079                           self.disk_total_bytes_sec_max))
 1080 
 1081         if self.disk_read_iops_sec_max is not None:
 1082             iotune.append(self._text_node("read_iops_sec_max",
 1083                           self.disk_read_iops_sec_max))
 1084 
 1085         if self.disk_write_iops_sec_max is not None:
 1086             iotune.append(self._text_node("write_iops_sec_max",
 1087                           self.disk_write_iops_sec_max))
 1088 
 1089         if self.disk_total_iops_sec_max is not None:
 1090             iotune.append(self._text_node("total_iops_sec_max",
 1091                           self.disk_total_iops_sec_max))
 1092 
 1093         if self.disk_size_iops_sec is not None:
 1094             iotune.append(self._text_node("size_iops_sec",
 1095                           self.disk_size_iops_sec))
 1096 
 1097         if len(iotune) > 0:
 1098             dev.append(iotune)
 1099 
 1100     @property
 1101     def uses_virtio(self):
 1102         return 'virtio' == self.target_bus
 1103 
 1104     def format_dom(self):
 1105         dev = super(LibvirtConfigGuestDisk, self).format_dom()
 1106 
 1107         dev.set("type", self.source_type)
 1108         dev.set("device", self.source_device)
 1109         if any((self.driver_name, self.driver_format, self.driver_cache,
 1110                 self.driver_discard, self.driver_iommu)):
 1111             drv = etree.Element("driver")
 1112             if self.driver_name is not None:
 1113                 drv.set("name", self.driver_name)
 1114             if self.driver_format is not None:
 1115                 drv.set("type", self.driver_format)
 1116             if self.driver_cache is not None:
 1117                 drv.set("cache", self.driver_cache)
 1118             if self.driver_discard is not None:
 1119                 drv.set("discard", self.driver_discard)
 1120             if self.driver_io is not None:
 1121                 drv.set("io", self.driver_io)
 1122             if self.driver_iommu:
 1123                 drv.set("iommu", "on")
 1124             dev.append(drv)
 1125 
 1126         if self.source_type == "file":
 1127             dev.append(etree.Element("source", file=self.source_path))
 1128         elif self.source_type == "block":
 1129             dev.append(etree.Element("source", dev=self.source_path))
 1130         elif self.source_type == "mount":
 1131             dev.append(etree.Element("source", dir=self.source_path))
 1132         elif self.source_type == "network" and self.source_protocol:
 1133             source = etree.Element("source", protocol=self.source_protocol)
 1134             if self.source_name is not None:
 1135                 source.set('name', self.source_name)
 1136             hosts_info = zip(self.source_hosts, self.source_ports)
 1137             for name, port in hosts_info:
 1138                 host = etree.Element('host', name=name)
 1139                 if port is not None:
 1140                     host.set('port', port)
 1141                 source.append(host)
 1142             dev.append(source)
 1143 
 1144         if self.auth_secret_type is not None:
 1145             auth = etree.Element("auth")
 1146             auth.set("username", self.auth_username)
 1147             auth.append(etree.Element("secret", type=self.auth_secret_type,
 1148                                       uuid=self.auth_secret_uuid))
 1149             dev.append(auth)
 1150 
 1151         if self.source_type == "mount":
 1152             dev.append(etree.Element("target", dir=self.target_path))
 1153         else:
 1154             dev.append(etree.Element("target", dev=self.target_dev,
 1155                                      bus=self.target_bus))
 1156 
 1157         if self.serial is not None:
 1158             dev.append(self._text_node("serial", self.serial))
 1159 
 1160         self._format_iotune(dev)
 1161 
 1162         # Block size tuning
 1163         if (self.logical_block_size is not None or
 1164                 self.physical_block_size is not None):
 1165 
 1166             blockio = etree.Element("blockio")
 1167             if self.logical_block_size is not None:
 1168                 blockio.set('logical_block_size', self.logical_block_size)
 1169 
 1170             if self.physical_block_size is not None:
 1171                 blockio.set('physical_block_size', self.physical_block_size)
 1172 
 1173             dev.append(blockio)
 1174 
 1175         if self.readonly:
 1176             dev.append(etree.Element("readonly"))
 1177         if self.shareable:
 1178             dev.append(etree.Element("shareable"))
 1179 
 1180         if self.boot_order:
 1181             dev.append(etree.Element("boot", order=self.boot_order))
 1182 
 1183         if self.device_addr:
 1184             dev.append(self.device_addr.format_dom())
 1185 
 1186         if self.encryption:
 1187             dev.append(self.encryption.format_dom())
 1188 
 1189         return dev
 1190 
 1191     def parse_dom(self, xmldoc):
 1192         super(LibvirtConfigGuestDisk, self).parse_dom(xmldoc)
 1193 
 1194         self.source_type = xmldoc.get('type')
 1195         self.snapshot = xmldoc.get('snapshot')
 1196 
 1197         for c in xmldoc:
 1198             if c.tag == 'driver':
 1199                 self.driver_name = c.get('name')
 1200                 self.driver_format = c.get('type')
 1201                 self.driver_cache = c.get('cache')
 1202                 self.driver_discard = c.get('discard')
 1203                 self.driver_io = c.get('io')
 1204                 self.driver_iommu = c.get('iommu', '') == "on"
 1205             elif c.tag == 'source':
 1206                 if self.source_type == 'file':
 1207                     self.source_path = c.get('file')
 1208                 elif self.source_type == 'block':
 1209                     self.source_path = c.get('dev')
 1210                 elif self.source_type == 'mount':
 1211                     self.source_path = c.get('dir')
 1212                 elif self.source_type == 'network':
 1213                     self.source_protocol = c.get('protocol')
 1214                     self.source_name = c.get('name')
 1215                     for sub in c:
 1216                         if sub.tag == 'host':
 1217                             self.source_hosts.append(sub.get('name'))
 1218                             self.source_ports.append(sub.get('port'))
 1219 
 1220             elif c.tag == 'serial':
 1221                 self.serial = c.text
 1222             elif c.tag == 'target':
 1223                 if self.source_type == 'mount':
 1224                     self.target_path = c.get('dir')
 1225                 else:
 1226                     self.target_dev = c.get('dev')
 1227 
 1228                 self.target_bus = c.get('bus', None)
 1229             elif c.tag == 'backingStore':
 1230                 b = LibvirtConfigGuestDiskBackingStore()
 1231                 b.parse_dom(c)
 1232                 self.backing_store = b
 1233             elif c.tag == 'readonly':
 1234                 self.readonly = True
 1235             elif c.tag == 'shareable':
 1236                 self.shareable = True
 1237             elif c.tag == 'address':
 1238                 obj = LibvirtConfigGuestDeviceAddress.parse_dom(c)
 1239                 self.device_addr = obj
 1240             elif c.tag == 'boot':
 1241                 self.boot_order = c.get('order')
 1242             elif c.tag == 'mirror':
 1243                 m = LibvirtConfigGuestDiskMirror()
 1244                 m.parse_dom(c)
 1245                 self.mirror = m
 1246             elif c.tag == 'encryption':
 1247                 e = LibvirtConfigGuestDiskEncryption()
 1248                 e.parse_dom(c)
 1249                 self.encryption = e
 1250 
 1251 
 1252 class LibvirtConfigGuestDiskBackingStore(LibvirtConfigObject):
 1253     def __init__(self, **kwargs):
 1254         super(LibvirtConfigGuestDiskBackingStore, self).__init__(
 1255             root_name="backingStore", **kwargs)
 1256 
 1257         self.index = None
 1258         self.source_type = None
 1259         self.source_file = None
 1260         self.source_protocol = None
 1261         self.source_name = None
 1262         self.source_hosts = []
 1263         self.source_ports = []
 1264         self.driver_name = None
 1265         self.driver_format = None
 1266         self.backing_store = None
 1267 
 1268     def parse_dom(self, xmldoc):
 1269         super(LibvirtConfigGuestDiskBackingStore, self).parse_dom(xmldoc)
 1270 
 1271         self.source_type = xmldoc.get('type')
 1272         self.index = xmldoc.get('index')
 1273 
 1274         for c in xmldoc:
 1275             if c.tag == 'driver':
 1276                 self.driver_name = c.get('name')
 1277                 self.driver_format = c.get('type')
 1278             elif c.tag == 'source':
 1279                 self.source_file = c.get('file')
 1280                 self.source_protocol = c.get('protocol')
 1281                 self.source_name = c.get('name')
 1282                 for d in c:
 1283                     if d.tag == 'host':
 1284                         self.source_hosts.append(d.get('name'))
 1285                         self.source_ports.append(d.get('port'))
 1286             elif c.tag == 'backingStore':
 1287                 if len(c):
 1288                     self.backing_store = LibvirtConfigGuestDiskBackingStore()
 1289                     self.backing_store.parse_dom(c)
 1290 
 1291 
 1292 class LibvirtConfigGuestSnapshotDisk(LibvirtConfigObject):
 1293     """Disk class for handling disk information in snapshots.
 1294 
 1295     Similar to LibvirtConfigGuestDisk, but used to represent
 1296     disk entities in <domainsnapshot> structures rather than
 1297     real devices.  These typically have fewer members, and
 1298     different expectations for which fields are required.
 1299     """
 1300 
 1301     def __init__(self, **kwargs):
 1302         super(LibvirtConfigGuestSnapshotDisk, self).__init__(root_name="disk",
 1303                                                              **kwargs)
 1304 
 1305         self.source_type = None
 1306         self.source_device = None
 1307         self.name = None
 1308         self.snapshot = None
 1309         self.driver_name = None
 1310         self.driver_format = None
 1311         self.driver_cache = None
 1312         self.source_path = None
 1313         self.source_protocol = None
 1314         self.source_name = None
 1315         self.source_hosts = []
 1316         self.source_ports = []
 1317         self.target_dev = None
 1318         self.target_path = None
 1319         self.target_bus = None
 1320         self.auth_username = None
 1321         self.auth_secret_type = None
 1322         self.auth_secret_uuid = None
 1323         self.serial = None
 1324 
 1325     def format_dom(self):
 1326         dev = super(LibvirtConfigGuestSnapshotDisk, self).format_dom()
 1327 
 1328         if self.name:
 1329             dev.attrib['name'] = self.name
 1330         if self.snapshot:
 1331             dev.attrib['snapshot'] = self.snapshot
 1332 
 1333         if self.source_type:
 1334             dev.set("type", self.source_type)
 1335 
 1336         if self.source_device:
 1337             dev.set("device", self.source_device)
 1338             if (self.driver_name is not None or
 1339                 self.driver_format is not None or
 1340                     self.driver_cache is not None):
 1341                 drv = etree.Element("driver")
 1342                 if self.driver_name is not None:
 1343                     drv.set("name", self.driver_name)
 1344                 if self.driver_format is not None:
 1345                     drv.set("type", self.driver_format)
 1346                 if self.driver_cache is not None:
 1347                     drv.set("cache", self.driver_cache)
 1348                 dev.append(drv)
 1349 
 1350         if self.source_type == "file":
 1351             dev.append(etree.Element("source", file=self.source_path))
 1352         elif self.source_type == "block":
 1353             dev.append(etree.Element("source", dev=self.source_path))
 1354         elif self.source_type == "mount":
 1355             dev.append(etree.Element("source", dir=self.source_path))
 1356         elif self.source_type == "network":
 1357             source = etree.Element("source", protocol=self.source_protocol)
 1358             if self.source_name is not None:
 1359                 source.set('name', self.source_name)
 1360             hosts_info = zip(self.source_hosts, self.source_ports)
 1361             for name, port in hosts_info:
 1362                 host = etree.Element('host', name=name)
 1363                 if port is not None:
 1364                     host.set('port', port)
 1365                 source.append(host)
 1366             dev.append(source)
 1367 
 1368         if self.auth_secret_type is not None:
 1369             auth = etree.Element("auth")
 1370             auth.set("username", self.auth_username)
 1371             auth.append(etree.Element("secret", type=self.auth_secret_type,
 1372                                       uuid=self.auth_secret_uuid))
 1373             dev.append(auth)
 1374 
 1375         if self.source_type == "mount":
 1376             dev.append(etree.Element("target", dir=self.target_path))
 1377         else:
 1378             if self.target_bus and self.target_dev:
 1379                 dev.append(etree.Element("target", dev=self.target_dev,
 1380                                          bus=self.target_bus))
 1381 
 1382         return dev
 1383 
 1384     def parse_dom(self, xmldoc):
 1385         super(LibvirtConfigGuestSnapshotDisk, self).parse_dom(xmldoc)
 1386 
 1387         self.source_type = xmldoc.get('type')
 1388         self.snapshot = xmldoc.get('snapshot')
 1389 
 1390         for c in xmldoc:
 1391             if c.tag == 'driver':
 1392                 self.driver_name = c.get('name')
 1393                 self.driver_format = c.get('type')
 1394                 self.driver_cache = c.get('cache')
 1395             elif c.tag == 'source':
 1396                 if self.source_type == 'file':
 1397                     self.source_path = c.get('file')
 1398                 elif self.source_type == 'block':
 1399                     self.source_path = c.get('dev')
 1400                 elif self.source_type == 'mount':
 1401                     self.source_path = c.get('dir')
 1402                 elif self.source_type == 'network':
 1403                     self.source_protocol = c.get('protocol')
 1404                     self.source_name = c.get('name')
 1405                     for sub in c:
 1406                         if sub.tag == 'host':
 1407                             self.source_hosts.append(sub.get('name'))
 1408                             self.source_ports.append(sub.get('port'))
 1409 
 1410             elif c.tag == 'serial':
 1411                 self.serial = c.text
 1412 
 1413         for c in xmldoc:
 1414             if c.tag == 'target':
 1415                 if self.source_type == 'mount':
 1416                     self.target_path = c.get('dir')
 1417                 else:
 1418                     self.target_dev = c.get('dev')
 1419 
 1420                 self.target_bus = c.get('bus', None)
 1421 
 1422 
 1423 class LibvirtConfigGuestFilesys(LibvirtConfigGuestDevice):
 1424 
 1425     def __init__(self, **kwargs):
 1426         super(LibvirtConfigGuestFilesys, self).__init__(root_name="filesystem",
 1427                                                         **kwargs)
 1428 
 1429         self.source_type = "mount"
 1430         self.source_dir = None
 1431         self.source_file = None
 1432         self.source_dev = None
 1433         self.target_dir = "/"
 1434         self.driver_type = "loop"
 1435         self.driver_format = "raw"
 1436 
 1437     def format_dom(self):
 1438         dev = super(LibvirtConfigGuestFilesys, self).format_dom()
 1439 
 1440         dev.set("type", self.source_type)
 1441 
 1442         if self.source_type == "file":
 1443             dev.append(etree.Element("driver", type = self.driver_type,
 1444                                      format = self.driver_format))
 1445             dev.append(etree.Element("source", file=self.source_file))
 1446         elif self.source_type == "block":
 1447             dev.append(etree.Element("source", dev=self.source_dev))
 1448         else:
 1449             dev.append(etree.Element("source", dir=self.source_dir))
 1450         dev.append(etree.Element("target", dir=self.target_dir))
 1451 
 1452         return dev
 1453 
 1454     def parse_dom(self, xmldoc):
 1455         super(LibvirtConfigGuestFilesys, self).parse_dom(xmldoc)
 1456 
 1457         self.source_type = xmldoc.get('type')
 1458 
 1459         for c in xmldoc:
 1460             if c.tag == 'driver':
 1461                 if self.source_type == 'file':
 1462                     self.driver_type = c.get('type')
 1463                     self.driver_format = c.get('format')
 1464             elif c.tag == 'source':
 1465                 if self.source_type == 'file':
 1466                     self.source_file = c.get('file')
 1467                 elif self.source_type == 'block':
 1468                     self.source_dev = c.get('dev')
 1469                 else:
 1470                     self.source_dir = c.get('dir')
 1471             elif c.tag == 'target':
 1472                 self.target_dir = c.get('dir')
 1473 
 1474 
 1475 class LibvirtConfigGuestDiskEncryptionSecret(LibvirtConfigObject):
 1476     def __init__(self, **kwargs):
 1477         super(LibvirtConfigGuestDiskEncryptionSecret, self).__init__(**kwargs)
 1478         self.type = None
 1479         self.uuid = None
 1480 
 1481     def parse_dom(self, xmldoc):
 1482         self.type = xmldoc.get('type')
 1483         self.uuid = xmldoc.get('uuid')
 1484 
 1485     def format_dom(self):
 1486         obj = etree.Element("secret")
 1487         obj.set("type", self.type)
 1488         obj.set("uuid", self.uuid)
 1489         return obj
 1490 
 1491 
 1492 class LibvirtConfigGuestDiskEncryption(LibvirtConfigObject):
 1493     """https://libvirt.org/formatstorageencryption.html
 1494     """
 1495     def __init__(self, **kwargs):
 1496         super(LibvirtConfigGuestDiskEncryption, self).__init__(**kwargs)
 1497         self.format = None
 1498         self.secret = None
 1499 
 1500     def parse_dom(self, xmldoc):
 1501         self.format = xmldoc.get('format')
 1502         for c in xmldoc:
 1503             if c.tag == 'secret':
 1504                 m = LibvirtConfigGuestDiskEncryptionSecret()
 1505                 m.parse_dom(c)
 1506                 self.secret = m
 1507 
 1508     def format_dom(self):
 1509         obj = etree.Element("encryption")
 1510         obj.set("format", self.format)
 1511         obj.append(self.secret.format_dom())
 1512 
 1513         return obj
 1514 
 1515 
 1516 class LibvirtConfigGuestDiskMirror(LibvirtConfigObject):
 1517 
 1518     def __init__(self, **kwargs):
 1519         super(LibvirtConfigGuestDiskMirror, self).__init__(**kwargs)
 1520         self.ready = None
 1521 
 1522     def parse_dom(self, xmldoc):
 1523         self.ready = xmldoc.get('ready')
 1524 
 1525 
 1526 class LibvirtConfigGuestIDMap(LibvirtConfigObject):
 1527 
 1528     def __init__(self, **kwargs):
 1529         super(LibvirtConfigGuestIDMap, self).__init__(**kwargs)
 1530         self.start = 0
 1531         self.target = 0
 1532         self.count = 10000
 1533 
 1534     def parse_dom(self, xmldoc):
 1535         self.start = int(xmldoc.get('start'))
 1536         self.target = int(xmldoc.get('target'))
 1537         self.count = int(xmldoc.get('count'))
 1538 
 1539     def format_dom(self):
 1540         obj = super(LibvirtConfigGuestIDMap, self).format_dom()
 1541 
 1542         obj.set("start", str(self.start))
 1543         obj.set("target", str(self.target))
 1544         obj.set("count", str(self.count))
 1545 
 1546         return obj
 1547 
 1548 
 1549 class LibvirtConfigGuestUIDMap(LibvirtConfigGuestIDMap):
 1550 
 1551     def __init__(self, **kwargs):
 1552         super(LibvirtConfigGuestUIDMap, self).__init__(root_name="uid",
 1553                                                        **kwargs)
 1554 
 1555 
 1556 class LibvirtConfigGuestGIDMap(LibvirtConfigGuestIDMap):
 1557 
 1558     def __init__(self, **kwargs):
 1559         super(LibvirtConfigGuestGIDMap, self).__init__(root_name="gid",
 1560                                                        **kwargs)
 1561 
 1562 
 1563 class LibvirtConfigGuestDeviceAddress(LibvirtConfigObject):
 1564     def __init__(self, type=None, **kwargs):
 1565         super(LibvirtConfigGuestDeviceAddress, self).__init__(
 1566             root_name='address', **kwargs)
 1567         self.type = type
 1568 
 1569     def format_dom(self):
 1570         xml = super(LibvirtConfigGuestDeviceAddress, self).format_dom()
 1571         xml.set("type", self.type)
 1572         return xml
 1573 
 1574     @staticmethod
 1575     def parse_dom(xmldoc):
 1576         addr_type = xmldoc.get('type')
 1577         if addr_type == 'pci':
 1578             obj = LibvirtConfigGuestDeviceAddressPCI()
 1579         elif addr_type == 'drive':
 1580             obj = LibvirtConfigGuestDeviceAddressDrive()
 1581         else:
 1582             return None
 1583         obj.parse_dom(xmldoc)
 1584         return obj
 1585 
 1586 
 1587 class LibvirtConfigGuestDeviceAddressDrive(LibvirtConfigGuestDeviceAddress):
 1588     def __init__(self, **kwargs):
 1589         super(LibvirtConfigGuestDeviceAddressDrive, self).\
 1590                 __init__(type='drive', **kwargs)
 1591         self.controller = None
 1592         self.bus = None
 1593         self.target = None
 1594         self.unit = None
 1595 
 1596     def format_dom(self):
 1597         xml = super(LibvirtConfigGuestDeviceAddressDrive, self).format_dom()
 1598 
 1599         if self.controller is not None:
 1600             xml.set("controller", str(self.controller))
 1601         if self.bus is not None:
 1602             xml.set("bus", str(self.bus))
 1603         if self.target is not None:
 1604             xml.set("target", str(self.target))
 1605         if self.unit is not None:
 1606             xml.set("unit", str(self.unit))
 1607 
 1608         return xml
 1609 
 1610     def parse_dom(self, xmldoc):
 1611         self.controller = xmldoc.get('controller')
 1612         self.bus = xmldoc.get('bus')
 1613         self.target = xmldoc.get('target')
 1614         self.unit = xmldoc.get('unit')
 1615 
 1616     def format_address(self):
 1617         return None
 1618 
 1619 
 1620 class LibvirtConfigGuestDeviceAddressPCI(LibvirtConfigGuestDeviceAddress):
 1621     def __init__(self, **kwargs):
 1622         super(LibvirtConfigGuestDeviceAddressPCI, self).\
 1623                 __init__(type='pci', **kwargs)
 1624         self.domain = None
 1625         self.bus = None
 1626         self.slot = None
 1627         self.function = None
 1628 
 1629     def format_dom(self):
 1630         xml = super(LibvirtConfigGuestDeviceAddressPCI, self).format_dom()
 1631 
 1632         if self.domain is not None:
 1633             xml.set("domain", str(self.domain))
 1634         if self.bus is not None:
 1635             xml.set("bus", str(self.bus))
 1636         if self.slot is not None:
 1637             xml.set("slot", str(self.slot))
 1638         if self.function is not None:
 1639             xml.set("function", str(self.function))
 1640 
 1641         return xml
 1642 
 1643     def parse_dom(self, xmldoc):
 1644         self.domain = xmldoc.get('domain')
 1645         self.bus = xmldoc.get('bus')
 1646         self.slot = xmldoc.get('slot')
 1647         self.function = xmldoc.get('function')
 1648 
 1649     def format_address(self):
 1650         if self.domain is not None:
 1651             return pci_utils.get_pci_address(self.domain[2:],
 1652                                              self.bus[2:],
 1653                                              self.slot[2:],
 1654                                              self.function[2:])
 1655 
 1656 
 1657 class LibvirtConfigGuestInterface(LibvirtConfigGuestDevice):
 1658 
 1659     def __init__(self, **kwargs):
 1660         super(LibvirtConfigGuestInterface, self).__init__(
 1661             root_name="interface",
 1662             **kwargs)
 1663 
 1664         self.net_type = None
 1665         self.target_dev = None
 1666         self.model = None
 1667         self.mac_addr = None
 1668         self.script = None
 1669         self.source_dev = None
 1670         self.source_mode = "private"
 1671         self.vporttype = None
 1672         self.vportparams = []
 1673         self.filtername = None
 1674         self.filterparams = []
 1675         self.driver_name = None
 1676         self.driver_iommu = False
 1677         self.vhostuser_mode = None
 1678         self.vhostuser_path = None
 1679         self.vhostuser_type = None
 1680         self.vhost_queues = None
 1681         self.vhost_rx_queue_size = None
 1682         self.vhost_tx_queue_size = None
 1683         self.vif_inbound_peak = None
 1684         self.vif_inbound_burst = None
 1685         self.vif_inbound_average = None
 1686         self.vif_outbound_peak = None
 1687         self.vif_outbound_burst = None
 1688         self.vif_outbound_average = None
 1689         self.vlan = None
 1690         self.device_addr = None
 1691         self.mtu = None
 1692 
 1693     def __eq__(self, other):
 1694         if not isinstance(other, LibvirtConfigGuestInterface):
 1695             return False
 1696 
 1697         # NOTE(arches) Skip checking target_dev for vhostuser
 1698         # vif type; target_dev is not a valid value for vhostuser.
 1699         # NOTE(gibi): For macvtap cases the domain has a target_dev
 1700         # generated by libvirt. It is not set by the vif driver code
 1701         # so it is not in config returned by the vif driver so we
 1702         # should not match on that.
 1703         return (
 1704             self.mac_addr == other.mac_addr and
 1705             self.net_type == other.net_type and
 1706             self.source_dev == other.source_dev and
 1707             (self.net_type == 'vhostuser' or not self.target_dev or
 1708                 self.target_dev == other.target_dev) and
 1709             self.vhostuser_path == other.vhostuser_path)
 1710 
 1711     @property
 1712     def uses_virtio(self):
 1713         return 'virtio' == self.model
 1714 
 1715     def format_dom(self):
 1716         dev = super(LibvirtConfigGuestInterface, self).format_dom()
 1717 
 1718         dev.set("type", self.net_type)
 1719         if self.net_type == "hostdev":
 1720             dev.set("managed", "yes")
 1721         dev.append(etree.Element("mac", address=self.mac_addr))
 1722         if self.model:
 1723             dev.append(etree.Element("model", type=self.model))
 1724 
 1725         drv_elem = None
 1726         if (self.driver_name or
 1727                 self.driver_iommu or
 1728                 self.net_type == "vhostuser"):
 1729 
 1730             drv_elem = etree.Element("driver")
 1731             if self.driver_name and self.net_type != "vhostuser":
 1732                 # For vhostuser interface we should not set the driver name.
 1733                 drv_elem.set("name", self.driver_name)
 1734             if self.driver_iommu:
 1735                 drv_elem.set("iommu", "on")
 1736 
 1737         if drv_elem is not None:
 1738             if self.vhost_queues is not None:
 1739                 drv_elem.set('queues', str(self.vhost_queues))
 1740             if self.vhost_rx_queue_size is not None:
 1741                 drv_elem.set('rx_queue_size', str(self.vhost_rx_queue_size))
 1742             if self.vhost_tx_queue_size is not None:
 1743                 drv_elem.set('tx_queue_size', str(self.vhost_tx_queue_size))
 1744 
 1745             if (drv_elem.get('name') or drv_elem.get('queues') or
 1746                 drv_elem.get('rx_queue_size') or
 1747                 drv_elem.get('tx_queue_size') or
 1748                 drv_elem.get('iommu')):
 1749                 # Append the driver element into the dom only if name
 1750                 # or queues or tx/rx or iommu attributes are set.
 1751                 dev.append(drv_elem)
 1752 
 1753         if self.net_type == "ethernet":
 1754             if self.script is not None:
 1755                 dev.append(etree.Element("script", path=self.script))
 1756             if self.mtu is not None:
 1757                 dev.append(etree.Element("mtu", size=str(self.mtu)))
 1758         elif self.net_type == "direct":
 1759             dev.append(etree.Element("source", dev=self.source_dev,
 1760                                      mode=self.source_mode))
 1761         elif self.net_type == "hostdev":
 1762             source_elem = etree.Element("source")
 1763             domain, bus, slot, func = \
 1764                 pci_utils.get_pci_address_fields(self.source_dev)
 1765             addr_elem = etree.Element("address", type='pci')
 1766             addr_elem.set("domain", "0x%s" % (domain))
 1767             addr_elem.set("bus", "0x%s" % (bus))
 1768             addr_elem.set("slot", "0x%s" % (slot))
 1769             addr_elem.set("function", "0x%s" % (func))
 1770             source_elem.append(addr_elem)
 1771             dev.append(source_elem)
 1772         elif self.net_type == "vhostuser":
 1773             dev.append(etree.Element("source", type=self.vhostuser_type,
 1774                                      mode=self.vhostuser_mode,
 1775                                      path=self.vhostuser_path))
 1776         elif self.net_type == "bridge":
 1777             dev.append(etree.Element("source", bridge=self.source_dev))
 1778             if self.script is not None:
 1779                 dev.append(etree.Element("script", path=self.script))
 1780             if self.mtu is not None:
 1781                 dev.append(etree.Element("mtu", size=str(self.mtu)))
 1782         else:
 1783             dev.append(etree.Element("source", bridge=self.source_dev))
 1784 
 1785         if self.vlan and self.net_type in ("direct", "hostdev"):
 1786             vlan_elem = etree.Element("vlan")
 1787             tag_elem = etree.Element("tag", id=str(self.vlan))
 1788             vlan_elem.append(tag_elem)
 1789             dev.append(vlan_elem)
 1790 
 1791         if self.target_dev is not None:
 1792             dev.append(etree.Element("target", dev=self.target_dev))
 1793 
 1794         if self.vporttype is not None:
 1795             vport = etree.Element("virtualport", type=self.vporttype)
 1796             for p in self.vportparams:
 1797                 param = etree.Element("parameters")
 1798                 param.set(p['key'], p['value'])
 1799                 vport.append(param)
 1800             dev.append(vport)
 1801 
 1802         if self.filtername is not None:
 1803             filter = etree.Element("filterref", filter=self.filtername)
 1804             for p in self.filterparams:
 1805                 filter.append(etree.Element("parameter",
 1806                                             name=p['key'],
 1807                                             value=p['value']))
 1808             dev.append(filter)
 1809 
 1810         if self.vif_inbound_average or self.vif_outbound_average:
 1811             bandwidth = etree.Element("bandwidth")
 1812             if self.vif_inbound_average is not None:
 1813                 vif_inbound = etree.Element("inbound",
 1814                 average=str(self.vif_inbound_average))
 1815                 if self.vif_inbound_peak is not None:
 1816                     vif_inbound.set("peak", str(self.vif_inbound_peak))
 1817                 if self.vif_inbound_burst is not None:
 1818                     vif_inbound.set("burst", str(self.vif_inbound_burst))
 1819                 bandwidth.append(vif_inbound)
 1820 
 1821             if self.vif_outbound_average is not None:
 1822                 vif_outbound = etree.Element("outbound",
 1823                 average=str(self.vif_outbound_average))
 1824                 if self.vif_outbound_peak is not None:
 1825                     vif_outbound.set("peak", str(self.vif_outbound_peak))
 1826                 if self.vif_outbound_burst is not None:
 1827                     vif_outbound.set("burst", str(self.vif_outbound_burst))
 1828                 bandwidth.append(vif_outbound)
 1829             dev.append(bandwidth)
 1830 
 1831         return dev
 1832 
 1833     def parse_dom(self, xmldoc):
 1834         super(LibvirtConfigGuestInterface, self).parse_dom(xmldoc)
 1835 
 1836         self.net_type = xmldoc.get('type')
 1837 
 1838         for c in xmldoc:
 1839             if c.tag == 'mac':
 1840                 self.mac_addr = c.get('address')
 1841             elif c.tag == 'model':
 1842                 self.model = c.get('type')
 1843             elif c.tag == 'driver':
 1844                 self.driver_name = c.get('name')
 1845                 self.driver_iommu = (c.get('iommu', '') == 'on')
 1846                 self.vhost_queues = c.get('queues')
 1847                 self.vhost_rx_queue_size = c.get('rx_queue_size')
 1848                 self.vhost_tx_queue_size = c.get('tx_queue_size')
 1849             elif c.tag == 'source':
 1850                 if self.net_type == 'direct':
 1851                     self.source_dev = c.get('dev')
 1852                     self.source_mode = c.get('mode', 'private')
 1853                 elif self.net_type == 'vhostuser':
 1854                     self.vhostuser_type = c.get('type')
 1855                     self.vhostuser_mode = c.get('mode')
 1856                     self.vhostuser_path = c.get('path')
 1857                 elif self.net_type == 'hostdev':
 1858                     for sub in c:
 1859                         if sub.tag == 'address' and sub.get('type') == 'pci':
 1860                             # strip the 0x prefix on each attribute since
 1861                             # format_dom puts them back on - note that
 1862                             # LibvirtConfigGuestHostdevPCI does not do this...
 1863                             self.source_dev = (
 1864                                 pci_utils.get_pci_address(
 1865                                     sub.get('domain')[2:],
 1866                                     sub.get('bus')[2:],
 1867                                     sub.get('slot')[2:],
 1868                                     sub.get('function')[2:]
 1869                                 )
 1870                             )
 1871                 else:
 1872                     self.source_dev = c.get('bridge')
 1873             elif c.tag == 'target':
 1874                 self.target_dev = c.get('dev')
 1875             elif c.tag == 'script':
 1876                 self.script = c.get('path')
 1877             elif c.tag == 'vlan':
 1878                 # NOTE(mriedem): The vlan element can have multiple tag
 1879                 # sub-elements but we're currently only storing a single tag
 1880                 # id in the vlan attribute.
 1881                 for sub in c:
 1882                     if sub.tag == 'tag' and sub.get('id'):
 1883                         self.vlan = int(sub.get('id'))
 1884                         break
 1885             elif c.tag == 'virtualport':
 1886                 self.vporttype = c.get('type')
 1887                 for sub in c:
 1888                     if sub.tag == 'parameters':
 1889                         for k, v in dict(sub.attrib).items():
 1890                             self.add_vport_param(k, v)
 1891             elif c.tag == 'filterref':
 1892                 self.filtername = c.get('filter')
 1893                 for sub in c:
 1894                     if sub.tag == 'parameter':
 1895                         self.add_filter_param(sub.get('name'),
 1896                                               sub.get('value'))
 1897             elif c.tag == 'bandwidth':
 1898                 for sub in c:
 1899                     # Note that only average is mandatory, burst and peak are
 1900                     # optional (and all are ints).
 1901                     if sub.tag == 'inbound':
 1902                         self.vif_inbound_average = int(sub.get('average'))
 1903                         if sub.get('burst'):
 1904                             self.vif_inbound_burst = int(sub.get('burst'))
 1905                         if sub.get('peak'):
 1906                             self.vif_inbound_peak = int(sub.get('peak'))
 1907                     elif sub.tag == 'outbound':
 1908                         self.vif_outbound_average = int(sub.get('average'))
 1909                         if sub.get('burst'):
 1910                             self.vif_outbound_burst = int(sub.get('burst'))
 1911                         if sub.get('peak'):
 1912                             self.vif_outbound_peak = int(sub.get('peak'))
 1913             elif c.tag == 'address':
 1914                 obj = LibvirtConfigGuestDeviceAddress.parse_dom(c)
 1915                 self.device_addr = obj
 1916             elif c.tag == 'mtu':
 1917                 self.mtu = int(c.get('size'))
 1918 
 1919     def add_filter_param(self, key, value):
 1920         self.filterparams.append({'key': key, 'value': value})
 1921 
 1922     def add_vport_param(self, key, value):
 1923         self.vportparams.append({'key': key, 'value': value})
 1924 
 1925 
 1926 class LibvirtConfigGuestInput(LibvirtConfigGuestDevice):
 1927 
 1928     def __init__(self, **kwargs):
 1929         super(LibvirtConfigGuestInput, self).__init__(root_name="input",
 1930                                                       **kwargs)
 1931 
 1932         self.type = "tablet"
 1933         self.bus = "usb"
 1934         self.driver_iommu = False
 1935 
 1936     def format_dom(self):
 1937         dev = super(LibvirtConfigGuestInput, self).format_dom()
 1938 
 1939         dev.set("type", self.type)
 1940         dev.set("bus", self.bus)
 1941         if self.driver_iommu:
 1942             dev.append(etree.Element('driver', iommu="on"))
 1943 
 1944         return dev
 1945 
 1946 
 1947 class LibvirtConfigGuestGraphics(LibvirtConfigGuestDevice):
 1948 
 1949     def __init__(self, **kwargs):
 1950         super(LibvirtConfigGuestGraphics, self).__init__(root_name="graphics",
 1951                                                          **kwargs)
 1952 
 1953         self.type = "vnc"
 1954         self.autoport = True
 1955         self.keymap = None
 1956         self.listen = None
 1957 
 1958     def format_dom(self):
 1959         dev = super(LibvirtConfigGuestGraphics, self).format_dom()
 1960 
 1961         dev.set("type", self.type)
 1962         if self.autoport:
 1963             dev.set("autoport", "yes")
 1964         else:
 1965             dev.set("autoport", "no")
 1966         if self.keymap:
 1967             dev.set("keymap", self.keymap)
 1968         if self.listen:
 1969             dev.set("listen", self.listen)
 1970 
 1971         return dev
 1972 
 1973 
 1974 class LibvirtConfigSeclabel(LibvirtConfigObject):
 1975 
 1976     def __init__(self, **kwargs):
 1977         super(LibvirtConfigSeclabel, self).__init__(root_name="seclabel",
 1978                                                       **kwargs)
 1979         self.type = 'dynamic'
 1980         self.baselabel = None
 1981 
 1982     def format_dom(self):
 1983         seclabel = super(LibvirtConfigSeclabel, self).format_dom()
 1984 
 1985         seclabel.set('type', self.type)
 1986         if self.baselabel:
 1987             seclabel.append(self._text_node("baselabel", self.baselabel))
 1988 
 1989         return seclabel
 1990 
 1991 
 1992 class LibvirtConfigGuestVideo(LibvirtConfigGuestDevice):
 1993 
 1994     def __init__(self, **kwargs):
 1995         super(LibvirtConfigGuestVideo, self).__init__(root_name="video",
 1996                                                       **kwargs)
 1997 
 1998         self.type = 'cirrus'
 1999         self.vram = None
 2000         self.heads = None
 2001         self.driver_iommu = False
 2002 
 2003     @property
 2004     def uses_virtio(self):
 2005         return 'virtio' == self.type
 2006 
 2007     def format_dom(self):
 2008         dev = super(LibvirtConfigGuestVideo, self).format_dom()
 2009 
 2010         model = etree.Element("model")
 2011         model.set("type", self.type)
 2012 
 2013         if self.vram:
 2014             model.set("vram", str(self.vram))
 2015 
 2016         if self.heads:
 2017             model.set("heads", str(self.heads))
 2018 
 2019         dev.append(model)
 2020 
 2021         if self.driver_iommu:
 2022             dev.append(etree.Element("driver", iommu="on"))
 2023 
 2024         return dev
 2025 
 2026 
 2027 class LibvirtConfigMemoryBalloon(LibvirtConfigGuestDevice):
 2028     def __init__(self, **kwargs):
 2029         super(LibvirtConfigMemoryBalloon, self).__init__(
 2030             root_name='memballoon',
 2031             **kwargs)
 2032         self.model = None
 2033         self.period = None
 2034         self.driver_iommu = False
 2035 
 2036     @property
 2037     def uses_virtio(self):
 2038         return 'virtio' == self.model
 2039 
 2040     def format_dom(self):
 2041         dev = super(LibvirtConfigMemoryBalloon, self).format_dom()
 2042         dev.set('model', str(self.model))
 2043         if self.period is not None:
 2044             dev.append(etree.Element('stats', period=str(self.period)))
 2045         if self.driver_iommu:
 2046             dev.append(etree.Element('driver', iommu='on'))
 2047         return dev
 2048 
 2049 
 2050 class LibvirtConfigGuestController(LibvirtConfigGuestDevice):
 2051 
 2052     def __init__(self, **kwargs):
 2053         super(LibvirtConfigGuestController,
 2054               self).__init__(root_name="controller", **kwargs)
 2055 
 2056         self.type = None
 2057         self.index = None
 2058         self.model = None
 2059         self.driver_iommu = False
 2060 
 2061     @property
 2062     def uses_virtio(self):
 2063         model_is_virtio = 'virtio-scsi' == self.model
 2064         type_is_virtio = 'virtio-serial' == self.type
 2065         return model_is_virtio or type_is_virtio
 2066 
 2067     def format_dom(self):
 2068         controller = super(LibvirtConfigGuestController, self).format_dom()
 2069         controller.set("type", self.type)
 2070 
 2071         if self.index is not None:
 2072             controller.set("index", str(self.index))
 2073 
 2074         if self.model:
 2075             controller.set("model", str(self.model))
 2076 
 2077         if self.driver_iommu:
 2078             controller.append(etree.Element("driver", iommu="on"))
 2079 
 2080         return controller
 2081 
 2082 
 2083 class LibvirtConfigGuestUSBHostController(LibvirtConfigGuestController):
 2084 
 2085     def __init__(self, **kwargs):
 2086         super(LibvirtConfigGuestUSBHostController, self).__init__(**kwargs)
 2087         self.type = 'usb'
 2088 
 2089 
 2090 class LibvirtConfigGuestPCIeRootController(LibvirtConfigGuestController):
 2091 
 2092     def __init__(self, **kwargs):
 2093         super(LibvirtConfigGuestPCIeRootController, self).\
 2094                 __init__(**kwargs)
 2095         self.type = 'pci'
 2096         self.model = 'pcie-root'
 2097 
 2098 
 2099 class LibvirtConfigGuestPCIeRootPortController(LibvirtConfigGuestController):
 2100 
 2101     def __init__(self, **kwargs):
 2102         super(LibvirtConfigGuestPCIeRootPortController, self).\
 2103                 __init__(**kwargs)
 2104         self.type = 'pci'
 2105         self.model = 'pcie-root-port'
 2106 
 2107 
 2108 class LibvirtConfigGuestHostdev(LibvirtConfigGuestDevice):
 2109     def __init__(self, **kwargs):
 2110         super(LibvirtConfigGuestHostdev, self).\
 2111                 __init__(root_name="hostdev", **kwargs)
 2112         self.mode = kwargs.get('mode')
 2113         self.type = kwargs.get('type')
 2114         # managed attribute is only used by PCI devices but mediated devices
 2115         # need to say managed=no
 2116         self.managed = kwargs.get('managed', 'yes')
 2117 
 2118     def format_dom(self):
 2119         dev = super(LibvirtConfigGuestHostdev, self).format_dom()
 2120         dev.set("mode", self.mode)
 2121         dev.set("type", self.type)
 2122         dev.set("managed", self.managed)
 2123         return dev
 2124 
 2125     def parse_dom(self, xmldoc):
 2126         super(LibvirtConfigGuestHostdev, self).parse_dom(xmldoc)
 2127         self.mode = xmldoc.get('mode')
 2128         self.type = xmldoc.get('type')
 2129         self.managed = xmldoc.get('managed')
 2130         return list(xmldoc)
 2131 
 2132 
 2133 class LibvirtConfigGuestHostdevPCI(LibvirtConfigGuestHostdev):
 2134     def __init__(self, **kwargs):
 2135         super(LibvirtConfigGuestHostdevPCI, self).\
 2136                 __init__(mode='subsystem', type='pci',
 2137                          **kwargs)
 2138         # These are returned from libvirt as hexadecimal strings with 0x prefix
 2139         # even if they have a different meaningful range: domain 16 bit,
 2140         # bus 8 bit, slot 5 bit, and function 3 bit
 2141         # On the other hand nova generates these values without the 0x prefix
 2142         self.domain = None
 2143         self.bus = None
 2144         self.slot = None
 2145         self.function = None
 2146 
 2147     def __eq__(self, other):
 2148         if not isinstance(other, LibvirtConfigGuestHostdevPCI):
 2149             return False
 2150 
 2151         # NOTE(gibi): nova generates hexa string without 0x prefix but
 2152         # libvirt uses that prefix when returns the config so we need to
 2153         # normalize the strings before comparison
 2154         return (
 2155             int(self.domain, 16) == int(other.domain, 16) and
 2156             int(self.bus, 16) == int(other.bus, 16) and
 2157             int(self.slot, 16) == int(other.slot, 16) and
 2158             int(self.function, 16) == int(other.function, 16))
 2159 
 2160     def format_dom(self):
 2161         dev = super(LibvirtConfigGuestHostdevPCI, self).format_dom()
 2162 
 2163         address = etree.Element(
 2164             "address",
 2165             domain=self.domain if self.domain.startswith('0x')
 2166                                else '0x' + self.domain,
 2167             bus=self.bus if self.bus.startswith('0x') else '0x' + self.bus,
 2168             slot=self.slot if self.slot.startswith('0x') else '0x' + self.slot,
 2169             function=self.function if self.function.startswith('0x')
 2170                                    else '0x' + self.function)
 2171         source = etree.Element("source")
 2172         source.append(address)
 2173         dev.append(source)
 2174         return dev
 2175 
 2176     def parse_dom(self, xmldoc):
 2177         childs = super(LibvirtConfigGuestHostdevPCI, self).parse_dom(xmldoc)
 2178         for c in childs:
 2179             if c.tag == "source":
 2180                 for sub in c:
 2181                     if sub.tag == 'address':
 2182                         self.domain = sub.get('domain')
 2183                         self.bus = sub.get('bus')
 2184                         self.slot = sub.get('slot')
 2185                         self.function = sub.get('function')
 2186 
 2187 
 2188 class LibvirtConfigGuestHostdevMDEV(LibvirtConfigGuestHostdev):
 2189     def __init__(self, **kwargs):
 2190         super(LibvirtConfigGuestHostdevMDEV, self).__init__(
 2191             mode='subsystem', type='mdev', managed='no', **kwargs)
 2192         # model attribute is only supported by mediated devices
 2193         self.model = kwargs.get('model', 'vfio-pci')
 2194         self.uuid = None
 2195 
 2196     def format_dom(self):
 2197         dev = super(LibvirtConfigGuestHostdevMDEV, self).format_dom()
 2198         if self.model:
 2199             dev.set("model", self.model)
 2200 
 2201         address = etree.Element("address", uuid=self.uuid)
 2202         source = etree.Element("source")
 2203         source.append(address)
 2204         dev.append(source)
 2205         return dev
 2206 
 2207     def parse_dom(self, xmldoc):
 2208         children = super(LibvirtConfigGuestHostdevMDEV, self).parse_dom(xmldoc)
 2209         if xmldoc.get('model'):
 2210             self.model = xmldoc.get('model')
 2211         for c in children:
 2212             if c.tag == "source":
 2213                 for sub in c:
 2214                     if sub.tag == 'address':
 2215                         self.uuid = sub.get('uuid')
 2216                         return
 2217 
 2218 
 2219 class LibvirtConfigGuestCharBase(LibvirtConfigGuestDevice):
 2220 
 2221     def __init__(self, **kwargs):
 2222         super(LibvirtConfigGuestCharBase, self).__init__(**kwargs)
 2223 
 2224         self.type = "pty"
 2225         self.source_path = None
 2226         self.listen_port = None
 2227         self.listen_host = None
 2228         self.log = None
 2229 
 2230     def format_dom(self):
 2231         dev = super(LibvirtConfigGuestCharBase, self).format_dom()
 2232 
 2233         dev.set("type", self.type)
 2234 
 2235         if self.type == "file":
 2236             dev.append(etree.Element("source", path=self.source_path))
 2237         elif self.type == "unix":
 2238             dev.append(etree.Element("source", mode="bind",
 2239                                     path=self.source_path))
 2240         elif self.type == "tcp":
 2241             dev.append(etree.Element("source", mode="bind",
 2242                                      host=self.listen_host,
 2243                                      service=str(self.listen_port)))
 2244 
 2245         if self.log:
 2246             dev.append(self.log.format_dom())
 2247 
 2248         return dev
 2249 
 2250 
 2251 class LibvirtConfigGuestChar(LibvirtConfigGuestCharBase):
 2252 
 2253     def __init__(self, **kwargs):
 2254         super(LibvirtConfigGuestChar, self).__init__(**kwargs)
 2255 
 2256         self.target_port = None
 2257         self.target_type = None
 2258 
 2259     def format_dom(self):
 2260         dev = super(LibvirtConfigGuestChar, self).format_dom()
 2261 
 2262         if self.target_port is not None or self.target_type is not None:
 2263             target = etree.Element("target")
 2264             if self.target_port is not None:
 2265                 target.set("port", str(self.target_port))
 2266             if self.target_type is not None:
 2267                 target.set("type", self.target_type)
 2268             dev.append(target)
 2269 
 2270         return dev
 2271 
 2272 
 2273 class LibvirtConfigGuestCharDeviceLog(LibvirtConfigObject):
 2274     """Represents a sub-element to a character device."""
 2275 
 2276     def __init__(self, **kwargs):
 2277         super(LibvirtConfigGuestCharDeviceLog, self).__init__(root_name="log",
 2278                                                               **kwargs)
 2279         self.file = None
 2280         self.append = "off"
 2281 
 2282     def parse_dom(self, xmldoc):
 2283         super(LibvirtConfigGuestCharDeviceLog, self).parse_dom(xmldoc)
 2284         self.file = xmldoc.get("file")
 2285         self.append = xmldoc.get("append")
 2286 
 2287     def format_dom(self):
 2288         log = super(LibvirtConfigGuestCharDeviceLog, self).format_dom()
 2289         log.set("file", self.file)
 2290         log.set("append", self.append)
 2291         return log
 2292 
 2293 
 2294 class LibvirtConfigGuestSerial(LibvirtConfigGuestChar):
 2295 
 2296     def __init__(self, **kwargs):
 2297         super(LibvirtConfigGuestSerial, self).__init__(root_name="serial",
 2298                                                        **kwargs)
 2299 
 2300 
 2301 class LibvirtConfigGuestConsole(LibvirtConfigGuestChar):
 2302 
 2303     def __init__(self, **kwargs):
 2304         super(LibvirtConfigGuestConsole, self).__init__(root_name="console",
 2305                                                         **kwargs)
 2306 
 2307 
 2308 class LibvirtConfigGuestChannel(LibvirtConfigGuestCharBase):
 2309 
 2310     def __init__(self, **kwargs):
 2311         super(LibvirtConfigGuestChannel, self).__init__(root_name="channel",
 2312                                                         **kwargs)
 2313 
 2314         self.target_type = "virtio"
 2315         self.target_name = None
 2316 
 2317     def format_dom(self):
 2318         dev = super(LibvirtConfigGuestChannel, self).format_dom()
 2319 
 2320         target = etree.Element("target", type=self.target_type)
 2321         if self.target_name is not None:
 2322             target.set("name", self.target_name)
 2323         dev.append(target)
 2324 
 2325         return dev
 2326 
 2327 
 2328 class LibvirtConfigGuestWatchdog(LibvirtConfigGuestDevice):
 2329     def __init__(self, **kwargs):
 2330         super(LibvirtConfigGuestWatchdog, self).__init__(root_name="watchdog",
 2331                                                          **kwargs)
 2332 
 2333         self.model = 'i6300esb'
 2334         self.action = 'reset'
 2335 
 2336     def format_dom(self):
 2337         dev = super(LibvirtConfigGuestWatchdog, self).format_dom()
 2338 
 2339         dev.set('model', self.model)
 2340         dev.set('action', self.action)
 2341 
 2342         return dev
 2343 
 2344 
 2345 class LibvirtConfigGuestCPUTuneVCPUPin(LibvirtConfigObject):
 2346 
 2347     def __init__(self, **kwargs):
 2348         super(LibvirtConfigGuestCPUTuneVCPUPin, self).__init__(
 2349             root_name="vcpupin",
 2350             **kwargs)
 2351 
 2352         self.id = None
 2353         self.cpuset = None
 2354 
 2355     def format_dom(self):
 2356         root = super(LibvirtConfigGuestCPUTuneVCPUPin, self).format_dom()
 2357 
 2358         root.set("vcpu", str(self.id))
 2359         if self.cpuset is not None:
 2360             root.set("cpuset",
 2361                      hardware.format_cpu_spec(self.cpuset))
 2362 
 2363         return root
 2364 
 2365 
 2366 class LibvirtConfigGuestCPUTuneEmulatorPin(LibvirtConfigObject):
 2367 
 2368     def __init__(self, **kwargs):
 2369         super(LibvirtConfigGuestCPUTuneEmulatorPin, self).__init__(
 2370             root_name="emulatorpin",
 2371             **kwargs)
 2372 
 2373         self.cpuset = None
 2374 
 2375     def format_dom(self):
 2376         root = super(LibvirtConfigGuestCPUTuneEmulatorPin, self).format_dom()
 2377 
 2378         if self.cpuset is not None:
 2379             root.set("cpuset",
 2380                      hardware.format_cpu_spec(self.cpuset))
 2381 
 2382         return root
 2383 
 2384 
 2385 class LibvirtConfigGuestCPUTuneVCPUSched(LibvirtConfigObject):
 2386 
 2387     def __init__(self, **kwargs):
 2388         super(LibvirtConfigGuestCPUTuneVCPUSched, self).__init__(
 2389             root_name="vcpusched",
 2390             **kwargs)
 2391 
 2392         self.vcpus = None
 2393         self.scheduler = None
 2394         self.priority = None
 2395 
 2396     def format_dom(self):
 2397         root = super(LibvirtConfigGuestCPUTuneVCPUSched, self).format_dom()
 2398 
 2399         if self.vcpus is not None:
 2400             root.set("vcpus",
 2401                      hardware.format_cpu_spec(self.vcpus))
 2402         if self.scheduler is not None:
 2403             root.set("scheduler", self.scheduler)
 2404         if self.priority is not None:
 2405             root.set("priority", str(self.priority))
 2406 
 2407         return root
 2408 
 2409 
 2410 class LibvirtConfigGuestCPUTune(LibvirtConfigObject):
 2411 
 2412     def __init__(self, **kwargs):
 2413         super(LibvirtConfigGuestCPUTune, self).__init__(root_name="cputune",
 2414                                                         **kwargs)
 2415         self.shares = None
 2416         self.quota = None
 2417         self.period = None
 2418         self.vcpupin = []
 2419         self.emulatorpin = None
 2420         self.vcpusched = []
 2421 
 2422     def format_dom(self):
 2423         root = super(LibvirtConfigGuestCPUTune, self).format_dom()
 2424 
 2425         if self.shares is not None:
 2426             root.append(self._text_node("shares", str(self.shares)))
 2427         if self.quota is not None:
 2428             root.append(self._text_node("quota", str(self.quota)))
 2429         if self.period is not None:
 2430             root.append(self._text_node("period", str(self.period)))
 2431 
 2432         if self.emulatorpin is not None:
 2433             root.append(self.emulatorpin.format_dom())
 2434         for vcpu in self.vcpupin:
 2435             root.append(vcpu.format_dom())
 2436         for sched in self.vcpusched:
 2437             root.append(sched.format_dom())
 2438 
 2439         return root
 2440 
 2441 
 2442 class LibvirtConfigGuestMemoryBacking(LibvirtConfigObject):
 2443 
 2444     def __init__(self, **kwargs):
 2445         super(LibvirtConfigGuestMemoryBacking, self).__init__(
 2446             root_name="memoryBacking", **kwargs)
 2447 
 2448         self.hugepages = []
 2449         self.sharedpages = True
 2450         self.locked = False
 2451         self.filesource = False
 2452         self.sharedaccess = False
 2453         self.allocateimmediate = False
 2454         self.discard = False
 2455 
 2456     def format_dom(self):
 2457         root = super(LibvirtConfigGuestMemoryBacking, self).format_dom()
 2458 
 2459         if self.hugepages:
 2460             hugepages = etree.Element("hugepages")
 2461             for item in self.hugepages:
 2462                 hugepages.append(item.format_dom())
 2463             root.append(hugepages)
 2464         if not self.sharedpages:
 2465             root.append(etree.Element("nosharepages"))
 2466         if self.locked:
 2467             root.append(etree.Element("locked"))
 2468         if self.filesource:
 2469             root.append(etree.Element("source", type="file"))
 2470         if self.sharedaccess:
 2471             root.append(etree.Element("access", mode="shared"))
 2472         if self.allocateimmediate:
 2473             root.append(etree.Element("allocation", mode="immediate"))
 2474         if self.discard:
 2475             root.append(etree.Element("discard"))
 2476 
 2477         return root
 2478 
 2479 
 2480 class LibvirtConfigGuestMemoryBackingPage(LibvirtConfigObject):
 2481 
 2482     def __init__(self, **kwargs):
 2483         super(LibvirtConfigGuestMemoryBackingPage, self).__init__(
 2484             root_name="page", **kwargs)
 2485 
 2486         self.size_kb = None
 2487         self.nodeset = None
 2488 
 2489     def format_dom(self):
 2490         page = super(LibvirtConfigGuestMemoryBackingPage, self).format_dom()
 2491 
 2492         page.set("size", str(self.size_kb))
 2493         page.set("nodeset", hardware.format_cpu_spec(self.nodeset))
 2494         page.set("unit", "KiB")
 2495 
 2496         return page
 2497 
 2498 
 2499 class LibvirtConfigGuestMemoryTune(LibvirtConfigObject):
 2500 
 2501     def __init__(self, **kwargs):
 2502         super(LibvirtConfigGuestMemoryTune, self).__init__(
 2503             root_name="memtune", **kwargs)
 2504 
 2505         self.hard_limit = None
 2506         self.soft_limit = None
 2507         self.swap_hard_limit = None
 2508         self.min_guarantee = None
 2509 
 2510     def format_dom(self):
 2511         root = super(LibvirtConfigGuestMemoryTune, self).format_dom()
 2512 
 2513         if self.hard_limit is not None:
 2514             root.append(self._text_node("hard_limit",
 2515                                         str(self.hard_limit),
 2516                                         unit="KiB"))
 2517         if self.soft_limit is not None:
 2518             root.append(self._text_node("soft_limit",
 2519                                         str(self.soft_limit),
 2520                                         unit="KiB"))
 2521         if self.swap_hard_limit is not None:
 2522             root.append(self._text_node("swap_hard_limit",
 2523                                         str(self.swap_hard_limit),
 2524                                         unit="KiB"))
 2525         if self.min_guarantee is not None:
 2526             root.append(self._text_node("min_guarantee",
 2527                                         str(self.min_guarantee),
 2528                                         unit="KiB"))
 2529 
 2530         return root
 2531 
 2532 
 2533 class LibvirtConfigGuestNUMATuneMemory(LibvirtConfigObject):
 2534 
 2535     def __init__(self, **kwargs):
 2536         super(LibvirtConfigGuestNUMATuneMemory, self).__init__(
 2537             root_name="memory", **kwargs)
 2538 
 2539         self.mode = "strict"
 2540         self.nodeset = []
 2541 
 2542     def format_dom(self):
 2543         root = super(LibvirtConfigGuestNUMATuneMemory, self).format_dom()
 2544 
 2545         root.set("mode", self.mode)
 2546         root.set("nodeset", hardware.format_cpu_spec(self.nodeset))
 2547 
 2548         return root
 2549 
 2550 
 2551 class LibvirtConfigGuestNUMATuneMemNode(LibvirtConfigObject):
 2552 
 2553     def __init__(self, **kwargs):
 2554         super(LibvirtConfigGuestNUMATuneMemNode, self).__init__(
 2555             root_name="memnode", **kwargs)
 2556 
 2557         self.cellid = 0
 2558         self.mode = "strict"
 2559         self.nodeset = []
 2560 
 2561     def format_dom(self):
 2562         root = super(LibvirtConfigGuestNUMATuneMemNode, self).format_dom()
 2563 
 2564         root.set("cellid", str(self.cellid))
 2565         root.set("mode", self.mode)
 2566         root.set("nodeset", hardware.format_cpu_spec(self.nodeset))
 2567 
 2568         return root
 2569 
 2570 
 2571 class LibvirtConfigGuestNUMATune(LibvirtConfigObject):
 2572 
 2573     def __init__(self, **kwargs):
 2574         super(LibvirtConfigGuestNUMATune, self).__init__(
 2575             root_name="numatune", **kwargs)
 2576 
 2577         self.memory = None
 2578         self.memnodes = []
 2579 
 2580     def format_dom(self):
 2581         root = super(LibvirtConfigGuestNUMATune, self).format_dom()
 2582 
 2583         if self.memory is not None:
 2584             root.append(self.memory.format_dom())
 2585         for node in self.memnodes:
 2586             root.append(node.format_dom())
 2587 
 2588         return root
 2589 
 2590 
 2591 class LibvirtConfigGuestFeature(LibvirtConfigObject):
 2592 
 2593     def __init__(self, name, **kwargs):
 2594         super(LibvirtConfigGuestFeature, self).__init__(root_name=name,
 2595                                                         **kwargs)
 2596 
 2597 
 2598 class LibvirtConfigGuestFeatureACPI(LibvirtConfigGuestFeature):
 2599 
 2600     def __init__(self, **kwargs):
 2601         super(LibvirtConfigGuestFeatureACPI, self).__init__("acpi",
 2602                                                             **kwargs)
 2603 
 2604 
 2605 class LibvirtConfigGuestFeatureAPIC(LibvirtConfigGuestFeature):
 2606 
 2607     def __init__(self, **kwargs):
 2608         super(LibvirtConfigGuestFeatureAPIC, self).__init__("apic",
 2609                                                             **kwargs)
 2610 
 2611 
 2612 class LibvirtConfigGuestFeaturePAE(LibvirtConfigGuestFeature):
 2613 
 2614     def __init__(self, **kwargs):
 2615         super(LibvirtConfigGuestFeaturePAE, self).__init__("pae",
 2616                                                            **kwargs)
 2617 
 2618 
 2619 class LibvirtConfigGuestFeatureKvmHidden(LibvirtConfigGuestFeature):
 2620 
 2621     def __init__(self, **kwargs):
 2622         super(LibvirtConfigGuestFeatureKvmHidden, self).__init__("kvm",
 2623                                                                  **kwargs)
 2624 
 2625     def format_dom(self):
 2626         root = super(LibvirtConfigGuestFeatureKvmHidden, self).format_dom()
 2627 
 2628         root.append(etree.Element("hidden", state="on"))
 2629 
 2630         return root
 2631 
 2632 
 2633 class LibvirtConfigGuestFeaturePMU(LibvirtConfigGuestFeature):
 2634 
 2635     def __init__(self, state, **kwargs):
 2636         super(LibvirtConfigGuestFeaturePMU, self).__init__("pmu", **kwargs)
 2637         # NOTE(sean-k-mooney): bool_from_string is needed to handle the raw
 2638         # flavor exta_sepc value. bool_from_string internally checks if the
 2639         # value is already a bool and returns it. As such it's safe to use
 2640         # with the image metadata property too, so we call it unconditionally.
 2641         self.state = strutils.bool_from_string(state)
 2642 
 2643     def format_dom(self):
 2644         root = super(LibvirtConfigGuestFeaturePMU, self).format_dom()
 2645         root.attrib['state'] = "on" if self.state else "off"
 2646         return root
 2647 
 2648 
 2649 class LibvirtConfigGuestFeatureHyperV(LibvirtConfigGuestFeature):
 2650 
 2651     # QEMU requires at least this value to be set
 2652     MIN_SPINLOCK_RETRIES = 4095
 2653     # The spoofed vendor_id can be any alphanumeric string
 2654     SPOOFED_VENDOR_ID = "1234567890ab"
 2655 
 2656     def __init__(self, **kwargs):
 2657         super(LibvirtConfigGuestFeatureHyperV, self).__init__("hyperv",
 2658                                                               **kwargs)
 2659 
 2660         self.relaxed = False
 2661         self.vapic = False
 2662         self.spinlocks = False
 2663         self.spinlock_retries = self.MIN_SPINLOCK_RETRIES
 2664         self.vendorid_spoof = False
 2665         self.vendorid = self.SPOOFED_VENDOR_ID
 2666 
 2667     def format_dom(self):
 2668         root = super(LibvirtConfigGuestFeatureHyperV, self).format_dom()
 2669 
 2670         if self.relaxed:
 2671             root.append(etree.Element("relaxed", state="on"))
 2672         if self.vapic:
 2673             root.append(etree.Element("vapic", state="on"))
 2674         if self.spinlocks:
 2675             root.append(etree.Element("spinlocks", state="on",
 2676                                       retries=str(self.spinlock_retries)))
 2677         if self.vendorid_spoof:
 2678             root.append(etree.Element("vendor_id", state="on",
 2679                                       value=self.vendorid))
 2680 
 2681         return root
 2682 
 2683 
 2684 class LibvirtConfigGuestSEVLaunchSecurity(LibvirtConfigObject):
 2685 
 2686     def __init__(self, **kwargs):
 2687         super(LibvirtConfigGuestSEVLaunchSecurity, self).__init__(
 2688             root_name='launchSecurity', **kwargs)
 2689 
 2690         self.cbitpos = None
 2691         self.reduced_phys_bits = None
 2692 
 2693     def format_dom(self):
 2694         root = super(LibvirtConfigGuestSEVLaunchSecurity, self).format_dom()
 2695 
 2696         root.set('type', 'sev')
 2697         policy = etree.Element('policy')
 2698         policy.text = '0x0033'  # hardcoded default according to the spec
 2699         root.append(policy)
 2700 
 2701         cbitpos = etree.Element('cbitpos')
 2702         cbitpos.text = str(self.cbitpos)
 2703         root.append(cbitpos)
 2704 
 2705         reducedPhysBits = etree.Element('reducedPhysBits')
 2706         reducedPhysBits.text = str(self.reduced_phys_bits)
 2707         root.append(reducedPhysBits)
 2708 
 2709         return root
 2710 
 2711 
 2712 class LibvirtConfigGuest(LibvirtConfigObject):
 2713 
 2714     def __init__(self, **kwargs):
 2715         super(LibvirtConfigGuest, self).__init__(root_name="domain",
 2716                                                  **kwargs)
 2717 
 2718         self.virt_type = None
 2719         self.uuid = None
 2720         self.name = None
 2721         self.memory = 500 * units.Mi
 2722         self.max_memory_size = None
 2723         self.max_memory_slots = 0
 2724         self.membacking = None
 2725         self.memtune = None
 2726         self.numatune = None
 2727         self.vcpus = 1
 2728         self.cpuset = None
 2729         self.cpu = None
 2730         self.cputune = None
 2731         self.features = []
 2732         self.clock = None
 2733         self.sysinfo = None
 2734         self.os_type = None
 2735         self.os_loader = None
 2736         self.os_loader_type = None
 2737         self.os_kernel = None
 2738         self.os_initrd = None
 2739         self.os_cmdline = None
 2740         self.os_init_env = {}
 2741         self.os_root = None
 2742         self.os_init_path = None
 2743         self.os_boot_dev = []
 2744         self.os_smbios = None
 2745         self.os_mach_type = None
 2746         self.os_bootmenu = False
 2747         self.devices = []
 2748         self.metadata = []
 2749         self.idmaps = []
 2750         self.perf_events = []
 2751         self.launch_security = None
 2752 
 2753     def _format_basic_props(self, root):
 2754         root.append(self._text_node("uuid", self.uuid))
 2755         root.append(self._text_node("name", self.name))
 2756         root.append(self._text_node("memory", self.memory))
 2757         if self.max_memory_size is not None:
 2758             max_memory = self._text_node("maxMemory", self.max_memory_size)
 2759             max_memory.set("slots", str(self.max_memory_slots))
 2760             root.append(max_memory)
 2761         if self.membacking is not None:
 2762             root.append(self.membacking.format_dom())
 2763         if self.memtune is not None:
 2764             root.append(self.memtune.format_dom())
 2765         if self.numatune is not None:
 2766             root.append(self.numatune.format_dom())
 2767         if self.cpuset is not None:
 2768             vcpu = self._text_node("vcpu", self.vcpus)
 2769             vcpu.set("cpuset", hardware.format_cpu_spec(self.cpuset))
 2770             root.append(vcpu)
 2771         else:
 2772             root.append(self._text_node("vcpu", self.vcpus))
 2773 
 2774         if len(self.metadata) > 0:
 2775             metadata = etree.Element("metadata")
 2776             for m in self.metadata:
 2777                 metadata.append(m.format_dom())
 2778             root.append(metadata)
 2779 
 2780     def _format_os(self, root):
 2781         os = etree.Element("os")
 2782         type_node = self._text_node("type", self.os_type)
 2783         if self.os_mach_type is not None:
 2784             type_node.set("machine", self.os_mach_type)
 2785         os.append(type_node)
 2786         if self.os_kernel is not None:
 2787             os.append(self._text_node("kernel", self.os_kernel))
 2788         if self.os_loader is not None:
 2789             # Generate XML nodes for UEFI boot.
 2790             if self.os_loader_type == "pflash":
 2791                 loader = self._text_node("loader", self.os_loader)
 2792                 loader.set("type", "pflash")
 2793                 loader.set("readonly", "yes")
 2794                 os.append(loader)
 2795             else:
 2796                 os.append(self._text_node("loader", self.os_loader))
 2797         if self.os_initrd is not None:
 2798             os.append(self._text_node("initrd", self.os_initrd))
 2799         if self.os_cmdline is not None:
 2800             os.append(self._text_node("cmdline", self.os_cmdline))
 2801         if self.os_root is not None:
 2802             os.append(self._text_node("root", self.os_root))
 2803         if self.os_init_path is not None:
 2804             os.append(self._text_node("init", self.os_init_path))
 2805         for name, value in self.os_init_env.items():
 2806             initenv = self._text_node("initenv", value)
 2807             initenv.set("name", name)
 2808             os.append(initenv)
 2809 
 2810         for boot_dev in self.os_boot_dev:
 2811             os.append(etree.Element("boot", dev=boot_dev))
 2812 
 2813         if self.os_smbios is not None:
 2814             os.append(self.os_smbios.format_dom())
 2815 
 2816         if self.os_bootmenu:
 2817             os.append(etree.Element("bootmenu", enable="yes"))
 2818         root.append(os)
 2819 
 2820     def _format_features(self, root):
 2821         if len(self.features) > 0:
 2822             features = etree.Element("features")
 2823             for feat in self.features:
 2824                 features.append(feat.format_dom())
 2825             root.append(features)
 2826 
 2827     def _format_devices(self, root):
 2828         if len(self.devices) == 0:
 2829             return
 2830         devices = etree.Element("devices")
 2831         for dev in self.devices:
 2832             devices.append(dev.format_dom())
 2833         root.append(devices)
 2834 
 2835     def _format_idmaps(self, root):
 2836         if len(self.idmaps) == 0:
 2837             return
 2838         idmaps = etree.Element("idmap")
 2839         for idmap in self.idmaps:
 2840             idmaps.append(idmap.format_dom())
 2841         root.append(idmaps)
 2842 
 2843     def _format_perf_events(self, root):
 2844         if len(self.perf_events) == 0:
 2845             return
 2846         perfs = etree.Element("perf")
 2847         for pe in self.perf_events:
 2848             event = etree.Element("event", name=pe, enabled="yes")
 2849             perfs.append(event)
 2850         root.append(perfs)
 2851 
 2852     def _format_sev(self, root):
 2853         if self.launch_security is not None:
 2854             root.append(self.launch_security.format_dom())
 2855 
 2856     def format_dom(self):
 2857         root = super(LibvirtConfigGuest, self).format_dom()
 2858 
 2859         root.set("type", self.virt_type)
 2860 
 2861         self._format_basic_props(root)
 2862 
 2863         if self.sysinfo is not None:
 2864             root.append(self.sysinfo.format_dom())
 2865 
 2866         self._format_os(root)
 2867         self._format_features(root)
 2868 
 2869         if self.cputune is not None:
 2870             root.append(self.cputune.format_dom())
 2871 
 2872         if self.clock is not None:
 2873             root.append(self.clock.format_dom())
 2874 
 2875         if self.cpu is not None:
 2876             root.append(self.cpu.format_dom())
 2877 
 2878         self._format_devices(root)
 2879 
 2880         self._format_idmaps(root)
 2881 
 2882         self._format_perf_events(root)
 2883 
 2884         self._format_sev(root)
 2885 
 2886         return root
 2887 
 2888     def _parse_basic_props(self, xmldoc):
 2889         # memmbacking, memtune, numatune, metadata are skipped just because
 2890         # corresponding config types do not implement parse_dom method
 2891         if xmldoc.tag == 'uuid':
 2892             self.uuid = xmldoc.text
 2893         elif xmldoc.tag == 'name':
 2894             self.name = xmldoc.text
 2895         elif xmldoc.tag == 'memory':
 2896             self.memory = int(xmldoc.text)
 2897         elif xmldoc.tag == 'vcpu':
 2898             self.vcpus = int(xmldoc.text)
 2899             if xmldoc.get('cpuset') is not None:
 2900                 self.cpuset = hardware.parse_cpu_spec(xmldoc.get('cpuset'))
 2901 
 2902     def _parse_os(self, xmldoc):
 2903         # smbios is skipped just because LibvirtConfigGuestSMBIOS
 2904         # does not implement parse_dom method
 2905         for c in xmldoc:
 2906             if c.tag == 'type':
 2907                 self.os_type = c.text
 2908                 self.os_mach_type = c.get('machine')
 2909             elif c.tag == 'kernel':
 2910                 self.os_kernel = c.text
 2911             elif c.tag == 'loader':
 2912                 self.os_loader = c.text
 2913                 if c.get('type') == 'pflash':
 2914                     self.os_loader_type = 'pflash'
 2915             elif c.tag == 'initrd':
 2916                 self.os_initrd = c.text
 2917             elif c.tag == 'cmdline':
 2918                 self.os_cmdline = c.text
 2919             elif c.tag == 'root':
 2920                 self.os_root = c.text
 2921             elif c.tag == 'init':
 2922                 self.os_init_path = c.text
 2923             elif c.tag == 'boot':
 2924                 self.os_boot_dev.append(c.get('dev'))
 2925             elif c.tag == 'bootmenu':
 2926                 if c.get('enable') == 'yes':
 2927                     self.os_bootmenu = True
 2928             elif c.tag == 'initenv':
 2929                 self.os_init_env[c.get('name')] = c.text
 2930 
 2931     def parse_dom(self, xmldoc):
 2932         self.virt_type = xmldoc.get('type')
 2933         # Note: This cover only for: LibvirtConfigGuestDisks
 2934         #                            LibvirtConfigGuestFilesys
 2935         #                            LibvirtConfigGuestHostdevPCI
 2936         #                            LibvirtConfigGuestHostdevMDEV
 2937         #                            LibvirtConfigGuestInterface
 2938         #                            LibvirtConfigGuestUidMap
 2939         #                            LibvirtConfigGuestGidMap
 2940         #                            LibvirtConfigGuestCPU
 2941         #                            LibvirtConfigGuestVPMEM
 2942         for c in xmldoc:
 2943             if c.tag == 'devices':
 2944                 for d in c:
 2945                     if d.tag == 'disk':
 2946                         obj = LibvirtConfigGuestDisk()
 2947                         obj.parse_dom(d)
 2948                         self.devices.append(obj)
 2949                     elif d.tag == 'filesystem':
 2950                         obj = LibvirtConfigGuestFilesys()
 2951                         obj.parse_dom(d)
 2952                         self.devices.append(obj)
 2953                     elif d.tag == 'hostdev' and d.get('type') == 'pci':
 2954                         obj = LibvirtConfigGuestHostdevPCI()
 2955                         obj.parse_dom(d)
 2956                         self.devices.append(obj)
 2957                     elif d.tag == 'hostdev' and d.get('type') == 'mdev':
 2958                         obj = LibvirtConfigGuestHostdevMDEV()
 2959                         obj.parse_dom(d)
 2960                         self.devices.append(obj)
 2961                     elif d.tag == 'interface':
 2962                         obj = LibvirtConfigGuestInterface()
 2963                         obj.parse_dom(d)
 2964                         self.devices.append(obj)
 2965                     elif d.tag == 'memory' and d.get('model') == 'nvdimm':
 2966                         obj = LibvirtConfigGuestVPMEM()
 2967                         obj.parse_dom(d)
 2968                         self.devices.append(obj)
 2969             if c.tag == 'idmap':
 2970                 for idmap in c:
 2971                     obj = None
 2972                     if idmap.tag == 'uid':
 2973                         obj = LibvirtConfigGuestUIDMap()
 2974                     elif idmap.tag == 'gid':
 2975                         obj = LibvirtConfigGuestGIDMap()
 2976 
 2977                     if obj:
 2978                         obj.parse_dom(idmap)
 2979                         self.idmaps.append(obj)
 2980             elif c.tag == 'cpu':
 2981                 obj = LibvirtConfigGuestCPU()
 2982                 obj.parse_dom(c)
 2983                 self.cpu = obj
 2984             elif c.tag == 'perf':
 2985                 for p in c:
 2986                     if p.get('enabled') and p.get('enabled') == 'yes':
 2987                         self.add_perf_event(p.get('name'))
 2988             elif c.tag == 'os':
 2989                 self._parse_os(c)
 2990             else:
 2991                 self._parse_basic_props(c)
 2992 
 2993     def add_device(self, dev):
 2994         self.devices.append(dev)
 2995 
 2996     def add_perf_event(self, event):
 2997         self.perf_events.append(event)
 2998 
 2999     def set_clock(self, clk):
 3000         self.clock = clk
 3001 
 3002 
 3003 class LibvirtConfigGuestSnapshot(LibvirtConfigObject):
 3004 
 3005     def __init__(self, **kwargs):
 3006         super(LibvirtConfigGuestSnapshot, self).__init__(
 3007             root_name="domainsnapshot",
 3008             **kwargs)
 3009 
 3010         self.name = None
 3011         self.disks = []
 3012 
 3013     def format_dom(self):
 3014         ss = super(LibvirtConfigGuestSnapshot, self).format_dom()
 3015 
 3016         if self.name:
 3017             ss.append(self._text_node("name", self.name))
 3018 
 3019         disks = etree.Element('disks')
 3020 
 3021         for disk in self.disks:
 3022             disks.append(disk.format_dom())
 3023 
 3024         ss.append(disks)
 3025 
 3026         return ss
 3027 
 3028     def add_disk(self, disk):
 3029         self.disks.append(disk)
 3030 
 3031 
 3032 class LibvirtConfigNodeDevice(LibvirtConfigObject):
 3033     """Libvirt Node Devices parser."""
 3034 
 3035     def __init__(self, **kwargs):
 3036         super(LibvirtConfigNodeDevice, self).__init__(root_name="device",
 3037                                                 **kwargs)
 3038         self.name = None
 3039         self.parent = None
 3040         self.pci_capability = None
 3041         self.mdev_information = None
 3042 
 3043     def parse_dom(self, xmldoc):
 3044         super(LibvirtConfigNodeDevice, self).parse_dom(xmldoc)
 3045 
 3046         for c in xmldoc:
 3047             if c.tag == "name":
 3048                 self.name = c.text
 3049             elif c.tag == "parent":
 3050                 self.parent = c.text
 3051             elif c.tag == "capability" and c.get("type") in ['pci', 'net']:
 3052                 pcicap = LibvirtConfigNodeDevicePciCap()
 3053                 pcicap.parse_dom(c)
 3054                 self.pci_capability = pcicap
 3055             elif c.tag == "capability" and c.get("type") in ['mdev']:
 3056                 mdev_info = LibvirtConfigNodeDeviceMdevInformation()
 3057                 mdev_info.parse_dom(c)
 3058                 self.mdev_information = mdev_info
 3059 
 3060 
 3061 class LibvirtConfigNodeDevicePciCap(LibvirtConfigObject):
 3062     """Libvirt Node Devices pci capability parser."""
 3063 
 3064     def __init__(self, **kwargs):
 3065         super(LibvirtConfigNodeDevicePciCap, self).__init__(
 3066             root_name="capability", **kwargs)
 3067         self.domain = None
 3068         self.bus = None
 3069         self.slot = None
 3070         self.function = None
 3071         self.product = None
 3072         self.product_id = None
 3073         self.vendor = None
 3074         self.vendor_id = None
 3075         self.numa_node = None
 3076         self.fun_capability = []
 3077         self.mdev_capability = []
 3078         self.interface = None
 3079         self.address = None
 3080         self.link_state = None
 3081         self.features = []
 3082 
 3083     def parse_dom(self, xmldoc):
 3084         super(LibvirtConfigNodeDevicePciCap, self).parse_dom(xmldoc)
 3085 
 3086         for c in xmldoc:
 3087             if c.tag == "domain":
 3088                 self.domain = int(c.text)
 3089             elif c.tag == "slot":
 3090                 self.slot = int(c.text)
 3091             elif c.tag == "bus":
 3092                 self.bus = int(c.text)
 3093             elif c.tag == "function":
 3094                 self.function = int(c.text)
 3095             elif c.tag == "product":
 3096                 self.product = c.text
 3097                 self.product_id = int(c.get('id'), 16)
 3098             elif c.tag == "vendor":
 3099                 self.vendor = c.text
 3100                 self.vendor_id = int(c.get('id'), 16)
 3101             elif c.tag == "numa":
 3102                 self.numa_node = int(c.get('node'))
 3103             elif c.tag == "interface":
 3104                 self.interface = c.text
 3105             elif c.tag == "address":
 3106                 self.address = c.text
 3107             elif c.tag == "link":
 3108                 self.link_state = c.get('state')
 3109             elif c.tag == "feature":
 3110                 self.features.append(c.get('name'))
 3111             elif c.tag == "capability" and c.get('type') in \
 3112                             ('virt_functions', 'phys_function'):
 3113                 funcap = LibvirtConfigNodeDevicePciSubFunctionCap()
 3114                 funcap.parse_dom(c)
 3115                 self.fun_capability.append(funcap)
 3116             elif c.tag == "capability" and c.get('type') in ('mdev_types',):
 3117                 mdevcap = LibvirtConfigNodeDeviceMdevCapableSubFunctionCap()
 3118                 mdevcap.parse_dom(c)
 3119                 self.mdev_capability.append(mdevcap)
 3120 
 3121 
 3122 class LibvirtConfigNodeDevicePciSubFunctionCap(LibvirtConfigObject):
 3123     def __init__(self, **kwargs):
 3124         super(LibvirtConfigNodeDevicePciSubFunctionCap, self).__init__(
 3125                                         root_name="capability", **kwargs)
 3126         self.type = None
 3127         self.device_addrs = list()  # list of tuple (domain,bus,slot,function)
 3128 
 3129     def parse_dom(self, xmldoc):
 3130         super(LibvirtConfigNodeDevicePciSubFunctionCap, self).parse_dom(xmldoc)
 3131         self.type = xmldoc.get("type")
 3132         for c in xmldoc:
 3133             if c.tag == "address":
 3134                 self.device_addrs.append((int(c.get('domain'), 16),
 3135                                           int(c.get('bus'), 16),
 3136                                           int(c.get('slot'), 16),
 3137                                           int(c.get('function'), 16)))
 3138 
 3139 
 3140 class LibvirtConfigNodeDeviceMdevCapableSubFunctionCap(LibvirtConfigObject):
 3141     def __init__(self, **kwargs):
 3142         super(LibvirtConfigNodeDeviceMdevCapableSubFunctionCap, self).__init__(
 3143                                         root_name="capability", **kwargs)
 3144         # mdev_types is a list of dictionaries where each item looks like:
 3145         # {'type': 'nvidia-11', 'name': 'GRID M60-0B', 'deviceAPI': 'vfio-pci',
 3146         #  'availableInstances': 16}
 3147         self.mdev_types = list()
 3148 
 3149     def parse_dom(self, xmldoc):
 3150         super(LibvirtConfigNodeDeviceMdevCapableSubFunctionCap,
 3151               self).parse_dom(xmldoc)
 3152         for c in xmldoc:
 3153             if c.tag == "type":
 3154                 mdev_type = {'type': c.get('id')}
 3155                 for e in c:
 3156                     mdev_type[e.tag] = (int(e.text)
 3157                                         if e.tag == 'availableInstances'
 3158                                         else e.text)
 3159                 self.mdev_types.append(mdev_type)
 3160 
 3161 
 3162 class LibvirtConfigNodeDeviceMdevInformation(LibvirtConfigObject):
 3163     def __init__(self, **kwargs):
 3164         super(LibvirtConfigNodeDeviceMdevInformation, self).__init__(
 3165                                         root_name="capability", **kwargs)
 3166         self.type = None
 3167         self.iommu_group = None
 3168 
 3169     def parse_dom(self, xmldoc):
 3170         super(LibvirtConfigNodeDeviceMdevInformation,
 3171               self).parse_dom(xmldoc)
 3172         for c in xmldoc:
 3173             if c.tag == "type":
 3174                 self.type = c.get('id')
 3175             if c.tag == "iommuGroup":
 3176                 self.iommu_group = int(c.get('number'))
 3177 
 3178 
 3179 class LibvirtConfigGuestRng(LibvirtConfigGuestDevice):
 3180 
 3181     def __init__(self, **kwargs):
 3182         super(LibvirtConfigGuestRng, self).__init__(root_name="rng",
 3183                                                       **kwargs)
 3184 
 3185         self.device_model = 'virtio'
 3186         self.model = 'random'
 3187         self.backend = None
 3188         self.rate_period = None
 3189         self.rate_bytes = None
 3190         self.driver_iommu = False
 3191 
 3192     @property
 3193     def uses_virtio(self):
 3194         return 'virtio' == self.device_model
 3195 
 3196     def format_dom(self):
 3197         dev = super(LibvirtConfigGuestRng, self).format_dom()
 3198         dev.set('model', self.device_model)
 3199 
 3200         backend = etree.Element("backend")
 3201         backend.set("model", self.model)
 3202         backend.text = self.backend
 3203 
 3204         if self.rate_period and self.rate_bytes:
 3205             rate = etree.Element("rate")
 3206             rate.set("period", str(self.rate_period))
 3207             rate.set("bytes", str(self.rate_bytes))
 3208             dev.append(rate)
 3209 
 3210         dev.append(backend)
 3211 
 3212         if self.driver_iommu:
 3213             dev.append(etree.Element('driver', iommu="on"))
 3214 
 3215         return dev
 3216 
 3217 
 3218 class LibvirtConfigGuestMetaNovaInstance(LibvirtConfigObject):
 3219 
 3220     def __init__(self):
 3221         super(LibvirtConfigGuestMetaNovaInstance,
 3222               self).__init__(root_name="instance",
 3223                              ns_prefix="nova",
 3224                              ns_uri=NOVA_NS)
 3225 
 3226         self.package = None
 3227         self.flavor = None
 3228         self.name = None
 3229         self.creationTime = None
 3230         self.owner = None
 3231         self.roottype = None
 3232         self.rootid = None
 3233 
 3234     def format_dom(self):
 3235         meta = super(LibvirtConfigGuestMetaNovaInstance, self).format_dom()
 3236 
 3237         pkg = self._new_node("package")
 3238         pkg.set("version", self.package)
 3239         meta.append(pkg)
 3240         if self.name is not None:
 3241             meta.append(self._text_node("name", self.name))
 3242         if self.creationTime is not None:
 3243             timestr = time.strftime("%Y-%m-%d %H:%M:%S",
 3244                                     time.gmtime(self.creationTime))
 3245             meta.append(self._text_node("creationTime", timestr))
 3246         if self.flavor is not None:
 3247             meta.append(self.flavor.format_dom())
 3248         if self.owner is not None:
 3249             meta.append(self.owner.format_dom())
 3250 
 3251         if self.roottype is not None and self.rootid is not None:
 3252             root = self._new_node("root")
 3253             root.set("type", self.roottype)
 3254             root.set("uuid", str(self.rootid))
 3255             meta.append(root)
 3256 
 3257         return meta
 3258 
 3259 
 3260 class LibvirtConfigGuestMetaNovaFlavor(LibvirtConfigObject):
 3261 
 3262     def __init__(self):
 3263         super(LibvirtConfigGuestMetaNovaFlavor,
 3264               self).__init__(root_name="flavor",
 3265                              ns_prefix="nova",
 3266                              ns_uri=NOVA_NS)
 3267 
 3268         self.name = None
 3269         self.memory = None
 3270         self.disk = None
 3271         self.swap = None
 3272         self.ephemeral = None
 3273         self.vcpus = None
 3274 
 3275     def format_dom(self):
 3276         meta = super(LibvirtConfigGuestMetaNovaFlavor, self).format_dom()
 3277         meta.set("name", self.name)
 3278         if self.memory is not None:
 3279             meta.append(self._text_node("memory", str(self.memory)))
 3280         if self.disk is not None:
 3281             meta.append(self._text_node("disk", str(self.disk)))
 3282         if self.swap is not None:
 3283             meta.append(self._text_node("swap", str(self.swap)))
 3284         if self.ephemeral is not None:
 3285             meta.append(self._text_node("ephemeral", str(self.ephemeral)))
 3286         if self.vcpus is not None:
 3287             meta.append(self._text_node("vcpus", str(self.vcpus)))
 3288         return meta
 3289 
 3290 
 3291 class LibvirtConfigGuestMetaNovaOwner(LibvirtConfigObject):
 3292 
 3293     def __init__(self):
 3294         super(LibvirtConfigGuestMetaNovaOwner,
 3295               self).__init__(root_name="owner",
 3296                              ns_prefix="nova",
 3297                              ns_uri=NOVA_NS)
 3298 
 3299         self.userid = None
 3300         self.username = None
 3301         self.projectid = None
 3302         self.projectname = None
 3303 
 3304     def format_dom(self):
 3305         meta = super(LibvirtConfigGuestMetaNovaOwner, self).format_dom()
 3306         if self.userid is not None and self.username is not None:
 3307             user = self._text_node("user", self.username)
 3308             user.set("uuid", self.userid)
 3309             meta.append(user)
 3310         if self.projectid is not None and self.projectname is not None:
 3311             project = self._text_node("project", self.projectname)
 3312             project.set("uuid", self.projectid)
 3313             meta.append(project)
 3314         return meta
 3315 
 3316 
 3317 class LibvirtConfigSecret(LibvirtConfigObject):
 3318 
 3319     def __init__(self):
 3320         super(LibvirtConfigSecret,
 3321               self).__init__(root_name="secret")
 3322         self.ephemeral = False
 3323         self.private = False
 3324         self.description = None
 3325         self.uuid = None
 3326         self.usage_type = None
 3327         self.usage_id = None
 3328 
 3329     def get_yes_no_str(self, value):
 3330         if value:
 3331             return 'yes'
 3332         return 'no'
 3333 
 3334     def format_dom(self):
 3335         root = super(LibvirtConfigSecret, self).format_dom()
 3336         root.set("ephemeral", self.get_yes_no_str(self.ephemeral))
 3337         root.set("private", self.get_yes_no_str(self.private))
 3338         if self.description is not None:
 3339             root.append(self._text_node("description", str(self.description)))
 3340         if self.uuid is not None:
 3341             root.append(self._text_node("uuid", str(self.uuid)))
 3342         usage = self._new_node("usage")
 3343         usage.set("type", self.usage_type)
 3344         if self.usage_type in ('ceph', 'vtpm'):
 3345             usage.append(self._text_node('name', str(self.usage_id)))
 3346         elif self.usage_type == 'iscsi':
 3347             usage.append(self._text_node('target', str(self.usage_id)))
 3348         elif self.usage_type == 'volume':
 3349             usage.append(self._text_node('volume', str(self.usage_id)))
 3350         root.append(usage)
 3351         return root
 3352 
 3353 
 3354 class LibvirtConfigGuestVPMEM(LibvirtConfigGuestDevice):
 3355     def __init__(self, **kwargs):
 3356         super(LibvirtConfigGuestVPMEM, self).__init__(
 3357             root_name="memory", **kwargs)
 3358 
 3359         self.model = "nvdimm"
 3360         self.access = "shared"
 3361         self.source_path = kwargs.get("devpath", "")
 3362         self.align_size = kwargs.get("align_kb", 0)
 3363         self.pmem = True
 3364 
 3365         self.target_size = kwargs.get("size_kb", 0)
 3366         self.target_node = 0
 3367         self.label_size = 2 * units.Ki
 3368 
 3369     def format_dom(self):
 3370         memory = super(LibvirtConfigGuestVPMEM, self).format_dom()
 3371 
 3372         memory.set("model", self.model)
 3373         memory.set("access", self.access)
 3374 
 3375         source = etree.Element("source")
 3376         source.append(self._text_node("path", self.source_path))
 3377         source.append(self._text_node("alignsize", self.align_size))
 3378         if self.pmem is True:
 3379             source.append(etree.Element("pmem"))
 3380 
 3381         target = etree.Element("target")
 3382         target.append(self._text_node("size", self.target_size))
 3383         target.append(self._text_node("node", self.target_node))
 3384         label = etree.Element("label")
 3385         label.append(self._text_node("size", self.label_size))
 3386         target.append(label)
 3387 
 3388         memory.append(source)
 3389         memory.append(target)
 3390 
 3391         return memory
 3392 
 3393     def parse_dom(self, xmldoc):
 3394         super(LibvirtConfigGuestVPMEM, self).parse_dom(xmldoc)
 3395         self.model = xmldoc.get("model")
 3396         self.access = xmldoc.get("access")
 3397 
 3398         for c in list(xmldoc):
 3399             if c.tag == "source":
 3400                 for sub in list(c):
 3401                     if sub.tag == "path":
 3402                         self.source_path = sub.text
 3403                     if sub.tag == "alignsize":
 3404                         self.align_size = sub.text
 3405             elif c.tag == "target":
 3406                 for sub in list(c):
 3407                     if sub.tag == "size":
 3408                         self.target_size = sub.text