Example #1
0
class VirtualDeviceMaster(XMLBuilderDomain):
    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        XMLBuilderDomain.__init__(self,
                                  conn,
                                  parsexml,
                                  parsexmlnode,
                                  caps=caps)

        self._startport = None

    def parse_friendly_master(self, masterstr):
        try:
            int(masterstr)
            self._startport = masterstr
        except:
            logging.exception("Error parsing device master.")
            return None

    def _get_startport(self):
        return self._startport

    def _set_startport(self, val):
        self._startport = val

    startport = _xml_property(_get_startport,
                              _set_startport,
                              xpath="./master/@startport")

    def _get_xml_config(self):
        if self.startport is None:
            return

        return "<master startport='%s'/>" % self.startport
def _get_mode_prop(channel_type):
    # pylint: disable=W0212
    xpath = "./channel[@name='%s']/@mode" % channel_type
    def get_mode(s):
        return s._channels.get(channel_type, None)
    def set_mode(s, val):
        s._channels[channel_type] = val
    return _xml_property(get_mode, set_mode, xpath=xpath)
Example #3
0
class CPUFeature(XMLBuilderDomain.XMLBuilderDomain):
    """
    Class for generating <cpu> child <feature> XML
    """

    POLICIES = ["force", "require", "optional", "disable", "forbid"]

    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
                                                   parsexmlnode, caps)

        self._name = None
        self._policy = None

        if self._is_parse():
            return

    def _get_name(self):
        return self._name
    def _set_name(self, val):
        self._name = val
    name = _xml_property(_get_name, _set_name,
                         xpath="./@name")

    def _get_policy(self):
        return self._policy
    def _set_policy(self, val):
        self._policy = val
    policy = _xml_property(_get_policy, _set_policy,
                           xpath="./@policy")

    def _get_xml_config(self):
        if not self.name:
            return ""

        xml = "    <feature"
        if self.policy:
            xml += " policy='%s'" % self.policy
        xml += " name='%s'/>" % self.name

        return xml
Example #4
0
class VirtualAudio(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_AUDIO

    MODEL_DEFAULT = "default"
    MODELS = ["es1370", "sb16", "pcspk", "ac97", "ich6", MODEL_DEFAULT]

    def __init__(self,
                 model=None,
                 conn=None,
                 parsexml=None,
                 parsexmlnode=None,
                 caps=None):
        VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)

        self._model = None
        if self._is_parse():
            return

        if model is None:
            model = self.MODEL_DEFAULT
        self.model = model

    def get_model(self):
        return self._model

    def set_model(self, new_model):
        if type(new_model) != str:
            raise ValueError(
                _("'model' must be a string, "
                  " was '%s'." % type(new_model)))
        if not self.MODELS.count(new_model):
            raise ValueError(_("Unsupported sound model '%s'" % new_model))
        self._model = new_model

    model = _xml_property(get_model, set_model, xpath="./@model")

    def _get_xml_config(self):
        model = self.model
        if model == self.MODEL_DEFAULT:
            model = "es1370"

        return "    <sound model='%s'/>" % model
class VirtualDeviceAlias(XMLBuilderDomain):
    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        XMLBuilderDomain.__init__(self,
                                  conn,
                                  parsexml,
                                  parsexmlnode,
                                  caps=caps)

        self._name = None

    def _get_name(self):
        return self._name

    def _set_name(self, val):
        self._name = val

    name = _xml_property(_get_name, _set_name, xpath="./alias/@name")

    def _get_xml_config(self):
        return ""
Example #6
0
class VirtualMemballoon(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_MEMBALLOON

    MODEL_DEFAULT = "virtio"
    MODELS = ["xen", "none", MODEL_DEFAULT]

    def __init__(self,
                 conn=None,
                 model=MODEL_DEFAULT,
                 parsexml=None,
                 parsexmlnode=None,
                 caps=None):
        VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)

        self._model = None

        if self._is_parse():
            return

        self.model = model

    def get_model(self):
        return self._model

    def set_model(self, new_model):
        if type(new_model) != str:
            raise ValueError(
                _("'model' must be a string, "
                  " was '%s'." % type(new_model)))
        if not self.MODELS.count(new_model):
            raise ValueError(_("Unsupported memballoon model '%s'" %
                               new_model))
        self._model = new_model

    model = _xml_property(get_model, set_model, xpath="./@model")

    def _get_xml_config(self):
        xml = "    <memballoon model='%s'" % self.model
        xml += "/>"
        return xml
Example #7
0
class Clock(XMLBuilderDomain.XMLBuilderDomain):
    """
    Class for generating <clock> XML
    """

    _dumpxml_xpath = "/domain/clock"
    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
                                                   parsexmlnode, caps)

        self._offset = None

    def get_offset(self):
        return self._offset
    def set_offset(self, val):
        self._offset = val
    offset = _xml_property(get_offset, set_offset,
                           xpath="./clock/@offset")

    def _get_xml_config(self):
        if not self.offset:
            return ""

        return """  <clock offset="%s"/>""" % self.offset
class VirtualSmartCardDevice(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_SMARTCARD

    # Default models list
    MODE_DEFAULT = "passthrough"
    _modes = ["passthrough", "host-certificates", "host"]

    TYPE_DEFAULT = "tcp"
    _types = ["tcp", "spicevmc", None]

    def __init__(self,
                 conn,
                 mode=MODE_DEFAULT,
                 parsexml=None,
                 parsexmlnode=None,
                 caps=None):
        VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)

        self._mode = None
        self._type = None

        if self._is_parse():
            return

        self.mode = mode

    def get_modes(self):
        return self._modes[:]

    modes = property(get_modes)

    def get_mode(self):
        return self._mode

    def set_mode(self, val):
        if val not in self.modes:
            raise ValueError(_("Unknown smartcard mode '%s'") % val)
        self._mode = val

    mode = _xml_property(get_mode, set_mode, xpath="./@mode")

    def get_types(self):
        return self._types[:]

    types = property(get_types)

    def get_type(self):
        if self._type is None and self.mode == "passthrough":
            return "spicevmc"
        return self._type

    def set_type(self, val):
        if val not in self.types:
            raise ValueError(_("Unknown smartcard type '%s'") % val)
        self._type = val

    type = _xml_property(get_type, set_type, xpath="./@type")

    def _get_xml_config(self):
        mode = self.mode

        xml = "    <smartcard mode='%s'" % mode
        if self.type:
            xml += " type='%s'" % self.type
        xml += ">\n"
        xml += "    </smartcard>"

        return xml
class VirtualGraphics(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_GRAPHICS

    TYPE_SDL = "sdl"
    TYPE_VNC = "vnc"
    TYPE_RDP = "rdp"
    TYPE_SPICE = "spice"
    types = [TYPE_VNC, TYPE_SDL, TYPE_RDP, TYPE_SPICE]

    CHANNEL_TYPE_MAIN     = "main"
    CHANNEL_TYPE_DISPLAY  = "display"
    CHANNEL_TYPE_INPUTS   = "inputs"
    CHANNEL_TYPE_CURSOR   = "cursor"
    CHANNEL_TYPE_PLAYBACK = "playback"
    CHANNEL_TYPE_RECORD   = "record"
    channel_types = [CHANNEL_TYPE_MAIN, CHANNEL_TYPE_DISPLAY,
                     CHANNEL_TYPE_INPUTS, CHANNEL_TYPE_CURSOR,
                     CHANNEL_TYPE_PLAYBACK, CHANNEL_TYPE_RECORD]

    CHANNEL_MODE_SECURE   = "secure"
    CHANNEL_MODE_INSECURE = "insecure"
    CHANNEL_MODE_ANY      = "any"
    channel_modes = [CHANNEL_MODE_SECURE, CHANNEL_MODE_INSECURE,
                     CHANNEL_MODE_ANY]

    KEYMAP_LOCAL = "local"
    KEYMAP_DEFAULT = "default"
    _special_keymaps = [KEYMAP_LOCAL, KEYMAP_DEFAULT]

    @staticmethod
    def valid_keymaps():
        """
        Return a list of valid keymap values.
        """
        from virtinst import hostkeymap

        orig_list = hostkeymap.keytable.values()
        sort_list = []

        orig_list.sort()
        for k in orig_list:
            if k not in sort_list:
                sort_list.append(k)

        return sort_list

    @staticmethod
    def pretty_type_simple(gtype):
        if (gtype in [VirtualGraphics.TYPE_VNC,
                      VirtualGraphics.TYPE_SDL,
                      VirtualGraphics.TYPE_RDP]):
            return str(gtype).upper()

        return str(gtype).capitalize()

    def __init__(self, type=TYPE_VNC, port=-1, listen=None, passwd=None,
                 keymap=KEYMAP_DEFAULT, conn=None, parsexml=None,
                 parsexmlnode=None, tlsPort=-1, channels=None,
                 caps=None, passwdValidTo=None):
        # pylint: disable=W0622
        # Redefining built-in 'type', but it matches the XML so keep it

        VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)

        self._type   = None
        self._port   = None
        self._tlsPort = None
        self._listen = None
        self._passwd = None
        self._passwdValidTo = None
        self._keymap = None
        self._xauth = None
        self._display = None
        self._socket = None
        self._channels = {}
        self._local_keymap = -1

        if self._is_parse():
            return

        self.type = type
        self.port = port
        self.tlsPort = tlsPort
        self.keymap = keymap
        self.listen = listen
        self.passwd = passwd
        self.passwdValidTo = passwdValidTo
        if channels:
            self.channels = channels

    def _cache(self):
        # Make sure we've cached the _local_keymap value before copy()
        self._default_keymap()

    def _default_keymap(self, force_local=False):
        if (not force_local and self.conn and
            support.check_conn_support(self.conn,
                                support.SUPPORT_CONN_KEYMAP_AUTODETECT)):
            return None

        if self._local_keymap == -1:
            from virtinst import hostkeymap
            self._local_keymap = hostkeymap.default_keymap()
        return self._local_keymap

    def get_type(self):
        return self._type
    def set_type(self, val):
        if val not in self.types:
            raise ValueError(_("Unknown graphics type '%s'") % val)

        self._type = val
    type = _xml_property(get_type, set_type,
                         xpath="./@type")

    def _get_xauth(self):
        return self._xauth
    def _set_xauth(self, val):
        self._xauth = val
    xauth = _xml_property(_get_xauth, _set_xauth,
                          xpath="./@xauth")

    def _get_display(self):
        return self._display
    def _set_display(self, val):
        self._display = val
    display = _xml_property(_get_display, _set_display,
                            xpath="./@display")

    def get_keymap(self):
        if self._keymap == self.KEYMAP_DEFAULT:
            return self._default_keymap()
        if self._keymap == self.KEYMAP_LOCAL:
            return self._default_keymap(force_local=True)
        return self._keymap
    def set_keymap(self, val):
        # At this point, 'None' is a valid value
        if val is None:
            self._keymap = None
            return

        if val in self._special_keymaps:
            self._keymap = val
            return

        if type(val) is not str:
            raise ValueError(_("Keymap must be a string"))
        if val.lower() == self.KEYMAP_LOCAL:
            val = self._default_keymap(force_local=True)
        elif len(val) > 16:
            raise ValueError(_("Keymap must be less than 16 characters"))
        elif re.match("^[a-zA-Z0-9_-]*$", val) is None:
            raise ValueError(_("Keymap can only contain alphanumeric, "
                               "'_', or '-' characters"))

        self._keymap = val
    keymap = _xml_property(get_keymap, set_keymap,
                           xpath="./@keymap")

    def get_port(self):
        return self._port
    def set_port(self, val):
        if val is None:
            val = -1

        try:
            val = int(val)
        except:
            pass

        if (type(val) is not int or
            (val != -1 and (val < 5900 or val > 65535))):
            raise ValueError(_("VNC port must be a number between "
                               "5900 and 65535, or -1 for auto allocation"))
        self._port = val
    port = _xml_property(get_port, set_port,
                         get_converter=lambda s, x: int(x or -1),
                         xpath="./@port")

    def get_listen(self):
        return self._listen
    def set_listen(self, val):
        self._listen = val
    listen = _xml_property(get_listen, set_listen,
                           xpath="./@listen")

    def get_passwd(self):
        return self._passwd
    def set_passwd(self, val):
        self._passwd = val
    passwd = _xml_property(get_passwd, set_passwd,
                           xpath="./@passwd")

    def get_passwdValidTo(self):
        return self._passwdValidTo
    def set_passwdValidTo(self, val):
        self._passwdValidTo = val
    passwdValidTo = _xml_property(get_passwdValidTo, set_passwdValidTo,
                                  xpath="./@passwdValidTo")

    def _get_socket(self):
        return self._socket
    def _set_socket(self, val):
        self._socket = val
    socket = _xml_property(_get_socket, _set_socket,
                           xpath="./@socket")

    def get_tlsPort(self):
        return self._tlsPort
    def set_tlsPort(self, val):
        if val is None:
            val = -1

        try:
            val = int(val)
        except:
            pass

        if (type(val) is not int or
            (val != -1 and (val < 5900 or val > 65535))):
            raise ValueError(_("TLS port must be a number between "
                               "5900 and 65535, or -1 for auto allocation"))
        self._tlsPort = val
    tlsPort = _xml_property(get_tlsPort, set_tlsPort,
                            get_converter=lambda s, x: int(x or -1),
                            xpath="./@tlsPort")

    channel_main_mode = _get_mode_prop(CHANNEL_TYPE_MAIN)
    channel_display_mode = _get_mode_prop(CHANNEL_TYPE_DISPLAY)
    channel_inputs_mode = _get_mode_prop(CHANNEL_TYPE_INPUTS)
    channel_cursor_mode = _get_mode_prop(CHANNEL_TYPE_CURSOR)
    channel_playback_mode = _get_mode_prop(CHANNEL_TYPE_PLAYBACK)
    channel_record_mode = _get_mode_prop(CHANNEL_TYPE_RECORD)

    def _build_xml(self, port=None, listen=None, keymap=None, passwd=None,
                   display=None, xauth=None, tlsPort=None, canautoport=False,
                   passwdValidTo=None, socket=None):

        doautoport = (canautoport and
                      (port in [None, -1] and
                       tlsPort in [None, -1]))
        portxml     = (port is not None and (" port='%d'" % port) or "")
        tlsportxml  = (tlsPort is not None and (" tlsPort='%d'" % tlsPort) or "")
        autoportxml = (doautoport and " autoport='yes'" or "")

        keymapxml   = (keymap and (" keymap='%s'" % keymap) or "")
        listenxml   = (listen and (" listen='%s'" % listen) or "")
        passwdxml   = (passwd and (" passwd='%s'" % passwd) or "")
        passwdValidToxml = (passwdValidTo and
                            (" passwdValidTo='%s'" % passwdValidTo) or "")

        xauthxml    = (xauth and (" xauth='%s'" % xauth) or "")
        displayxml  = (display and (" display='%s'" % display) or "")

        socketxml   = (socket and (" socket='%s'" % socket) or "")

        xml = ("    " +
               "<graphics type='%s'" % self.type +
               portxml +
               tlsportxml +
               autoportxml +
               keymapxml +
               listenxml +
               passwdxml +
               passwdValidToxml +
               socketxml +
               displayxml +
               xauthxml +
               "/>")
        return xml

    def _sdl_config(self):
        if "DISPLAY" not in os.environ and not self.display:
            raise RuntimeError("No DISPLAY environment variable set.")

        disp  = self.display or os.environ["DISPLAY"]
        xauth = self.xauth or os.path.expanduser("~/.Xauthority")

        return self._build_xml(display=disp, xauth=xauth)

    def _spice_config(self):
        return self._build_xml(port=self.port, keymap=self.keymap,
                               passwd=self.passwd, listen=self.listen,
                               tlsPort=self.tlsPort, canautoport=True,
                               passwdValidTo=self.passwdValidTo)

    def _vnc_config(self):
        return self._build_xml(port=self.port, keymap=self.keymap,
                               passwd=self.passwd, listen=self.listen,
                               # VNC supports autoport, but use legacy
                               # syntax to not break XML tests
                               canautoport=False,
                               passwdValidTo=self.passwdValidTo,
                               socket=self.socket)

    def _get_xml_config(self):
        if self._type == self.TYPE_SDL:
            return self._sdl_config()
        if self._type == self.TYPE_SPICE:
            return self._spice_config()
        if self._type == self.TYPE_VNC:
            return self._vnc_config()
        else:
            raise ValueError(_("Unknown graphics type"))
