On 28/01/2015 11:20, lvroyce(a)linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Storage update abandoned async task because mem copy is not long lasting
task and does not need to use task to track its status.
So update just do the data upload, and following storage volume lookup
will take care of current upload progress.
Signed-off-by: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
---
src/kimchi/i18n.py | 1 +
src/kimchi/model/storagevolumes.py | 61 +++++++++++++++++---------------------
2 files changed, 28 insertions(+), 34 deletions(-)
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index af912bd..af0dc4f 100644
--- a/src/kimchi/i18n.py
+++ b/src/kimchi/i18n.py
@@ -211,6 +211,7 @@ messages = {
"KCHVOL0022E": _("Unable to access file %(url)s. Please, check
it."),
"KCHVOL0023E": _("Unable to clone storage volume '%(name)s'
in pool '%(pool)s'. Details: %(err)s"),
"KCHVOL0024E": _("Upload volume chunk index, size and total size
must be integer"),
+ "KCHVOL0025E": _("Upload volume fails. Details: %(err)s"),
"KCHVOL0026E": _("Inconsistent upload count"),
"KCHIFACE0001E": _("Interface %(name)s does not exist"),
diff --git a/src/kimchi/model/storagevolumes.py b/src/kimchi/model/storagevolumes.py
index cb79966..ff99972 100644
--- a/src/kimchi/model/storagevolumes.py
+++ b/src/kimchi/model/storagevolumes.py
@@ -34,6 +34,7 @@ from kimchi.isoinfo import IsoImage
from kimchi.model.diskutils import get_disk_ref_cnt
from kimchi.model.storagepools import StoragePoolModel
from kimchi.model.tasks import TaskModel
+from kimchi.model.utils import get_vol_update_lock, release_vol_update_lock
from kimchi.utils import add_task, get_next_clone_name, get_unique_file_name
from kimchi.utils import kimchi_log
from kimchi.xmlutils.utils import xpath_get_text
@@ -58,7 +59,7 @@ class StorageVolumesModel(object):
self.task = TaskModel(**kargs)
def create(self, pool_name, params):
- vol_source = ['file', 'url', 'capacity']
+ vol_source = ['url', 'capacity']
name = params.get('name')
@@ -89,9 +90,7 @@ class StorageVolumesModel(object):
# if 'name' is omitted - except for the methods listed in
# 'REQUIRE_NAME_PARAMS' - the default volume name will be the
# file/URL basename.
- if create_param == 'file':
- name = os.path.basename(params['file'].filename)
- elif create_param == 'url':
+ if create_param == 'url':
name = os.path.basename(params['url'])
else:
name = 'upload-%s' % int(time.time())
@@ -120,36 +119,6 @@ class StorageVolumesModel(object):
taskid = add_task(targeturi, create_func, self.objstore, params)
return self.task.lookup(taskid)
- def _create_volume_with_file(self, cb, params):
- pool_name = params.pop('pool')
- dir_path = StoragePoolModel(
- conn=self.conn, objstore=self.objstore).lookup(pool_name)['path']
- file_path = os.path.join(dir_path, params['name'])
- if os.path.exists(file_path):
- raise InvalidParameter('KCHVOL0001E', {'name':
params['name']})
-
- upload_file = params['file']
- f_len = upload_file.fp.length
- try:
- size = 0
- with open(file_path, 'wb') as f:
- while True:
- data = upload_file.file.read(READ_CHUNK_SIZE)
- if not data:
- break
- size += len(data)
- f.write(data)
- cb('%s/%s' % (size, f_len))
- except Exception as e:
- raise OperationFailed('KCHVOL0007E',
- {'name': params['name'],
- 'pool': pool_name,
- 'err': e.message})
-
- # Refresh to make sure volume can be found in following lookup
- StoragePoolModel.get_storagepool(pool_name, self.conn).refresh(0)
- cb('OK', True)
-
def _create_volume_with_capacity(self, cb, params):
pool_name = params.pop('pool')
vol_xml = """
@@ -464,6 +433,30 @@ class StorageVolumeModel(object):
cb('OK', True)
+ def update(self, pool, name, params):
Prior to the PUT requests we must have a POST to create the volume.
+ vol = StorageVolumeModel.get_storagevolume(pool, name,
self.conn)
+ vol_path = vol.path()
+
+ chunk_size = int(params['chunk_size'])
+ index = int(params['index'])
+ pos = chunk_size * index
+ lock = get_vol_update_lock(vol_path)
+ try:
+ with lock:
+ st = self.conn.get().newStream(0)
+ vol.upload(st, pos, chunk_size)
+ st.send(params['chunk'].fullvalue())
+ st.finish()
+ except Exception as e:
+ st and st.abort()
+ raise OperationFailed('KCHVOL0025E',
+ {'err': e.message})
+ finally:
+ release_vol_update_lock(vol_path)
+
+ # Refresh to make sure volume can be found in following lookup
+ StoragePoolModel.get_storagepool(pool, self.conn).refresh(0)
+
class IsoVolumesModel(object):
def __init__(self, **kargs):