[virt-tools-list] [PATCH] wip: add VirtualSmartCardDevice

Cole Robinson crobinso at redhat.com
Tue Jul 5 19:35:30 UTC 2011


On 06/23/2011 11:33 AM, Marc-André Lureau wrote:
> From: Marc-André Lureau <marcandre.lureau at redhat.com>
> 
> This is not a complete patch (it doesn't support all the smartcard
> options, in particular host-certificates method), but it does good
> enough for spice smartcard passthrough & virt-manager integration.
> 
> Feel free to take it up from there and improving it if you feel like
> it's not ready for merge.

Pushed with man pages and a few fixes:

http://git.fedorahosted.org/git?p=python-virtinst.git;a=commit;h=b4237e50d4a5f50a1b951a33d5fef7b4e2f1eaaf

Thanks!
Cole

> ---
>  tests/clitest.py                   |   27 +++++++++++
>  tests/xmlparse.py                  |   17 +++++++
>  virt-image                         |    1 +
>  virt-install                       |    4 ++
>  virtinst/Guest.py                  |    1 +
>  virtinst/VirtualDevice.py          |    4 +-
>  virtinst/VirtualSmartCardDevice.py |   88 ++++++++++++++++++++++++++++++++++++
>  virtinst/__init__.py               |    4 +-
>  virtinst/cli.py                    |   49 ++++++++++++++++++++
>  9 files changed, 193 insertions(+), 2 deletions(-)
>  create mode 100644 virtinst/VirtualSmartCardDevice.py
> 
> diff --git a/tests/clitest.py b/tests/clitest.py
> index 31cd061..10a3f70 100644
> --- a/tests/clitest.py
> +++ b/tests/clitest.py
> @@ -349,6 +349,33 @@ args_dict = {
>  
>       }, # category "graphics"
>  
> +     "smartcard": {
> +      "args": "--noautoconsole --nodisks --pxe",
> +
> +      "valid": [
> +        # --smartcard host
> +        "--graphics host",
> +        # --smartcard none,
> +        "--graphics none",
> +        # --smartcard mode with type
> +        "--graphics passthrough,type=spicevmc",
> +        # --smartcard mode with type
> +        "--graphics passthrough,type=tcp",
> +      ],
> +
> +      "invalid": [
> +        # Missing argument
> +        "--smartcard",
> +        # Invalid argument
> +        "--smartcard foo",
> +        # Invalid type
> +        "--smartcard passthrough,type=foo",
> +        # --smartcard bogus
> +        "--smarcard host,foobar=baz",
> +      ],
> +
> +     }, # category "smartcard"
> +
>      "char" : {
>       "args": "--hvm --nographics --noautoconsole --nodisks --pxe",
>  
> diff --git a/tests/xmlparse.py b/tests/xmlparse.py
> index 3f19c98..636e043 100644
> --- a/tests/xmlparse.py
> +++ b/tests/xmlparse.py
> @@ -639,6 +639,23 @@ class XMLParseTest(unittest.TestCase):
>  
>          self._alter_compare(guest.get_config_xml(), outfile)
>  
> +    def testAlterSmartCard(self):
> +        infile  = "tests/xmlparse-xml/change-smartcard-in.xml"
> +        outfile = "tests/xmlparse-xml/change-smartcard-out.xml"
> +        guest = virtinst.Guest(connection=conn,
> +                               parsexml=file(infile).read())
> +
> +        dev1 = guest.get_devices("smartcard")[0]
> +        dev2 = guest.get_devices("smartcard")[1]
> +
> +        check = self._make_checker(dev1)
> +        check("type", None, "tcp")
> +
> +        check = self._make_checker(dev2)
> +        check("mode", "passthrough", "host")
> +        check("type", "spicevmc", None)
> +
> +        self._alter_compare(guest.get_config_xml(), outfile)
>  
>      def testConsoleCompat(self):
>          infile  = "tests/xmlparse-xml/console-compat-in.xml"
> diff --git a/virt-image b/virt-image
> index ea55181..19fa5d4 100755
> --- a/virt-image
> +++ b/virt-image
> @@ -172,6 +172,7 @@ def main():
>  
>      get_graphics(image.domain, guest, options)
>      cli.get_video(guest)
> +    cli.get_smartcard(guest, options.smartcard)
>  
>      cli.set_os_variant(guest, options.distro_type, options.distro_variant)
>  
> diff --git a/virt-install b/virt-install
> index e2309b9..62c79c1 100755
> --- a/virt-install
> +++ b/virt-install
> @@ -488,6 +488,7 @@ def build_guest_instance(conn, options):
>      get_chardevs(VirtualDevice.VIRTUAL_DEV_CHANNEL, options.channels, guest)
>      get_chardevs(VirtualDevice.VIRTUAL_DEV_CONSOLE, options.consoles, guest)
>      cli.get_hostdevs(options.hostdevs, guest)
> +    cli.get_smartcard(guest, options.smartcard)
>  
>  
>      # Install options
> @@ -867,6 +868,9 @@ def parse_args():
>                      help=_("Don't create network interfaces for the guest."))
>      parser.add_option_group(netg)
>  
> +    scg = cli.smartcard_option_group(parser)
> +    parser.add_option_group(scg)
> +
>      vncg = cli.graphics_option_group(parser)
>      vncg.add_option("", "--noautoconsole", action="store_false",
>                      dest="autoconsole", default=True,
> diff --git a/virtinst/Guest.py b/virtinst/Guest.py
> index 60b8175..430dd8d 100644
> --- a/virtinst/Guest.py
> +++ b/virtinst/Guest.py
> @@ -784,6 +784,7 @@ class Guest(XMLBuilderDomain.XMLBuilderDomain):
>              "watchdog"  : virtinst.VirtualWatchdog,
>              "controller": virtinst.VirtualController,
>              "filesystem": virtinst.VirtualFilesystem,
> +            "smartcard" : virtinst.VirtualSmartCardDevice,
>          }
>  
>          # Hand off all child element parsing to relevant classes
> diff --git a/virtinst/VirtualDevice.py b/virtinst/VirtualDevice.py
> index 87af418..158037c 100644
> --- a/virtinst/VirtualDevice.py
> +++ b/virtinst/VirtualDevice.py
> @@ -41,6 +41,7 @@ class VirtualDevice(XMLBuilderDomain):
>      VIRTUAL_DEV_CONTROLLER      = "controller"
>      VIRTUAL_DEV_WATCHDOG        = "watchdog"
>      VIRTUAL_DEV_FILESYSTEM      = "filesystem"
> +    VIRTUAL_DEV_SMARTCARD       = "smartcard"
>  
>      # Ordering in this list is important: it will be the order the
>      # Guest class outputs XML. So changing this may upset the test suite
> @@ -57,7 +58,8 @@ class VirtualDevice(XMLBuilderDomain):
>                              VIRTUAL_DEV_AUDIO,
>                              VIRTUAL_DEV_VIDEO,
>                              VIRTUAL_DEV_HOSTDEV,
> -                            VIRTUAL_DEV_WATCHDOG]
> +                            VIRTUAL_DEV_WATCHDOG,
> +                            VIRTUAL_DEV_SMARTCARD]
>  
>      # General device type (disk, interface, etc.)
>      _virtual_device_type = None
> diff --git a/virtinst/VirtualSmartCardDevice.py b/virtinst/VirtualSmartCardDevice.py
> new file mode 100644
> index 0000000..f07bbf3
> --- /dev/null
> +++ b/virtinst/VirtualSmartCardDevice.py
> @@ -0,0 +1,88 @@
> +# coding=utf-8
> +#
> +# Copyright 2011  Red Hat, Inc.
> +# Cole Robinson <crobinso at redhat.com>
> +# Marc-André Lureau <marcandre.lureau at 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 XMLBuilderDomain import _xml_property
> +from virtinst import _virtinst as _
> +
> +class VirtualSmartCardDevice(VirtualDevice.VirtualDevice):
> +
> +    _virtual_device_type = VirtualDevice.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.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 += "      <protocol type='raw'/>\n"
> +        xml += "    </smartcard>"
> +
> +        return xml
> diff --git a/virtinst/__init__.py b/virtinst/__init__.py
> index 287e90e..6460e95 100644
> --- a/virtinst/__init__.py
> +++ b/virtinst/__init__.py
> @@ -44,6 +44,7 @@ from VirtualVideoDevice import VirtualVideoDevice
>  from VirtualController import VirtualController
>  from VirtualWatchdog import VirtualWatchdog
>  from VirtualFilesystem import VirtualFilesystem
> +from VirtualSmartCardDevice import VirtualSmartCardDevice
>  from FullVirtGuest import FullVirtGuest
>  from ParaVirtGuest import ParaVirtGuest
>  from DistroInstaller import DistroInstaller
> @@ -73,4 +74,5 @@ __all__ = ["Guest", "XenGuest", "VirtualNetworkInterface",
>             "CPU",
>             "VirtualHostDevice", "VirtualHostDeviceUSB", "VirtualVideoDevice",
>             "VirtualHostDevicePCI", "VirtualCharDevice", "VirtualInputDevice",
> -           "VirtualController", "VirtualWatchdog"]
> +           "VirtualController", "VirtualWatchdog",
> +           "VirtualFilesystem", "VirtualSmartCardDevice"]
> diff --git a/virtinst/cli.py b/virtinst/cli.py
> index 4f78738..19602cf 100644
> --- a/virtinst/cli.py
> +++ b/virtinst/cli.py
> @@ -969,6 +969,16 @@ def get_hostdevs(hostdevs, guest):
>                                                            name=devname)
>          guest.hostdevs.append(dev)
>  
> +def get_smartcard(guest, sc_opts):
> +    for sc in sc_opts:
> +        try:
> +            dev = parse_smartcard(guest, sc)
> +        except Exception, e:
> +            fail(_("Error in smartcard device parameters: %s") % str(e))
> +
> +        if dev:
> +            guest.add_device(dev)
> +
>  #############################
>  # Common CLI option/group   #
>  #############################
> @@ -1036,6 +1046,17 @@ def network_option_group(parser):
>  
>      return netg
>  
> +def smartcard_option_group(parser):
> +    """
> +    Register smartcard options for virt-install and virt-image
> +    """
> +    scg = optparse.OptionGroup(parser, _("SmartCard Configuration"))
> +
> +    scg.add_option("-S", "--smartcard", dest="smartcard", action="append",
> +      help=_("Add a smartcard device to the domain. Ex:\n"
> +             "--smartcard mode=passthrough\n"))
> +    return scg
> +
>  #############################################
>  # CLI complex parsing helpers               #
>  # (for options like --disk, --network, etc. #
> @@ -1480,6 +1501,34 @@ def parse_graphics(guest, optstring):
>  
>      return dev
>  
> +#######################
> +# --smartcard parsing #
> +#######################
> +def parse_smartcard(guest, optstring):
> +    if optstring is None:
> +        return None
> +
> +    # Peel the mode off the front
> +    opts = parse_optstr(optstring, remove_first="mode")
> +    if opts.get("mode") == "none":
> +        return None
> +    dev = virtinst.VirtualSmartCardDevice(guest.conn, opts.get("mode"))
> +
> +    def set_param(paramname, dictname, val=None):
> +        val = get_opt_param(opts, dictname, val)
> +        if val == None:
> +            return
> +
> +        setattr(dev, paramname, val)
> +
> +    set_param("mode", "mode")
> +    set_param("type", "type")
> +
> +    if opts:
> +        raise ValueError(_("Unknown options %s") % opts.keys())
> +
> +    return dev
> +
>  ######################
>  # --watchdog parsing #
>  ######################




More information about the virt-tools-list mailing list