Example #10
0
class CPU(XMLBuilderDomain.XMLBuilderDomain):
    """
    Class for generating <cpu> XML
    """

    _dumpxml_xpath = "/domain/cpu"

    MATCHS = ["minimum", "exact", "strict"]

    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        self._model = None
        self._match = None
        self._vendor = None
        self._mode = None
        self._features = []

        self._sockets = None
        self._cores = None
        self._threads = None

        XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
                                                   parsexmlnode, caps)
        if self._is_parse():
            return

    def _parsexml(self, xml, node):
        XMLBuilderDomain.XMLBuilderDomain._parsexml(self, xml, node)

        for node in self._xml_node.children:
            if node.name != "feature":
                continue
            feature = CPUFeature(self.conn, parsexmlnode=node)
            self._features.append(feature)

    def _get_features(self):
        return self._features[:]
    features = _xml_property(_get_features)

    def add_feature(self, name, policy="require"):
        feature = CPUFeature(self.conn)
        feature.name = name
        feature.policy = policy

        if self._is_parse():
            xml = feature.get_xml_config()
            node = libxml2.parseDoc(xml).children
            feature.set_xml_node(node)
            self._add_child_node("./cpu", node)

        self._features.append(feature)

    def remove_feature(self, feature):
        if self._is_parse() and feature in self._features:
            xpath = feature.get_xml_node_path()
            if xpath:
                self._remove_child_xpath(xpath)

        self._features.remove(feature)


    def _get_model(self):
        return self._model
    def _set_model(self, val):
        if val:
            self.mode = "custom"
        if val and not self.match:
            self.match = "exact"
        self._model = val
    model = _xml_property(_get_model, _set_model,
                          xpath="./cpu/model")

    def _get_match(self):
        return self._match
    def _set_match(self, val):
        self._match = val
    match = _xml_property(_get_match, _set_match,
                          xpath="./cpu/@match")

    def _get_vendor(self):
        return self._vendor
    def _set_vendor(self, val):
        self._vendor = val
    vendor = _xml_property(_get_vendor, _set_vendor,
                           xpath="./cpu/vendor")

    def _get_mode(self):
        return self._mode
    def _set_mode(self, val):
        self._mode = val
    mode = _xml_property(_get_mode, _set_mode,
                         xpath="./cpu/@mode")

    # Topology properties
    def _get_sockets(self):
        return self._sockets
    def _set_sockets(self, val):
        self._sockets = _int_or_none(val)
    sockets = _xml_property(_get_sockets, _set_sockets,
                            get_converter=lambda s, x: _int_or_none(x),
                            xpath="./cpu/topology/@sockets")

    def _get_cores(self):
        return self._cores
    def _set_cores(self, val):
        self._cores = _int_or_none(val)
    cores = _xml_property(_get_cores, _set_cores,
                          get_converter=lambda s, x: _int_or_none(x),
                          xpath="./cpu/topology/@cores")

    def _get_threads(self):
        return self._threads
    def _set_threads(self, val):
        self._threads = _int_or_none(val)
    threads = _xml_property(_get_threads, _set_threads,
                            get_converter=lambda s, x: _int_or_none(x),
                            xpath="./cpu/topology/@threads")

    def clear_attrs(self):
        self.match = None
        self.mode = None
        self.vendor = None
        self.model = None

        for feature in self.features:
            self.remove_feature(feature)

    def copy_host_cpu(self):
        """
        Enact the equivalent of qemu -cpu host, pulling all info
        from capabilities about the host CPU
        """
        cpu = self._get_caps().host.cpu
        if not cpu.model:
            raise ValueError(_("No host CPU reported in capabilities"))

        self.mode = "custom"
        self.match = "exact"
        self.model = cpu.model
        self.vendor = cpu.vendor

        for feature in self.features:
            self.remove_feature(feature)
        for name in cpu.features.names():
            self.add_feature(name)

    def vcpus_from_topology(self):
        """
        Determine the CPU count represented by topology, or 1 if
        no topology is set
        """
        self.set_topology_defaults()
        if self.sockets:
            return self.sockets * self.cores * self.threads
        return 1

    def set_topology_defaults(self, vcpus=None):
        """
        Fill in unset topology values, using the passed vcpus count if
        required
        """
        if (self.sockets is None and
            self.cores is None and
            self.threads is None):
            return

        if vcpus is None:
            if self.sockets is None:
                self.sockets = 1
            if self.threads is None:
                self.threads = 1
            if self.cores is None:
                self.cores = 1

        vcpus = int(vcpus or 0)
        if not self.sockets:
            if not self.cores:
                self.sockets = vcpus / self.threads
            else:
                self.sockets = vcpus / self.cores

        if not self.cores:
            if not self.threads:
                self.cores = vcpus / self.sockets
            else:
                self.cores = vcpus / (self.sockets * self.threads)

        if not self.threads:
            self.threads = vcpus / (self.sockets * self.cores)

        return

    def _get_topology_xml(self):
        xml = ""
        if self.sockets:
            xml += " sockets='%s'" % self.sockets
        if self.cores:
            xml += " cores='%s'" % self.cores
        if self.threads:
            xml += " threads='%s'" % self.threads

        if not xml:
            return ""
        return "    <topology%s/>\n" % xml

    def _get_feature_xml(self):
        xml = ""
        for feature in self._features:
            xml += feature.get_xml_config() + "\n"
        return xml

    def _get_xml_config(self):
        top_xml = self._get_topology_xml()
        feature_xml = self._get_feature_xml()
        mode_xml = ""
        match_xml = ""
        if self.match:
            match_xml = " match='%s'" % self.match
        xml = ""

        if self.model == "host-passthrough":
            self.mode = "host-passthrough"
            mode_xml = " mode='%s'" % self.mode
            xml += "  <cpu%s/>" % mode_xml
            return xml
        else:
            self.mode = "custom"
            mode_xml = " mode='%s'" % self.mode

        if not (self.model or top_xml or feature_xml):
            return ""

        # Simple topology XML mode
        xml += "  <cpu%s%s>\n" % (mode_xml, match_xml)
        if self.model:
            xml += "    <model>%s</model>\n" % self.model
        if self.vendor:
            xml += "    <vendor>%s</vendor>\n" % self.vendor
        if top_xml:
            xml += top_xml
        if feature_xml:
            xml += feature_xml

        xml += "  </cpu>"
        return xml
class VirtualRNGDevice(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_RNG

    TYPE_RANDOM = "random"
    TYPE_EGD = "egd"
    TYPES = [TYPE_RANDOM, TYPE_EGD]

    BACKEND_TYPE_UDP = "udp"
    BACKEND_TYPE_TCP = "tcp"
    BACKEND_TYPES = [BACKEND_TYPE_UDP, BACKEND_TYPE_TCP]

    BACKEND_MODE_BIND = "bind"
    BACKEND_MODE_CONNECT = "connect"
    BACKEND_MODES = [BACKEND_MODE_BIND, BACKEND_MODE_CONNECT]

    def __init__(self, conn=None, parsexml=None, parsexmlnode=None, caps=None):
        VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)
        self._type = None
        self._model = None
        self._backend_type = None
        self._bind_host = None
        self._bind_service = None
        self._connect_host = None
        self._connect_service = None
        self._rate_bytes = None
        self._rate_period = None

        self._device = None
        if self._is_parse():
            return

    @staticmethod
    def get_pretty_type(rng_type):
        if rng_type == VirtualRNGDevice.TYPE_RANDOM:
            return _("Random")
        if rng_type == VirtualRNGDevice.TYPE_EGD:
            return _("Entropy Gathering Daemon")
        return rng_type

    @staticmethod
    def get_pretty_backend_type(backend_type):
        return {"udp": "UDP", "tcp": "TCP"}.get(backend_type) or backend_type

    @staticmethod
    def get_pretty_mode(mode):
        return {"bind": "Bind", "connect": "Connect"}.get(mode) or mode

    def backend_mode(self):
        ret = []
        if self.bind_host or self.bind_service:
            ret.append(VirtualRNGDevice.BACKEND_MODE_BIND)
        if self.connect_host or self.connect_service:
            ret.append(VirtualRNGDevice.BACKEND_MODE_CONNECT)
        return ret

    def supports_property(self, propname):
        """
        Whether the rng dev type supports the passed property name
        """
        users = {
            "type": [self.TYPE_EGD, self.TYPE_RANDOM],
            "model": [self.TYPE_EGD, self.TYPE_RANDOM],
            "bind_host": [self.TYPE_EGD],
            "bind_service": [self.TYPE_EGD],
            "connect_host": [self.TYPE_EGD],
            "connect_service": [self.TYPE_EGD],
            "backend_type": [self.TYPE_EGD],
            "device": [self.TYPE_RANDOM],
            "rate_bytes": [self.TYPE_EGD, self.TYPE_RANDOM],
            "rate_period": [self.TYPE_EGD, self.TYPE_RANDOM],
        }
        if users.get(propname):
            return self.type in users[propname]

        return hasattr(self, propname)

    def _get_type(self):
        return self._type

    def _set_type(self, m):
        self._type = m

    type = _xml_property(_get_type, _set_type, xpath="./backend/@model")

    def _get_model(self):
        return self._model

    def _set_model(self, m):
        self._model = m

    model = _xml_property(_get_model, _set_model, xpath="./@model")

    def _get_backend_type(self):
        return self._backend_type

    def _set_backend_type(self, t):
        self._backend_type = t

    backend_type = _xml_property(_get_backend_type,
                                 _set_backend_type,
                                 xpath="./backend/@type")

    def _get_bind_host(self):
        return self._bind_host

    def _set_bind_host(self, m):
        self._bind_host = m

    bind_host = _xml_property(_get_bind_host,
                              _set_bind_host,
                              xpath="./backend/source[@mode='bind']/@host")

    def _get_connect_host(self):
        return self._connect_host

    def _set_connect_host(self, m):
        self._connect_host = m

    connect_host = _xml_property(
        _get_connect_host,
        _set_connect_host,
        xpath="./backend/source[@mode='connect']/@host")

    def _get_bind_service(self):
        return self._bind_service

    def _set_bind_service(self, m):
        self._bind_service = m

    bind_service = _xml_property(
        _get_bind_service,
        _set_bind_service,
        xpath="./backend/source[@mode='bind']/@service")

    def _get_connect_service(self):
        return self._connect_service

    def _set_connect_service(self, m):
        self._connect_service = m

    connect_service = _xml_property(
        _get_connect_service,
        _set_connect_service,
        xpath="./backend/source[@mode='connect']/@service")

    def _get_rate_bytes(self):
        return self._rate_bytes

    def _set_rate_bytes(self, b):
        self._rate_bytes = b

    rate_bytes = _xml_property(_get_rate_bytes,
                               _set_rate_bytes,
                               xpath="./rate/@bytes")

    def _get_rate_period(self):
        return self._rate_period

    def _set_rate_period(self, p):
        self._rate_period = p

    rate_period = _xml_property(_get_rate_period,
                                _set_rate_period,
                                xpath="./rate/@period")

    def _get_device(self):
        if self._type == self.TYPE_RANDOM:
            return self._device
        return None

    def _set_device(self, d):
        self._device = d

    device = _xml_property(_get_device, _set_device, xpath="./backend")

    def _get_xml_config(self):
        rng_model = self.model or "virtio"
        xml = ("    <rng model='%s'>\n" % rng_model)

        if self.rate_bytes or self.rate_period:
            xml += "      <rate"
            if self.rate_period:
                xml += " period='%s'" % self.rate_period
            if self.rate_bytes:
                xml += " bytes='%s'" % self.rate_bytes
            xml += "/>\n"

        if self.type == self.TYPE_RANDOM:
            xml += "      <backend model='random'>%s</backend>\n" % self.device
        else:
            model = "model='%s'" % self.type
            backend_type = "type='%s'" % (self.backend_type or "tcp")
            xml += "      <backend %s %s>\n" % (model, backend_type)

            def add_source(mode, host, service):
                ret = "        <source mode='%s'" % mode
                if host:
                    ret += " host='%s'" % host
                if service:
                    ret += " service='%s'" % service
                return ret + "/>\n"

            if self.bind_host or self.bind_service:
                xml += add_source("bind", self.bind_host, self.bind_service)
            if self.connect_host or self.connect_service:
                xml += add_source("connect", self.connect_host, \
                                  self.connect_service)
            xml += "      </backend>\n"

        xml += "    </rng>"
        return xml
