[libvirt] [v2 3/4] Add --usbredir device

Marc-André Lureau marcandre.lureau at gmail.com
Mon Aug 29 20:13:24 UTC 2011


Allows to add a USB redirected device.

Via TCP server:

--usbredir tcp,server=host:port

Or over Spice:

--usbredir spicevmc
---
 man/en/virt-install.1         |   18 ++++++++++
 man/en/virt-install.pod.in    |   20 ++++++++++++
 tests/clitest.py              |   26 +++++++++++++++
 virt-install                  |    1 +
 virtinst/VirtualHostDevice.py |   70 +++++++++++++++++++++++++++++++++++++++++
 virtinst/__init__.py          |    5 ++-
 virtinst/cli.py               |   39 +++++++++++++++++++++++
 7 files changed, 177 insertions(+), 2 deletions(-)

diff --git a/man/en/virt-install.1 b/man/en/virt-install.1
index 5f15e8c..21a5ac1 100644
--- a/man/en/virt-install.1
+++ b/man/en/virt-install.1
@@ -1106,6 +1106,24 @@ to the guest
 See \f(CW\*(C`http://libvirt.org/formatdomain.html#elementsSmartcard\*(C'\fR for complete
 details.
 .RE
+.IP "\-\-usbredir=SOURCE[,OPTS]" 2
+.IX Item "--usbredir=SOURCE[,OPTS]"
+Add a \s-1USB\s0 redirected device.
+.RS 2
+.IP "\fBserver\fR" 4
+.IX Item "server"
+The \s-1USB\s0 server connection details, of the form 'server:port'.
+.RE
+.RS 2
+.Sp
+An example invocation:
+.IP "\fB\-\-usbredir tcp,server=localhost:4000\fR" 4
+.IX Item "--usbredir tcp,server=localhost:4000"
+Add a \s-1USB\s0 redirected device provided by the \s-1TCP\s0 server on 'localhost'
+port 4000.
+.RE
+.RS 2
+.RE
 .SS "Miscellaneous Options"
 .IX Subsection "Miscellaneous Options"
 .IP "\-\-autostart" 2
diff --git a/man/en/virt-install.pod.in b/man/en/virt-install.pod.in
index 392137f..f174250 100644
--- a/man/en/virt-install.pod.in
+++ b/man/en/virt-install.pod.in
@@ -1104,8 +1104,28 @@ to the guest
 See C<http://libvirt.org/formatdomain.html#elementsSmartcard> for complete
 details.
 
+=item --usbredir=SOURCE[,OPTS]
 
+Add a USB redirected device.
 
+=over 4
+
+=item B<server>
+
+The USB server connection details, of the form 'server:port'.
+
+=back
+
+An example invocation:
+
+=over 4
+
+=item B<--usbredir tcp,server=localhost:4000>
+
+Add a USB redirected device provided by the TCP server on 'localhost'
+port 4000.
+
+=back
 
 =back
 
diff --git a/tests/clitest.py b/tests/clitest.py
index c0f9294..d0499a8 100644
--- a/tests/clitest.py
+++ b/tests/clitest.py
@@ -645,6 +645,32 @@ args_dict = {
       ],
      }, # category "hostdev"
 
+     "usbredir" : {
+      "args": "--noautoconsole --nographics --nodisks --pxe",
+
+      "valid" : [
+        "--usbredir spicevmc",
+        "--usbredir tcp,server=localhost:4000",
+        # Different host server
+        "--usbredir tcp,server=127.0.0.1:4002",
+      ],
+
+      "invalid" : [
+        # Missing argument
+        "--usbredir",
+        # Invalid argument
+        "--usbredir spicevmc,server=foo:12",
+        # Missing argument
+        "--usbredir tcp,server=",
+        # Invalid address
+        "--usbredir tcp,server=localhost:p4000",
+        # Missing address
+        "--usbredir tcp,server=localhost:",
+        # Missing host
+        "--usbredir tcp,server=:399",
+      ],
+     }, # category "usbredir"
+
      "remote" : {
       "args": "--connect %(REMOTEURI)s --nographics --noautoconsole",
 
diff --git a/virt-install b/virt-install
index 837475d..6b20efe 100755
--- a/virt-install
+++ b/virt-install
@@ -480,6 +480,7 @@ def build_guest_instance(conn, options):
 
     # Non-default devices
     cli.get_controller(guest, options.controller)
+    cli.get_usbredir(guest, options.usbredir)
     if not options.nonetworks:
         get_networks(guest, options)
     get_graphics(guest, options)
diff --git a/virtinst/VirtualHostDevice.py b/virtinst/VirtualHostDevice.py
index 2175266..dd0604f 100644
--- a/virtinst/VirtualHostDevice.py
+++ b/virtinst/VirtualHostDevice.py
@@ -93,6 +93,9 @@ class VirtualHostDevice(VirtualDevice.VirtualDevice):
         self._domain = "0x0"
         self._slot = None
         self._function = None
+        self._host = None
+        self._service = None
+        self._redirection = None
 
         if self._is_parse():
             return
@@ -116,6 +119,13 @@ class VirtualHostDevice(VirtualDevice.VirtualDevice):
     type = _xml_property(get_type, set_type,
                          xpath="./@type")
 
+    def get_redirection(self):
+        return self._redirection
+    def set_redirection(self, val):
+        self._redirection = val
+    redirection = _xml_property(get_redirection, set_redirection,
+                         xpath="./@redirection")
+
     def get_managed(self):
         return self._managed
     def set_managed(self, val):
@@ -174,6 +184,23 @@ class VirtualHostDevice(VirtualDevice.VirtualDevice):
     slot = _xml_property(get_slot, set_slot,
                          xpath="./source/address/@slot")
 
+    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 _get_source_xml(self):
         raise NotImplementedError("Must be implemented in subclass")
 
@@ -245,6 +272,49 @@ class VirtualHostDeviceUSB(VirtualHostDevice):
         # No libvirt api support for USB Detach/Reset yet
         return
 
+
+class VirtualHostDeviceUSBRedir(VirtualHostDevice):
+
+    def __init__(self, conn, nodedev=None, redirection=None, serverstr=None):
+        VirtualHostDevice.__init__(self, conn, nodedev)
+
+        self.mode = "subsystem"
+        self.type = "usb"
+        self.redirection = redirection
+        if serverstr:
+            self.parse_friendly_server(serverstr)
+
+    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  = ("    <hostdev mode='%s' type='%s' redirection='%s'" % \
+                    (self.mode, self.type, self.redirection))
+        if self.redirection == 'spicevmc':
+            xml += "/>"
+            return xml
+        xml += ">\n"
+        xml += ("      <source mode='connect' host='%s' service='%s'/>\n" % \
+                    (self.host, self.service))
+        xml += "    </hostdev>"
+        return xml
+
+    def _get_source_xml(self): # unused
+        return ""
+
+    def setup(self, conn=None):
+        """
+        DEPRECATED: Please use setup_dev instead
+        """
+        if not conn:
+            conn = self.conn
+
+        # No libvirt api support for USB Detach/Reset yet
+        return
+
 class VirtualHostDevicePCI(VirtualHostDevice):
 
     def __init__(self, conn, nodedev=None):
diff --git a/virtinst/__init__.py b/virtinst/__init__.py
index d7c328b..3c4ffd3 100644
--- a/virtinst/__init__.py
+++ b/virtinst/__init__.py
@@ -43,7 +43,7 @@ from VirtualAudio import VirtualAudio
 from VirtualInputDevice import VirtualInputDevice
 from VirtualDisk import VirtualDisk, XenDisk
 from VirtualHostDevice import (VirtualHostDevice, VirtualHostDeviceUSB,
-                               VirtualHostDevicePCI)
+                               VirtualHostDevicePCI, VirtualHostDeviceUSBRedir)
 from VirtualCharDevice import VirtualCharDevice
 from VirtualVideoDevice import VirtualVideoDevice
 from VirtualController import VirtualController
@@ -80,4 +80,5 @@ __all__ = ["Guest", "XenGuest", "VirtualNetworkInterface",
            "VirtualHostDevice", "VirtualHostDeviceUSB", "VirtualVideoDevice",
            "VirtualHostDevicePCI", "VirtualCharDevice", "VirtualInputDevice",
            "VirtualController", "VirtualWatchdog",
-           "VirtualFilesystem", "VirtualSmartCardDevice"]
+           "VirtualFilesystem", "VirtualSmartCardDevice",
+           "VirtualHostDeviceUSBRedir"]
diff --git a/virtinst/cli.py b/virtinst/cli.py
index 07481dd..11b46e5 100644
--- a/virtinst/cli.py
+++ b/virtinst/cli.py
@@ -1004,6 +1004,16 @@ def get_controller(guest, sc_opts):
         if dev:
             guest.add_device(dev)
 
+def get_usbredir(guest, sc_opts):
+    for sc in listify(sc_opts):
+        try:
+            dev = parse_usbredir(guest, sc)
+        except Exception, e:
+            fail(_("Error in usbredir device parameters: %s") % str(e))
+
+        if dev:
+            guest.add_device(dev)
+
 #############################
 # Common CLI option/group   #
 #############################
@@ -1096,6 +1106,9 @@ def add_device_options(devg):
     devg.add_option("", "--smartcard", dest="smartcard", action="append",
                     help=_("Configure a guest smartcard device. Ex:\n"
                            "--smartcard mode=passthrough"))
+    devg.add_option("", "--usbredir", dest="usbredir", action="append",
+                    help=_("Configure a guest USB redirection device. Ex:\n"
+                           "--usbredir tcp,server=192.168.1.1:4000"))
 
 def add_gfx_option(devg):
     devg.add_option("", "--graphics", dest="graphics", action="append",
@@ -1749,6 +1762,32 @@ def parse_smartcard(guest, optstring, dev=None):
     return dev
 
 ######################
+# --usbredir parsing #
+######################
+
+def parse_usbredir(guest, optstring, dev=None):
+    if optstring is None:
+        return None
+
+    # Peel the mode off the front
+    opts = parse_optstr(optstring, remove_first="source")
+    source = get_opt_param(opts, "source")
+    server = get_opt_param(opts, "server")
+
+    if source == "none":
+        return None
+
+    if not dev:
+        dev = virtinst.VirtualHostDeviceUSBRedir(guest.conn,
+                                                 redirection=source,
+                                                 serverstr=server)
+
+    if opts:
+        raise ValueError(_("Unknown options %s") % opts.keys())
+
+    return dev
+
+######################
 # --watchdog parsing #
 ######################
 
-- 
1.7.6




More information about the libvir-list mailing list