[PATCH][Kimchi] Avoid race condition in vm lookup
by Rodrigo Trujillo
In guest lookup, libvirt domain is instanciated and then a info()
function is called, but it is possible that the guest be removed between
these two operations, raising an exception that is not treated.
This patch fix this issue, catching the exception, logging and returning
the correct error to the request.
Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo(a)linux.vnet.ibm.com>
---
model/vms.py | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/model/vms.py b/model/vms.py
index 4f5d442..780e578 100644
--- a/model/vms.py
+++ b/model/vms.py
@@ -1272,7 +1272,15 @@ class VMModel(object):
def lookup(self, name):
dom = self.get_vm(name, self.conn)
- info = dom.info()
+ try:
+ # Avoid race condition, where guests may be deleted before below
+ # command.
+ info = dom.info()
+ except libvirt.libvirtError as e:
+ wok_log.error('Operation error while retrieving virtual machine '
+ '"%s" information: %s', name, e.message)
+ raise OperationFailed('KCHVM0009E', {'name': name,
+ 'err': e.message})
state = DOM_STATE_MAP[info[0]]
screenshot = None
# (type, listen, port, passwd, passwdValidTo)
--
2.1.0
8 years, 8 months
[PATCHv3] [Kimchi] Create Template UI adjustments including size and loading
by Socorro Stoppler
v3:
Added loading icon since at times, it takes a while for the ISOs to load
v2:
Added 'Not Available' for size to be displayed when there's no value
for size; otherwise, the container for the templates are showing up
as different sizes due to missing value for the size field. Also
moved the local/remote iso icon to bottom right corner
v1:
This is a brand new patch to implement create template UI without the user
having to distinguish between iso and image files since the original
one wasn't done quite right. Therefore, please ignore the original patch
and this is v1.
There are no longer any radio buttons, all the remote and local isos, if any,
are displayed in the same panel and are distinguished by having a 'globe' icon for
remote and a 'hdd' icon for local at the top left corner of each tile. Also,
filtering by typing in the textbox has been added.
Socorro Stoppler (1):
Create Template UI adjustments based on feedback; added Not
Available to be displayed for Size when there's no size and move
remote/local iso icon to bottom right; add loading icon
ui/css/kimchi.css | 36 ++++
ui/css/src/modules/_templates.scss | 30 +++
ui/js/src/kimchi.template_add_main.js | 342 +++++++---------------------------
ui/pages/i18n.json.tmpl | 1 +
ui/pages/template-add.html.tmpl | 88 ++-------
5 files changed, 148 insertions(+), 349 deletions(-)
--
2.5.0
8 years, 8 months
[PATCHv2] [Kimchi] Create Template UI adjustments including size
by Socorro Stoppler
v2:
Added 'Not Available' for size to be displayed when there's no value
for size; otherwise, the container for the templates are showing up
as different sizes due to missing value for the size field. Also
moved the local/remote iso icon to bottom right corner
v1:
This is a brand new patch to implement create template UI without the user
having to distinguish between iso and image files since the original
one wasn't done quite right. Therefore, please ignore the original patch
and this is v1.
There are no longer any radio buttons, all the remote and local isos, if any,
are displayed in the same panel and are distinguished by having a 'globe' icon for
remote and a 'hdd' icon for local at the top left corner of each tile. Also,
filtering by typing in the textbox has been added.
Socorro Stoppler (1):
Create Template UI adjustments based on feedback; added Not
Available to be displayed for Size when there's no size and move
remote/local iso icon to bottom right
ui/css/kimchi.css | 36 ++++
ui/css/src/modules/_templates.scss | 30 +++
ui/js/src/kimchi.template_add_main.js | 337 ++++++----------------------------
ui/pages/i18n.json.tmpl | 1 +
ui/pages/template-add.html.tmpl | 81 ++------
5 files changed, 136 insertions(+), 349 deletions(-)
--
2.5.0
8 years, 8 months
[PATCH v4] [Kimchi] Issue #920: Template is removed if an ISO doesn't exist
by Jose Ricardo Ziviani
- This commit changes the way the template update works. Now, it
really updates the existing template instead of creating a new
one (and deleting the old one)
Signed-off-by: Jose Ricardo Ziviani <joserz(a)linux.vnet.ibm.com>
---
i18n.py | 2 ++
model/templates.py | 35 ++++++++++++++++++++++-------------
tests/test_template.py | 6 +++++-
3 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/i18n.py b/i18n.py
index 7cce796..14ae166 100644
--- a/i18n.py
+++ b/i18n.py
@@ -155,6 +155,7 @@ messages = {
"KCHVMIF0011E": _("Cannot change MAC address of a running virtual machine"),
"KCHTMPL0001E": _("Template %(name)s already exists"),
+ "KCHTMPL0002E": _("Source media %(path)s not found"),
"KCHTMPL0003E": _("Network '%(network)s' specified for template %(template)s does not exist"),
"KCHTMPL0004E": _("Storage pool %(pool)s specified for template %(template)s does not exist"),
"KCHTMPL0006E": _("Invalid parameter '%(param)s' specified for CDROM."),
@@ -181,6 +182,7 @@ messages = {
"KCHTMPL0029E": _("Disk format must be 'raw', for logical, iscsi, and scsi pools."),
"KCHTMPL0030E": _("Memory expects an object with one or both parameters: 'current' and 'maxmemory'"),
"KCHTMPL0031E": _("Memory value (%(mem)sMiB) must be equal or lesser than maximum memory value (%(maxmem)sMiB)"),
+ "KCHTMPL0032E": _("Unable to update template due error: %(err)s"),
"KCHPOOL0001E": _("Storage pool %(name)s already exists"),
"KCHPOOL0002E": _("Storage pool %(name)s does not exist"),
diff --git a/model/templates.py b/model/templates.py
index a02099c..431cae0 100644
--- a/model/templates.py
+++ b/model/templates.py
@@ -72,8 +72,7 @@ class TemplatesModel(object):
# image does not exists: raise error
elif not os.path.exists(path):
- raise InvalidParameter("Unable to find file %(path)s" %
- {"path": path})
+ raise InvalidParameter("KCHTMPL0002E", {'path': path})
# create magic object to discover file type
file_type = magic.open(magic.MAGIC_NONE)
@@ -204,31 +203,30 @@ class TemplateModel(object):
raise OperationFailed('KCHTMPL0021E', {'err': e.message})
def update(self, name, params):
- old_t = self.lookup(name)
- new_t = copy.copy(old_t)
+ edit_template = self.lookup(name)
# Merge graphics settings
graph_args = params.get('graphics')
if graph_args:
- graphics = dict(new_t['graphics'])
+ graphics = dict(edit_template['graphics'])
graphics.update(graph_args)
params['graphics'] = graphics
# Merge cpu_info settings
new_cpu_info = params.get('cpu_info')
if new_cpu_info:
- cpu_info = dict(new_t['cpu_info'])
+ cpu_info = dict(edit_template['cpu_info'])
cpu_info.update(new_cpu_info)
params['cpu_info'] = cpu_info
# Fix memory values, because method update does not work recursively
new_mem = params.get('memory')
if new_mem is not None:
- params['memory'] = copy.copy(old_t.get('memory'))
+ params['memory'] = copy.copy(edit_template.get('memory'))
params['memory'].update(new_mem)
validate_memory(params['memory'])
- new_t.update(params)
+ edit_template.update(params)
for net_name in params.get(u'networks', []):
try:
@@ -238,13 +236,24 @@ class TemplateModel(object):
raise InvalidParameter("KCHTMPL0003E", {'network': net_name,
'template': name})
- self.delete(name)
try:
- ident = self.templates.save_template(new_t)
- except:
- ident = self.templates.save_template(old_t)
+ # make sure the new template will be created
+ t = LibvirtVMTemplate(edit_template, scan=True, conn=self.conn)
+ t.cpuinfo_validate()
+ t._validate_memory()
+
+ # remove the current one
+ self.delete(name)
+
+ # save the template
+ return self.templates.save_template(edit_template)
+
+ except InvalidOperation:
raise
- return ident
+ except Exception, e:
+ raise OperationFailed('KCHTMPL0032E', {'err': e.message})
+
+ return params['name']
def validate_memory(memory):
diff --git a/tests/test_template.py b/tests/test_template.py
index 158bbeb..f0ef030 100644
--- a/tests/test_template.py
+++ b/tests/test_template.py
@@ -256,7 +256,11 @@ class TemplateTests(unittest.TestCase):
self.assertEquals(1024, update_tmpl['memory']['maxmemory'])
# Update cdrom
- cdrom_data = {'cdrom': '/tmp/mock2.iso'}
+ cdrom_data = {'cdrom': 'inexistent.iso'}
+ resp = self.request(new_tmpl_uri, json.dumps(cdrom_data), 'PUT')
+ self.assertEquals(400, resp.status)
+
+ cdrom_data = {'cdrom': '/tmp/existent.iso'}
resp = self.request(new_tmpl_uri, json.dumps(cdrom_data), 'PUT')
self.assertEquals(200, resp.status)
update_tmpl = json.loads(resp.read())
--
1.9.1
8 years, 8 months
[PATCH][Kimchi] Pass disk path when template is image based
by Ramon Medeiros
UI wasn't passing path to image disk when updating it, so the backend
was losing the disk.
Signed-off-by: Ramon Medeiros <ramonn(a)linux.vnet.ibm.com>
---
ui/js/src/kimchi.template_edit_main.js | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/ui/js/src/kimchi.template_edit_main.js b/ui/js/src/kimchi.template_edit_main.js
index de72452..8b5abfb 100644
--- a/ui/js/src/kimchi.template_edit_main.js
+++ b/ui/js/src/kimchi.template_edit_main.js
@@ -20,6 +20,7 @@ kimchi.template_edit_main = function() {
var origDisks;
var origNetworks;
var templateDiskSize;
+ var baseImageTemplate;
$('#template-name', templateEditMain).val(kimchi.selectedTemplate);
$('#edit-template-tabs a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
$('.tab-content').css('overflow','hidden');
@@ -89,6 +90,7 @@ kimchi.template_edit_main = function() {
}
return false;
}
+ baseImageTemplate = isImageBasedTemplate;
enableSpice();
$('#template-edit-graphics').selectpicker();
@@ -334,7 +336,9 @@ kimchi.template_edit_main = function() {
var data = {};
var disks = $('.template-tab-body .item', '#form-template-storage');
var disksForUpdate = new Array();
+
$.each(disks, function(index, diskEntity) {
+
var newDisk = {
'index' : index,
'pool' : {'name': '/plugins/kimchi/storagepools/' + $(diskEntity).find('.template-storage-name').val()},
@@ -342,6 +346,11 @@ kimchi.template_edit_main = function() {
'format' : $(diskEntity).find('.template-storage-disk-format').val()
};
+ // image based template: add base to dictionary
+ if ((baseImageTemplate()) && (index == 0)) {
+ newDisk["base"] = $('#template-edit-vmimage-textbox').val();
+ }
+
var storageType = $(diskEntity).find('.template-storage-type').val();
if(storageType === 'iscsi' || storageType === 'scsi') {
newDisk['volume'] = newDisk['pool']['name'].split('/').pop();
--
2.5.5
8 years, 8 months
[PATCH] [Kimchi 0/2] Add support for editing virtual networks
by Lucio Correia
Lucio Correia (2):
Add backend support for editing virtual networks
Add network rename tests
API.json | 31 ++++++++++++++++++++++++++++
control/networks.py | 1 +
docs/API.md | 8 ++++++++
i18n.py | 9 +++++---
model/networks.py | 50 ++++++++++++++++++++++++++++++++++++++++++++-
tests/test_model_network.py | 13 +++++++++++-
6 files changed, 107 insertions(+), 5 deletions(-)
--
1.9.1
8 years, 8 months
[PATCH V4] [Kimchi 0/2] Issue #817 - PCI attach/detach improvements.
by pvital@linux.vnet.ibm.com
From: Paulo Vital <pvital(a)linux.vnet.ibm.com>
V4:
* Removed Libvirt events implementation.
V3:
* Fixed copyright line of new files.
V2:
This is the backend part of the solution to Issue #817. In this solution the
support for handle Libvirt events is added, as well, the attach and detach
functions were modified to return AsyncTasks (then frontend can be informed
when a device is really attached/detached).
Patch "Add support to Libvirt Events." is the third version of previous
submitted patch.
Patch "Make detach device return an AsyncTask" needs submitted Wok patch
"Update AsyncResource class with delete method." to work.
Paulo Vital (2):
Make attach device return an AsyncTask
Make detach device return an AsyncTask
control/vm/hostdevs.py | 6 +--
model/vmhostdevs.py | 103 +++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 89 insertions(+), 20 deletions(-)
--
2.5.5
8 years, 8 months
[PATCH] [Kimchi] Create Template UI adjustments based on feedback
by Socorro Stoppler
This is a brand new patch to implement create template UI without the user
having to distinguish between iso and image files since the original
one wasn't done quite right. Therefore, please ignore the original patch
and this is v1.
There are no longer any radio buttons, all the remote and local isos, if any,
are displayed in the same panel and are distinguished by having a 'globe' icon for
remote and a 'hdd' icon for local at the top left corner of each tile. Also,
filtering by typing in the textbox has been added.
Socorro Stoppler (1):
Create Template UI adjustments based on feedback
ui/css/kimchi.css | 29 +++
ui/css/src/modules/_templates.scss | 24 +++
ui/js/src/kimchi.template_add_main.js | 334 ++++++----------------------------
ui/pages/template-add.html.tmpl | 80 +-------
4 files changed, 118 insertions(+), 349 deletions(-)
--
2.5.0
8 years, 8 months
[PATCH v3] [Kimchi] Replace backing image by clone when using template based on existing img
by Jose Ricardo Ziviani
- This commit replaces the current backing image to a complete clone
when using a template based on an existing template.
Signed-off-by: Jose Ricardo Ziviani <joserz(a)linux.vnet.ibm.com>
---
model/templates.py | 26 +++++++++++++++++++++++++-
tests/test_rest.py | 19 +++++++++++++++----
vmtemplate.py | 8 --------
3 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/model/templates.py b/model/templates.py
index a02099c..1cdb99b 100644
--- a/model/templates.py
+++ b/model/templates.py
@@ -23,6 +23,7 @@ import magic
import os
import platform
import psutil
+import shutil
import stat
import urlparse
@@ -378,7 +379,30 @@ class LibvirtVMTemplate(VMTemplate):
for v in vol_list:
pool = self._get_storage_pool(v['pool'])
# outgoing text to libvirt, encode('utf-8')
- pool.createXML(v['xml'].encode('utf-8'), 0)
+ if 'base' in v and 'path' in v['base']:
+ conn = self.conn.get()
+ try:
+ volume_base = conn.storageVolLookupByPath(
+ v['base']['path'])
+
+ except libvirt.libvirtError as e:
+ image_dir = os.path.dirname(v['base']['path'])
+ image_name = os.path.basename(v['base']['path'])
+ volume_dir = os.path.dirname(v['path'])
+
+ if image_dir != volume_dir:
+ shutil.copy(v['base']['path'], volume_dir)
+
+ pool.refresh()
+
+ volume_base = pool.storageVolLookupByName(image_name)
+
+ pool.createXMLFrom(v['xml'].encode('utf-8'),
+ volume_base,
+ 0)
+ else:
+ pool.createXML(v['xml'].encode('utf-8'), 0)
+
except libvirt.libvirtError as e:
raise OperationFailed("KCHVMSTOR0008E", {'error': e.message})
return vol_list
diff --git a/tests/test_rest.py b/tests/test_rest.py
index a009ed3..997611e 100644
--- a/tests/test_rest.py
+++ b/tests/test_rest.py
@@ -1030,9 +1030,13 @@ class RestTests(unittest.TestCase):
self.assertIn(u"KCHVM0012E", resp['reason'])
def test_create_vm_with_img_based_template(self):
+ self._create_pool('pool-imgbs')
+ self.request('/plugins/kimchi/storagepools/pool-imgbs/activate', '{}',
+ 'POST')
+
resp = json.loads(
self.request(
- '/plugins/kimchi/storagepools/default-pool/storagevolumes'
+ '/plugins/kimchi/storagepools/pool-imgbs/storagevolumes'
).read()
)
self.assertEquals(0, len(resp))
@@ -1040,8 +1044,15 @@ class RestTests(unittest.TestCase):
# Create a Template
mock_base = '/tmp/mock.img'
os.system("qemu-img create -f qcow2 %s 10M" % mock_base)
- req = json.dumps({'name': 'test', 'source_media': mock_base})
- resp = self.request('/plugins/kimchi/templates', req, 'POST')
+
+ tmpl_params = {
+ 'name': 'test', 'source_media': mock_base,
+ 'disks': [{'pool':
+ {'name': '/plugins/kimchi/storagepools/pool-imgbs'}}]}
+
+ resp = self.request('/plugins/kimchi/templates',
+ json.dumps(tmpl_params),
+ 'POST')
self.assertEquals(201, resp.status)
req = json.dumps({'template': '/plugins/kimchi/templates/test'})
@@ -1053,7 +1064,7 @@ class RestTests(unittest.TestCase):
# Test storage volume created with backing store of base file
resp = json.loads(
self.request(
- '/plugins/kimchi/storagepools/default-pool/storagevolumes'
+ '/plugins/kimchi/storagepools/pool-imgbs/storagevolumes'
).read()
)
self.assertEquals(1, len(resp))
diff --git a/vmtemplate.py b/vmtemplate.py
index a223beb..4ce5d19 100644
--- a/vmtemplate.py
+++ b/vmtemplate.py
@@ -264,14 +264,6 @@ class VMTemplate(object):
v_tree.append(E.capacity(str(info['capacity']), unit='G'))
target_fmt = info['format']
- if 'base' in d:
- # target must be qcow2 in order to use a backing file
- target_fmt = 'qcow2'
-
- v_tree.append(E.backingStore(
- E.path(info['base']['path']),
- E.format(type=info['base']['format'])))
-
target = E.target(
E.format(type=target_fmt), E.path(info['path']))
v_tree.append(target)
--
1.9.1
8 years, 8 months
[PATCH] [Kimchi 0/3] Issue #924: Avoid deleting storage pool in
by Jose Ricardo Ziviani
This patchset disable buttons to remove and deactivate storagepools that
are currently in use by any template.
Jose Ricardo Ziviani (3):
Issue #924: Add field to inform front-end if storage is in use
Issue #924: Disable deactivate/delete buttons if storage is in use
Issue #924: Update test case with new storage pool field
control/storagepools.py | 3 ++-
model/storagepools.py | 3 ++-
tests/test_model_storagepool.py | 2 +-
ui/js/src/kimchi.storage_main.js | 13 +++++++++----
ui/pages/tabs/storage.html.tmpl | 6 +++---
5 files changed, 17 insertions(+), 10 deletions(-)
--
1.9.1
8 years, 8 months