[Kimchi-devel] [PATCH 4/5] Add volume ref_cnt: Add model and mockmodel implementation

lvroyce0210 at gmail.com lvroyce0210 at gmail.com
Tue Feb 18 14:07:44 UTC 2014


From: Royce Lv <lvroyce at linux.vnet.ibm.com>

Set ref_cnt to 0 when new volume created,
report it when lookup storage volume, for volume outside kimchi scope,
set ref_cnt to be -1.

Signed-off-by: Royce Lv <lvroyce at linux.vnet.ibm.com>
---
 src/kimchi/mockmodel.py            |  3 +++
 src/kimchi/model/storagevolumes.py | 35 +++++++++++++++++++++++++++++++++--
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py
index 0c2da8a..76b2221 100644
--- a/src/kimchi/mockmodel.py
+++ b/src/kimchi/mockmodel.py
@@ -419,6 +419,7 @@ class MockModel(object):
             name = params['name']
             volume = MockStorageVolume(pool, name, params)
             volume.info['type'] = params['type']
+            volume.info['ref_cnt'] = params.get('ref_cnt', 0)
             volume.info['format'] = params['format']
             volume.info['path'] = os.path.join(
                 pool.info['path'], name)
@@ -834,6 +835,7 @@ class MockVMTemplate(VMTemplate):
         disk_paths = []
         for vol_info in volumes:
             vol_info['capacity'] = vol_info['capacity'] << 10
+            vol_info['ref_cnt'] = 1
             self.model.storagevolumes_create(pool.name, vol_info)
             disk_paths.append({'pool': pool.name, 'volume': vol_info['name']})
         return disk_paths
@@ -945,6 +947,7 @@ class MockStorageVolume(object):
                      'capacity': capacity << 20,
                      'allocation': params.get('allocation','512'),
                      'path': params.get('path'),
+                     'ref_cnt': params.get('ref_cnt'),
                      'format': fmt}
         if fmt == 'iso':
             self.info['allocation'] = self.info['capacity']
diff --git a/src/kimchi/model/storagevolumes.py b/src/kimchi/model/storagevolumes.py
index e3f00ca..9906f33 100644
--- a/src/kimchi/model/storagevolumes.py
+++ b/src/kimchi/model/storagevolumes.py
@@ -29,6 +29,8 @@ from kimchi.exception import InvalidOperation, IsoFormatError
 from kimchi.exception import MissingParameter, NotFoundError, OperationFailed
 from kimchi.isoinfo import IsoImage
 from kimchi.model.storagepools import StoragePoolModel
+from kimchi.model.vms import VMsModel
+from kimchi.model.vmstorages import VMStoragesModel, VMStorageModel
 
 
 VOLUME_TYPE_MAP = {0: 'file',
@@ -40,6 +42,7 @@ VOLUME_TYPE_MAP = {0: 'file',
 class StorageVolumesModel(object):
     def __init__(self, **kargs):
         self.conn = kargs['conn']
+        self.objstore = kargs['objstore']
 
     def create(self, pool, params):
         vol_xml = """
@@ -58,6 +61,7 @@ class StorageVolumesModel(object):
         params.setdefault('format', 'qcow2')
 
         name = params['name']
+        vol_id = '%s:%s' % (pool, name)
         try:
             pool = StoragePoolModel.get_storagepool(pool, self.conn)
             xml = vol_xml % params
@@ -71,6 +75,10 @@ class StorageVolumesModel(object):
             raise OperationFailed("KCHVOL0007E",
                                   {'name': name, 'pool': pool,
                                    'err': e.get_error_message()})
+
+        with self.objstore as session:
+            session.store('storagevolume', vol_id, {'ref_cnt': 0})
+
         return name
 
     def get_list(self, pool_name):
@@ -79,7 +87,7 @@ class StorageVolumesModel(object):
             raise InvalidOperation("KCHVOL0006E", {'pool': pool_name})
         try:
             pool.refresh(0)
-            return pool.listVolumes()
+            return sorted(map(lambda x: x.decode('utf-8'), pool.listVolumes()))
         except libvirt.libvirtError as e:
             raise OperationFailed("KCHVOL0008E",
                                   {'pool': pool_name,
@@ -89,13 +97,14 @@ class StorageVolumesModel(object):
 class StorageVolumeModel(object):
     def __init__(self, **kargs):
         self.conn = kargs['conn']
+        self.objstore = kargs['objstore']
 
     def _get_storagevolume(self, pool, name):
         pool = StoragePoolModel.get_storagepool(pool, self.conn)
         if not pool.isActive():
             raise InvalidOperation("KCHVOL0006E", {'name': pool})
         try:
-            return pool.storageVolLookupByName(name)
+            return pool.storageVolLookupByName(name.encode("utf-8"))
         except libvirt.libvirtError as e:
             if e.get_error_code() == libvirt.VIR_ERR_NO_STORAGE_VOL:
                 raise NotFoundError("KCHVOL0002E", {'name': name,
@@ -103,16 +112,38 @@ class StorageVolumeModel(object):
             else:
                 raise
 
+    def _get_ref_cnt(self, pool, name, path):
+        vol_id = '%s:%s' % (pool, name)
+        with self.objstore as session:
+            try:
+                ref_cnt = session.get('storagevolume', vol_id)['ref_cnt']
+            except NotFoundError:
+                # Fix storage volume created outside kimchi scope
+                ref_cnt = 0
+                args = {'conn': self.conn, 'objstore': self.objstore}
+                # try to find this volume in exsisted vm
+                vms = VMsModel(**args).get_list()
+                for vm in vms:
+                    storages = VMStoragesModel(**args).get_list(vm)
+                    for disk in storages:
+                        if path == VMStorageModel(**args).lookup(vm, disk)['path']:
+                            ref_cnt = ref_cnt + 1
+                session.store('storagevolume', vol_id, {'ref_cnt': ref_cnt})
+
+        return ref_cnt
+
     def lookup(self, pool, name):
         vol = self._get_storagevolume(pool, name)
         path = vol.path()
         info = vol.info()
         xml = vol.XMLDesc(0)
         fmt = xmlutils.xpath_get_text(xml, "/volume/target/format/@type")[0]
+        ref_cnt = self._get_ref_cnt(pool, name, path)
         res = dict(type=VOLUME_TYPE_MAP[info[0]],
                    capacity=info[1],
                    allocation=info[2],
                    path=path,
+                   ref_cnt=ref_cnt,
                    format=fmt)
         if fmt == 'iso':
             if os.path.islink(path):
-- 
1.8.1.2




More information about the Kimchi-devel mailing list