[PATCH] [Wok 1/3] Add option to get Wok message text without code
by Lucio Correia
Signed-off-by: Lucio Correia <luciojhc(a)linux.vnet.ibm.com>
---
src/wok/message.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/wok/message.py b/src/wok/message.py
index a3794d0..a7162c7 100644
--- a/src/wok/message.py
+++ b/src/wok/message.py
@@ -78,7 +78,11 @@ class WokMessage(object):
return translation.gettext(text)
- def get_text(self):
+ def get_text(self, prepend_code=True):
msg = self._get_translation()
msg = unicode(msg, 'utf-8') % self.args
- return "%s: %s" % (self.code, msg)
+
+ if prepend_code:
+ return "%s: %s" % (self.code, msg)
+
+ return msg
--
1.9.1
8 years, 7 months
[PATCH] [Wok 0/3] Add translation support to user log
by Lucio Correia
Lucio Correia (3):
Add option to get Wok message text without code
Add support and translate user request log messages
Use past verbs
src/wok/control/base.py | 17 ++++++++++++-----
src/wok/i18n.py | 6 ++++++
src/wok/message.py | 8 ++++++--
src/wok/root.py | 13 +++++++++----
4 files changed, 33 insertions(+), 11 deletions(-)
--
1.9.1
8 years, 7 months
[PATCH v2] [Kimchi] Check if qemu/libvirt user has permission to use the image
by Jose Ricardo Ziviani
- Based on this check this patch returns a new field to the
interface be able to disable such ISO before creating any
templates with it.
Signed-off-by: Jose Ricardo Ziviani <joserz(a)linux.vnet.ibm.com>
---
v2:
- check permission is now generic for any image
control/storagevolumes.py | 3 ++-
docs/API.md | 2 ++
mockmodel.py | 6 ++++--
model/storagevolumes.py | 10 ++++++++--
tests/test_model_storagevolume.py | 2 +-
tests/test_rest.py | 1 +
6 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/control/storagevolumes.py b/control/storagevolumes.py
index a04ad35..e7f5b54 100644
--- a/control/storagevolumes.py
+++ b/control/storagevolumes.py
@@ -83,7 +83,8 @@ class StorageVolume(Resource):
'path': self.info['path'],
'used_by': self.info['used_by'],
'format': self.info['format'],
- 'isvalid': self.info['isvalid']}
+ 'isvalid': self.info['isvalid'],
+ 'has_permission': self.info['has_permission']}
for key in ('os_version', 'os_distro', 'bootable', 'base'):
val = self.info.get(key)
diff --git a/docs/API.md b/docs/API.md
index 6d502a9..83f9d38 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -614,6 +614,8 @@ A interface represents available network interface on VM.
* bootable *(optional)*: True if iso image is bootable and not corrupted.
* used_by: Name of vms which use this volume.
* isvalid: True if is a valid volume.
+ * has_permission: qemu/libvirt user has the right permission to
+ to use the image
* **DELETE**: Remove the Storage Volume
* **POST**: *See Storage Volume Actions*
diff --git a/mockmodel.py b/mockmodel.py
index 142e81f..38d08b5 100644
--- a/mockmodel.py
+++ b/mockmodel.py
@@ -476,14 +476,16 @@ class MockStorageVolumes(object):
'type': 'block',
'path': base_path + '1',
'used_by': [],
- 'isvalid': True},
+ 'isvalid': True,
+ 'has_permission': True},
'unit:0:0:2': {'capacity': 2048,
'format': 'unknown',
'allocation': 512,
'type': 'block',
'path': base_path + '2',
'used_by': [],
- 'isvalid': True}}
+ 'isvalid': True,
+ 'has_permission': True}}
class MockVolumeGroups(object):
diff --git a/model/storagevolumes.py b/model/storagevolumes.py
index e037e35..da42e85 100644
--- a/model/storagevolumes.py
+++ b/model/storagevolumes.py
@@ -30,12 +30,14 @@ from lxml.builder import E
from wok.exception import InvalidOperation, InvalidParameter, IsoFormatError
from wok.exception import MissingParameter, NotFoundError, OperationFailed
-from wok.utils import add_task, get_unique_file_name, wok_log
+from wok.utils import add_task, get_unique_file_name
+from wok.utils import probe_file_permission_as_user, wok_log
from wok.xmlutils.utils import xpath_get_text
from wok.model.tasks import TaskModel
from wok.plugins.kimchi.config import READONLY_POOL_TYPE
from wok.plugins.kimchi.isoinfo import IsoImage
+from wok.plugins.kimchi.kvmusertests import UserTests
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.storagepools import StoragePoolModel
@@ -273,6 +275,7 @@ class StorageVolumeModel(object):
self.task = TaskModel(**kargs)
self.storagevolumes = StorageVolumesModel(**kargs)
self.storagepool = StoragePoolModel(**kargs)
+ self.libvirt_user = UserTests().probe_user()
@staticmethod
def get_storagevolume(poolname, name, conn):
@@ -329,13 +332,15 @@ class StorageVolumeModel(object):
isvalid = False
used_by = get_disk_used_by(self.objstore, self.conn, path)
+ ret, _ = probe_file_permission_as_user(path, self.libvirt_user)
res = dict(type=VOLUME_TYPE_MAP[info[0]],
capacity=info[1],
allocation=info[2],
path=path,
used_by=used_by,
format=fmt,
- isvalid=isvalid)
+ isvalid=isvalid,
+ has_permission=ret)
if fmt == 'iso':
if os.path.islink(path):
path = os.path.join(os.path.dirname(path), os.readlink(path))
@@ -347,6 +352,7 @@ class StorageVolumeModel(object):
bootable = True
except IsoFormatError:
bootable = False
+
res.update(
dict(os_distro=os_distro, os_version=os_version, path=path,
bootable=bootable))
diff --git a/tests/test_model_storagevolume.py b/tests/test_model_storagevolume.py
index 7dbda97..56dda8f 100644
--- a/tests/test_model_storagevolume.py
+++ b/tests/test_model_storagevolume.py
@@ -258,7 +258,7 @@ class StorageVolumeTests(unittest.TestCase):
self.assertEquals(200, resp.status)
keys = [u'name', u'type', u'capacity', u'allocation', u'path',
- u'used_by', u'format', u'isvalid']
+ u'used_by', u'format', u'isvalid', u'has_permission']
for vol in json.loads(resp.read()):
resp = self.request(uri + '/' + vol['name'])
self.assertEquals(200, resp.status)
diff --git a/tests/test_rest.py b/tests/test_rest.py
index c1294ee..cae196e 100644
--- a/tests/test_rest.py
+++ b/tests/test_rest.py
@@ -1174,6 +1174,7 @@ class RestTests(unittest.TestCase):
self.assertEquals('17', storagevolume['os_version'])
self.assertEquals('fedora', storagevolume['os_distro'])
self.assertEquals(True, storagevolume['bootable'])
+ self.assertEquals(True, storagevolume['has_permission'])
# Create a template
# In real model os distro/version can be omitted
--
2.7.4
8 years, 7 months
[PATCH][Kimchi 1/2] Implements support to memory hotplug in non-NUMA guests
by Rodrigo Trujillo
This patch makes necessary changes in Kimchi guest update to support
memory hotplug operations in non-numa guests, due to latest Libvirt
changes.
---
model/utils.py | 18 ++++++++++++++++++
model/vms.py | 53 +++++++++++++++++------------------------------------
2 files changed, 35 insertions(+), 36 deletions(-)
diff --git a/model/utils.py b/model/utils.py
index b7ea82e..da62971 100644
--- a/model/utils.py
+++ b/model/utils.py
@@ -129,3 +129,21 @@ def metadata_exists(dom):
if root.find("metadata") is None:
return False
return True
+
+
+def has_cpu_numa(dom):
+ """
+ Verify if domain has NUMA configuration
+ Returns: True or False
+ """
+ root = etree.fromstring(dom.XMLDesc(0))
+ return (root.find('./cpu/numa') is not None)
+
+
+def set_numa_memory(mem, root):
+ """
+ Set new NUMA memory value
+ Returns: etree element updated
+ """
+ root.find('./cpu/numa/cell').set('memory', str(mem))
+ return root
diff --git a/model/vms.py b/model/vms.py
index cf40ad1..f88cfdb 100644
--- a/model/vms.py
+++ b/model/vms.py
@@ -61,9 +61,9 @@ from wok.plugins.kimchi.model.utils import set_metadata_node
from wok.plugins.kimchi.screenshot import VMScreenshot
from wok.plugins.kimchi.utils import get_next_clone_name
from wok.plugins.kimchi.utils import template_name_from_uri
-from wok.plugins.kimchi.xmlutils.cpu import get_cpu_xml, get_numa_xml
from wok.plugins.kimchi.xmlutils.cpu import get_topology_xml
from wok.plugins.kimchi.xmlutils.disk import get_vm_disk_info, get_vm_disks
+from utils import has_cpu_numa, set_numa_memory
DOM_STATE_MAP = {0: 'nostate',
@@ -769,10 +769,10 @@ class VMModel(object):
# topology is being undefined: remove it
new_xml = xml_item_remove(new_xml, XPATH_TOPOLOGY)
- # Updating memory and NUMA if necessary, if vm is offline
+ # Updating memory if vm is offline
if (not dom.isActive() and 'memory' in params and
params['memory'] != {}):
- new_xml = self._update_memory_config(new_xml, params)
+ new_xml = self._update_memory_config(new_xml, params, dom)
if 'graphics' in params:
new_xml = self._update_graphics(dom, new_xml, params)
@@ -810,7 +810,7 @@ class VMModel(object):
vm_name = name
return (nonascii_name if nonascii_name is not None else vm_name, dom)
- def _update_memory_config(self, xml, params):
+ def _update_memory_config(self, xml, params, dom):
# Cannot pass max memory if there is not support to memory hotplug
# Then set max memory as memory, just to continue with the update
if not self.caps.mem_hotplug_support:
@@ -905,16 +905,18 @@ class VMModel(object):
root.remove(currentMem)
memory = root.find('.memory')
- # If host/guest does not support memory hot plug, then there is
- # NUMA configure, we must update the tag directly
- if not self.caps.mem_hotplug_support:
- if memory is not None:
- memory.text = str(newMem)
- else:
+ # Set NUMA parameterers if necessary. NUMA is not required for CPU
+ # and Memory hotplug anymore
+ if has_cpu_numa(dom):
if memory is not None:
# Libvirt is going to set the value automatically with
# the value configured in NUMA tag
root.remove(memory)
+ root = set_numa_memory(newMem, root)
+ else:
+ # update the memory tag directly
+ if memory is not None:
+ memory.text = str(newMem)
if (maxMemTag is not None) and (not hasMaxMem):
if newMem == newMaxMem:
@@ -922,22 +924,6 @@ class VMModel(object):
else:
maxMemTag.set('slots', str(_get_slots(newMem, newMaxMem)))
- # Set NUMA parameterers and create it if does not exist
- # CPU tag DO NOT exist? Create it
- cpu = root.find(XPATH_CPU)
- if cpu is None:
- cpu = get_cpu_xml(0, newMem)
- root.insert(0, ET.fromstring(cpu))
- else:
- # Does NUMA tag exist ?
- numaTag = cpu.find('./numa')
- if numaTag is None:
- numa_element = get_numa_xml(0, newMem)
- cpu.insert(0, ET.fromstring(numa_element))
- else:
- cellTag = cpu.find('./numa/cell')
- cellTag.set('memory', str(newMem))
-
# Setting memory hard limit to max_memory + 1GiB
memtune = root.find('memtune')
if memtune is not None:
@@ -990,12 +976,9 @@ class VMModel(object):
if not self.caps.mem_hotplug_support:
raise InvalidOperation("KCHVM0046E")
- # Check if the vm xml supports memory hotplug, if not, static update
- # must be done firstly, then Kimchi is going to update the xml
xml = dom.XMLDesc(0)
- numa_mem = xpath_get_text(xml, XPATH_NUMA_CELL + '/@memory')
max_mem = xpath_get_text(xml, './maxMemory')
- if numa_mem == [] or max_mem == []:
+ if max_mem == []:
raise OperationFailed('KCHVM0042E', {'name': dom.name()})
# Memory live update must be done in chunks of 1024 Mib or 1Gib
@@ -1038,12 +1021,10 @@ class VMModel(object):
# Hot add given number of memory devices in the guest
flags = libvirt.VIR_DOMAIN_MEM_CONFIG | libvirt.VIR_DOMAIN_MEM_LIVE
# Create memory device xml
- mem_dev_xml = etree.tostring(
- E.memory(
- E.target(
- E.size('1', unit='GiB'),
- E.node('0')),
- model='dimm'))
+ tmp_xml = E.memory(E.target(E.size('1', unit='GiB')), model='dimm')
+ if has_cpu_numa(dom):
+ tmp_xml.find('target').append(E.node('0'))
+ mem_dev_xml = etree.tostring(tmp_xml)
# Add chunks of 1G of memory
for i in range(amount):
dom.attachDeviceFlags(mem_dev_xml, flags)
--
2.1.0
8 years, 7 months
[PATCH v2] [Kimchi 0/2] Filtering VEPA interfaces
by dhbarboza82@gmail.com
From: Daniel Henrique Barboza <dhbarboza82(a)gmail.com>
v2:
- fixed issue found by Aline
This patch set filters the VEPA interfaces to be used
in network creation by eliminating the ConnectX-4
cards.
Unit tests, docs and UI changes included.
Daniel Henrique Barboza (2):
Filter VEPA interfaces: adding 'module' to interfaces API
Filter VEPA interfaces: JS changes
control/interfaces.py | 3 ++-
docs/API.md | 2 ++
tests/test_rest.py | 2 +-
ui/js/src/kimchi.api.js | 14 ++++++++++++++
ui/js/src/kimchi.network_add_main.js | 12 ++++++++++--
5 files changed, 29 insertions(+), 4 deletions(-)
--
2.5.5
8 years, 7 months
[PATCH][Kimchi] Fix memory return in vm with memory devices hotplugged
by Rodrigo Trujillo
Libvirt is updating 'currentmemory' and 'memory' if its values are
equal, when user attaches a memory device. So, we can use the function
maxMemory() of Libvirt API to retrieve the value of memory.
Kimchi does not use currentMemory tag, but once it is the amount seen
inside a running guest, if it was changed outside kimchi, we must
sum the memory devices values (if any) to have the right value seen
inside guest.
Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo(a)linux.vnet.ibm.com>
---
model/vms.py | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/model/vms.py b/model/vms.py
index 7bf4c77..2374d31 100644
--- a/model/vms.py
+++ b/model/vms.py
@@ -1210,24 +1210,21 @@ class VMModel(object):
'threads': threads,
}
- if state == 'shutoff':
- val = xpath_get_text(xml, XPATH_DOMAIN_MEMORY)[0]
- unit_list = xpath_get_text(xml, XPATH_DOMAIN_MEMORY_UNIT)
- if len(unit_list) > 0:
- unit = unit_list[0]
- else:
- unit = 'KiB'
- memory = convert_data_size(val, unit, 'MiB')
- else:
- # Return current memory plus the amount of memory given by memory
- # devices
+ # Kimchi does not make use of 'currentMemory' tag, it only updates
+ # NUMA memory config or 'memory' tag directly. In memory hotplug,
+ # Libvirt always updates 'memory', so we can use this tag retrieving
+ # from Libvirt API maxMemory() function, regardeless of the VM state
+ # Case VM changed currentMemory outside Kimchi, sum mem devs
+ memory = dom.maxMemory() >> 10
+ curr_mem = (info[2] >> 10)
+ if memory != curr_mem:
root = ET.fromstring(xml)
totMemDevs = 0
for size in root.findall('./devices/memory/target/size'):
totMemDevs += convert_data_size(size.text,
size.get('unit'),
'MiB')
- memory = (info[2] >> 10) + totMemDevs
+ memory = curr_mem + totMemDevs
# assure there is no zombie process left
for proc in self._serial_procs[:]:
--
2.1.0
8 years, 7 months
[PATCH][Kimchi] Does not use slot in memory device removal
by Rodrigo Trujillo
Latest Libvirt version changed, and does not add anymore automatically
address/slots for memory devices hotplugged. Kimchi tries to remove
memory devices by theirs slot number, when virtual machine is offline,
and if it has memory devices configured.
This behavior will raise an error, so this patch fix this problem.
Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo(a)linux.vnet.ibm.com>
---
model/vms.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/model/vms.py b/model/vms.py
index b617b1d..7bf4c77 100644
--- a/model/vms.py
+++ b/model/vms.py
@@ -846,9 +846,9 @@ class VMModel(object):
newMem = newMem - (len(memDevs) * (1024 << 10))
elif newMem < (oldMem << 10):
devsRemove = len(memDevs) - (oldMem - (newMem >> 10))/1024 - 1
- for dev in memDevs:
- if int(dev.xpath('./address/@slot')[0]) > devsRemove:
- root.find('./devices').remove(dev)
+ for dev in enumerate(memDevs):
+ if dev[0] > devsRemove:
+ root.find('./devices').remove(dev[1])
newMem = \
newMem - (
len(root.findall('./devices/memory')) * 1024 << 10
--
2.1.0
8 years, 7 months
[PATCH] [Kimchi] Check if qemu/libvirt user has permission to use an ISO
by Jose Ricardo Ziviani
- Based on this check this patch returns a new field to the
interface be able to disable such ISO before creating any
templates with it.
Signed-off-by: Jose Ricardo Ziviani <joserz(a)linux.vnet.ibm.com>
---
control/storagevolumes.py | 3 +++
docs/API.md | 2 ++
model/storagevolumes.py | 9 +++++++--
tests/test_model_storagevolume.py | 3 ++-
tests/test_rest.py | 1 +
5 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/control/storagevolumes.py b/control/storagevolumes.py
index a04ad35..08cd989 100644
--- a/control/storagevolumes.py
+++ b/control/storagevolumes.py
@@ -90,6 +90,9 @@ class StorageVolume(Resource):
if val:
res[key] = val
+ if self.info['format'] == 'iso':
+ res['has_permission'] = self.info.get('has_permission', False)
+
return res
diff --git a/docs/API.md b/docs/API.md
index 9d42c53..6afa6e4 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -613,6 +613,8 @@ A interface represents available network interface on VM.
* bootable *(optional)*: True if iso image is bootable and not corrupted.
* used_by: Name of vms which use this volume.
* isvalid: True if is a valid volume.
+ * has_permission *(optional)*: qemu/libvirt user has the right permission to
+ to use the image
* **DELETE**: Remove the Storage Volume
* **POST**: *See Storage Volume Actions*
diff --git a/model/storagevolumes.py b/model/storagevolumes.py
index e037e35..9d4ac43 100644
--- a/model/storagevolumes.py
+++ b/model/storagevolumes.py
@@ -30,12 +30,14 @@ from lxml.builder import E
from wok.exception import InvalidOperation, InvalidParameter, IsoFormatError
from wok.exception import MissingParameter, NotFoundError, OperationFailed
-from wok.utils import add_task, get_unique_file_name, wok_log
+from wok.utils import add_task, get_unique_file_name
+from wok.utils import probe_file_permission_as_user, wok_log
from wok.xmlutils.utils import xpath_get_text
from wok.model.tasks import TaskModel
from wok.plugins.kimchi.config import READONLY_POOL_TYPE
from wok.plugins.kimchi.isoinfo import IsoImage
+from wok.plugins.kimchi.kvmusertests import UserTests
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.storagepools import StoragePoolModel
@@ -347,9 +349,12 @@ class StorageVolumeModel(object):
bootable = True
except IsoFormatError:
bootable = False
+
+ user = UserTests().probe_user()
+ ret, _ = probe_file_permission_as_user(path, user)
res.update(
dict(os_distro=os_distro, os_version=os_version, path=path,
- bootable=bootable))
+ bootable=bootable, has_permission=ret))
return res
def wipe(self, pool, name):
diff --git a/tests/test_model_storagevolume.py b/tests/test_model_storagevolume.py
index 7dbda97..bb7758f 100644
--- a/tests/test_model_storagevolume.py
+++ b/tests/test_model_storagevolume.py
@@ -266,7 +266,8 @@ class StorageVolumeTests(unittest.TestCase):
all_keys = keys[:]
vol_info = json.loads(resp.read())
if vol_info['format'] == 'iso':
- all_keys.extend([u'os_distro', u'os_version', u'bootable'])
+ all_keys.extend([u'os_distro', u'os_version', u'bootable',
+ u'has_permission'])
self.assertEquals(sorted(all_keys), sorted(vol_info.keys()))
diff --git a/tests/test_rest.py b/tests/test_rest.py
index b73d16c..516a38b 100644
--- a/tests/test_rest.py
+++ b/tests/test_rest.py
@@ -1174,6 +1174,7 @@ class RestTests(unittest.TestCase):
self.assertEquals('17', storagevolume['os_version'])
self.assertEquals('fedora', storagevolume['os_distro'])
self.assertEquals(True, storagevolume['bootable'])
+ self.assertEquals(True, storagevolume['has_permission'])
# Create a template
# In real model os distro/version can be omitted
--
2.7.4
8 years, 7 months
[PATCH] [Kimchi] Depends on Fixed "Add Template" modal window alignment patch; add loading/creating
by Socorro Stoppler
This patch address the suggestions made by Aline in previous review:
- Add a loader icon until get all the information to display the ISOs (as Ramon also suggested)
- When selecting "Create" button, it may take some time, specially when using an local Image file, so once user selects it, disable the button and change its label to "Creating..."
like it was before. When you receive the server response, display the error or close the dialog on success.
- Move the filter input box to the same line of select "All" check box. (Addressed by Samuel's patch - Fixed "Add Template" modal window alignment patch)
Socorro Stoppler (1):
Added loading icon and 'Creating' for create template
ui/js/src/kimchi.template_add_main.js | 25 +++++++++++++++++++------
ui/pages/template-add.html.tmpl | 16 ++++++++--------
2 files changed, 27 insertions(+), 14 deletions(-)
--
2.5.0
8 years, 7 months