Example #12
0
class Installer(XMLBuilderDomain.XMLBuilderDomain):
    """
    Installer classes attempt to encapsulate all the parameters needed
    to 'install' a guest: essentially, booting the guest with the correct
    media for the OS install phase (if there is one), and setting up the
    guest to boot to the correct media for all subsequent runs.

    Some of the actual functionality:

        - Determining what type of install media has been requested, and
          representing it correctly to the Guest

        - Fetching install kernel/initrd or boot.iso from a URL

        - Setting the boot device as appropriate depending on whether we
          are booting into an OS install, or booting post-install

    Some of the information that the Installer needs to know to accomplish
    this:

        - Install media location (could be a URL, local path, ...)
        - Virtualization type (parameter 'os_type') ('xen', 'hvm', etc.)
        - Hypervisor name (parameter 'type') ('qemu', 'kvm', 'xen', etc.)
        - Guest architecture ('i686', 'x86_64')
    """
    _dumpxml_xpath = "/domain/os"
    _has_install_phase = True

    def __init__(self,
                 type="xen",
                 location=None,
                 extraargs=None,
                 os_type=None,
                 conn=None,
                 parsexml=None,
                 parsexmlnode=None,
                 caps=None):
        # pylint: disable=W0622
        # Redefining built-in 'type', but it matches the XML so keep it

        XMLBuilderDomain.XMLBuilderDomain.__init__(self,
                                                   conn,
                                                   parsexml,
                                                   parsexmlnode,
                                                   caps=caps)

        self._type = None
        self._location = None
        self._initrd_injections = []
        self._cdrom = False
        self._os_type = None
        self._scratchdir = None
        self._arch = None
        self._machine = None
        self._loader = None
        self._init = None
        self._install_bootconfig = Boot(self.conn)
        self._bootconfig = Boot(self.conn, parsexml, parsexmlnode)

        # Devices created/added during the prepare() stage
        self.install_devices = []

        if self._is_parse():
            return

        # FIXME: Better solution? Skip validating this since we may not be
        # able to install a VM of the host arch
        if self._get_caps():
            self._arch = self._get_caps().host.arch

        if type is None:
            type = "xen"
        self.type = type

        if not os_type is None:
            self.os_type = os_type
        else:
            self.os_type = "xen"
        if not location is None:
            self.location = location

        self.extraargs = extraargs

        self._tmpfiles = []
        self._tmpvols = []

    def get_conn(self):
        return self._conn

    conn = property(get_conn)

    def _get_bootconfig(self):
        return self._bootconfig

    bootconfig = property(_get_bootconfig)

    # Hypervisor name (qemu, kvm, xen, lxc, etc.)
    def get_type(self):
        return self._type

    def set_type(self, val):
        self._type = val

    type = _xml_property(get_type, set_type, xpath="./@type")

    # Virtualization type ('xen' == xen paravirt, or 'hvm)
    def get_os_type(self):
        return self._os_type

    def set_os_type(self, val):
        # Older libvirt back compat: if user specifies 'linux', convert
        # internally to newer equivalent value 'xen'
        if val == "linux":
            val = "xen"

        # XXX: Need to validate this: have some whitelist based on caps?
        self._os_type = val

    os_type = _xml_property(get_os_type, set_os_type, xpath="./os/type")

    def get_arch(self):
        return self._arch

    def set_arch(self, val):
        # XXX: Sanitize to a consisten value (i368 -> i686)
        # XXX: Validate against caps
        self._arch = val

    arch = _xml_property(get_arch, set_arch, xpath="./os/type/@arch")

    def _get_machine(self):
        return self._machine

    def _set_machine(self, val):
        self._machine = val

    machine = _xml_property(_get_machine,
                            _set_machine,
                            xpath="./os/type/@machine")

    def _get_loader(self):
        return self._loader

    def _set_loader(self, val):
        self._loader = val

    loader = _xml_property(_get_loader, _set_loader, xpath="./os/loader")

    def _get_init(self):
        return self._init

    def _set_init(self, val):
        self._init = val

    init = _xml_property(_get_init, _set_init, xpath="./os/init")

    def get_scratchdir(self):
        if not self.scratchdir_required():
            return None

        if not self._scratchdir:
            self._scratchdir = self._get_scratchdir()
            logging.debug("scratchdir=%s", self._scratchdir)
        return self._scratchdir

    scratchdir = property(get_scratchdir)

    def get_cdrom(self):
        return self._cdrom

    def set_cdrom(self, enable):
        if enable not in [True, False]:
            raise ValueError(_("Guest.cdrom must be a boolean type"))
        self._cdrom = enable

    cdrom = property(get_cdrom, set_cdrom)

    def get_location(self):
        return self._location

    def set_location(self, val):
        self._location = val

    location = property(get_location, set_location)

    def get_initrd_injections(self):
        return self._initrd_injections

    def set_initrd_injections(self, val):
        self._initrd_injections = val

    initrd_injections = property(get_initrd_injections, set_initrd_injections)

    # extra arguments to pass to the guest installer
    def get_extra_args(self):
        return self._install_bootconfig.kernel_args

    def set_extra_args(self, val):
        self._install_bootconfig.kernel_args = val

    extraargs = property(get_extra_args, set_extra_args)

    # Public helper methods
    def scratchdir_required(self):
        """
        Returns true if scratchdir is needed for the passed install parameters.
        Apps can use this to determine if they should attempt to ensure
        scratchdir permissions are adequate
        """
        return False

    def is_hvm(self):
        return self.os_type == "hvm"

    def is_xenpv(self):
        return self.os_type in ["xen", "linux"]

    def is_container(self):
        return self.os_type == "exe"

    # Private methods
    def _get_system_scratchdir(self):
        if platform.system() == "SunOS":
            return "/var/tmp"

        if self.type == "test":
            return "/tmp"
        elif self.type == "xen":
            return XEN_SCRATCH
        else:
            return LIBVIRT_SCRATCH

    def _get_scratchdir(self):
        scratch = None
        if not self.is_session_uri():
            scratch = self._get_system_scratchdir()

        if (not scratch or not os.path.exists(scratch)
                or not os.access(scratch, os.W_OK)):
            scratch = os.path.expanduser("~/.virtinst/boot")
            if not os.path.exists(scratch):
                os.makedirs(scratch, 0751)

        return scratch

    def _get_bootdev(self, isinstall, guest):
        raise NotImplementedError("Must be implemented in subclass")

    def _build_boot_order(self, isinstall, guest):
        bootorder = [self._get_bootdev(isinstall, guest)]

        # If guest has an attached disk, always have 'hd' in the boot
        # list, so disks are marked as bootable/installable (needed for
        # windows virtio installs, and booting local disk from PXE)
        for disk in guest.get_devices("disk"):
            if disk.device == disk.DEVICE_DISK:
                bootdev = self.bootconfig.BOOT_DEVICE_HARDDISK
                if bootdev not in bootorder:
                    bootorder.append(bootdev)
                break

        return bootorder

    def _get_default_init(self, guest):
        if not self.is_container():
            return

        for fs in guest.get_devices("filesystem"):
            if fs.target == "/":
                return "/sbin/init"
        return "/bin/sh"

    def _get_osblob_helper(self, guest, isinstall, bootconfig):
        conn = guest.conn
        arch = self.arch
        machine = self.machine
        hvtype = self.type
        loader = self.loader
        os_type = self.os_type
        init = self.init or self._get_default_init(guest)

        hvxen = (hvtype == "xen")

        if not loader and self.is_hvm() and hvxen:
            loader = "/usr/lib/xen/boot/hvmloader"

        # Use older libvirt 'linux' value for back compat
        if os_type == "xen" and hvxen:
            os_type = "linux"

        if (not isinstall and self.is_xenpv() and not self.bootconfig.kernel):
            return "<bootloader>%s</bootloader>" % _pygrub_path(conn)

        osblob = "<os>"

        typexml = "    <type"
        if arch:
            typexml += " arch='%s'" % arch
        if machine:
            typexml += " machine='%s'" % machine
        typexml += ">%s</type>" % os_type

        osblob = util.xml_append(osblob, typexml)

        if init:
            osblob = util.xml_append(
                osblob, "    <init>%s</init>" % util.xml_escape(init))
        if loader:
            osblob = util.xml_append(
                osblob, "    <loader>%s</loader>" % util.xml_escape(loader))

        if not self.is_container():
            osblob = util.xml_append(osblob, bootconfig.get_xml_config())
        osblob = util.xml_append(osblob, "  </os>")

        return osblob

    # Method definitions

    def _get_xml_config(self, guest, isinstall):
        """
        Generate the portion of the guest xml that determines boot devices
        and parameters. (typically the <os></os> block)

        @param guest: Guest instance we are installing
        @type guest: L{Guest}
        @param isinstall: Whether we want xml for the 'install' phase or the
                          'post-install' phase.
        @type isinstall: C{bool}
        """
        # pylint: disable=W0221
        # Argument number differs from overridden method

        if isinstall:
            bootconfig = self._install_bootconfig
        else:
            bootconfig = self.bootconfig

        if isinstall and not self.has_install_phase():
            return

        bootorder = self._build_boot_order(isinstall, guest)
        bootconfig = copy.copy(bootconfig)
        if not bootconfig.bootorder:
            bootconfig.bootorder = bootorder

        return self._get_osblob_helper(guest, isinstall, bootconfig)

    def has_install_phase(self):
        """
        Return True if the requested setup is actually installing an OS
        into the guest. Things like LiveCDs, Import, or a manually specified
        bootorder do not have an install phase.
        """
        return self._has_install_phase

    def cleanup(self):
        """
        Remove any temporary files retrieved during installation
        """
        for f in self._tmpfiles:
            logging.debug("Removing " + f)
            os.unlink(f)

        for vol in self._tmpvols:
            logging.debug("Removing volume '%s'", vol.name())
            vol.delete(0)

        self._tmpvols = []
        self._tmpfiles = []
        self.install_devices = []

    def prepare(self, guest, meter):
        """
        Fetch any files needed for installation.
        @param guest: guest instance being installed
        @type guest: L{Guest}
        @param meter: progress meter
        @type meter: Urlgrabber ProgressMeter
        """
        raise NotImplementedError("Must be implemented in subclass")

    def detect_distro(self):
        """
        Attempt to detect the distro for the Installer's 'location'. If
        an error is encountered in the detection process (or if detection
        is not relevant for the Installer type), (None, None) is returned

        @returns: (distro type, distro variant) tuple
        """
        return (None, None)

    def guest_from_installer(self):
        """
        Return a L{Guest} instance wrapping the current installer.

        If all the appropriate values are present in the installer
        (conn, type, os_type, arch, machine), we have everything we need
        to determine what L{Guest} class is expected and what default values
        to pass it. This is a convenience method to save the API user from
        having to enter all these known details twice.
        """

        if not self.conn:
            raise ValueError(_("A connection must be specified."))

        guest, domain = CapabilitiesParser.guest_lookup(conn=self.conn,
                                                        caps=self._get_caps(),
                                                        os_type=self.os_type,
                                                        typ=self.type,
                                                        arch=self.arch,
                                                        machine=self.machine)

        gobj = virtinst.Guest(installer=self, conn=self.conn)
        gobj.arch = guest.arch
        gobj.emulator = domain.emulator
        self.loader = domain.loader

        return gobj
