[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