[PATCH v2] [Kimchi] Issue #921: Peers button disappears
by sguimaraes943@gmail.com
From: Samuel Guimarães <sguimaraes943(a)gmail.com>
This patch moves peers list from the drop-down on the top navigation bar to a DataTable that will be rendered on Host Dashboard if the user has Gingerbased installed.
Samuel Guimarães (1):
Issue #921: Peers button disappears
root.py | 6 ++
ui/js/kimchi.peers.js | 145 ++++++++++++++++++++++++++++++++++++++++++++++++
ui/js/src/kimchi.api.js | 14 -----
ui/pages/i18n.json.tmpl | 4 +-
4 files changed, 154 insertions(+), 15 deletions(-)
create mode 100644 ui/js/kimchi.peers.js
--
2.5.5
8 years
[PATCH] [Kimchi 0/2] Kimchi Issues #606 and #939
by sguimaraes943@gmail.com
From: Samuel Guimarães <sguimaraes943(a)gmail.com>
-Issue #939 requires patch "Minor fixes in form fields" applied in Wok
-Issue #606 requires patch "Icons for Kimchi issue #606" applied in Wok
Samuel Guimarães (2):
Issue #939: [UI] Guest tab is not rendered correctly if guests are not
in 'running' or ''shutoff' state
Issue #606: Change icon to distinguish image generated template and
iso generated template
ui/css/kimchi.css | 169 +++++++++++---------
ui/css/src/modules/_guests.scss | 147 ++++++++++--------
ui/css/src/modules/_iso-list.scss | 2 +-
ui/css/src/modules/_templates.scss | 62 +++++---
ui/js/src/kimchi.template_add_main.js | 5 +
ui/js/src/kimchi.template_edit_main.js | 206 +++++++++++++------------
ui/pages/guest.html.tmpl | 6 +-
ui/pages/template-add.html.tmpl | 2 +-
ui/pages/template-edit.html.tmpl | 272 +++++++++++++++++----------------
9 files changed, 485 insertions(+), 386 deletions(-)
--
2.5.5
8 years
[PATCH v2] [Wok] Removing Kimchi Peers dropdown from Wok navbar
by sguimaraes943@gmail.com
From: Samuel Guimarães <sguimaraes943(a)gmail.com>
This patch moves peers list from the drop-down on the top navigation bar to a DataTable that will be rendered on Host Dashboard if the user has Gingerbased installed. Additional patches are necessary (Kimchi and Gingerbase).
Samuel Guimarães (1):
Removing Kimchi Peers dropdown from Wok navbar
ui/js/src/wok.main.js | 29 +----------------------------
1 file changed, 1 insertion(+), 28 deletions(-)
--
2.5.5
8 years
[PATCH 0/2] [Wok] Minor fixes in form fields
by sguimaraes943@gmail.com
From: Samuel Guimarães <sguimaraes943(a)gmail.com>
Patches required for issues #606 and #939
Samuel Guimarães (2):
Minor fixes in form fields
Icons for Kimchi issue #606
ui/css/src/modules/_wok-forms.scss | 11 +++
ui/css/wok.css | 11 +++
ui/images/theme-default/file-o-img.svg | 149 +++++++++++++++++++++++++++++++++
ui/images/theme-default/file-o-iso.svg | 149 +++++++++++++++++++++++++++++++++
4 files changed, 320 insertions(+)
create mode 100644 ui/images/theme-default/file-o-img.svg
create mode 100644 ui/images/theme-default/file-o-iso.svg
--
2.5.5
8 years
[PATCH] [Kimchi] /plugins/kimchi/ovsbridges API
by sureshab@linux.vnet.ibm.com
From: Suresh Babu Angadi <sureshab(a)in.ibm.com>
As Per RFC:
[Kimchi-devel] [RFC] listing of ovs bridges
this patch adds new API /plugins/kimchi/ovsbridges
to list ovsbridges
Signed-off-by: Suresh Babu Angadi <sureshab(a)in.ibm.com>
---
control/ovsbridges.py | 29 +++++++++++++++++++++++++++++
docs/API.md | 8 ++++++++
model/ovsbridges.py | 31 +++++++++++++++++++++++++++++++
3 files changed, 68 insertions(+)
create mode 100644 control/ovsbridges.py
create mode 100644 model/ovsbridges.py
diff --git a/control/ovsbridges.py b/control/ovsbridges.py
new file mode 100644
index 0000000..974e954
--- /dev/null
+++ b/control/ovsbridges.py
@@ -0,0 +1,29 @@
+#
+# Project Kimchi
+#
+# Copyright IBM Corp, 2016
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+from wok.control.base import SimpleCollection
+from wok.control.utils import UrlSubNode
+
+
+@UrlSubNode("ovsbridges", True)
+class OVSBridges(SimpleCollection):
+ def __init__(self, model):
+ super(OVSBridges, self).__init__(model)
+ self.role_key = 'ovsbridges'
+ self.admin_methods = ['GET']
diff --git a/docs/API.md b/docs/API.md
index 7bd677f..49540b9 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -1028,3 +1028,11 @@ List of available groups.
* **GET**: Return the list of Kimchi peers in the same network
(It uses openSLP for discovering)
+
+### Simple Collection: OVSBridges
+
+**URI:** /plugins/kimchi/ovsbridges
+
+**Methods:**
+
+* **GET**: Return list of OVS bridges of the host.
diff --git a/model/ovsbridges.py b/model/ovsbridges.py
new file mode 100644
index 0000000..212520f
--- /dev/null
+++ b/model/ovsbridges.py
@@ -0,0 +1,31 @@
+#
+# Project Kimchi
+#
+# Copyright IBM Corp, 2016
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+from wok.plugins.gingerbase.netinfo import ovs_bridges
+
+
+class OVSBridgesModel(object):
+
+ def get_list(self):
+ """
+
+ Returns: list of ovs bridge names
+
+ """
+ return ovs_bridges()
--
1.8.3.1
8 years
[PATCH V2] Issue #992 : Create template on s390x without libvirt storage
by harshalp@linux.vnet.ibm.com
From: Harshal Patil <harshalp(a)linux.vnet.ibm.com>
V1:
This patch adds support for creating templates on s390x arch
without using libvirt related storage calls
V2:
Review comments
Signed-off-by: Harshal Patil <harshalp(a)linux.vnet.ibm.com>
---
docs/API.md | 2 +
i18n.py | 3 ++
model/storagepools.py | 17 ++++++--
model/storagevolumes.py | 1 -
model/templates.py | 27 +++++++++----
model/vms.py | 9 ++++-
osinfo.py | 47 ++++++++++++++++++++--
utils.py | 34 ++++++++++++++++
vmtemplate.py | 105 ++++++++++++++++++++++++++++++------------------
9 files changed, 189 insertions(+), 56 deletions(-)
diff --git a/docs/API.md b/docs/API.md
index 7bd677f..d8d191a 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -427,6 +427,7 @@ A interface represents available network interface on VM.
over current will be used exclusively for memory hotplug
* cdrom: A volume name or URI to an ISO image
* storagepool: URI of the storagepool where template allocates vm storage.
+ * path : Storage path to store virtual disks without libvirt
* networks *(optional)*: list of networks will be assigned to the new VM.
* disks: An array of requested disks with the following optional fields
(either *size* or *volume* must be specified):
@@ -481,6 +482,7 @@ A interface represents available network interface on VM.
* format: Format of the image. Valid formats: qcow, qcow2, qed, raw, vmdk, vpc.
* pool: Storage pool information
* name: URI of the storagepool where template allocates vm disk.
+ * path (optional): Either pool or path to store the virtual disks should be specified
* graphics *(optional)*: A dict of graphics paramenters of this template
* type: The type of graphics. It can be VNC or spice or None.
* vnc: Graphical display using the Virtual Network
diff --git a/i18n.py b/i18n.py
index ea2c4ab..7e60079 100644
--- a/i18n.py
+++ b/i18n.py
@@ -190,6 +190,9 @@ messages = {
"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"),
"KCHTMPL0033E": _("Parameter 'disks' requires at least one disk object"),
+ "KCHTMPL0034E": _("Storage without libvirt pool is not supported on this architecture"),
+ "KCHTMPL0035E": _("Error while creating the virtual disk for the guest. Details: %(err)s"),
+ "KCHTMPL0036E": _("When setting template disks without libvirt, following parameters are required: 'index', 'format', 'path', 'size'"),
"KCHPOOL0001E": _("Storage pool %(name)s already exists"),
"KCHPOOL0002E": _("Storage pool %(name)s does not exist"),
diff --git a/model/storagepools.py b/model/storagepools.py
index af92ec9..08e6426 100644
--- a/model/storagepools.py
+++ b/model/storagepools.py
@@ -33,7 +33,7 @@ from wok.plugins.kimchi.model.host import DeviceModel
from wok.plugins.kimchi.model.libvirtstoragepool import StoragePoolDef
from wok.plugins.kimchi.osinfo import defaults as tmpl_defaults
from wok.plugins.kimchi.scan import Scanner
-from wok.plugins.kimchi.utils import pool_name_from_uri
+from wok.plugins.kimchi.utils import pool_name_from_uri, is_s390x
ISO_POOL_NAME = u'kimchi_isos'
@@ -57,6 +57,7 @@ STORAGE_SOURCES = {'netfs': {'addr': '/pool/source/host/@name',
class StoragePoolsModel(object):
+
def __init__(self, **kargs):
self.conn = kargs['conn']
self.objstore = kargs['objstore']
@@ -72,6 +73,13 @@ class StoragePoolsModel(object):
def _check_default_pools(self):
pools = {}
+ if 'disks' not in tmpl_defaults or len(tmpl_defaults['disks']) == 0 \
+ or (not tmpl_defaults.get('disks')[0].get(
+ 'pool') and is_s390x()):
+ # Since libvirt pools are not supported on s390x
+ # No need to check for default pools on s390x
+ return
+ tmpl_defaults.get('disks')
default_pool = tmpl_defaults['disks'][0]['pool']['name']
default_pool = default_pool.split('/')[-1]
@@ -437,9 +445,10 @@ class StoragePoolModel(object):
for tmpl in templates:
t_info = session.get('template', tmpl)
for disk in t_info['disks']:
- t_pool = disk['pool']['name']
- if pool_name_from_uri(t_pool) == pool_name:
- return True
+ if 'pool' in disk:
+ t_pool = disk['pool']['name']
+ if pool_name_from_uri(t_pool) == pool_name:
+ return True
return False
def deactivate(self, name):
diff --git a/model/storagevolumes.py b/model/storagevolumes.py
index 4708674..d721d3b 100644
--- a/model/storagevolumes.py
+++ b/model/storagevolumes.py
@@ -44,7 +44,6 @@ from wok.plugins.kimchi.model.diskutils import set_disk_used_by
from wok.plugins.kimchi.model.storagepools import StoragePoolModel
from wok.plugins.kimchi.utils import get_next_clone_name
-
VOLUME_TYPE_MAP = {0: 'file',
1: 'block',
2: 'directory',
diff --git a/model/templates.py b/model/templates.py
index 8df8c3b..c749f4b 100644
--- a/model/templates.py
+++ b/model/templates.py
@@ -28,13 +28,15 @@ import urlparse
from wok.exception import InvalidOperation, InvalidParameter
from wok.exception import NotFoundError, OperationFailed
-from wok.utils import probe_file_permission_as_user, run_setfacl_set_attr
+from wok.utils import probe_file_permission_as_user
+from wok.utils import run_setfacl_set_attr
from wok.xmlutils.utils import xpath_get_text
from wok.plugins.kimchi.config import get_kimchi_version
from wok.plugins.kimchi.kvmusertests import UserTests
from wok.plugins.kimchi.model.cpuinfo import CPUInfoModel
from wok.plugins.kimchi.utils import is_libvirtd_up, pool_name_from_uri
+from wok.plugins.kimchi.utils import create_disk_image
from wok.plugins.kimchi.vmtemplate import VMTemplate
ISO_TYPE = "ISO 9660 CD-ROM"
@@ -400,15 +402,26 @@ class LibvirtVMTemplate(VMTemplate):
def fork_vm_storage(self, vm_uuid):
# Provision storages:
- vol_list = self.to_volume_list(vm_uuid)
+ disk_and_vol_list = self.to_volume_list(vm_uuid)
try:
- 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)
+ for v in disk_and_vol_list:
+ if v['pool'] is not None:
+ pool = self._get_storage_pool(v['pool'])
+ # outgoing text to libvirt, encode('utf-8')
+ pool.createXML(v['xml'].encode('utf-8'), 0)
+ else:
+ capacity = v['capacity']
+ format_type = v['format']
+ path = v['path']
+ create_disk_image(
+ format_type=format_type,
+ path=path,
+ capacity=capacity)
+
except libvirt.libvirtError as e:
raise OperationFailed("KCHVMSTOR0008E", {'error': e.message})
- return vol_list
+
+ return disk_and_vol_list
def set_cpu_info(self):
# undefined topology: consider these values to calculate maxvcpus
diff --git a/model/vms.py b/model/vms.py
index 7f607f5..3ad722e 100644
--- a/model/vms.py
+++ b/model/vms.py
@@ -61,7 +61,7 @@ from wok.plugins.kimchi.model.utils import remove_metadata_node
from wok.plugins.kimchi.model.utils import set_metadata_node
from wok.plugins.kimchi.osinfo import defaults, MEM_DEV_SLOTS
from wok.plugins.kimchi.screenshot import VMScreenshot
-from wok.plugins.kimchi.utils import get_next_clone_name
+from wok.plugins.kimchi.utils import get_next_clone_name, is_s390x
from wok.plugins.kimchi.utils import template_name_from_uri
from wok.plugins.kimchi.xmlutils.bootorder import get_bootorder_node
from wok.plugins.kimchi.xmlutils.bootorder import get_bootmenu_node
@@ -1395,6 +1395,13 @@ class VMModel(object):
except libvirt.libvirtError as e:
wok_log.error('Unable to get storage volume by path: %s' %
e.message)
+ try:
+ if is_s390x() and os.path.exists(path):
+ os.remove(path)
+ except Exception as e:
+ wok_log.error('Unable to delete storage path: %s' %
+ e.message)
+
except Exception as e:
raise OperationFailed('KCHVOL0017E', {'err': e.message})
diff --git a/osinfo.py b/osinfo.py
index 528cf14..d60cc15 100644
--- a/osinfo.py
+++ b/osinfo.py
@@ -158,6 +158,12 @@ def _get_tmpl_defaults():
'maxmemory': _get_default_template_mem()}
tmpl_defaults['storage']['disk.0'] = {'size': 10, 'format': 'qcow2',
'pool': 'default'}
+ is_on_s390x = True if _get_arch() == 's390x' else False
+
+ if is_on_s390x:
+ tmpl_defaults['storage']['disk.0']['path'] = '/var/lib/libvirt/images/'
+ del tmpl_defaults['storage']['disk.0']['pool']
+
tmpl_defaults['processor']['vcpus'] = 1
tmpl_defaults['processor']['maxvcpus'] = 1
tmpl_defaults['graphics'] = {'type': 'vnc', 'listen': '127.0.0.1'}
@@ -165,7 +171,12 @@ def _get_tmpl_defaults():
default_config = ConfigObj(tmpl_defaults)
# Load template configuration file
- config_file = os.path.join(kimchiPaths.sysconf_dir, 'template.conf')
+ if is_on_s390x:
+ config_file = os.path.join(
+ kimchiPaths.sysconf_dir,
+ 'template_s390x.conf')
+ else:
+ config_file = os.path.join(kimchiPaths.sysconf_dir, 'template.conf')
config = ConfigObj(config_file)
# Merge default configuration with file configuration
@@ -186,11 +197,39 @@ def _get_tmpl_defaults():
# Parse storage section to get disks values
storage_section = default_config.pop('storage')
defaults['disks'] = []
- for disk in storage_section.keys():
+
+ pool_exists = False
+ path_exists = False
+ for index, disk in enumerate(storage_section.keys()):
data = storage_section[disk]
data['index'] = int(disk.split('.')[1])
- data['pool'] = {"name": '/plugins/kimchi/storagepools/' +
- storage_section[disk].pop('pool')}
+ # Right now 'Path' is only supported on s390x
+ if storage_section[disk].get('path') and is_on_s390x:
+ path_exists = True
+ data['path'] = storage_section[disk].pop('path')
+ if 'size' not in storage_section[disk]:
+ data['size'] = tmpl_defaults['storage']['disk.0']['size']
+ else:
+ data['size'] = storage_section[disk].pop('size')
+
+ if 'format' not in storage_section[disk]:
+ data['format'] = tmpl_defaults['storage']['disk.0']['format']
+ else:
+ data['format'] = storage_section[disk].pop('format')
+ else:
+ storage_section[disk].get('pool')
+ pool_exists = True
+ data['pool'] = {"name": '/plugins/kimchi/storagepools/' +
+ storage_section[disk].pop('pool')}
+
+ # If both pool and path don't exist, pick the defaults
+ if index == len(storage_section.keys()) - 1 and \
+ (not pool_exists and not path_exists):
+ if is_on_s390x: # Special handling for s390x
+ data['path'] = tmpl_defaults['storage']['disk.0']['path']
+ else:
+ data['pool'] = {"name": '/plugins/kimchi/storagepools/default'}
+
defaults['disks'].append(data)
# Parse processor section to get vcpus and cpu_topology values
diff --git a/utils.py b/utils.py
index 26d3cf6..0fca191 100644
--- a/utils.py
+++ b/utils.py
@@ -24,6 +24,7 @@ import platform
import re
import sqlite3
import time
+import os
import urllib2
from httplib import HTTPConnection, HTTPException
from urlparse import urlparse
@@ -31,6 +32,7 @@ from urlparse import urlparse
from wok.exception import InvalidParameter, OperationFailed
from wok.plugins.kimchi import config
from wok.plugins.kimchi.osinfo import get_template_default
+from wok.stringutils import encode_value
from wok.utils import run_command, wok_log
from wok.xmlutils.utils import xpath_get_text
@@ -272,3 +274,35 @@ def is_libvirtd_up():
output, error, rc = run_command(cmd, silent=True)
return True if output == 'active\n' else False
+
+
+def is_s390x():
+ """
+ Check if current arch is 's390x'
+ Returns:
+ """
+ if os.uname()[4] == 's390x':
+ return True
+
+ return False
+
+
+def create_disk_image(format_type, path, capacity):
+ """
+ Create a disk image for the Guest
+ Args:
+ format: Format of the storage. e.g. qcow2
+ path: Path where the virtual disk will be created
+ capacity: Capacity of the virtual disk in GBs
+
+ Returns:
+
+ """
+ out, err, rc = run_command(
+ ["/usr/bin/qemu-img", "create", "-f", format_type, "-o",
+ "preallocation=metadata", path, encode_value(capacity) + "G"])
+
+ if rc != 0:
+ raise OperationFailed("KCHTMPL0035E", {'err': err})
+
+ return
\ No newline at end of file
diff --git a/vmtemplate.py b/vmtemplate.py
index babf050..3b9eb32 100644
--- a/vmtemplate.py
+++ b/vmtemplate.py
@@ -31,7 +31,8 @@ from wok.exception import MissingParameter, OperationFailed
from wok.plugins.kimchi import imageinfo
from wok.plugins.kimchi import osinfo
from wok.plugins.kimchi.isoinfo import IsoImage
-from wok.plugins.kimchi.utils import check_url_path, pool_name_from_uri
+from wok.plugins.kimchi.utils import check_url_path, is_s390x
+from wok.plugins.kimchi.utils import pool_name_from_uri
from wok.plugins.kimchi.xmlutils.bootorder import get_bootorder_xml
from wok.plugins.kimchi.xmlutils.cpu import get_cpu_xml
from wok.plugins.kimchi.xmlutils.disk import get_disk_xml
@@ -42,6 +43,7 @@ from wok.plugins.kimchi.xmlutils.serial import get_serial_xml
class VMTemplate(object):
+
def __init__(self, args, scan=False, netboot=False):
"""
Construct a VM Template from a widely variable amount of information.
@@ -95,35 +97,49 @@ class VMTemplate(object):
disks = self.info.get('disks')
basic_disk = ['index', 'format', 'pool', 'size']
+ basic_path_disk = ['index', 'format', 'path', 'size']
ro_disk = ['index', 'format', 'pool', 'volume']
base_disk = ['index', 'base', 'pool', 'size', 'format']
for index, disk in enumerate(disks):
disk_info = dict(default_disk)
-
- pool = disk.get('pool', default_disk['pool'])
- pool_type = self._get_storage_type(pool['name'])
-
- if pool_type in ['iscsi', 'scsi']:
- disk_info = {'index': 0, 'format': 'raw', 'volume': None}
-
- disk_info.update(disk)
- pool_name = disk_info.get('pool', {}).get('name')
- if pool_name is None:
- raise MissingParameter('KCHTMPL0028E')
-
- keys = sorted(disk_info.keys())
- if ((keys != sorted(basic_disk)) and (keys != sorted(ro_disk)) and
- (keys != sorted(base_disk))):
- raise MissingParameter('KCHTMPL0028E')
-
- if pool_type in ['logical', 'iscsi', 'scsi']:
- if disk_info['format'] != 'raw':
- raise InvalidParameter('KCHTMPL0029E')
-
- disk_info['pool']['type'] = pool_type
- disk_info['index'] = disk_info.get('index', index)
- self.info['disks'][index] = disk_info
+ if disk.get('pool'):
+ pool = disk.get('pool', default_disk.get('pool'))
+ pool_type = self._get_storage_type(pool['name'])
+ if pool_type in ['iscsi', 'scsi']:
+ disk_info = {'index': 0, 'format': 'raw', 'volume': None}
+
+ disk_info.update(disk)
+ pool_name = disk_info.get('pool', {}).get('name')
+ if pool_name is None:
+ raise MissingParameter('KCHTMPL0028E')
+
+ keys = sorted(disk_info.keys())
+ if ((keys != sorted(basic_disk)) and
+ (keys != sorted(ro_disk)) and
+ (keys != sorted(base_disk)) and
+ (keys != basic_path_disk)):
+ raise MissingParameter('KCHTMPL0028E')
+
+ if pool_type in ['logical', 'iscsi', 'scsi']:
+ if disk_info['format'] != 'raw':
+ raise InvalidParameter('KCHTMPL0029E')
+
+ disk_info['pool']['type'] = pool_type
+ disk_info['index'] = disk_info.get('index', index)
+ self.info['disks'][index] = disk_info
+ elif is_s390x():
+ # For now support 'path' only on s390x
+ path = disk.get('path', default_disk['path'])
+ disk_info.update(disk)
+ keys = sorted(disk_info.keys())
+ if keys != sorted(basic_path_disk):
+ raise MissingParameter('KCHTMPL0036E')
+ disk_info['path'] = path
+ disk_info['index'] = disk_info.get('index', index)
+ self.info['disks'][index] = disk_info
+ else:
+ raise InvalidParameter('KCHTMPL0034E')
def _get_os_info(self, args, scan):
distro = version = 'unknown'
@@ -217,8 +233,9 @@ class VMTemplate(object):
params = dict(base_disk_params)
params['format'] = disk['format']
params['index'] = index
- params.update(locals().get('%s_disk_params' %
- disk['pool']['type'], {}))
+ if disk.get('pool'):
+ params.update(locals().get('%s_disk_params' %
+ disk['pool']['type'], {}))
volume = disk.get('volume')
if volume is not None:
@@ -226,9 +243,13 @@ class VMTemplate(object):
volume)
else:
img = "%s-%s.img" % (vm_uuid, params['index'])
- storage_path = self._get_storage_path(disk['pool']['name'])
+ if disk.get('pool'):
+ storage_path = self._get_storage_path(disk['pool']['name'])
+ params['pool_type'] = disk['pool']['type']
+ elif disk.get('path'):
+ storage_path = disk.get('path')
+ params['pool_type'] = None
params['path'] = os.path.join(storage_path, img)
- params['pool_type'] = disk['pool']['type']
disks_xml += get_disk_xml(params)[1]
return unicode(disks_xml, 'utf-8')
@@ -237,20 +258,24 @@ class VMTemplate(object):
ret = []
for i, d in enumerate(self.info['disks']):
# Create only .img. If storagepool is (i)SCSI, volumes will be LUNs
- if d['pool']['type'] in ["iscsi", "scsi"]:
+ if 'pool' in d and d['pool']['type'] in ["iscsi", "scsi"]:
continue
index = d.get('index', i)
volume = "%s-%s.img" % (vm_uuid, index)
- storage_path = self._get_storage_path(d['pool']['name'])
+ if 'path' in d:
+ storage_path = d['path']
+ else:
+ storage_path = self._get_storage_path(d['pool']['name'])
+
info = {'name': volume,
'capacity': d['size'],
'format': d['format'],
'path': '%s/%s' % (storage_path, volume),
- 'pool': d['pool']['name']}
+ 'pool': d['pool']['name'] if 'pool' in d else None}
- if 'logical' == d['pool']['type'] or \
+ if ('pool' in d and 'logical' == d['pool']['type']) or \
info['format'] not in ['qcow2', 'raw']:
info['allocation'] = info['capacity']
else:
@@ -447,8 +472,9 @@ class VMTemplate(object):
def validate(self):
for disk in self.info.get('disks'):
- pool_uri = disk.get('pool', {}).get('name')
- self._get_storage_pool(pool_uri)
+ if 'pool' in disk:
+ pool_uri = disk.get('pool', {}).get('name')
+ self._get_storage_pool(pool_uri)
self._network_validate()
self._iso_validate()
self.cpuinfo_validate()
@@ -499,10 +525,11 @@ class VMTemplate(object):
# validate storagepools and image-based templates integrity
for disk in self.info['disks']:
- pool_uri = disk['pool']['name']
- pool_name = pool_name_from_uri(pool_uri)
- if pool_name not in self._get_active_storagepools_name():
- invalid['storagepools'] = [pool_name]
+ if 'pool' in disk:
+ pool_uri = disk['pool']['name']
+ pool_name = pool_name_from_uri(pool_uri)
+ if pool_name not in self._get_active_storagepools_name():
+ invalid['storagepools'] = [pool_name]
if disk.get("base") is None:
continue
--
1.9.1
8 years
[PATCH] [Kimchi] Storagebuttons not behaving properly
by Socorro Stoppler
From: Socorro <socorro(a)linux.vnet.ibm.com>
Signed-off-by: Socorro <socorro(a)linux.vnet.ibm.com>
---
ui/js/src/kimchi.storage_main.js | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/ui/js/src/kimchi.storage_main.js b/ui/js/src/kimchi.storage_main.js
index 6c99f93..ea58012 100644
--- a/ui/js/src/kimchi.storage_main.js
+++ b/ui/js/src/kimchi.storage_main.js
@@ -310,6 +310,14 @@ kimchi.storageBindClick = function() {
$('.pool-delete').on('click', function(event) {
event.preventDefault();
var $pool = $(this);
+ var in_use = $pool.data('inuse');
+ if ('active' === $pool.data('stat') || in_use) {
+ $pool.parent().addClass('disabled');
+ return false;
+ } else {
+ $pool.parent().removeClass('disabled');
+ }
+
var settings = {
title : i18n['KCHAPI6001M'],
content : i18n['KCHPOOL6001M'],
@@ -339,6 +347,15 @@ kimchi.storageBindClick = function() {
$('.pool-deactivate').on('click', function(event) {
event.preventDefault();
var poolName = $(this).data('name');
+ var $poolDeactivate = $(this);
+ var in_use = $poolDeactivate.data('inuse');
+ if (in_use) {
+ $poolDeactivate.parent().addClass('disabled');
+ return false;
+ } else {
+ $poolDeactivate.parent().removeClass('disabled');
+ }
+
var settings = {
title : i18n['KCHAPI6001M'],
content : i18n['KCHPOOL6012M'],
--
2.7.4
8 years
[PATCH] [Kimchi] Issue #626: Snapshot revert does not release storage volume
by bianca@linux.vnet.ibm.com
From: Bianca Carvalho <bianca(a)linux.vnet.ibm.com>
Edited diskutils.py file to remove used_by verification in
objstore, now this field will be only verified in the vm
when get_disk_used_by is used by StorageVolumeModel lookup.
Signed-off-by: Bianca Carvalho <bianca(a)linux.vnet.ibm.com>
---
model/diskutils.py | 50 ++++++++++++++++++++++----------------------------
1 file changed, 22 insertions(+), 28 deletions(-)
diff --git a/model/diskutils.py b/model/diskutils.py
index 6faab7c..3b8f441 100644
--- a/model/diskutils.py
+++ b/model/diskutils.py
@@ -17,7 +17,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-from wok.exception import OperationFailed, NotFoundError
+from wok.exception import OperationFailed
from wok.utils import wok_log
from wok.plugins.kimchi.config import get_kimchi_version
@@ -34,34 +34,28 @@ from wok.plugins.kimchi.xmlutils.disk import get_vm_disk_info, get_vm_disks
def get_disk_used_by(objstore, conn, path):
try:
with objstore as session:
+ used_by = []
+ # try to find this volume in existing vm
+ vms_list = VMsModel.get_vms(conn)
+ for vm in vms_list:
+ dom = VMModel.get_vm(vm, conn)
+ storages = get_vm_disks(dom)
+ for disk in storages.keys():
+ d_info = get_vm_disk_info(dom, disk)
+ if path == d_info['path']:
+ used_by.append(vm)
try:
- used_by = session.get('storagevolume', path)['used_by']
- except (KeyError, NotFoundError):
- wok_log.info('Volume %s not found in obj store.' % path)
- used_by = []
- # try to find this volume in existing vm
- vms_list = VMsModel.get_vms(conn)
- for vm in vms_list:
- dom = VMModel.get_vm(vm, conn)
- storages = get_vm_disks(dom)
- for disk in storages.keys():
- d_info = get_vm_disk_info(dom, disk)
- if path == d_info['path']:
- used_by.append(vm)
- try:
- session.store('storagevolume', path,
- {'used_by': used_by},
- get_kimchi_version())
- except Exception as e:
- # Let the exception be raised. If we allow disks'
- # used_by to be out of sync, data corruption could
- # occour if a disk is added to two guests
- # unknowingly.
- wok_log.error('Unable to store storage volume id in'
- ' objectstore due error: %s',
- e.message)
- raise OperationFailed('KCHVOL0017E',
- {'err': e.message})
+ session.store('storagevolume', path, {'used_by': used_by},
+ get_kimchi_version())
+ except Exception as e:
+ # Let the exception be raised. If we allow disks'
+ # used_by to be out of sync, data corruption could
+ # occour if a disk is added to two guests
+ # unknowingly.
+ wok_log.error('Unable to store storage volume id in'
+ ' objectstore due error: %s',
+ e.message)
+ raise OperationFailed('KCHVOL0017E', {'err': e.message})
except Exception as e:
# This exception is going to catch errors returned by 'with',
# specially ones generated by 'session.store'. It is outside
--
2.7.4
8 years
[PATCH] [Kimchi 0/2] Enhancement to /plugins/kimchi/interfaces
by sureshab@linux.vnet.ibm.com
From: Suresh Babu Angadi <sureshab(a)in.ibm.com>
Suresh Babu Angadi (2):
Enhancement to /plugins/kimchi/interfaces
Per RFC: [Kimchi-devel] [RFC] changes to /plugins/kimchi/interfaces
* this patch includes backend changes to add '_inuse' filter
* Updated API.md to include '_inuse' filter for /interfaces Collection
* modified api call to plugins/kimchi/interfaces?_inuse=false in
kimchi.api.js, since unused interfaces are used to create virtual network
Enhancement to /plugins/kimchi/interfaces
modified api calls to /plugins/kimchi/interfaces?_inuse=false
in test cases which were referring /plugins/kimchi/interfaces
to create virtual network
docs/API.md | 3 +++
i18n.py | 1 +
model/interfaces.py | 20 ++++++++++++++++----
tests/test_mock_network.py | 4 ++--
tests/test_model_network.py | 4 ++--
tests/test_template.py | 4 ++--
ui/js/src/kimchi.api.js | 2 +-
7 files changed, 27 insertions(+), 11 deletions(-)
--
1.8.3.1
8 years
[PATCH] [Wok 0/7] Issue #141 - Handle AsyncTasks in request log
by Lucio Correia
Lucio Correia (7):
Create log_request() method for code simplification
Improve plugin lookup by request
Update Request Logger to handle AsyncTask status
Log AsyncTask success or failure
Save log entry IDs for requests that generate tasks
Put failure details into parenthesis
Change location of User Requests Log
src/wok/asynctask.py | 46 +++++++++++++--
src/wok/config.py.in | 4 ++
src/wok/control/base.py | 75 +++++++++++++-----------
src/wok/i18n.py | 2 +
src/wok/message.py | 2 +-
src/wok/reqlogger.py | 150 +++++++++++++++++++++++++++---------------------
src/wok/root.py | 41 ++-----------
src/wok/utils.py | 14 +++--
8 files changed, 189 insertions(+), 145 deletions(-)
--
1.9.1
8 years