class VirtualWatchdog(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_WATCHDOG

    MODEL_DEFAULT = "default"
    MODELS = ["i6300esb", "ib700", MODEL_DEFAULT]

    ACTION_DEFAULT = "default"
    ACTION_SHUTDOWN = "shutdown"
    ACTION_RESET = "reset"
    ACTION_POWEROFF = "poweroff"
    ACTION_PAUSE = "pause"
    ACTION_NONE = "none"
    ACTIONS = [
        ACTION_RESET, ACTION_SHUTDOWN, ACTION_POWEROFF, ACTION_PAUSE,
        ACTION_NONE, ACTION_DEFAULT
    ]

    @staticmethod
    def get_action_desc(action):
        if action == VirtualWatchdog.ACTION_RESET:
            return _("Forcefully reset the guest")
        if action == VirtualWatchdog.ACTION_SHUTDOWN:
            return _("Gracefully shutdown the guest")
        if action == VirtualWatchdog.ACTION_POWEROFF:
            return _("Forcefully power off the guest")
        if action == VirtualWatchdog.ACTION_PAUSE:
            return _("Pause the guest")
        if action == VirtualWatchdog.ACTION_NONE:
            return _("No action")
        if action == VirtualWatchdog.ACTION_DEFAULT:
            return _("Hypervisor default")
        else:
            return action

    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)

        self._model = None
        self._action = None

        if self._is_parse():
            return

        self.model = self.MODEL_DEFAULT
        self.action = self.ACTION_DEFAULT

    def get_model(self):
        return self._model

    def set_model(self, new_model):
        if type(new_model) != str:
            raise ValueError(
                _("'model' must be a string, "
                  " was '%s'." % type(new_model)))
        if not self.MODELS.count(new_model):
            raise ValueError(_("Unsupported watchdog model '%s'" % new_model))
        self._model = new_model

    model = _xml_property(get_model, set_model, xpath="./@model")

    def get_action(self):
        return self._action

    def set_action(self, val):
        if val not in self.ACTIONS:
            raise ValueError("Unknown watchdog action '%s'." % val)
        self._action = val

    action = _xml_property(get_action, set_action, xpath="./@action")

    def _get_xml_config(self):
        model = self.model
        if model == self.MODEL_DEFAULT:
            model = "i6300esb"

        action = self.action
        if action == self.ACTION_DEFAULT:
            action = self.ACTION_RESET

        xml = "    <watchdog model='%s'" % model
        if action:
            xml += " action='%s'" % action
        xml += "/>"

        return xml
Example #14
0
class DomainNumatune(XMLBuilderDomain.XMLBuilderDomain):
    """
    Class for generating <numatune> XML
    """
    @staticmethod
    def validate_cpuset(conn, val):
        if val is None or val == "":
            return

        if not isinstance(val, str) or len(val) == 0:
            raise ValueError(_("cpuset must be string"))
        if re.match("^[0-9,-^]*$", val) is None:
            raise ValueError(
                _("cpuset can only contain numeric, ',', '^', or "
                  "'-' characters"))

        pcpus = get_phy_cpus(conn)
        for c in val.split(','):
            # Redundant commas
            if not c:
                continue

            if "-" in c:
                (x, y) = c.split('-', 1)
                x = int(x)
                y = int(y)
                if x > y:
                    raise ValueError(_("cpuset contains invalid format."))
                if x >= pcpus or y >= pcpus:
                    raise ValueError(
                        _("cpuset's pCPU numbers must be less "
                          "than pCPUs."))
            else:
                if c.startswith("^"):
                    c = c[1:]
                c = int(c)

                if c >= pcpus:
                    raise ValueError(
                        _("cpuset's pCPU numbers must be less "
                          "than pCPUs."))

    @staticmethod
    def cpuset_str_to_tuple(conn, cpuset):
        DomainNumatune.validate_cpuset(conn, cpuset)
        pinlist = [False] * get_phy_cpus(conn)

        entries = cpuset.split(",")
        for e in entries:
            series = e.split("-", 1)

            if len(series) == 1:
                pinlist[int(series[0])] = True
                continue

            start = int(series[0])
            end = int(series[1])

            for i in range(start, end + 1):
                pinlist[i] = True

        return tuple(pinlist)

    _dumpxml_xpath = "/domain/numatune"

    MEMORY_MODES = ["interleave", "strict", "preferred"]

    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        self._memory_nodeset = None
        self._memory_mode = None

        XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
                                                   parsexmlnode, caps)
        if self._is_parse():
            return

    def _get_memory_nodeset(self):
        return self._memory_nodeset

    def _set_memory_nodeset(self, val):
        self._memory_nodeset = val

    memory_nodeset = _xml_property(_get_memory_nodeset,
                                   _set_memory_nodeset,
                                   xpath="./numatune/memory/@nodeset")

    def _get_memory_mode(self):
        return self._memory_mode

    def _set_memory_mode(self, val):
        self._memory_mode = val

    memory_mode = _xml_property(_get_memory_mode,
                                _set_memory_mode,
                                xpath="./numatune/memory/@mode")

    def _get_memory_xml(self):
        if not self.memory_nodeset:
            return ""

        xml = "    <memory"
        if self.memory_mode:
            xml += " mode='%s'" % self.memory_mode
        if self.memory_nodeset:
            xml += " nodeset='%s'" % self.memory_nodeset
        xml += "/>\n"
        return xml

    def _get_xml_config(self):
        mem_xml = self._get_memory_xml()
        if not mem_xml:
            return ""

        xml = "  <numatune>\n"
        xml += mem_xml
        xml += "  </numatune>"
        return xml
