I believe this new behavior deserves at least one new unit test
(or changing an existing one) to ensure that it works as expected
in the future.
All existing unit tests passed (= no new failures) in both x86 and ppc
running pkvm.
One more comment below:
On 11/10/2015 04:12 PM, pvital(a)linux.vnet.ibm.com wrote:
From: Paulo Vital <pvital(a)linux.vnet.ibm.com>
Add back-end support to create new storage volume (new virtual disk) when
attaching disk to a guest created before.
There are three essential parameters to create the new volume:
* vol: Storage volume name of disk image, that should be 'new_vol'.
* capacity: The total space which can be used to store new volumes.
The unit is bytes.
* format: The format of the defined Storage Volume. Only used when creating
a storage volume with 'capacity'.
Signed-off-by: Paulo Vital <pvital(a)linux.vnet.ibm.com>
---
src/wok/plugins/kimchi/API.json | 12 ++++++++++++
src/wok/plugins/kimchi/docs/API.md | 6 +++++-
src/wok/plugins/kimchi/i18n.py | 1 +
src/wok/plugins/kimchi/model/vmstorages.py | 28 +++++++++++++++++++++++++++-
4 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/src/wok/plugins/kimchi/API.json b/src/wok/plugins/kimchi/API.json
index 961f35f..8822520 100644
--- a/src/wok/plugins/kimchi/API.json
+++ b/src/wok/plugins/kimchi/API.json
@@ -564,6 +564,18 @@
"type": "string",
"pattern":
"^((/)|(http)[s]?:|[t]?(ftp)[s]?:)+.*$",
"error": "KCHVMSTOR0003E"
+ },
+ "capacity": {
+ "description": "The total size (MiB) of the storage
volume",
+ "type": "number",
+ "minimum": 1,
+ "error": "KCHVOL0020E"
+ },
+ "format": {
+ "description": "The format of the volume",
+ "type": "string",
+ "pattern":
"^(|bochs|cloop|cow|dmg|qcow|qcow2|qed|raw|vmdk|vpc)$",
+ "error": "KCHVOL0015E"
}
}
},
diff --git a/src/wok/plugins/kimchi/docs/API.md b/src/wok/plugins/kimchi/docs/API.md
index 52368b7..d00c2fe 100644
--- a/src/wok/plugins/kimchi/docs/API.md
+++ b/src/wok/plugins/kimchi/docs/API.md
@@ -205,7 +205,11 @@ Represents a snapshot of the Virtual Machine's primary monitor.
* type: The type of the storage (currently support 'cdrom' and
'disk').
* path: Path of cdrom iso.
* pool: Storage pool which disk image file locate in.
- * vol: Storage volume name of disk image.
+ * vol: Storage volume name of disk image ('new_vol' for create a new
volume).
+ * capacity: The total space which can be used to store new volumes.
+ The unit is bytes.
+ * format: The format of the defined Storage Volume. Only used when creating
+ a storage volume with 'capacity'.
### Sub-resource: storage
**URI:** /plugins/kimchi/vms/*:name*/storages/*:dev*
diff --git a/src/wok/plugins/kimchi/i18n.py b/src/wok/plugins/kimchi/i18n.py
index 42a5e16..53a0b6b 100644
--- a/src/wok/plugins/kimchi/i18n.py
+++ b/src/wok/plugins/kimchi/i18n.py
@@ -278,6 +278,7 @@ messages = {
"KCHVMSTOR0016E": _("Volume already in use by other virtual
machine."),
"KCHVMSTOR0017E": _("Only one of path or pool/volume can be
specified to add a new virtual machine disk"),
"KCHVMSTOR0018E": _("Volume chosen with format %(format)s does not
fit in the storage type %(type)s"),
+ "KCHVMSTOR0019E": _("The format msust be used only when creating a
new storage volume with 'capacity'."),
"KCHSNAP0001E": _("Virtual machine '%(vm)s' must be stopped
before creating a snapshot of it."),
"KCHSNAP0002E": _("Unable to create snapshot '%(name)s' on
virtual machine '%(vm)s'. Details: %(err)s"),
diff --git a/src/wok/plugins/kimchi/model/vmstorages.py
b/src/wok/plugins/kimchi/model/vmstorages.py
index 23db0a6..f6b3918 100644
--- a/src/wok/plugins/kimchi/model/vmstorages.py
+++ b/src/wok/plugins/kimchi/model/vmstorages.py
@@ -22,12 +22,14 @@ from lxml import etree
from wok.exception import InvalidOperation, InvalidParameter, NotFoundError
from wok.exception import OperationFailed
+from wok.model.tasks import TaskModel
from wok.utils import wok_log
from wok.plugins.kimchi.model.config import CapabilitiesModel
from wok.plugins.kimchi.model.diskutils import get_disk_used_by
from wok.plugins.kimchi.model.diskutils import set_disk_used_by
from wok.plugins.kimchi.model.storagevolumes import StorageVolumeModel
+from wok.plugins.kimchi.model.storagevolumes import StorageVolumesModel
from wok.plugins.kimchi.model.utils import get_vm_config_flag
from wok.plugins.kimchi.model.vms import DOM_STATE_MAP, VMModel
from wok.plugins.kimchi.osinfo import lookup
@@ -51,6 +53,7 @@ class VMStoragesModel(object):
self.conn = kargs['conn']
self.objstore = kargs['objstore']
self.caps = CapabilitiesModel(**kargs)
+ self.task = TaskModel(**kargs)
def _get_available_bus_address(self, bus_type, vm_name):
if bus_type not in ['ide']:
@@ -85,9 +88,12 @@ class VMStoragesModel(object):
if not ('vol' in params) ^ ('path' in params):
raise InvalidParameter("KCHVMSTOR0017E")
+ if ('format' in params) and ('capacity' not in params):
+ raise InvalidParameter("KCHVMSTOR0019E")
+
dom = VMModel.get_vm(vm_name, self.conn)
params['bus'] = _get_device_bus(params['type'], dom)
- params['format'] = 'raw'
+ params['format'] = params['format'] if 'format' in
params else 'raw'
Why not use dict.get() instead? It's simpler and produces the same effect:
params['format'] = params.get('format', 'raw')
dev_list = [dev for dev, bus in get_vm_disks(dom).iteritems()
if bus == params['bus']]
@@ -102,6 +108,26 @@ class VMStoragesModel(object):
DOM_STATE_MAP[dom.info()[0]] != 'shutoff'):
raise InvalidOperation('KCHVMSTOR0011E')
+ if params.get('capacity'):
+ # If 'capacity' is in the parameters a new storage volume will
+ # be created and allocated to the VM.
+ if params['vol'] == 'new_vol':
+ # Set the name of the volume as the same pattern used when
+ # creating a VM based on Template (VM UUID + disk index).
+ # Otherwise, use the name provided by the user.
+ params['vol'] = "%s-%s.img" % (dom.UUIDString(),
+ params['index'])
+ vol_info = dict(name=params['vol'],
+ type=params['type'],
+ capacity=params['capacity'],
+ allocation=params['capacity'],
+ format=params['format'],
+ )
+ storage_volumes = StorageVolumesModel(conn=self.conn,
+ objstore=self.objstore)
+ mytask = storage_volumes.create(params['pool'], vol_info)
+ self.task.wait(mytask['id'])
+
if params.get('vol'):
try:
pool = params['pool']