[Kimchi-devel] [PATCH V4 1/5] Add spice backend support for kimchi

Aline Manera alinefm at linux.vnet.ibm.com
Fri Dec 27 12:59:42 UTC 2013


Reviewed-by: Aline Manera <alinefm at linux.vnet.ibm.com>

On 12/25/2013 12:51 PM, apporc wrote:
> 1.  Add spice support for kimchi template
>      Now we can specify a spice parameter when creating a template and updating it.
>
> 2.  Add spice support for kimchi vm
>      When creating a vm, we have a chance to change the graphics configuration to override
>      the value from the template.
>
> 3.  Expose the real port for vnc/spice, so that users can connect vm with popular
>      vnc/spice client tool.
>
> 4.  Spice-vdagent support is added too, so that when users happended to install
>      spice-tool/spice-vdagent in their vm, they will get improved spice graphics effect immediately.
>
> 5.  Specifying graphics parameters when updating vm is not supported yet, it will be added separately
>      in another patch.
>
> Signed-off-by: apporc <appleorchard2000 at gmail.com>
> ---
>   src/kimchi/controller.py | 10 +++++++---
>   src/kimchi/model.py      | 43 ++++++++++++++++++++++++++-----------------
>   src/kimchi/osinfo.py     |  5 +++--
>   src/kimchi/vmtemplate.py | 31 +++++++++++++++++++++++++++++--
>   4 files changed, 65 insertions(+), 24 deletions(-)
>
> diff --git a/src/kimchi/controller.py b/src/kimchi/controller.py
> index 2940278..dacaa6a 100644
> --- a/src/kimchi/controller.py
> +++ b/src/kimchi/controller.py
> @@ -384,7 +384,10 @@ class VM(Resource):
>                   'screenshot': self.info['screenshot'],
>                   'icon': self.info['icon'],
>                   'graphics': {'type': self.info['graphics']['type'],
> -                             'port': self.info['graphics']['port']}}
> +                             'listen': self.info['graphics']['listen'],
> +                             'port': self.info['graphics']['port'],
> +                             'real_port': self.info['graphics']['real_port']}
> +                }
>
>
>   class VMScreenShot(Resource):
> @@ -406,7 +409,7 @@ class Template(Resource):
>           super(Template, self).__init__(model, ident)
>           self.update_params = ["name", "folder", "icon", "os_distro",
>                                 "storagepool", "os_version", "cpus",
> -                              "memory", "cdrom", "disks"]
> +                              "memory", "cdrom", "disks", "graphics"]
>           self.uri_fmt = "/templates/%s"
>
>       @property
> @@ -420,7 +423,8 @@ class Template(Resource):
>                   'cdrom': self.info['cdrom'],
>                   'disks': self.info['disks'],
>                   'storagepool': self.info['storagepool'],
> -                'folder': self.info.get('folder', [])}
> +                'folder': self.info.get('folder', []),
> +                'graphics': self.info['graphics']}
>
>
>   class Interfaces(Collection):
> diff --git a/src/kimchi/model.py b/src/kimchi/model.py
> index a6790b8..dc2ccf5 100644
> --- a/src/kimchi/model.py
> +++ b/src/kimchi/model.py
> @@ -503,10 +503,11 @@ class Model(object):
>           info = dom.info()
>           state = Model.dom_state_map[info[0]]
>           screenshot = None
> -        graphics_type, _ = self._vm_get_graphics(name)
>           # 'port' must remain None until a connect call is issued
> -        graphics_port = (self.graphics_ports.get(name, None) if state == 'running'
> -                      else None)
> +        graphics_type, graphics_listen, real_port = self._vm_get_graphics(name)
> +        real_port = real_port if state == 'running' else None
> +        graphics_port = (self.graphics_ports.get(name) if state == 'running'
> +                         else None)
>           try:
>               if state == 'running':
>                   screenshot = self.vmscreenshot_lookup(name)
> @@ -539,7 +540,12 @@ class Model(object):
>                   'cpus': info[3],
>                   'screenshot': screenshot,
>                   'icon': icon,
> -                'graphics': {"type": graphics_type, "port": graphics_port}}
> +                'graphics': {"type": graphics_type,
> +                             "listen": graphics_listen,
> +                             "port": graphics_port,
> +                             "real_port": real_port
> +                             }
> +                }
>
>       def _vm_get_disk_paths(self, dom):
>           xml = dom.XMLDesc(0)
> @@ -581,24 +587,23 @@ class Model(object):
>           expr = "/domain/devices/graphics/@type"
>           res = xmlutils.xpath_get_text(xml, expr)
>           graphics_type = res[0] if res else None
> -        port = None
> +        expr = "/domain/devices/graphics/@listen"
> +        res = xmlutils.xpath_get_text(xml, expr)
> +        graphics_listen = res[0] if res else None
> +        graphics_port = None
>           if graphics_type:
>               expr = "/domain/devices/graphics[@type='%s']/@port" % graphics_type
>               res = xmlutils.xpath_get_text(xml, expr)
> -            port = int(res[0]) if res else None
> -        # FIX ME
> -        # graphics_type should be 'vnc' or None.  'spice' should only be
> -        # returned if we support it in the future.
> -        graphics_type = None if graphics_type != "vnc" else graphics_type
> -        return graphics_type, port
> +            graphics_port = int(res[0]) if res else None
> +        return graphics_type, graphics_listen, graphics_port
>
>       def vm_connect(self, name):
> -        graphics, port = self._vm_get_graphics(name)
> -        if graphics == "vnc" and port != None:
> -            port = vnc.new_ws_proxy(port)
> -            self.graphics_ports[name] = port
> +        graphics_type, graphics_listen, graphics_port \
> +            = self._vm_get_graphics(name)
> +        if graphics_port is not None:
> +            self.graphics_ports[name] = vnc.new_ws_proxy(graphics_port)
>           else:
> -            raise OperationFailed("Unable to find VNC port in %s" % name)
> +            raise OperationFailed("Unable to find connection port in %s" % name)
>
>       def vms_create(self, params):
>           conn = self.conn.get()
> @@ -629,8 +634,12 @@ class Model(object):
>                   session.store('vm', vm_uuid, {'icon': icon})
>
>           libvirt_stream = False if len(self.libvirt_stream_protocols) == 0 else True
> +        graphics = params.get('graphics')
>
> -        xml = t.to_vm_xml(name, vm_uuid, libvirt_stream, self.qemu_stream_dns)
> +        xml = t.to_vm_xml(name, vm_uuid,
> +                          libvirt_stream=libvirt_stream,
> +                          qemu_stream_dns=self.qemu_stream_dns,
> +                          graphics=graphics)
>           try:
>               dom = conn.defineXML(xml.encode('utf-8'))
>           except libvirt.libvirtError as e:
> diff --git a/src/kimchi/osinfo.py b/src/kimchi/osinfo.py
> index da70b30..141be82 100644
> --- a/src/kimchi/osinfo.py
> +++ b/src/kimchi/osinfo.py
> @@ -180,7 +180,8 @@ isolinks = {
>   }
>
>   defaults = {'network': 'default', 'storagepool': '/storagepools/default',
> -        'domain': 'kvm', 'arch': os.uname()[4]
> +        'domain': 'kvm', 'arch': os.uname()[4],
> +        'graphics':{'type': 'vnc', 'listen': '0.0.0.0'}
>   }
>
>   def lookup(distro, version):
> @@ -193,7 +194,7 @@ def lookup(distro, version):
>       for name, entry in osinfo:
>           # Test if this entry is a valid match
>           if entry['version'](distro, version):
> -            params = copy.copy(defaults)
> +            params = copy.deepcopy(defaults)
>               params['os_distro'] = distro
>               params['os_version'] = version
>               params.update(entry)
> diff --git a/src/kimchi/vmtemplate.py b/src/kimchi/vmtemplate.py
> index dd43faa..5e2fff6 100644
> --- a/src/kimchi/vmtemplate.py
> +++ b/src/kimchi/vmtemplate.py
> @@ -74,6 +74,11 @@ class VMTemplate(object):
>           self.info.update(entry)
>
>           # Override with the passed in parameters
> +        graph_args = args.get('graphics')
> +        if graph_args:
> +            graphics = dict(self.info['graphics'])
> +            graphics.update(graph_args)
> +            args['graphics'] = graphics
>           self.info.update(args)
>
>       def _get_cdrom_xml(self, libvirt_stream, qemu_stream_dns):
> @@ -155,6 +160,24 @@ class VMTemplate(object):
>               """ % params
>           return ret
>
> +    def _get_graphics_xml(self, params):
> +        graphics_xml = """
> +            <graphics type='%(type)s' autoport='yes' listen='%(listen)s'>
> +            </graphics>
> +        """
> +        spicevmc_xml = """
> +            <channel type='spicevmc'>
> +              <target type='virtio' name='com.redhat.spice.0'/>
> +            </channel>
> +        """
> +        graphics = dict(self.info['graphics'])
> +        if params:
> +            graphics.update(params)
> +        graphics_xml = graphics_xml % graphics
> +        if graphics['type'] == 'spice':
> +            graphics_xml = graphics_xml + spicevmc_xml
> +        return graphics_xml
> +
>       def to_volume_list(self, vm_uuid):
>           storage_path = self._get_storage_path()
>           ret = []
> @@ -182,7 +205,7 @@ class VMTemplate(object):
>               ret.append(info)
>           return ret
>
> -    def to_vm_xml(self, vm_name, vm_uuid, libvirt_stream = False, qemu_stream_dns = False):
> +    def to_vm_xml(self, vm_name, vm_uuid, **kwargs):
>           params = dict(self.info)
>           params['name'] = vm_name
>           params['uuid'] = vm_uuid
> @@ -190,7 +213,11 @@ class VMTemplate(object):
>           params['qemu-namespace'] = ''
>           params['cdroms'] = ''
>           params['qemu-stream-cmdline'] = ''
> +        graphics = kwargs.get('graphics')
> +        params['graphics'] = self._get_graphics_xml(graphics)
>
> +        qemu_stream_dns = kwargs.get('qemu_stream_dns', False)
> +        libvirt_stream = kwargs.get('libvirt_stream', False)
>           cdrom_xml = self._get_cdrom_xml(libvirt_stream, qemu_stream_dns)
>           if not libvirt_stream and params.get('iso_stream', False):
>               params['qemu-namespace'] = QEMU_NAMESPACE
> @@ -224,7 +251,7 @@ class VMTemplate(object):
>                 <source network='%(network)s'/>
>                 <model type='%(nic_model)s'/>
>               </interface>
> -            <graphics type='vnc' />
> +            %(graphics)s
>               <sound model='ich6' />
>               <memballoon model='virtio' />
>             </devices>




More information about the Kimchi-devel mailing list