Example #15
0
class VirtualCharDevice(VirtualDevice):
    """
    Base class for all character devices. Shouldn't be instantiated
    directly.
    """

    DEV_SERIAL   = "serial"
    DEV_PARALLEL = "parallel"
    DEV_CONSOLE  = "console"
    DEV_CHANNEL  = "channel"
    dev_types    = [DEV_SERIAL, DEV_PARALLEL, DEV_CONSOLE, DEV_CHANNEL]

    CHAR_PTY      = "pty"
    CHAR_DEV      = "dev"
    CHAR_STDIO    = "stdio"
    CHAR_PIPE     = "pipe"
    CHAR_FILE     = "file"
    CHAR_VC       = "vc"
    CHAR_NULL     = "null"
    CHAR_TCP      = "tcp"
    CHAR_UDP      = "udp"
    CHAR_UNIX     = "unix"
    CHAR_SPICEVMC = "spicevmc"
    char_types  = [CHAR_PTY, CHAR_DEV, CHAR_STDIO, CHAR_FILE, CHAR_VC,
                    CHAR_PIPE, CHAR_NULL, CHAR_TCP, CHAR_UDP, CHAR_UNIX,
                    CHAR_SPICEVMC]

    _non_channel_types = char_types[:]
    _non_channel_types.remove(CHAR_SPICEVMC)

    char_types_for_dev_type = {
        DEV_SERIAL: _non_channel_types,
        DEV_PARALLEL: _non_channel_types,
        DEV_CONSOLE: _non_channel_types,
        DEV_CHANNEL: [CHAR_SPICEVMC],
   }

    CHAR_MODE_CONNECT = "connect"
    CHAR_MODE_BIND = "bind"
    char_modes = [CHAR_MODE_CONNECT, CHAR_MODE_BIND]

    CHAR_PROTOCOL_RAW = "raw"
    CHAR_PROTOCOL_TELNET = "telnet"
    char_protocols = [CHAR_PROTOCOL_RAW, CHAR_PROTOCOL_TELNET]

    CHAR_CHANNEL_TARGET_GUESTFWD = "guestfwd"
    CHAR_CHANNEL_TARGET_VIRTIO = "virtio"
    target_types = [CHAR_CHANNEL_TARGET_GUESTFWD,
                     CHAR_CHANNEL_TARGET_VIRTIO]

    CHAR_CHANNEL_ADDRESS_VIRTIO_SERIAL = "virtio-serial"
    address_types = [CHAR_CHANNEL_ADDRESS_VIRTIO_SERIAL]

    CHAR_CONSOLE_TARGET_SERIAL = "serial"
    CHAR_CONSOLE_TARGET_UML = "uml"
    CHAR_CONSOLE_TARGET_XEN = "xen"
    CHAR_CONSOLE_TARGET_VIRTIO = "virtio"

    has_target = False

    def get_char_type_desc(char_type):
        """
        Return a human readable description of the passed char type
        """
        desc = ""

        if char_type == VirtualCharDevice.CHAR_PTY:
            desc = _("Pseudo TTY")
        elif char_type == VirtualCharDevice.CHAR_DEV:
            desc = _("Physical host character device")
        elif char_type == VirtualCharDevice.CHAR_STDIO:
            desc = _("Standard input/output")
        elif char_type == VirtualCharDevice.CHAR_PIPE:
            desc = _("Named pipe")
        elif char_type == VirtualCharDevice.CHAR_FILE:
            desc = _("Output to a file")
        elif char_type == VirtualCharDevice.CHAR_VC:
            desc = _("Virtual console")
        elif char_type == VirtualCharDevice.CHAR_NULL:
            desc = _("Null device")
        elif char_type == VirtualCharDevice.CHAR_TCP:
            desc = _("TCP net console")
        elif char_type == VirtualCharDevice.CHAR_UDP:
            desc = _("UDP net console")
        elif char_type == VirtualCharDevice.CHAR_UNIX:
            desc = _("Unix socket")
        elif char_type == VirtualCharDevice.CHAR_SPICEVMC:
            desc = _("Spice agent")

        return desc
    get_char_type_desc = staticmethod(get_char_type_desc)

    def get_char_mode_desc(char_mode):
        """
        Return a human readable description of the passed char type
        """
        desc = ""

        if char_mode == VirtualCharDevice.CHAR_MODE_CONNECT:
            desc = _("Client mode")
        elif char_mode == VirtualCharDevice.CHAR_MODE_BIND:
            desc = _("Server mode")

        return desc
    get_char_mode_desc = staticmethod(get_char_mode_desc)

    # 'char_type' of class (must be properly set in subclass)
    _char_type = None

    def get_dev_instance(conn, dev_type, char_type):
        """
        Set up the class attributes for the passed char_type
        """

        # By default, all the possible parameters are enabled for the
        # device class. We go through here and del() all the ones that
        # don't apply. This is kind of whacky, but it's nice to to
        # allow an API user to just use hasattr(obj, paramname) to see
        # what parameters apply, instead of having to hardcode all that
        # information.
        if char_type == VirtualCharDevice.CHAR_PTY:
            c = VirtualCharPtyDevice
        elif char_type == VirtualCharDevice.CHAR_STDIO:
            c = VirtualCharStdioDevice
        elif char_type == VirtualCharDevice.CHAR_NULL:
            c = VirtualCharNullDevice
        elif char_type == VirtualCharDevice.CHAR_VC:
            c = VirtualCharVcDevice
        elif char_type == VirtualCharDevice.CHAR_DEV:
            c = VirtualCharDevDevice
        elif char_type == VirtualCharDevice.CHAR_FILE:
            c = VirtualCharFileDevice
        elif char_type == VirtualCharDevice.CHAR_PIPE:
            c = VirtualCharPipeDevice
        elif char_type == VirtualCharDevice.CHAR_TCP:
            c = VirtualCharTcpDevice
        elif char_type == VirtualCharDevice.CHAR_UNIX:
            c = VirtualCharUnixDevice
        elif char_type == VirtualCharDevice.CHAR_UDP:
            c = VirtualCharUdpDevice
        elif char_type == VirtualCharDevice.CHAR_SPICEVMC:
            c = VirtualCharSpicevmcDevice
        else:
            raise ValueError(_("Unknown character device type '%s'.") %
                             char_type)

        if dev_type == VirtualCharDevice.DEV_CONSOLE:
            return VirtualConsoleDevice(conn)

        return c(conn, dev_type)
    get_dev_instance = staticmethod(get_dev_instance)

    def __init__(self, conn, dev_type,
                 parsexml=None, parsexmlnode=None, caps=None):
        if dev_type not in self.dev_types:
            raise ValueError(_("Unknown character device type '%s'") % dev_type)
        self._dev_type = dev_type
        self._virtual_device_type = self._dev_type

        VirtualDevice.__init__(self, conn,
                                             parsexml, parsexmlnode, caps)

        # Init
        self._source_path = None
        self._source_mode = self.CHAR_MODE_BIND
        self._source_host = "127.0.0.1"
        self._source_port = None
        self._target_type = None
        self._target_address = None
        self._target_port = None
        self._target_name = None
        self._bind_host = None
        self._bind_port = None
        self._protocol = self.CHAR_PROTOCOL_RAW
        self._address_type = None

        if self.char_type == self.CHAR_UDP:
            self._source_mode = self.CHAR_MODE_CONNECT

        if self._is_parse():
            return

        if not self._char_type:
            raise ValueError("Must be instantiated through a subclass.")

        self.char_type = self._char_type

    def supports_property(self, propname, ro=False):
        """
        Whether the character dev type supports the passed property name
        """
        users = {
            "source_path"   : [self.CHAR_FILE, self.CHAR_UNIX,
                               self.CHAR_DEV,  self.CHAR_PIPE],
            "source_mode"   : [self.CHAR_UNIX, self.CHAR_TCP],
            "source_host"   : [self.CHAR_TCP, self.CHAR_UDP],
            "source_port"   : [self.CHAR_TCP, self.CHAR_UDP],
            "protocol"      : [self.CHAR_TCP],
            "bind_host"     : [self.CHAR_UDP],
            "bind_port"     : [self.CHAR_UDP],
       }

        if ro:
            users["source_path"] += [self.CHAR_PTY]

        channel_users = {
            "target_name"   : [self.CHAR_CHANNEL_TARGET_VIRTIO],
       }

        if users.get(propname):
            return self.char_type in users[propname]
        if channel_users.get(propname):
            return (self.dev_type == self.DEV_CHANNEL and
                    self.target_type in channel_users[propname])
        return hasattr(self, propname)

    # Properties
    def get_dev_type(self):
        return self._dev_type
    dev_type = property(get_dev_type)

    def get_char_type(self):
        return self._char_type
    def set_char_type(self, val):
        if val not in self.char_types:
            raise ValueError(_("Unknown character device type '%s'")
                             % val)
        self._char_type = val
    char_type = _xml_property(get_char_type, set_char_type,
                doc=_("Method used to expose character device in the host."),
                xpath="./@type")

    # Properties functions used by the various subclasses
    def get_source_path(self):
        return self._source_path
    def set_source_path(self, val):
        self._source_path = val
    def _sourcepath_get_xpath(self):
        return "./source/@path | ./@tty"
    source_path = _xml_property(get_source_path, set_source_path,
                                xml_get_xpath=_sourcepath_get_xpath,
                                xpath="./source/@path")

    def get_source_mode(self):
        return self._source_mode
    def set_source_mode(self, val):
        if val not in self.char_modes:
            raise ValueError(_("Unknown character mode '%s'.") % val)
        self._source_mode = val
    def _sourcemode_xpath(self):
        if self.char_type == self.CHAR_UDP:
            return "./source[@mode='connect']/@mode"
        return "./source/@mode"
    source_mode = _xml_property(get_source_mode, set_source_mode,
                                xml_get_xpath=_sourcemode_xpath,
                                xml_set_xpath=_sourcemode_xpath)

    def get_source_host(self):
        return self._source_host
    def set_source_host(self, val):
        self._source_host = val
    def _sourcehost_xpath(self):
        return "./source[@mode='%s']/@host" % self.source_mode
    source_host = _xml_property(get_source_host, set_source_host,
                                xml_get_xpath=_sourcehost_xpath,
                                xml_set_xpath=_sourcehost_xpath)

    def get_source_port(self):
        return self._source_port
    def set_source_port(self, val):
        self._source_port = int(val)
    def _sourceport_xpath(self):
        return "./source[@mode='%s']/@service" % self.source_mode
    source_port = _xml_property(get_source_port, set_source_port,
                                xml_get_xpath=_sourceport_xpath,
                                xml_set_xpath=_sourceport_xpath)

    def get_bind_host(self):
        return self._bind_host
    def set_bind_host(self, val):
        self._bind_host = val
    bind_host = _xml_property(get_bind_host, set_bind_host,
                              xpath="./source[@mode='bind']/@host")

    def get_bind_port(self):
        return self._bind_port
    def set_bind_port(self, val):
        self._bind_port = int(val)
    bind_port = _xml_property(get_bind_port, set_bind_port,
                              xpath="./source[@mode='bind']/@service")

    def get_protocol(self):
        return self._protocol
    def set_protocol(self, val):
        if val not in self.char_protocols:
            raise ValueError(_("Unknown protocol '%s'.") % val)
        self._protocol = val
    protocol = _xml_property(get_protocol, set_protocol,
                             xpath="./protocol/@type")

    # GuestFWD target properties
    def get_target_type(self):
        return self._target_type
    def set_target_type(self, val):
        if val not in self.target_types:
            raise ValueError(_("Unknown target type '%s'. Must be in: ") % val,
                             self.target_types)
        self._target_type = val
    target_type = _xml_property(get_target_type, set_target_type,
                                doc=_("Channel type as exposed in the guest."),
                                xpath="./target/@type")

    def set_target_address(self, val):
        self._target_address = val
    def get_target_address(self):
        return self._target_address
    target_address = _xml_property(get_target_address, set_target_address,
                        doc=_("Guest forward channel address in the guest."),
                        xpath="./target/@address")

    def set_target_port(self, val):
        self._target_port = val
    def get_target_port(self):
        return self._target_port
    target_port = _xml_property(get_target_port, set_target_port,
                           doc=_("Guest forward channel port in the guest."),
                           xpath="./target/@port")

    def set_target_name(self, val):
        self._target_name = val
    def get_target_name(self):
        return self._target_name
    target_name = _xml_property(get_target_name, set_target_name,
                           doc=_("Sysfs name of virtio port in the guest"),
                           xpath="./target/@name")

    def get_address_type(self):
        return self._address_type
    def set_address_type(self, val):
        if val not in self.address_types:
            raise ValueError(_("Unknown address type '%s'. Must be in: ") % val,
                             self.address_types)
        self._address_type = val
    address_type = _xml_property(get_address_type, set_address_type,
                                doc=_("Channel type as exposed in the guest."),
                                xpath="./address/@type")

    # XML building helpers
    def _char_empty_xml(self):
        """
        Provide source xml for devices with no params (null, stdio, ...)
        """
        return ""

    def _char_file_xml(self):
        """
        Provide source xml for devs that require only a path (dev, pipe)
        """
        file_xml = ""
        mode_xml = ""
        if self.source_path:
            file_xml = " path='%s'" % xml_escape(self.source_path)
        else:
            raise ValueError(_("A source path is required for character "
                               "device type '%s'" % self.char_type))

        if self.supports_property("source_mode") and self.source_mode:
            mode_xml = " mode='%s'" % xml_escape(self.source_mode)

        xml = "      <source%s%s/>\n" % (mode_xml, file_xml)
        return xml

    def _char_xml(self):
        pass

    def _get_target_xml(self):
        xml = ""
        if not self.target_type:
            return xml

        xml = "      <target type='%s'" % self.target_type

        if self._dev_type == self.DEV_CHANNEL:
            if self.target_type == self.CHAR_CHANNEL_TARGET_GUESTFWD:
                if not self.target_address and not self.target_port:
                    raise RuntimeError("A target address and port must be "
                                       "specified for '%s'" % self.target_type)

                xml += " address='%s'" % self.target_address
                xml += " port='%s'" % self.target_port

            elif self.target_type == self.CHAR_CHANNEL_TARGET_VIRTIO:
                if self.target_name:
                    xml += " name='%s'" % self.target_name


        xml += "/>\n"
        return xml

    def _get_address_xml(self):
        xml = ""
        if not self.address_type:
            return xml

        xml = "      <address type='%s'" % self.address_type
        xml += "/>\n"
        return xml


    def _get_xml_config(self):
        xml  = "    <%s type='%s'" % (self._dev_type, self._char_type)
        char_xml = self._char_xml()
        target_xml = self._get_target_xml()
        has_target = (self._dev_type == self.DEV_CHANNEL or
                      self._dev_type == self.DEV_CONSOLE or
                      self.has_target)

        if target_xml and not has_target:
            raise RuntimeError(
                "Target parameters not used with '%s' devices, only '%s'" %
                (self._dev_type, self.DEV_CHANNEL))

        address_xml = self._get_address_xml()
        has_address = self._target_type == self.CHAR_CHANNEL_TARGET_VIRTIO
        if address_xml and not has_address:
            raise RuntimeError(
                "Address parameters not used with '%s' target, only '%s'" %
                (self._target_type, self.CHAR_CHANNEL_TARGET_VIRTIO))

        if char_xml or target_xml or address_xml:
            xml += ">"
            if char_xml:
                xml += "\n%s" % char_xml

            if target_xml:
                xml += "\n%s" % target_xml

            if address_xml:
                xml += "\n%s" % target_xml

            xml += "    </%s>" % self._dev_type
        else:
            xml += "/>"

        return xml
        if newnet is not None and self.conn:
            try:
                net = self.conn.networkLookupByName(newnet)
            except libvirt.libvirtError, e:
                raise ValueError(
                    _("Virtual network '%s' does not exist: %s") %
                    (newnet, str(e)))
            if not _is_net_active(net):
                raise ValueError(
                    _("Virtual network '%s' has not been "
                      "started.") % newnet)

        self._network = newnet

    network = _xml_property(get_network,
                            set_network,
                            xpath="./source/@network")

    def get_bridge(self):
        if (not self._is_parse() and not self._bridge
                and self.type == self.TYPE_BRIDGE):
            return self._generate_default_bridge()
        return self._bridge

    def set_bridge(self, val):
        self._bridge = val

    bridge = _xml_property(get_bridge, set_bridge, xpath="./source/@bridge")

    def get_model(self):
        return self._model
Example #17
0
class DomainFeatures(XMLBuilderDomain.XMLBuilderDomain):
    """
    Class for generating <features> XML
    """

    _dumpxml_xpath = "/domain/features"

    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
                                                   parsexmlnode, caps)

        self._acpi = None
        self._apic = None
        self._pae = None

    def get_acpi(self):
        return self._acpi

    def set_acpi(self, val):
        self._acpi = _none_or_bool(val)

    acpi = _xml_property(get_acpi,
                         set_acpi,
                         xpath="./features/acpi",
                         is_bool=True)

    def get_apic(self):
        return self._apic

    def set_apic(self, val):
        self._apic = _none_or_bool(val)

    apic = _xml_property(get_apic,
                         set_apic,
                         xpath="./features/apic",
                         is_bool=True)

    def get_pae(self):
        return self._pae

    def set_pae(self, val):
        self._pae = _none_or_bool(val)

    pae = _xml_property(get_pae, set_pae, xpath="./features/pae", is_bool=True)

    def __setitem__(self, attr, val):
        return setattr(self, attr, val)

    def __getitem__(self, attr):
        return getattr(self, attr)

    def __delitem__(self, attr):
        return setattr(self, attr, None)

    def _get_xml_config(self, defaults=None):
        # pylint: disable=W0221
        # Argument number differs from overridden method

        if not defaults:
            defaults = {}
        ret = ""

        feature_xml = ""
        if self.acpi or (self.acpi is None and defaults.get("acpi")):
            feature_xml += "<acpi/>"
        if self.apic or (self.apic is None and defaults.get("apic")):
            feature_xml += "<apic/>"
        if self.pae or (self.pae is None and defaults.get("pae")):
            feature_xml += "<pae/>"

        if feature_xml:
            ret += "  <features>\n"
            ret += "    %s\n" % feature_xml
            ret += "  </features>"

        return ret
Example #18
0
class VirtualController(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_CONTROLLER

    CONTROLLER_TYPE_IDE = "ide"
    CONTROLLER_TYPE_FDC = "fdc"
    CONTROLLER_TYPE_SCSI = "scsi"
    CONTROLLER_TYPE_SATA = "sata"
    CONTROLLER_TYPE_VIRTIOSERIAL = "virtio-serial"
    CONTROLLER_TYPE_USB = "usb"
    CONTROLLER_TYPE_PCI = "pci"
    CONTROLLER_TYPE_CCID = "ccid"
    CONTROLLER_TYPES = [
        CONTROLLER_TYPE_IDE, CONTROLLER_TYPE_FDC, CONTROLLER_TYPE_SCSI,
        CONTROLLER_TYPE_SATA, CONTROLLER_TYPE_VIRTIOSERIAL,
        CONTROLLER_TYPE_USB, CONTROLLER_TYPE_PCI, CONTROLLER_TYPE_CCID
    ]

    @staticmethod
    def pretty_type(ctype):
        pretty_mappings = {
            VirtualController.CONTROLLER_TYPE_IDE: "IDE",
            VirtualController.CONTROLLER_TYPE_FDC: "Floppy",
            VirtualController.CONTROLLER_TYPE_SCSI: "SCSI",
            VirtualController.CONTROLLER_TYPE_SATA: "SATA",
            VirtualController.CONTROLLER_TYPE_VIRTIOSERIAL: "Virtio Serial",
            VirtualController.CONTROLLER_TYPE_USB: "USB",
            VirtualController.CONTROLLER_TYPE_PCI: "PCI",
            VirtualController.CONTROLLER_TYPE_CCID: "CCID",
        }

        if ctype not in pretty_mappings:
            return ctype
        return pretty_mappings[ctype]

    @staticmethod
    def get_class_for_type(ctype):
        if ctype not in VirtualController.CONTROLLER_TYPES:
            raise ValueError("Unknown controller type '%s'" % ctype)

        if ctype == VirtualController.CONTROLLER_TYPE_IDE:
            return VirtualControllerIDE
        elif ctype == VirtualController.CONTROLLER_TYPE_FDC:
            return VirtualControllerFDC
        elif ctype == VirtualController.CONTROLLER_TYPE_SCSI:
            return VirtualControllerSCSI
        elif ctype == VirtualController.CONTROLLER_TYPE_SATA:
            return VirtualControllerSATA
        elif ctype == VirtualController.CONTROLLER_TYPE_VIRTIOSERIAL:
            return VirtualControllerVirtioSerial
        elif ctype == VirtualController.CONTROLLER_TYPE_USB:
            return VirtualControllerUSB

    _controller_type = None

    def __init__(self,
                 conn,
                 parsexml=None,
                 parsexmlnode=None,
                 caps=None,
                 model=None):
        VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)

        self._index = 0
        self._ports = None
        self._vectors = None
        self._model = None
        self._master = VirtualDeviceMaster(conn,
                                           parsexml=parsexml,
                                           parsexmlnode=parsexmlnode,
                                           caps=caps)

        if self._is_parse():
            return

        self.model = model

    def get_type(self):
        return self._controller_type

    type = _xml_property(get_type, xpath="./@type")

    def get_model(self):
        return self._model

    def set_model(self, model):
        self._model = model

    model = _xml_property(get_model, set_model, xpath="./@model")

    def get_index(self):
        return self._index

    def set_index(self, val):
        self._index = int(val)

    index = _xml_property(get_index, set_index, xpath="./@index")

    def get_vectors(self):
        return self._vectors

    def set_vectors(self, val):
        self._vectors = val

    vectors = _xml_property(get_vectors, set_vectors, xpath="./@vectors")

    def get_ports(self):
        return self._ports

    def set_ports(self, val):
        self._ports = val

    ports = _xml_property(get_ports, set_ports, xpath="./@ports")

    def set_master(self, masterstr):
        self._master.parse_friendly_master(masterstr)

    def get_master(self):
        return self._master

    def _extra_config(self):
        return ""

    def _get_xml_config(self):
        extra = self._extra_config()

        xml = "    <controller type='%s' index='%s'" % (self.type, self.index)
        if self.model:
            xml += " model='%s'" % self.model
        xml += extra
        childxml = self.indent(self._master.get_xml_config(), 6)
        childxml += self.indent(self.address.get_xml_config(), 6)
        if len(childxml) == 0:
            return xml + "/>"
        xml += ">\n"
        xml += childxml
        xml += "    </controller>"
        return xml
