From: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
set ticket as attribute of vm info.
vm lookup will get ticket.
API user should check the expire of ticket.
vm update method can edit ticket.
when set a ticket, it will take effect on both persistent and live
configure.
Signed-off-by: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
---
src/kimchi/model/vms.py | 68 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/src/kimchi/model/vms.py b/src/kimchi/model/vms.py
index 8c0dcb1..2681e95 100644
--- a/src/kimchi/model/vms.py
+++ b/src/kimchi/model/vms.py
@@ -19,7 +19,10 @@
from lxml.builder import E
import lxml.etree as ET
+from lxml import etree, objectify
import os
+import random
+import string
import time
import uuid
from xml.etree import ElementTree
@@ -246,6 +249,12 @@ def __init__(self, **kargs):
self.groups = import_class('kimchi.model.host.GroupsModel')(**kargs)
def update(self, name, params):
+ if 'ticket' in params:
+ password = params['ticket'].get("passwd")
+ password = password if password is not None else "".join(
+ random.sample(string.ascii_letters + string.digits, 8))
+ params['ticket']['passwd'] = password
+
dom = self.get_vm(name, self.conn)
dom = self._static_vm_update(dom, params)
self._live_vm_update(dom, params)
@@ -304,6 +313,47 @@ def vm_update_os_metadata(dom, params):
os_elem = E.os({"distro": distro, "version": version})
set_metadata_node(dom, os_elem)
+ def _set_ticket(self, xml, params, flag=0):
+ DEFAULT_VALID_TO = 30
+ password = params.get("passwd")
+ expire = params.get("expire")
+ root = objectify.fromstring(xml)
+ graphic = root.devices.find("graphics")
+ graphic.attrib['passwd'] = password
+ to = graphic.attrib.get('passwdValidTo')
+ if to is not None:
+ if (time.mktime(time.strptime(to, '%Y-%m-%dT%H:%M:%S'))
+ - time.time() <= 0):
+ expire = expire if expire is not None else DEFAULT_VALID_TO
+
+ if expire is not None:
+ expire_time = time.gmtime(time.time() + float(expire))
+ valid_to = time.strftime('%Y-%m-%dT%H:%M:%S', expire_time)
+ graphic.attrib['passwdValidTo'] = valid_to
+
+ return root if flag == 0 else graphic
+
+ def _set_persistent_ticket(self, dom, xml, params):
+ if 'ticket' not in params:
+ # store the password for copy
+ ticket = self._get_ticket(dom)
+ if ticket['passwd'] is None:
+ return xml
+ else:
+ params['ticket'] = ticket
+ node = self._set_ticket(xml, params['ticket'])
+ return ET.tostring(node, encoding="utf-8")
+
+ def _set_live_ticket(self, dom, params):
+ if 'ticket' not in params:
+ return
+ if dom.isActive():
+ xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE)
+ flag = libvirt.VIR_DOMAIN_XML_SECURE
+ node = self._set_ticket(xml, params['ticket'], flag)
+ dom.updateDeviceFlags(etree.tostring(node),
+ libvirt.VIR_DOMAIN_AFFECT_LIVE)
+
def _static_vm_update(self, dom, params):
state = DOM_STATE_MAP[dom.info()[0]]
old_xml = new_xml = dom.XMLDesc(0)
@@ -319,6 +369,8 @@ def _static_vm_update(self, dom, params):
xpath = VM_STATIC_UPDATE_PARAMS[key]
new_xml = xmlutils.xml_item_update(new_xml, xpath, val)
+ new_xml = self._set_persistent_ticket(dom, new_xml, params)
+
conn = self.conn.get()
try:
if 'name' in params:
@@ -340,11 +392,26 @@ def _static_vm_update(self, dom, params):
def _live_vm_update(self, dom, params):
self._vm_update_access_metadata(dom, params)
+ self._set_live_ticket(dom, params)
def _has_video(self, dom):
dom = ElementTree.fromstring(dom.XMLDesc(0))
return dom.find('devices/video') is not None
+ def _get_ticket(self, dom):
+ xml = dom.XMLDesc(libvirt.VIR_DOMAIN_XML_SECURE)
+ root = objectify.fromstring(xml)
+ graphic = root.devices.find("graphics")
+ passwd = graphic.attrib.get('passwd')
+ ticket = {"passwd": passwd}
+ valid_to = graphic.attrib.get('passwdValidTo')
+ ticket['expire'] = None
+ if valid_to is not None:
+ to = time.mktime(time.strptime(valid_to, '%Y-%m-%dT%H:%M:%S'))
+ ticket['expire'] = to - time.mktime(time.gmtime())
+
+ return ticket
+
def lookup(self, name):
dom = self.get_vm(name, self.conn)
info = dom.info()
@@ -394,6 +461,7 @@ def lookup(self, name):
'graphics': {"type": graphics_type,
"listen": graphics_listen,
"port": graphics_port},
+ 'ticket': self._get_ticket(dom),
'users': users,
'groups': groups,
'access': 'full'
--
1.9.3