[Kimchi-devel] [PATCH 15/23] refactor model: Create a separated model for template resource

Aline Manera alinefm at linux.vnet.ibm.com
Wed Jan 29 23:34:56 UTC 2014


From: Aline Manera <alinefm at br.ibm.com>

The model implementation for template and its sub-resources were added to
model_/templates.py

Signed-off-by: Aline Manera <alinefm at br.ibm.com>
---
 src/kimchi/model_/templates.py |  172 ++++++++++++++++++++++++++++++++++++++++
 src/kimchi/utils.py            |   14 ++++
 2 files changed, 186 insertions(+)
 create mode 100644 src/kimchi/model_/templates.py

diff --git a/src/kimchi/model_/templates.py b/src/kimchi/model_/templates.py
new file mode 100644
index 0000000..03632a6
--- /dev/null
+++ b/src/kimchi/model_/templates.py
@@ -0,0 +1,172 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2013
+#
+# Authors:
+#  Aline Manera <alinefm at linux.vnet.ibm.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+
+import copy
+
+import libvirt
+
+from kimchi import xmlutils
+from kimchi.exception import InvalidOperation, InvalidParameter, NotFoundError
+from kimchi.utils import pool_name_from_uri
+from kimchi.vmtemplate import VMTemplate
+
+
+class TemplatesModel(object):
+    def __init__(self, **kargs):
+        self.objstore = kargs['objstore']
+        self.conn = kargs['conn']
+
+    def create(self, params):
+        name = params['name']
+        conn = self.conn.get()
+
+        pool_uri = params.get(u'storagepool', '')
+        if pool_uri:
+            pool_name = pool_name_from_uri(pool_uri)
+            try:
+                conn.storagePoolLookupByName(pool_name)
+            except Exception as e:
+                err = "Storagepool specified is not valid: %s."
+                raise InvalidParameter(err % e.message)
+
+        for net_name in params.get(u'networks', []):
+            try:
+                conn.networkLookupByName(net_name)
+            except Exception, e:
+                raise InvalidParameter("Network '%s' specified by template "
+                                       "does not exist." % net_name)
+
+        with self.objstore as session:
+            if name in session.get_list('template'):
+                raise InvalidOperation("Template already exists")
+            t = LibvirtVMTemplate(params, scan=True)
+            session.store('template', name, t.info)
+        return name
+
+    def get_list(self):
+        with self.objstore as session:
+            return session.get_list('template')
+
+
+class TemplateModel(object):
+    def __init__(self, **kargs):
+        self.objstore = kargs['objstore']
+        self.conn = kargs['conn']
+        self.templates = TemplatesModel(**kargs)
+
+    @staticmethod
+    def get_template(name, objstore, conn, overrides=None):
+        with objstore as session:
+            params = session.get('template', name)
+        if overrides:
+            params.update(overrides)
+        return LibvirtVMTemplate(params, False, conn)
+
+    def lookup(self, name):
+        t = self.get_template(name, self.objstore, self.conn)
+        return t.info
+
+    def delete(self, name):
+        with self.objstore as session:
+            session.delete('template', name)
+
+    def update(self, name, params):
+        old_t = self.lookup(name)
+        new_t = copy.copy(old_t)
+        new_t.update(params)
+        ident = name
+
+        pool_uri = new_t.get(u'storagepool', '')
+        pool_name = pool_name_from_uri(pool_uri)
+        try:
+            conn = self.conn.get()
+            conn.storagePoolLookupByName(pool_name)
+        except Exception as e:
+            err = "Storagepool specified is not valid: %s."
+            raise InvalidParameter(err % e.message)
+
+        for net_name in params.get(u'networks', []):
+            try:
+                conn = self.conn.get()
+                conn.networkLookupByName(net_name)
+            except Exception, e:
+                raise InvalidParameter("Network '%s' specified by template "
+                                       "does not exist" % net_name)
+
+        self.delete(name)
+        try:
+            ident = self.templates.create(new_t)
+        except:
+            ident = self.templates.create(old_t)
+            raise
+        return ident
+
+
+class LibvirtVMTemplate(VMTemplate):
+    def __init__(self, args, scan=False, conn=None):
+        VMTemplate.__init__(self, args, scan)
+        self.conn = conn
+
+    def _storage_validate(self):
+        pool_uri = self.info['storagepool']
+        pool_name = pool_name_from_uri(pool_uri)
+        try:
+            conn = self.conn.get()
+            pool = conn.storagePoolLookupByName(pool_name)
+        except libvirt.libvirtError:
+            err = 'Storage specified by template does not exist'
+            raise InvalidParameter(err)
+
+        if not pool.isActive():
+            err = 'Storage specified by template is not active'
+            raise InvalidParameter(err)
+
+        return pool
+
+    def _network_validate(self):
+        names = self.info['networks']
+        for name in names:
+            try:
+                conn = self.conn.get()
+                network = conn.networkLookupByName(name)
+            except libvirt.libvirtError:
+                err = 'Network specified by template does not exist'
+                raise InvalidParameter(err)
+
+            if not network.isActive():
+                err = 'Network specified by template is not active'
+                raise InvalidParameter(err)
+
+    def _get_storage_path(self):
+        pool = self._storage_validate()
+        xml = pool.XMLDesc(0)
+        return xmlutils.xpath_get_text(xml, "/pool/target/path")[0]
+
+    def fork_vm_storage(self, vm_uuid):
+        # Provision storage:
+        # TODO: Rebase on the storage API once upstream
+        pool = self._storage_validate()
+        vol_list = self.to_volume_list(vm_uuid)
+        for v in vol_list:
+            # outgoing text to libvirt, encode('utf-8')
+            pool.createXML(v['xml'].encode('utf-8'), 0)
+        return vol_list
diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
index 30c09d4..5345d28 100644
--- a/src/kimchi/utils.py
+++ b/src/kimchi/utils.py
@@ -23,6 +23,7 @@
 
 import cherrypy
 import os
+import re
 import subprocess
 import urllib2
 from threading import Timer
@@ -31,12 +32,25 @@ from cherrypy.lib.reprconf import Parser
 
 from kimchi import config
 from kimchi.asynctask import AsyncTask
+from kimchi.exception import InvalidParameter, TimeoutExpired
 
 
 kimchi_log = cherrypy.log.error_log
 task_id = 0
 
 
+def _uri_to_name(collection, uri):
+    expr = '/%s/(.*?)/?$' % collection
+    m = re.match(expr, uri)
+    if not m:
+        raise InvalidParameter(uri)
+    return m.group(1)
+
+
+def pool_name_from_uri(uri):
+    return _uri_to_name('storagepools', uri)
+
+
 def get_next_task_id():
     global task_id
     task_id += 1
-- 
1.7.10.4




More information about the Kimchi-devel mailing list