Example #19
0
class VirtualHostDevice(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_HOSTDEV

    def device_from_node(conn, name=None, nodedev=None, is_dup=False):
        """
        Convert the passed device name to a VirtualHostDevice
        instance, with proper error reporting. Name can be any of the
        values accepted by NodeDeviceParser.lookupNodeName. If a node
        device name is not specified, a virtinst.NodeDevice instance can
        be passed in to create a dev from.

        @param conn: libvirt.virConnect instance to perform the lookup on
        @param name: optional libvirt node device name to lookup
        @param nodedev: optional L{virtinst.NodeDevice} instance to use

        @rtype: L{virtinst.VirtualHostDevice} instance
        """

        if not name and not nodedev:
            raise ValueError(_("'name' or 'nodedev' required."))

        if nodedev:
            nodeinst = nodedev
        else:
            nodeinst, addr_type = NodeDeviceParser.lookupNodeName(conn, name)
            if addr_type == NodeDeviceParser.HOSTDEV_ADDR_TYPE_USB_BUSADDR:
                is_dup = True

        if isinstance(nodeinst, NodeDeviceParser.PCIDevice):
            return VirtualHostDevicePCI(conn, nodedev=nodeinst)
        elif isinstance(nodeinst, NodeDeviceParser.USBDevice):
            return VirtualHostDeviceUSB(conn, nodedev=nodeinst, is_dup=is_dup)
        elif isinstance(nodeinst, NodeDeviceParser.NetDevice):
            parentname = nodeinst.parent
            try:
                return VirtualHostDevice.device_from_node(conn,
                                                          name=parentname)
            except:
                logging.exception("Fetching net parent device failed.")

        raise ValueError(
            _("Node device type '%s' cannot be attached to "
              " guest.") % nodeinst.device_type)

    device_from_node = staticmethod(device_from_node)

    def __init__(self,
                 conn,
                 nodedev=None,
                 parsexml=None,
                 parsexmlnode=None,
                 caps=None):
        """
        @param conn: Connection the device/guest will be installed on
        @type conn: libvirt.virConnect
        @param nodedev: Optional NodeDevice instance for device being
                         attached to the guest
        @type nodedev: L{virtinst.NodeDeviceParser.NodeDevice}
        """
        VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)

        self._mode = None
        self._type = None
        self._managed = None
        self._nodedev = nodedev
        self._vendor = None
        self._product = None
        self._bus = None
        self._device = None
        self._domain = "0x0"
        self._slot = None
        self._function = None

        if self._is_parse():
            return

        self.managed = True
        if self.is_xen():
            self.managed = False

    def get_mode(self):
        return self._mode

    def set_mode(self, val):
        self._mode = val

    mode = _xml_property(get_mode, set_mode, xpath="./@mode")

    def get_type(self):
        return self._type

    def set_type(self, val):
        self._type = val

    type = _xml_property(get_type, set_type, xpath="./@type")

    def get_managed(self):
        return self._managed

    def set_managed(self, val):
        self._managed = bool(val)

    managed = _xml_property(get_managed,
                            set_managed,
                            get_converter=lambda s, x: bool(x == "yes"),
                            set_converter=lambda s, x: x and "yes" or "no",
                            xpath="./@managed")

    def get_vendor(self):
        return self._vendor

    def set_vendor(self, val):
        self._vendor = val

    vendor = _xml_property(get_vendor, set_vendor, xpath="./source/vendor/@id")

    def get_product(self):
        return self._product

    def set_product(self, val):
        self._product = val

    product = _xml_property(get_product,
                            set_product,
                            xpath="./source/product/@id")

    def get_device(self):
        return self._device

    def set_device(self, val):
        self._device = val

    device = _xml_property(get_device,
                           set_device,
                           xpath="./source/address/@device")

    def get_bus(self):
        return self._bus

    def set_bus(self, val):
        self._bus = val

    bus = _xml_property(get_bus, set_bus, xpath="./source/address/@bus")

    def get_function(self):
        return self._function

    def set_function(self, val):
        self._function = val

    function = _xml_property(get_function,
                             set_function,
                             xpath="./source/address/@function")

    def get_domain(self):
        return self._domain

    def set_domain(self, val):
        self._domain = val

    domain = _xml_property(get_domain,
                           set_domain,
                           xpath="./source/address/@domain")

    def get_slot(self):
        return self._slot

    def set_slot(self, val):
        self._slot = val

    slot = _xml_property(get_slot, set_slot, xpath="./source/address/@slot")

    def _get_source_xml(self):
        raise NotImplementedError("Must be implemented in subclass")

    def setup(self, conn=None):
        """
        Unused

        @param conn: libvirt virConnect instance to use (defaults to devices
                     connection)
        """
        ignore = conn

    def _get_xml_config(self):
        xml = ("    <hostdev mode='%s' type='%s' managed='%s'>\n" %
               (self.mode, self.type, self.managed and "yes" or "no"))
        xml += "      <source>\n"
        xml += self._get_source_xml()
        xml += "      </source>\n"
        xml += "    </hostdev>"
        return xml
Example #20
0
class VirtualFilesystem(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_FILESYSTEM

    _target_props = ["dir", "name", "file", "dev"]

    TYPE_MOUNT = "mount"
    TYPE_TEMPLATE = "template"
    TYPE_FILE = "file"
    TYPE_BLOCK = "block"
    TYPE_DEFAULT = "default"
    TYPES = [TYPE_MOUNT, TYPE_TEMPLATE, TYPE_FILE, TYPE_BLOCK, TYPE_DEFAULT]

    MODE_PASSTHROUGH = "passthrough"
    MODE_MAPPED = "mapped"
    MODE_SQUASH = "squash"
    MODE_DEFAULT = "default"
    MOUNT_MODES = [MODE_PASSTHROUGH, MODE_MAPPED, MODE_SQUASH, MODE_DEFAULT]

    WRPOLICY_IMM = "immediate"
    WRPOLICY_DEFAULT = "default"
    WRPOLICIES = [WRPOLICY_IMM, WRPOLICY_DEFAULT]

    DRIVER_PATH = "path"
    DRIVER_HANDLE = "handle"
    DRIVER_PROXY = "proxy"
    DRIVER_DEFAULT = "default"
    DRIVER_TYPES = [DRIVER_PATH, DRIVER_HANDLE, DRIVER_PROXY, DRIVER_DEFAULT]

    @staticmethod
    def type_to_source_prop(fs_type):
        """
        Convert a value of VirtualFilesystem.type to it's associated XML
        source @prop name
        """
        if (fs_type == VirtualFilesystem.TYPE_MOUNT
                or fs_type == VirtualFilesystem.TYPE_DEFAULT
                or fs_type is None):
            return "dir"
        elif fs_type == VirtualFilesystem.TYPE_TEMPLATE:
            return "name"
        elif fs_type == VirtualFilesystem.TYPE_FILE:
            return "file"
        elif fs_type == VirtualFilesystem.TYPE_BLOCK:
            return "dev"
        return "dir"

    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)

        self._type = None
        self._mode = None
        self._driver = None
        self._target = None
        self._source = None
        self._readonly = None
        self._wrpolicy = None

        if self._is_parse():
            return

        self.mode = self.MODE_DEFAULT
        self.type = self.TYPE_DEFAULT
        self.driver = self.DRIVER_DEFAULT
        self.wrpolicy = self.WRPOLICY_DEFAULT

    def _get_type(self):
        return self._type

    def _set_type(self, val):
        if val is not None and not self.TYPES.count(val):
            raise ValueError(_("Unsupported filesystem type '%s'" % val))
        self._type = val

    type = _xml_property(_get_type, _set_type, xpath="./@type")

    def _get_mode(self):
        return self._mode

    def _set_mode(self, val):
        if val is not None and not self.MOUNT_MODES.count(val):
            raise ValueError(_("Unsupported filesystem mode '%s'" % val))
        self._mode = val

    mode = _xml_property(_get_mode, _set_mode, xpath="./@accessmode")

    def _get_wrpolicy(self):
        return self._wrpolicy

    def _set_wrpolicy(self, val):
        if val is not None and not self.WRPOLICIES.count(val):
            raise ValueError(
                _("Unsupported filesystem write policy '%s'" % val))
        self._wrpolicy = val

    wrpolicy = _xml_property(_get_wrpolicy,
                             _set_wrpolicy,
                             xpath="./driver/@wrpolicy")

    def _get_readonly(self):
        return self._readonly

    def _set_readonly(self, val):
        self._readonly = val

    readonly = _xml_property(_get_readonly,
                             _set_readonly,
                             xpath="./readonly",
                             is_bool=True)

    def _get_driver(self):
        return self._driver

    def _set_driver(self, val):
        if val is not None and not self.DRIVER_TYPES.count(val):
            raise ValueError(_("Unsupported filesystem driver '%s'" % val))
        self._driver = val

    driver = _xml_property(_get_driver, _set_driver, xpath="./driver/@type")

    def _get_source(self):
        return self._source

    def _set_source(self, val):
        if self.type != self.TYPE_TEMPLATE:
            val = os.path.abspath(val)
        self._source = val

    def _xml_get_source_xpath(self):
        xpath = None
        ret = "./source/@dir"
        for prop in self._target_props:
            xpath = "./source/@" + prop
            if self._xml_ctx.xpathEval(xpath):
                ret = xpath

        return ret

    def _xml_set_source_xpath(self):
        ret = "./source/@" + self.type_to_source_prop(self.type)
        return ret

    source = _xml_property(_get_source,
                           _set_source,
                           xml_get_xpath=_xml_get_source_xpath,
                           xml_set_xpath=_xml_set_source_xpath)

    def _get_target(self):
        return self._target

    def _set_target(self, val):
        is_qemu = self.is_qemu()

        # In case of qemu for default fs type (mount) target is not
        # actually a directory, it is merely a arbitrary string tag
        # that is exported to the guest as a hint for where to mount
        if (is_qemu and
            (self.type == self.TYPE_DEFAULT or self.type == self.TYPE_MOUNT)):
            pass
        elif not os.path.isabs(val):
            raise ValueError(
                _("Filesystem target '%s' must be an absolute "
                  "path") % val)
        self._target = val

    target = _xml_property(_get_target, _set_target, xpath="./target/@dir")

    def _get_xml_config(self):
        mode = self.mode
        ftype = self.type
        driver = self.driver
        source = self.source
        target = self.target
        readonly = self.readonly
        wrpolicy = self.wrpolicy

        if mode == self.MODE_DEFAULT:
            mode = None
        if ftype == self.TYPE_DEFAULT:
            ftype = None
        if driver == self.DRIVER_DEFAULT:
            driver = None
            wrpolicy = None
        if wrpolicy == self.WRPOLICY_DEFAULT:
            wrpolicy = None

        if not source or not target:
            raise ValueError(
                _("A filesystem source and target must be specified"))

        fsxml = "    <filesystem"
        if ftype:
            fsxml += " type='%s'" % ftype
        if mode:
            fsxml += " accessmode='%s'" % mode
        fsxml += ">\n"

        if driver:
            if not wrpolicy:
                fsxml += "      <driver type='%s'/>\n" % driver
            else:
                fsxml += "      <driver type='%s' wrpolicy='%s' />\n" % (
                    driver, wrpolicy)

        fsxml += "      <source %s='%s'/>\n" % (
            self.type_to_source_prop(ftype), source)
        fsxml += "      <target dir='%s'/>\n" % target

        if readonly:
            fsxml += "      <readonly/>\n"

        fsxml += "    </filesystem>"

        return fsxml
