[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [virt-tools-list] [PATCH 3/4] Add --redirdev device



On Tue, Sep 13, 2011 at 4:35 PM, Cole Robinson <crobinso redhat com> wrote:
>>  man/en/virt-install.1         |   38 ++++++++++++++++++++++++++-----
>>  man/en/virt-install.pod.in    |   28 +++++++++++++++++++++++
>>  tests/clitest.py              |   28 +++++++++++++++++++++++
>>  tests/xmlparse.py             |   18 +++++++++++++++
>>  virt-install                  |    1 +
>>  virtinst/Guest.py             |    1 +
>>  virtinst/VirtualDevice.py     |    4 ++-
>>  virtinst/VirtualHostDevice.py |    1 +
>>  virtinst/__init__.py          |    4 ++-
>>  virtinst/cli.py               |   49 +++++++++++++++++++++++++++++++++++++++++
>>  10 files changed, 164 insertions(+), 8 deletions(-)
>>
>
> Sorry for the review delay, but this seems to be missing the file for
> VirtualRedirDev?

Ooops Attached is the updated patch

cheers

-- 
Marc-André Lureau
From bd52796a1c24b5da68c8c8a18505a2e37ac72201 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre lureau redhat com>
Date: Tue, 23 Aug 2011 15:36:02 +0300
Subject: [PATCH] Add --redirdev device

Allows to add a redirected device.

USB redirection via TCP server:

--redirdev usb,type=tcp,server=host:port

Or over Spice:

--redirdev usb,type=spicevmc
---
 man/en/virt-install.1          |   38 +++++++++++--
 man/en/virt-install.pod.in     |   28 ++++++++++
 tests/clitest.py               |   28 ++++++++++
 tests/xmlparse.py              |   18 ++++++
 virt-install                   |    1 +
 virtinst/Guest.py              |    1 +
 virtinst/VirtualDevice.py      |    4 +-
 virtinst/VirtualHostDevice.py  |    1 +
 virtinst/VirtualRedirDevice.py |  118 ++++++++++++++++++++++++++++++++++++++++
 virtinst/__init__.py           |    4 +-
 virtinst/cli.py                |   49 +++++++++++++++++
 11 files changed, 282 insertions(+), 8 deletions(-)
 create mode 100644 virtinst/VirtualRedirDevice.py

diff --git a/man/en/virt-install.1 b/man/en/virt-install.1
index 7bd35df..31c9c10 100644
--- a/man/en/virt-install.1
+++ b/man/en/virt-install.1
@@ -124,7 +124,7 @@
 .\" ========================================================================
 .\"
 .IX Title "VIRT-INSTALL 1"
-.TH VIRT-INSTALL 1 "2011-07-28" "" "Virtual Machine Install Tools"
+.TH VIRT-INSTALL 1 "2011-09-02" "" "Virtual Machine Install Tools"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -415,6 +415,8 @@ Values for some recent \s-1OS\s0 options are:
 .IX Item "freebsd8             : FreeBSD 8.x"
 .IP "generic              : Generic" 2
 .IX Item "generic              : Generic"
+.IP "debianwheezy         : Debian Wheezy" 2
+.IX Item "debianwheezy         : Debian Wheezy"
 .IP "debiansqueeze        : Debian Squeeze" 2
 .IX Item "debiansqueeze        : Debian Squeeze"
 .IP "debianlenny          : Debian Lenny" 2
@@ -988,18 +990,18 @@ Named pipe (see \fIpipe\fR\|(7))
 .IP "\fB\-\-serial tcp,host=HOST:PORT,mode=MODE,protocol=PROTOCOL\fR" 4
 .IX Item "--serial tcp,host=HOST:PORT,mode=MODE,protocol=PROTOCOL"
 \&\s-1TCP\s0 net console. \s-1MODE\s0 is either 'bind' (wait for connections on \s-1HOST:PORT\s0)
-or 'connect' (send output to \s-1HOST:PORT\s0), default is 'connect'. \s-1HOST\s0 defaults
+or 'connect' (send output to \s-1HOST:PORT\s0), default is 'bind'. \s-1HOST\s0 defaults
 to '127.0.0.1', but \s-1PORT\s0 is required. \s-1PROTOCOL\s0 can be either 'raw' or 'telnet'
 (default 'raw'). If 'telnet', the port acts like a telnet server or client.
 Some examples:
 .Sp
-Connect to localhost, port 1234:
+Wait for connections on any address, port 4567:
 .Sp
-\&\-\-serial tcp,host=:1234
+\&\-\-serial tcp,host=0.0.0.0:4567
 .Sp
-Wait for connections on any address, port 4567:
+Connect to localhost, port 1234:
 .Sp
-\&\-\-serial tcp,host=0.0.0.0:4567,mode=bind
+\&\-\-serial tcp,host=:1234,mode=connect
 .Sp
 Wait for telnet connection on localhost, port 2222. The user could then
 connect interactively to this console via 'telnet localhost 2222':
@@ -1106,6 +1108,30 @@ to the guest
 See \f(CW\*(C`http://libvirt.org/formatdomain.html#elementsSmartcard\*(C'\fR for complete
 details.
 .RE
+.IP "\-\-redirdev=BUS[,OPTS]" 2
+.IX Item "--redirdev=BUS[,OPTS]"
+Add a redirected device.
+.RS 2
+.IP "\fBtype\fR" 4
+.IX Item "type"
+The redirection type, currently supported is \fBtcp\fR or \fBspicevmc\fR.
+.IP "\fBserver\fR" 4
+.IX Item "server"
+The \s-1TCP\s0 server connection details, of the form 'server:port'.
+.RE
+.RS 2
+.Sp
+Examples of invocation:
+.IP "\fB\-\-redirdev usb,type=tcp,server=localhost:4000\fR" 4
+.IX Item "--redirdev usb,type=tcp,server=localhost:4000"
+Add a \s-1USB\s0 redirected device provided by the \s-1TCP\s0 server on 'localhost'
+port 4000.
+.IP "\fB\-\-redirdev usb,type=spicevmc\fR" 4
+.IX Item "--redirdev usb,type=spicevmc"
+Add a \s-1USB\s0 device redirected via a dedicated Spice channel.
+.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 da4142d..8239067 100644
--- a/man/en/virt-install.pod.in
+++ b/man/en/virt-install.pod.in
@@ -1104,8 +1104,36 @@ to the guest
 See C<http://libvirt.org/formatdomain.html#elementsSmartcard> for complete
 details.
 
+=item --redirdev=BUS[,OPTS]
 
+Add a redirected device.
 
+=over 4
+
+=item B<type>
+
+The redirection type, currently supported is B<tcp> or B<spicevmc>.
+
+=item B<server>
+
+The TCP server connection details, of the form 'server:port'.
+
+=back
+
+Examples of invocation:
+
+=over 4
+
+=item B<--redirdev usb,type=tcp,server=localhost:4000>
+
+Add a USB redirected device provided by the TCP server on 'localhost'
+port 4000.
+
+=item B<--redirdev usb,type=spicevmc>
+
+Add a USB device redirected via a dedicated Spice channel.
+
+=back
 
 =back
 
diff --git a/tests/clitest.py b/tests/clitest.py
index 9fe2d2f..128e1f2 100644
--- a/tests/clitest.py
+++ b/tests/clitest.py
@@ -698,6 +698,34 @@ args_dict = {
       ],
      }, # category "hostdev"
 
+     "redirdev" : {
+      "args": "--noautoconsole --nographics --nodisks --pxe",
+
+      "valid" : [
+        "--redirdev usb,type=spicevmc",
+        "--redirdev usb,type=tcp,server=localhost:4000",
+        # Different host server
+        "--redirdev usb,type=tcp,server=127.0.0.1:4002",
+      ],
+
+      "invalid" : [
+        # Missing argument
+        "--redirdev",
+        # Unsupported bus
+        "--redirdev pci",
+        # Invalid argument
+        "--redirdev usb,type=spicevmc,server=foo:12",
+        # Missing argument
+        "--redirdev usb,type=tcp,server=",
+        # Invalid address
+        "--redirdev usb,type=tcp,server=localhost:p4000",
+        # Missing address
+        "--redirdev usb,type=tcp,server=localhost:",
+        # Missing host
+        "--redirdev usb,type=tcp,server=:399",
+      ],
+     }, # category "redirdev"
+
      "remote" : {
       "args": "--connect %(REMOTEURI)s --nographics --noautoconsole",
 
diff --git a/tests/xmlparse.py b/tests/xmlparse.py
index 0ec0ad9..674f28e 100644
--- a/tests/xmlparse.py
+++ b/tests/xmlparse.py
@@ -672,6 +672,24 @@ class XMLParseTest(unittest.TestCase):
 
         self._alter_compare(guest.get_config_xml(), outfile)
 
+    def testAlterRedirdev(self):
+        infile  = "tests/xmlparse-xml/change-redirdev-in.xml"
+        outfile = "tests/xmlparse-xml/change-redirdev-out.xml"
+        guest = virtinst.Guest(conn=conn,
+                               parsexml=file(infile).read())
+
+        dev1 = guest.get_devices("redirdev")[0]
+        dev2 = guest.get_devices("redirdev")[1]
+
+        check = self._make_checker(dev1)
+        check("host", "foo", "bar")
+        check("service", "12", "42")
+
+        check = self._make_checker(dev2)
+        check("type", "spicevmc")
+
+        self._alter_compare(guest.get_config_xml(), outfile)
+
     def testConsoleCompat(self):
         infile  = "tests/xmlparse-xml/console-compat-in.xml"
         outfile = "tests/xmlparse-xml/console-compat-out.xml"
diff --git a/virt-install b/virt-install
index e398481..1dd97a6 100755
--- a/virt-install
+++ b/virt-install
@@ -491,6 +491,7 @@ def build_guest_instance(conn, options):
 
     # Non-default devices
     cli.get_controller(guest, options.controller)
+    cli.get_redirdev(guest, options.redirdev)
     if not options.nonetworks:
         get_networks(guest, options)
     get_graphics(guest, options)
diff --git a/virtinst/Guest.py b/virtinst/Guest.py
index dfb5ed2..3dd04d1 100644
--- a/virtinst/Guest.py
+++ b/virtinst/Guest.py
@@ -772,6 +772,7 @@ class Guest(XMLBuilderDomain.XMLBuilderDomain):
             "controller": virtinst.VirtualController,
             "filesystem": virtinst.VirtualFilesystem,
             "smartcard" : virtinst.VirtualSmartCardDevice,
+            "redirdev"   : virtinst.VirtualRedirDevice,
         }
 
         # Hand off all child element parsing to relevant classes
diff --git a/virtinst/VirtualDevice.py b/virtinst/VirtualDevice.py
index e817bf7..2234979 100644
--- a/virtinst/VirtualDevice.py
+++ b/virtinst/VirtualDevice.py
@@ -43,6 +43,7 @@ class VirtualDevice(XMLBuilderDomain):
     VIRTUAL_DEV_WATCHDOG        = "watchdog"
     VIRTUAL_DEV_FILESYSTEM      = "filesystem"
     VIRTUAL_DEV_SMARTCARD       = "smartcard"
+    VIRTUAL_DEV_REDIRDEV        = "redirdev"
 
     # Ordering in this list is important: it will be the order the
     # Guest class outputs XML. So changing this may upset the test suite
@@ -60,7 +61,8 @@ class VirtualDevice(XMLBuilderDomain):
                             VIRTUAL_DEV_VIDEO,
                             VIRTUAL_DEV_HOSTDEV,
                             VIRTUAL_DEV_WATCHDOG,
-                            VIRTUAL_DEV_SMARTCARD]
+                            VIRTUAL_DEV_SMARTCARD,
+                            VIRTUAL_DEV_REDIRDEV]
 
     # General device type (disk, interface, etc.)
     _virtual_device_type = None
diff --git a/virtinst/VirtualHostDevice.py b/virtinst/VirtualHostDevice.py
index 2175266..b90518d 100644
--- a/virtinst/VirtualHostDevice.py
+++ b/virtinst/VirtualHostDevice.py
@@ -245,6 +245,7 @@ class VirtualHostDeviceUSB(VirtualHostDevice):
         # No libvirt api support for USB Detach/Reset yet
         return
 
+
 class VirtualHostDevicePCI(VirtualHostDevice):
 
     def __init__(self, conn, nodedev=None):
diff --git a/virtinst/VirtualRedirDevice.py b/virtinst/VirtualRedirDevice.py
new file mode 100644
index 0000000..602d237
--- /dev/null
+++ b/virtinst/VirtualRedirDevice.py
@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright 2011  Red Hat, Inc.
+# Cole Robinson <crobinso redhat com>
+# Marc-André Lureau <marcandre lureau redhat com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free  Software Foundation; either version 2 of the License, or
+# (at your option)  any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301 USA.
+
+import VirtualDevice
+
+from virtinst import _gettext as _
+from XMLBuilderDomain import _xml_property
+
+class VirtualRedirDevice(VirtualDevice.VirtualDevice):
+
+    _virtual_device_type = VirtualDevice.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
+        @param nodedev: Optional NodeDevice instance for device being
+                         attached to the guest
+        @type nodedev: L{virtinst.NodeDeviceParser.NodeDevice}
+        """
+        VirtualDevice.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
diff --git a/virtinst/__init__.py b/virtinst/__init__.py
index d7c328b..efa4d0d 100644
--- a/virtinst/__init__.py
+++ b/virtinst/__init__.py
@@ -50,6 +50,7 @@ from VirtualController import VirtualController
 from VirtualWatchdog import VirtualWatchdog
 from VirtualFilesystem import VirtualFilesystem
 from VirtualSmartCardDevice import VirtualSmartCardDevice
+from VirtualRedirDevice import VirtualRedirDevice
 from FullVirtGuest import FullVirtGuest
 from ParaVirtGuest import ParaVirtGuest
 from DistroInstaller import DistroInstaller
@@ -80,4 +81,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 40cabff..14ecbe7 100644
--- a/virtinst/cli.py
+++ b/virtinst/cli.py
@@ -1007,6 +1007,16 @@ def get_controller(guest, sc_opts):
         if dev:
             guest.add_device(dev)
 
+def get_redirdev(guest, sc_opts):
+    for sc in listify(sc_opts):
+        try:
+            dev = parse_redirdev(guest, sc)
+        except Exception, e:
+            fail(_("Error in redirdev device parameters: %s") % str(e))
+
+        if dev:
+            guest.add_device(dev)
+
 #############################
 # Common CLI option/group   #
 #############################
@@ -1099,6 +1109,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("", "--redirdev", dest="redirdev", action="append",
+                    help=_("Configure a guest redirection device. Ex:\n"
+                           "--redirdev usb,type=tcp,server=192.168.1.1:4000"))
 
 def add_gfx_option(devg):
     devg.add_option("", "--graphics", dest="graphics", action="append",
@@ -1752,6 +1765,42 @@ def parse_smartcard(guest, optstring, dev=None):
     return dev
 
 ######################
+# --redirdev parsing #
+######################
+
+def parse_redirdev(guest, optstring, dev=None):
+    if optstring is None:
+        return None
+
+    # Peel the mode off the front
+    opts = parse_optstr(optstring, remove_first="bus")
+    bus = get_opt_param(opts, "bus")
+    stype = get_opt_param(opts, "type")
+    server = get_opt_param(opts, "server")
+
+    if bus == "none":
+        return None
+
+    if not dev:
+        dev = virtinst.VirtualRedirDevice(bus=bus,
+                                          stype=stype,
+                                          conn=guest.conn)
+
+    if stype == "spicevmc" and server:
+        raise ValueError(_("The server option is invalid with spicevmc redirection"))
+
+    if stype == "tcp" and not server:
+        raise ValueError(_("The server option is missing for TCP redirection"))
+
+    if server:
+        dev.parse_friendly_server(server)
+
+    if opts:
+        raise ValueError(_("Unknown options %s") % opts.keys())
+
+    return dev
+
+######################
 # --watchdog parsing #
 ######################
 
-- 
1.7.6


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]