class VirtualVideoDevice(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_VIDEO

    # Default models list
    MODEL_DEFAULT = "default"
    _model_types = ["cirrus", "vga", "vmvga", "xen", "qxl", MODEL_DEFAULT]

    @staticmethod
    def pretty_model(model):
        if model in ["qxl", "vmvga"]:
            return model.upper()
        return model.capitalize()

    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        VirtualDevice.__init__(self, conn,
                                             parsexml, parsexmlnode, caps)

        self._model_type    = None
        self._vram          = None
        self._heads         = None

        if self._is_parse():
            return

        self.model_type = self.MODEL_DEFAULT

    def get_model_types(self):
        return self._model_types[:]
    model_types = property(get_model_types)

    def get_model_type(self):
        return self._model_type
    def set_model_type(self, val):
        self._model_type = val
    model_type = _xml_property(get_model_type, set_model_type,
                               xpath="./model/@type")

    def get_vram(self):
        return self._vram
    def set_vram(self, val):
        self._vram = val
    vram = _xml_property(get_vram, set_vram,
                         xpath="./model/@vram")
    ram = _xml_property(lambda o: None, lambda o, v: None,
                        xpath="./model/@ram")


    def get_heads(self):
        return self._heads
    def set_heads(self, val):
        self._heads = val
    heads = _xml_property(get_heads, set_heads,
                          xpath="./model/@heads")

    def _get_xml_config(self):
        model = self.model_type
        if self.model_type == self.MODEL_DEFAULT:
            model = "cirrus"

        model_xml = "      <model"
        if self.model_type:
            model_xml += " type='%s'" % model
        if self.vram:
            model_xml += " vram='%s'" % self.vram
        if self.heads:
            model_xml += " heads='%s'" % self.heads
        model_xml += "/>\n"

        xml = ("    <video>\n" +
               model_xml +
               "    </video>")
        return xml
Example #22
0
class Seclabel(XMLBuilderDomain.XMLBuilderDomain):
    """
    Class for generating <seclabel> XML
    """

    SECLABEL_TYPE_DYNAMIC = "dynamic"
    SECLABEL_TYPE_STATIC = "static"
    SECLABEL_TYPE_DEFAULT = "default"
    SECLABEL_TYPES = [SECLABEL_TYPE_DYNAMIC, SECLABEL_TYPE_STATIC]

    MODEL_DEFAULT = "default"

    SECLABEL_MODEL_TEST = "testSecurity"
    SECLABEL_MODEL_SELINUX = "selinux"
    SECLABEL_MODEL_DAC = "dac"
    SECLABEL_MODEL_NONE = "none"
    SECLABEL_MODELS = [
        SECLABEL_MODEL_SELINUX, SECLABEL_MODEL_DAC, SECLABEL_MODEL_NONE
    ]

    _dumpxml_xpath = "/domain/seclabel"

    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
                                                   parsexmlnode, caps)

        self._type = None
        self._model = None
        self._label = None
        self._imagelabel = None
        self._relabel = None

        if self._is_parse():
            return

        self.model = self.MODEL_DEFAULT
        self.type = self.SECLABEL_TYPE_DEFAULT

    def _get_default_model(self):
        caps = self._get_caps()
        if caps:
            if (self.SECLABEL_MODEL_TEST
                    in [x.model for x in caps.host.secmodels]):
                return self.SECLABEL_MODEL_TEST

            for model in self.SECLABEL_MODELS:
                if model in [x.model for x in caps.host.secmodels]:
                    return model
        raise RuntimeError("No supported model found in capabilities")

    def _guess_secmodel(self, label, imagelabel):
        # We always want the testSecurity model when running tests
        caps = self._get_caps()
        if (caps and self.SECLABEL_MODEL_TEST
                in [x.model for x in caps.host.secmodels]):
            return self.SECLABEL_MODEL_TEST

        if not label and not imagelabel:
            return self._get_default_model()

        lab_len = imglab_len = None
        if label:
            lab_len = min(3, len(label.split(':')))
        if imagelabel:
            imglab_len = min(3, len(imagelabel.split(':')))
        if lab_len and imglab_len and lab_len != imglab_len:
            raise ValueError("Label and Imagelabel are incompatible")

        lab_len = lab_len or imglab_len
        if lab_len == 3:
            return self.SECLABEL_MODEL_SELINUX
        elif lab_len == 2:
            return self.SECLABEL_MODEL_DAC
        else:
            raise ValueError("Unknown model type for label '%s'" % self.label)

    def get_type(self):
        return self._type

    def set_type(self, val):
        if (val not in self.SECLABEL_TYPES
                and val != self.SECLABEL_TYPE_DEFAULT):
            raise ValueError("Unknown security type '%s'" % val)
        self._type = val

    type = _xml_property(get_type, set_type, xpath="./seclabel/@type")

    def get_model(self):
        return self._model

    def set_model(self, val):
        self._model = val

    model = _xml_property(get_model,
                          set_model,
                          xpath="./seclabel/@model",
                          default_converter=_get_default_model)

    def get_label(self):
        return self._label

    def set_label(self, val):
        self._label = val

    label = _xml_property(get_label, set_label, xpath="./seclabel/label")

    def _get_relabel(self):
        return self._relabel

    def _set_relabel(self, val):
        self._relabel = val

    relabel = _xml_property(_get_relabel,
                            _set_relabel,
                            xpath="./seclabel/@relabel")

    def get_imagelabel(self):
        return self._imagelabel

    def set_imagelabel(self, val):
        self._imagelabel = val

    imagelabel = _xml_property(get_imagelabel,
                               set_imagelabel,
                               xpath="./seclabel/imagelabel")

    def _get_xml_config(self):
        if (self.model == self.MODEL_DEFAULT
                and self.type == self.SECLABEL_TYPE_DEFAULT):
            return ""

        model = self.model
        typ = self.type
        relabel = self.relabel

        if typ == self.SECLABEL_TYPE_DEFAULT:
            typ = self.SECLABEL_TYPE_DYNAMIC

        if not typ:
            raise RuntimeError("Security type and model must be specified")

        if typ == self.SECLABEL_TYPE_STATIC:
            if not self.label:
                raise RuntimeError("A label must be specified for static "
                                   "security type.")

        if model == self.MODEL_DEFAULT:
            model = self._guess_secmodel(self.label, self.imagelabel)

        label_xml = ""
        xml = "  <seclabel type='%s' model='%s'" % (typ, model)
        if relabel is not None:
            xml += " relabel='%s'" % (relabel and "yes" or "no")

        if self.label:
            label_xml += "    <label>%s</label>\n" % self.label
        if self.imagelabel:
            label_xml += "    <imagelabel>%s</imagelabel>\n" % self.imagelabel

        if label_xml:
            xml += ">\n"
            xml += label_xml
            xml += "  </seclabel>"
        else:
            xml += "/>"

        return xml
class VirtualNetworkInterface(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_NET

    TYPE_BRIDGE = "bridge"
    TYPE_VIRTUAL = "network"
    TYPE_USER = "******"
    TYPE_ETHERNET = "ethernet"
    TYPE_DIRECT = "direct"
    network_types = [
        TYPE_BRIDGE, TYPE_VIRTUAL, TYPE_USER, TYPE_ETHERNET, TYPE_DIRECT
    ]

    def get_network_type_desc(net_type):
        """
        Return human readable description for passed network type
        """
        desc = net_type.capitalize()

        if net_type == VirtualNetworkInterface.TYPE_BRIDGE:
            desc = _("Shared physical device")
        elif net_type == VirtualNetworkInterface.TYPE_VIRTUAL:
            desc = _("Virtual networking")
        elif net_type == VirtualNetworkInterface.TYPE_USER:
            desc = _("Usermode networking")

        return desc

    get_network_type_desc = staticmethod(get_network_type_desc)

    def __init__(self,
                 macaddr=None,
                 type=TYPE_BRIDGE,
                 bridge=None,
                 network=None,
                 model=None,
                 conn=None,
                 parsexml=None,
                 parsexmlnode=None,
                 caps=None):
        # pylint: disable=W0622
        # Redefining built-in 'type', but it matches the XML so keep it

        VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)

        self._network = None
        self._bridge = None
        self._macaddr = None
        self._type = None
        self._model = None
        self._target_dev = None
        self._source_dev = None
        self._source_mode = "vepa"
        self._virtualport = VirtualPort(conn, parsexml, parsexmlnode, caps)

        # Generate _random_mac
        self._random_mac = None
        self._default_bridge = None

        if self._is_parse():
            return

        self.type = type
        self.macaddr = macaddr
        self.bridge = bridge
        self.source_dev = bridge
        self.network = network
        self.model = model

        if self.type == self.TYPE_VIRTUAL:
            if network is None:
                raise ValueError(_("A network name was not provided"))

    def _generate_default_bridge(self):
        ret = self._default_bridge
        if ret is None:
            ret = False
            default = util.default_bridge(self.conn)
            if default:
                ret = default[1]

        self._default_bridge = ret
        return ret or None

    def _generate_random_mac(self):
        if self.conn and not self._random_mac:
            found = False
            for ignore in range(256):
                self._random_mac = util.randomMAC(self.conn.getType().lower(),
                                                  conn=self.conn)
                ret = self.is_conflict_net(self.conn, self._random_mac)
                if ret[1] is not None:
                    continue
                found = True
                break

            if not found:
                logging.debug("Failed to generate non-conflicting MAC")
        return self._random_mac

    def get_source(self):
        """
        Convenince function, try to return the relevant <source> value
        per the network type.
        """
        if self.type == self.TYPE_VIRTUAL:
            return self.network
        if self.type == self.TYPE_BRIDGE:
            return self.bridge
        if self.type == self.TYPE_ETHERNET or self.type == self.TYPE_DIRECT:
            return self.source_dev
        if self.type == self.TYPE_USER:
            return None
        return self.network or self.bridge or self.source_dev

    def set_source(self, newsource):
        """
        Conveninece function, try to set the relevant <source> value
        per the network type
        """
        if self.type == self.TYPE_VIRTUAL:
            self.network = newsource
        elif self.type == self.TYPE_BRIDGE:
            self.bridge = newsource
        elif self.type == self.TYPE_ETHERNET or self.type == self.TYPE_DIRECT:
            self.source_dev = newsource
        return

    source = property(get_source, set_source)

    def _get_virtualport(self):
        return self._virtualport

    virtualport = property(_get_virtualport)

    def get_type(self):
        return self._type

    def set_type(self, val):
        if val not in self.network_types:
            raise ValueError(_("Unknown network type %s") % val)
        self._type = val

    type = _xml_property(get_type, set_type, xpath="./@type")

    def get_macaddr(self):
        # Don't generate a random MAC if parsing XML, since it can be slow
        if not self._macaddr and not self._is_parse():
            return self._generate_random_mac()
        return self._macaddr

    def set_macaddr(self, val):
        util.validate_macaddr(val)
        self._macaddr = val

    macaddr = _xml_property(get_macaddr, set_macaddr, xpath="./mac/@address")

    def get_network(self):
        return self._network

    def set_network(self, newnet):
        def _is_net_active(netobj):
            # Apparently the 'info' command was never hooked up for
            # libvirt virNetwork python apis.
            if not self.conn:
                return True
            return self.conn.listNetworks().count(netobj.name())

        if newnet is not None and self.conn:
            try:
                net = self.conn.networkLookupByName(newnet)
            except libvirt.libvirtError, e:
                raise ValueError(
                    _("Virtual network '%s' does not exist: %s") %
                    (newnet, str(e)))
            if not _is_net_active(net):
                raise ValueError(
                    _("Virtual network '%s' has not been "
                      "started.") % newnet)

        self._network = newnet
Example #24
0
class Boot(XMLBuilderDomain.XMLBuilderDomain):
    """
    Class for generating boot device related XML
    """

    BOOT_DEVICE_HARDDISK = "hd"
    BOOT_DEVICE_CDROM = "cdrom"
    BOOT_DEVICE_FLOPPY = "fd"
    BOOT_DEVICE_NETWORK = "network"
    boot_devices = [
        BOOT_DEVICE_HARDDISK, BOOT_DEVICE_CDROM, BOOT_DEVICE_FLOPPY,
        BOOT_DEVICE_NETWORK
    ]

    _dumpxml_xpath = "/domain/os"

    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml,
                                                   parsexmlnode, caps)

        self._bootorder = []
        self._enable_bootmenu = None
        self._kernel = None
        self._initrd = None
        self._kernel_args = None

    def _get_enable_bootmenu(self):
        return self._enable_bootmenu

    def _set_enable_bootmenu(self, val):
        self._enable_bootmenu = val

    def _get_menu_converter(self, val):
        ignore = self
        if val is None:
            return None
        return bool(val == "yes")

    enable_bootmenu = _xml_property(
        _get_enable_bootmenu,
        _set_enable_bootmenu,
        get_converter=_get_menu_converter,
        set_converter=lambda s, x: x and "yes" or "no",
        xpath="./os/bootmenu/@enable")

    def _get_bootorder(self):
        return self._bootorder

    def _set_bootorder(self, val):
        self._bootorder = val

    def _bootorder_xpath_list(self):
        l = []
        for idx in range(len(self._get_bootorder())):
            l.append("./os/boot[%d]/@dev" % (idx + 1))
        return l

    bootorder = _xml_property(_get_bootorder,
                              _set_bootorder,
                              is_multi=True,
                              xml_set_list=_bootorder_xpath_list,
                              xpath="./os/boot/@dev")

    def _get_kernel(self):
        return self._kernel

    def _set_kernel(self, val):
        self._kernel = val

    kernel = _xml_property(_get_kernel, _set_kernel, xpath="./os/kernel")

    def _get_initrd(self):
        return self._initrd

    def _set_initrd(self, val):
        self._initrd = val

    initrd = _xml_property(_get_initrd, _set_initrd, xpath="./os/initrd")

    def _get_kernel_args(self):
        return self._kernel_args

    def _set_kernel_args(self, val):
        self._kernel_args = val

    kernel_args = _xml_property(_get_kernel_args,
                                _set_kernel_args,
                                xpath="./os/cmdline")

    def _get_xml_config(self):
        xml = ""

        if self.kernel:
            xml = util.xml_append(
                xml, "    <kernel>%s</kernel>" % util.xml_escape(self.kernel))
            if self.initrd:
                xml = util.xml_append(
                    xml,
                    "    <initrd>%s</initrd>" % util.xml_escape(self.initrd))
            if self.kernel_args:
                xml = util.xml_append(
                    xml, "    <cmdline>%s</cmdline>" %
                    util.xml_escape(self.kernel_args))

        else:
            for dev in self.bootorder:
                xml = util.xml_append(xml, "    <boot dev='%s'/>" % dev)

            if self.enable_bootmenu in [True, False]:
                val = self.enable_bootmenu and "yes" or "no"
                xml = util.xml_append(xml, "    <bootmenu enable='%s'/>" % val)

        return xml
class VirtualPort(XMLBuilderDomain.XMLBuilderDomain):
    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        XMLBuilderDomain.XMLBuilderDomain.__init__(self,
                                                   conn,
                                                   parsexml,
                                                   parsexmlnode,
                                                   caps=caps)
        self._type = None
        self._managerid = None
        self._typeid = None
        self._typeidversion = None
        self._instanceid = None

    def get_type(self):
        return self._type

    def set_type(self, val):
        self._type = val

    type = _xml_property(get_type, set_type, xpath="./virtualport/@type")

    def get_managerid(self):
        return self._managerid

    def set_managerid(self, val):
        self._managerid = val

    managerid = _xml_property(get_managerid,
                              set_managerid,
                              xpath="./virtualport/parameters/@managerid")

    def get_typeid(self):
        return self._typeid

    def set_typeid(self, val):
        self._typeid = val

    typeid = _xml_property(get_typeid,
                           set_typeid,
                           xpath="./virtualport/parameters/@typeid")

    def get_typeidversion(self):
        return self._typeidversion

    def set_typeidversion(self, val):
        self._typeidversion = val

    typeidversion = _xml_property(
        get_typeidversion,
        set_typeidversion,
        xpath="./virtualport/parameters/@typeidversion")

    def get_instanceid(self):
        return self._instanceid

    def set_instanceid(self, val):
        self._instanceid = val

    instanceid = _xml_property(get_instanceid,
                               set_instanceid,
                               xpath="./virtualport/parameters/@instanceid")

    def _get_xml_config(self):
        # FIXME: This should be implemented, currently we can only parse
        return ""
            if not self.conn:
                return True
            return self.conn.listNetworks().count(netobj.name())

        if newnet is not None and self.conn:
            try:
                net = self.conn.networkLookupByName(newnet)
            except libvirt.libvirtError, e:
                raise ValueError(_("Virtual network '%s' does not exist: %s")
                                   % (newnet, str(e)))
            if not _is_net_active(net):
                raise ValueError(_("Virtual network '%s' has not been "
                                   "started.") % newnet)

        self._network = newnet
    network = _xml_property(get_network, set_network,
                            xpath="./source/@network")

    def get_bridge(self):
        if (not self._is_parse() and
            not self._bridge and
            self.type == self.TYPE_BRIDGE):
            return self._generate_default_bridge()
        return self._bridge
    def set_bridge(self, val):
        self._bridge = val
    bridge = _xml_property(get_bridge, set_bridge,
                           xpath="./source/@bridge")

    def get_model(self):
        return self._model
    def set_model(self, val):
Example #27
0
class VirtualInputDevice(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_INPUT

    INPUT_TYPE_MOUSE = "mouse"
    INPUT_TYPE_TABLET = "tablet"
    INPUT_TYPE_DEFAULT = "default"
    input_types = [INPUT_TYPE_MOUSE, INPUT_TYPE_TABLET, INPUT_TYPE_DEFAULT]

    INPUT_BUS_PS2 = "ps2"
    INPUT_BUS_USB = "usb"
    INPUT_BUS_XEN = "xen"
    INPUT_BUS_DEFAULT = "default"
    input_buses = [
        INPUT_BUS_PS2, INPUT_BUS_USB, INPUT_BUS_XEN, INPUT_BUS_DEFAULT
    ]

    def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None):
        VirtualDevice.__init__(self, conn, parsexml, parsexmlnode, caps)

        self._type = None
        self._bus = None

        if self._is_parse():
            return

        self.type = self.INPUT_TYPE_DEFAULT
        self.bus = self.INPUT_BUS_DEFAULT

    def _convert_default_bus(self, val):
        if val == self.INPUT_BUS_DEFAULT:
            return self.INPUT_BUS_XEN
        return val

    def _convert_default_type(self, val):
        if val == self.INPUT_TYPE_DEFAULT:
            return self.INPUT_TYPE_MOUSE
        return val

    def get_type(self):
        return self._type

    def set_type(self, val):
        if val not in self.input_types:
            raise ValueError(_("Unknown input type '%s'.") % val)
        self._type = val

    type = _xml_property(get_type, set_type, xpath="./@type")

    def get_bus(self):
        return self._bus

    def set_bus(self, val):
        if val not in self.input_buses:
            raise ValueError(_("Unknown input bus '%s'.") % val)
        self._bus = val

    bus = _xml_property(get_bus, set_bus, xpath="./@bus")

    def _get_xml_config(self):
        typ = self._convert_default_type(self.type)
        bus = self._convert_default_bus(self.bus)

        return "    <input type='%s' bus='%s'/>" % (typ, bus)
Example #28
0
class VirtualDeviceAddress(XMLBuilderDomain):

    ADDRESS_TYPE_PCI = "pci"
    ADDRESS_TYPE_DRIVE = "drive"
    ADDRESS_TYPE_VIRTIO_SERIAL = "virtio-serial"
    ADDRESS_TYPE_CCID = "ccid"
    ADDRESS_TYPE_SPAPR_VIO = "spapr-vio"

    TYPES = [
        ADDRESS_TYPE_PCI, ADDRESS_TYPE_DRIVE, ADDRESS_TYPE_VIRTIO_SERIAL,
        ADDRESS_TYPE_CCID, ADDRESS_TYPE_SPAPR_VIO
    ]

    def __init__(self,
                 conn,
                 parsexml=None,
                 parsexmlnode=None,
                 caps=None,
                 addrstr=None):
        XMLBuilderDomain.__init__(self,
                                  conn,
                                  parsexml,
                                  parsexmlnode,
                                  caps=caps)

        self._type = None

        # PCI address:
        # <address type='pci' domain='0x0000' bus='0x00' slot='0x04' \
        #                     function='0x0'/>
        self._bus = None
        self._domain = None
        self._slot = None
        self._function = None

        self._multifunction = None

        # Drive address:
        # <address type='drive' controller='0' bus='0' target='0' unit='0'/>
        self._controller = None
        self._target = None
        self._unit = None

        # VirtioSerial address:
        # <address type='virtio-serial' controller='1' bus='0' port='4'/>
        self._port = None

        # CCID address:
        # <address type='ccid' controller='0' slot='0'/>

        if addrstr:
            self.parse_friendly_address(addrstr)

    def parse_friendly_address(self, addrstr):
        try:
            if addrstr.count(":") in [1, 2] and addrstr.count("."):
                self.type = self.ADDRESS_TYPE_PCI
                addrstr, self.function = addrstr.split(".", 1)
                addrstr, self.slot = addrstr.rsplit(":", 1)
                self.domain = "0"
                if addrstr.count(":"):
                    self.domain, self.bus = addrstr.split(":", 1)
            elif addrstr == "spapr-vio":
                self.type = self.ADDRESS_TYPE_SPAPR_VIO
            else:
                raise ValueError(
                    _("Could not determine or unsupported format of '%s'") %
                    addrstr)
        except:
            logging.exception("Error parsing address.")
            return None

    def clear(self):
        self._type = None
        self._bus = None
        self._domain = None
        self._slot = None
        self._function = None
        self._controller = None
        self._target = None
        self._unit = None
        self._port = None
        self._multifunction = None

        if self._is_parse():
            self._remove_child_xpath("./address")

    def _get_type(self):
        return self._type

    def _set_type(self, val):
        self._type = val

    type = _xml_property(_get_type, _set_type, xpath="./address/@type")

    def _get_domain(self):
        return self._domain

    def _set_domain(self, val):
        self._domain = val

    domain = _xml_property(_get_domain, _set_domain, xpath="./address/@domain")

    def _get_bus(self):
        return self._bus

    def _set_bus(self, val):
        self._bus = val

    bus = _xml_property(_get_bus, _set_bus, xpath="./address/@bus")

    def _get_slot(self):
        return self._slot

    def _set_slot(self, val):
        self._slot = val

    slot = _xml_property(_get_slot, _set_slot, xpath="./address/@slot")

    def _get_function(self):
        return self._function

    def _set_function(self, val):
        self._function = val

    function = _xml_property(_get_function,
                             _set_function,
                             xpath="./address/@function")

    def _get_controller(self):
        return self._controller

    def _set_controller(self, val):
        self._controller = val

    controller = _xml_property(_get_controller,
                               _set_controller,
                               xpath="./address/@controller")

    def _get_target(self):
        return self._target

    def _set_target(self, val):
        self._target = val

    target = _xml_property(_get_target, _set_target, xpath="./address/@target")

    def _get_unit(self):
        return self._unit

    def _set_unit(self, val):
        self._unit = val

    unit = _xml_property(_get_unit, _set_unit, xpath="./address/@unit")

    def _get_port(self):
        return self._port

    def _set_port(self, val):
        self._port = val

    port = _xml_property(_get_port, _set_port, xpath="./address/@port")

    def _get_multifunction(self):
        return self._multifunction

    def _set_multifunction(self, val):
        self._multifunction = val

    multifunction = _xml_property(_get_multifunction,
                                  _set_multifunction,
                                  xpath="./address/@multifunction")

    def _get_xml_config(self):
        if not self.type:
            return

        def format_props(*args):
            return "".join([
                " %s='%s'" % (k, getattr(self, k)) for k in args
                if getattr(self, k, None) is not None
            ])

        xml = "<address type='%s'" % self.type
        if self.type == self.ADDRESS_TYPE_PCI:
            xml += format_props("domain", "bus", "slot", "function",
                                "multifunction")
        elif self.type == self.ADDRESS_TYPE_DRIVE:
            xml += format_props("controller", "bus", "target", "unit")
        elif self.type == self.ADDRESS_TYPE_VIRTIO_SERIAL:
            xml += format_props("controller", "bus", "port")
        elif self.type == self.ADDRESS_TYPE_CCID:
            xml += format_props("controller", "slot")
        xml += "/>"
        return xml
Example #29
0
class VirtualRedirDevice(VirtualDevice):

    _virtual_device_type = VirtualDevice.VIRTUAL_DEV_REDIRDEV

    BUS_DEFAULT = "usb"
    _buses = ["usb"]

    TYPE_DEFAULT = "spicevmc"
    _types = ["tcp", "spicevmc", None]

    def __init__(self, bus=BUS_DEFAULT, stype=TYPE_DEFAULT,
                 conn=None, parsexml=None, parsexmlnode=None, caps=None):
        """
        @param conn: Connection the device/guest will be installed on
        @type conn: libvirt.virConnect
        """
        VirtualDevice.__init__(self, conn, parsexml,
                                             parsexmlnode, caps)

        self._type = None
        self._bus = None
        self._host = None
        self._service = None
        if self._is_parse():
            return

        self.bus = bus
        self.type = stype

    def get_buses(self):
        return self._buses[:]
    buses = property(get_buses)

    def get_bus(self):
        return self._bus
    def set_bus(self, new_val):
        if new_val not in self.buses:
            raise ValueError(_("Unsupported bus '%s'" % new_val))
        self._bus = new_val
    bus = _xml_property(get_bus, set_bus,
                        xpath="./@bus")

    def get_types(self):
        return self._types[:]
    types = property(get_types)

    def get_type(self):
        return self._type
    def set_type(self, new_val):
        if new_val not in self.types:
            raise ValueError(_("Unsupported redirection type '%s'" % new_val))
        self._type = new_val
    type = _xml_property(get_type, set_type,
                         xpath="./@type")

    def get_host(self):
        return self._host
    def set_host(self, val):
        if len(val) == 0:
            raise ValueError(_("Invalid host value"))
        self._host = val
    host = _xml_property(get_host, set_host,
                        xpath="./source/@host")

    def get_service(self):
        return self._service
    def set_service(self, val):
        int(val)
        self._service = val
    service = _xml_property(get_service, set_service,
                        xpath="./source/@service")

    def parse_friendly_server(self, serverstr):
        if serverstr.count(":") == 1:
            self.host, self.service = serverstr.split(":")
        else:
            raise ValueError(_("Could not determine or unsupported format of '%s'") % serverstr)

    def _get_xml_config(self):
        xml  = ("    <redirdev bus='%s' type='%s'" %
                    (self.bus, self.type))
        if self.type == 'spicevmc':
            xml += "/>"
            return xml
        xml += ">\n"
        xml += ("      <source mode='connect' host='%s' service='%s'/>\n" %
                    (self.host, self.service))
        xml += "    </redirdev>"
        return xml