[PATCH v2] RollbackContext: Make it complied with Python Standard
by Zhou Zheng Sheng
According to Python documentation, context managers should not re-raise
the exception passed to __exit__ method. If __exit__() does not return
True, Python re-raises this exception automatically. Context managers
should only raise exception from __exit__() itself. This means we should
only re-raise exception caught from the undo functions.
Another problem of the current implementation is that it suppresses str
exceptions. This is because of bug in old Python version. When an
exception is raised from within a "with" statement, exc_value would be a
raw str or int rather than Exception instance, so when we re-raise the
stored exc_value, it triggers another exception saying "exceptions must
be old-style classes or derived from BaseException, not str".
This patch fix this problem by raising the stored exception value along
with its store exception type.
This patch also adds unit test for RollbackContext.
http://docs.python.org/2/library/stdtypes.html#contextmanager.__exit__
v1 -> v2
Add tests/test_rollbackcontext.py to tests/Makefile.am.
Add tests/test_rollbackcontext.py to Makefile.am PEP8 list.
Signed-off-by: Zhou Zheng Sheng <zhshzhou(a)linux.vnet.ibm.com>
---
Makefile.am | 1 +
src/kimchi/rollbackcontext.py | 26 +++++------
tests/Makefile.am | 1 +
tests/test_rollbackcontext.py | 102 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 117 insertions(+), 13 deletions(-)
create mode 100644 tests/test_rollbackcontext.py
diff --git a/Makefile.am b/Makefile.am
index 04ad696..b09a545 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -60,6 +60,7 @@ PEP8_WHITELIST = \
tests/test_model.py \
tests/test_plugin.py \
tests/test_rest.py \
+ tests/test_rollbackcontext.py \
tests/test_storagepool.py \
tests/utils.py \
$(NULL)
diff --git a/src/kimchi/rollbackcontext.py b/src/kimchi/rollbackcontext.py
index 2afd114..d493af2 100644
--- a/src/kimchi/rollbackcontext.py
+++ b/src/kimchi/rollbackcontext.py
@@ -6,6 +6,7 @@
# Authors:
# Adam Litke <agl(a)linux.vnet.ibm.com>
# ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
+# Zhou Zheng Sheng <zhshzhou(a)linux.vnet.ibm.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -45,24 +46,23 @@ class RollbackContext(object):
return self
def __exit__(self, exc_type, exc_value, traceback):
- firstException = exc_value
-
+ """
+ According to Python official doc. This function should only re-raise
+ the exception from undo functions. Python automatically re-raises the
+ original exception when this function does not return True.
+ http://docs.python.org/2/library/stdtypes.html#contextmanager.__exit__
+ """
+ undoExcInfo = None
for undo, args, kwargs in self._finally:
try:
undo(*args, **kwargs)
- except Exception as e:
+ except Exception:
# keep the earliest exception info
- if not firstException:
- firstException = e
- # keep the original traceback info
- traceback = sys.exc_info()[2]
+ if undoExcInfo is None:
+ undoExcInfo = sys.exc_info()
- # re-raise the earliest exception
- if firstException is not None:
- if type(firstException) is str:
- sys.stderr.write(firstException)
- else:
- raise firstException, None, traceback
+ if exc_type is None and undoExcInfo is not None:
+ raise undoExcInfo[0], undoExcInfo[1], undoExcInfo[2]
def defer(self, func, *args, **kwargs):
self._finally.append((func, args, kwargs))
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 55d3ab4..59e344d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -31,6 +31,7 @@ EXTRA_DIST = \
test_osinfo.py \
test_plugin.py \
test_rest.py \
+ test_rollbackcontext.py \
test_server.py \
test_storagepool.py \
test_vmtemplate.py \
diff --git a/tests/test_rollbackcontext.py b/tests/test_rollbackcontext.py
new file mode 100644
index 0000000..fea430d
--- /dev/null
+++ b/tests/test_rollbackcontext.py
@@ -0,0 +1,102 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2014
+#
+# Authors:
+# Zhou Zheng Sheng <zhshzhou(a)linux.vnet.ibm.com>
+#
+# 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
+
+import unittest
+
+from kimchi.rollbackcontext import RollbackContext
+
+
+class FirstError(Exception):
+ '''A hypothetical exception to be raise in the test firstly.'''
+ pass
+
+
+class SecondError(Exception):
+ '''A hypothetical exception to be raise in the test secondly.'''
+ pass
+
+
+class RollbackContextTests(unittest.TestCase):
+
+ def setUp(self):
+ self._counter = 0
+
+ def _inc_counter(self):
+ self._counter += 1
+
+ def _raise(self, exception=FirstError):
+ raise exception()
+
+ def test_rollback(self):
+ with RollbackContext() as rollback:
+ rollback.prependDefer(self._inc_counter)
+ rollback.prependDefer(self._inc_counter)
+ self.assertEquals(self._counter, 2)
+
+ def test_raise(self):
+ try:
+ with RollbackContext() as rollback:
+ rollback.prependDefer(self._inc_counter)
+ rollback.prependDefer(self._inc_counter)
+ raise FirstError()
+ rollback.prependDefer(self._inc_counter)
+ except FirstError:
+ # All undo before the FirstError should be run
+ self.assertEquals(self._counter, 2)
+ else:
+ self.fail('Should have raised FirstError')
+
+ def test_raise_undo(self):
+ try:
+ with RollbackContext() as rollback:
+ rollback.prependDefer(self._inc_counter)
+ rollback.prependDefer(self._raise)
+ rollback.prependDefer(self._inc_counter)
+ except FirstError:
+ # All undo should be run
+ self.assertEquals(self._counter, 2)
+ else:
+ self.fail('Should have raised FirstError')
+
+ def test_raise_prefer_original(self):
+ try:
+ with RollbackContext() as rollback:
+ rollback.prependDefer(self._raise, SecondError)
+ raise FirstError()
+ except FirstError:
+ pass
+ except SecondError:
+ self.fail('Should have preferred FirstError to SecondError')
+ else:
+ self.fail('Should have raised FirstError')
+
+ def test_raise_prefer_first_undo(self):
+ try:
+ with RollbackContext() as rollback:
+ rollback.prependDefer(self._raise, SecondError)
+ rollback.prependDefer(self._raise, FirstError)
+ except FirstError:
+ pass
+ except SecondError:
+ self.fail('Should have preferred FirstError to SecondError')
+ else:
+ self.fail('Should have raised FirstError')
--
1.7.11.7
10 years, 10 months
[PATCH] RollbackContext: Make it complied with Python Standard
by Zhou Zheng Sheng
According to Python documentation, context managers should not re-raise
the exception passed to __exit__ method. If __exit__() does not return
True, Python re-raises this exception automatically. Context managers
should only raise exception from __exit__() itself. This means we should
only re-raise exception caught from the undo functions.
Another problem of the current implementation is that it suppresses str
exceptions. This is because of bug in old Python version. When an
exception is raised from within a "with" statement, exc_value would be a
raw str or int rather than Exception instance, so when we re-raise the
stored exc_value, it triggers another exception saying "exceptions must
be old-style classes or derived from BaseException, not str".
This patch fix this problem by raising the stored exception value along
with its store exception type.
http://docs.python.org/2/library/stdtypes.html#contextmanager.__exit__
Signed-off-by: Zhou Zheng Sheng <zhshzhou(a)linux.vnet.ibm.com>
---
src/kimchi/rollbackcontext.py | 25 +++++------
tests/test_rollbackcontext.py | 102 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 114 insertions(+), 13 deletions(-)
create mode 100644 tests/test_rollbackcontext.py
diff --git a/src/kimchi/rollbackcontext.py b/src/kimchi/rollbackcontext.py
index 2afd114..9502169 100644
--- a/src/kimchi/rollbackcontext.py
+++ b/src/kimchi/rollbackcontext.py
@@ -45,24 +45,23 @@ class RollbackContext(object):
return self
def __exit__(self, exc_type, exc_value, traceback):
- firstException = exc_value
-
+ """
+ According to Python official doc. This function should only re-raise
+ the exception from undo functions. Python automatically re-raises the
+ original exception when this function does not return True.
+ http://docs.python.org/2/library/stdtypes.html#contextmanager.__exit__
+ """
+ undoExcInfo = None
for undo, args, kwargs in self._finally:
try:
undo(*args, **kwargs)
- except Exception as e:
+ except Exception:
# keep the earliest exception info
- if not firstException:
- firstException = e
- # keep the original traceback info
- traceback = sys.exc_info()[2]
+ if undoExcInfo is None:
+ undoExcInfo = sys.exc_info()
- # re-raise the earliest exception
- if firstException is not None:
- if type(firstException) is str:
- sys.stderr.write(firstException)
- else:
- raise firstException, None, traceback
+ if exc_type is None and undoExcInfo is not None:
+ raise undoExcInfo[0], undoExcInfo[1], undoExcInfo[2]
def defer(self, func, *args, **kwargs):
self._finally.append((func, args, kwargs))
diff --git a/tests/test_rollbackcontext.py b/tests/test_rollbackcontext.py
new file mode 100644
index 0000000..23b41c4
--- /dev/null
+++ b/tests/test_rollbackcontext.py
@@ -0,0 +1,102 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2013
+#
+# Authors:
+# Zhou Zheng Sheng <zhshzhou(a)linux.vnet.ibm.com>
+#
+# 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
+
+import unittest
+
+from kimchi.rollbackcontext import RollbackContext
+
+
+class FirstError(Exception):
+ '''A hypothetical exception to be raise in the test firstly.'''
+ pass
+
+
+class SecondError(Exception):
+ '''A hypothetical exception to be raise in the test secondly.'''
+ pass
+
+
+class RollbackContextTests(unittest.TestCase):
+
+ def setUp(self):
+ self._counter = 0
+
+ def _inc_counter(self):
+ self._counter += 1
+
+ def _raise(self, exception=FirstError):
+ raise exception()
+
+ def test_rollback(self):
+ with RollbackContext() as rollback:
+ rollback.prependDefer(self._inc_counter)
+ rollback.prependDefer(self._inc_counter)
+ self.assertEquals(self._counter, 2)
+
+ def test_raise(self):
+ try:
+ with RollbackContext() as rollback:
+ rollback.prependDefer(self._inc_counter)
+ rollback.prependDefer(self._inc_counter)
+ raise FirstError()
+ rollback.prependDefer(self._inc_counter)
+ except FirstError:
+ # All undo before the FirstError should be run
+ self.assertEquals(self._counter, 2)
+ else:
+ self.fail('Should have raised FirstError')
+
+ def test_raise_undo(self):
+ try:
+ with RollbackContext() as rollback:
+ rollback.prependDefer(self._inc_counter)
+ rollback.prependDefer(self._raise)
+ rollback.prependDefer(self._inc_counter)
+ except FirstError:
+ # All undo should be run
+ self.assertEquals(self._counter, 2)
+ else:
+ self.fail('Should have raised FirstError')
+
+ def test_raise_prefer_original(self):
+ try:
+ with RollbackContext() as rollback:
+ rollback.prependDefer(self._raise, SecondError)
+ raise FirstError()
+ except FirstError:
+ pass
+ except SecondError:
+ self.fail('Should have preferred FirstError to SecondError')
+ else:
+ self.fail('Should have raised FirstError')
+
+ def test_raise_prefer_first_undo(self):
+ try:
+ with RollbackContext() as rollback:
+ rollback.prependDefer(self._raise, SecondError)
+ rollback.prependDefer(self._raise, FirstError)
+ except FirstError:
+ pass
+ except SecondError:
+ self.fail('Should have preferred FirstError to SecondError')
+ else:
+ self.fail('Should have raised FirstError')
--
1.7.11.7
10 years, 10 months
[PATCH] Abstract vm element class for live update
by lvroyce0210@gmail.com
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Abstract vm element class for live update to be compatible with different
element type and their various libvirt calls.
Royce Lv (1):
Abstract vm element updater for common usage
src/kimchi/model.py | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 63 insertions(+), 2 deletions(-)
--
1.8.1.2
10 years, 10 months
[PATCH 0/3] (WIP) Storagepool SCSI/FC
by Rodrigo Trujillo
NOTICE: THIS FEATURE IS STILL UNDER DISCUSSION/AGREEMENT/DEVELOPMENT
This patch set implements the basic functions in order to create a SCSI
storagepool based in fibre channel protocol.
--- What is implemented? ---
* backend API
It is possible to create a pool with curl POST request like:
curl -X POST -u <USER> -H 'Content-type: application/json' \
-H 'Accept: application/json' http://localhost:8000/storagepools \
--data '{ \
"name": "testFC", \
"source": { "adapter_type": "scsi_host", \
"adapter_name": "scsi_hostX", \
"wwnn":"112233789", \
"wwpn":"44332211" }, \
"path": "/dev/disk/by-id", \
"type": "scsi" }'
* json schema updated
* created a function to test the host libvirt version
SCSI FC pool and volumes have theirself configuration only after
libvirt version 1.0.5. If lesser, I must use older configuration
tags
* updates the VM guest template with proper disk xml
Create volumes in a SCSI pool is not supported by libvirt, because
volumes are the LUNS preconfigured and available in the SAN. Disk
will have the biggest LUN found assigned.
--- What does need to be discussed? Ideas? ---
1) Backend expects right information from UI, so UI would have to ask
and send 'adapter_name', 'wwnn' and 'wwpn' (other fields can be fi
xed). However, the UI coud show the FC_Hosts available and let user
select which one he wants. This would require to implement more ba
ck-end functions to gather FC_host info, automatically (name, wwnn,
wwpn).
So, at this moment, just create an UI with input fields or facili
tate the users life ?
2) Currently the user have no choice on with LUN to assign to a guest.
LUN is selected automatically and if not LUN is available, guest
will not have any disk. In order to improve this, the guest creation
fase could have one more step, if the pool in the template in SCSI
type. If SCSI, user could choose which LUN he wants to assign to VM.
Notice that the disk size in the template have been, and will be, ig
nored.
What do you guys think about this approach ?
3) LUNs refresh: Once the storage admin creates more LUNs, the host admin
needs to perform some commands in order to kernel 'see' and map new
devices. I am implementing this backend functionality. A refresh bu
tton will be necessary in the UI, where could it be placed?
- In the storagepool creation window ? When select SCSI type
- In the window to select the LUN, when creating new guest (if
approved this extra step)
- In the storagepool tab, in the pool section, if its a SCSI type
- Also, when the user expands a SCSI pool section, which will show
the volumes (LUNs), this function can be triggered.
4) More ideas/concerns/suggestions ?
Rodrigo Trujillo (3):
Storagepool: SCSI/Fibre Channel backend implementation
Storagepools: Function to check libvirt version
Storagepools: Assign SCSI fibre channel LUN as disk to a new guest
docs/API.md | 6 ++++
src/kimchi/API.json | 18 ++++++++++-
src/kimchi/model.py | 79 +++++++++++++++++++++++++++++++++++++++++++++---
src/kimchi/utils.py | 14 +++++++++
src/kimchi/vmtemplate.py | 40 +++++++++++++++++++++++-
5 files changed, 151 insertions(+), 6 deletions(-)
--
1.8.1.4
10 years, 10 months
[PATCH V3] UI bug fix: Set vlan_id value only if 'Enable VLAN' is checked
by Aline Manera
From: Aline Manera <alinefm(a)br.ibm.com>
V2 -> V3:
- Add validation to vlan id
- Reset vlan id input box when checkbox isn't checked
- Update po files
V1 -> V2:
- Remove alert used for testing
Aline Manera (1):
UI bug fix: Set vlan_id value only if 'Enable VLAN' is checked
po/en_US.po | 10 ++++++++--
po/kimchi.pot | 9 ++++++++-
po/pt_BR.po | 10 ++++++++--
po/zh_CN.po | 10 ++++++++--
ui/js/src/kimchi.network.js | 14 +++++++++++---
ui/pages/i18n.html.tmpl | 1 +
6 files changed, 44 insertions(+), 10 deletions(-)
--
1.7.10.4
10 years, 10 months
[PATCH] Add the iSCSI dependency packages to README
by Crístian Viana
The README file contains instructions to build Kimchi from the source
tree, including the exact commands (e.g. yum, apt-get, zypper) to install the
dependencies on the main Linux distros. But none of those commands contain the
iSCSI package which is needed to validate some types of storage pool devices.
Add the iSCSI package ("iscsi-initiator-utils" or "open-iscsi", depending on the
distro) to the install commands in the README file.
Signed-off-by: Crístian Viana <vianac(a)linux.vnet.ibm.com>
---
docs/README.md | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/docs/README.md b/docs/README.md
index 1ccea01..d80486b 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -37,7 +37,8 @@ Install Dependencies
libvirt libxml2-python python-imaging \
PyPAM m2crypto python-jsonschema rpm-build \
qemu-kvm python-psutil python-ethtool sos \
- python-ipaddr python-lxml nfs-utils
+ python-ipaddr python-lxml nfs-utils \
+ iscsi-initiator-utils
# If using RHEL6, install the following additional packages:
$ sudo yum install python-unittest2 python-ordereddict
# Restart libvirt to allow configuration changes to take effect
@@ -58,7 +59,8 @@ for more information on how to configure your system to access this repository.
libvirt-bin python-libxml2 python-imaging \
python-pam python-m2crypto python-jsonschema \
qemu-kvm libtool python-psutil python-ethtool \
- sosreport python-ipaddr python-lxml nfs-common
+ sosreport python-ipaddr python-lxml nfs-common \
+ open-iscsi
Packages version requirement:
python-jsonschema >= 1.3.0
@@ -71,7 +73,7 @@ for more information on how to configure your system to access this repository.
libvirt python-libxml2 python-imaging \
python-pam python-M2Crypto python-jsonschema \
rpm-build kvm python-psutil python-ethtool \
- python-ipaddr python-lxml nfs-client
+ python-ipaddr python-lxml nfs-client open-iscsi
Packages version requirement:
python-psutil >= 0.6.0
--
1.8.4.2
10 years, 10 months
[RFC]: a new mechanism to improve controller
by Sheldon
as we all know we will use the follow URL for vm device.
/vms/vm-name/devices/device-name
we will create a new path "vm" for these devices in source tree.
all device collections and resources will be in this path.
|-- src
| |-- distros.d
| | `-- ubuntu.json
| |-- kimchi
| | |-- control
| | | |-- base.py
| | | |-- vm
| | | | |-- ifaces.py
| | | | `-- cdroms.py
Now, I'd like to introduce a new mechanism to dispatch the vm
devices(sub-collections).
you can see this patch
[PATCH 2/7] add a method to load vms sub collection automatically
After this patch, we can dispatch the vm sub-collections more easily.
For example, if we want to add a sub-collection ifaces, we can just
define it as follow in iface.py
+@SubCollection('ifaces')
+class VmIfaces(Collection):
+ def __init__(self, model, vm):
+ super(VmIfaces, self).__init__(model)
+ self.resource = VmIface
+ self.vm = vm
+ self.resource_args = [self.vm, ]
+ self.model_args = [self.vm, ]
We do not need to touch the vm.py any more.
The tag @SubCollection('ifaces') means this is sub-collection of VM and
the URL is
/vms/vm-name/ifaces/iface-name
discuss with Mark and Royce, they think we can improve the root also by
this way.
Such as we can define vms collection in vms.py as follow:
+@SubCollection('vms', auth=True)
+class VMs(Collection):
+ def __init__(self, model, vm):
+ super(Vms, self).__init__(model)
+ self.resource = vm
For @SubCollection('vms', auth=True):
the "vms" means the URL is /vms and "auth=True" means it will set
tools.kimchiauth.on ad True.
After we tag the Collection with the tag @SubCollection('vms', auth=True),
We do not need to touch root.py and server.py any more when we add new
Collections.
And we can remove the follow codes.
diff --git a/src/kimchi/root.py b/src/kimchi/root.py
index 3cc6321..2bac4e1 100644
--- a/src/kimchi/root.py
+++ b/src/kimchi/root.py
@@ -27,19 +27,6 @@ import json
from kimchi import auth
from kimchi import template
-from kimchi.config import get_api_schema_file
-from kimchi.control.base import Resource
-from kimchi.control.config import Config
-from kimchi.control.debugreports import DebugReports
-from kimchi.control.host import Host
-from kimchi.control.interfaces import Interfaces
-from kimchi.control.networks import Networks
-from kimchi.control.plugins import Plugins
-from kimchi.control.storagepools import StoragePools
-from kimchi.control.tasks import Tasks
-from kimchi.control.templates import Templates
-from kimchi.control.utils import parse_request
-from kimchi.control.vms import VMs
from kimchi.exception import OperationFailed
@@ -57,16 +44,6 @@ class Root(Resource):
for key in self._handled_error])
Resource.__init__(self, model)
- self.vms = VMs(model)
- self.templates = Templates(model)
- self.storagepools = StoragePools(model)
- self.interfaces = Interfaces(model)
- self.networks = Networks(model)
- self.tasks = Tasks(model)
- self.config = Config(model)
- self.host = Host(model)
- self.debugreports = DebugReports(model)
- self.plugins = Plugins(model)
self.api_schema = json.load(open(get_api_schema_file()))
def error_production_handler(self, status, message, traceback, version):
diff --git a/src/kimchi/server.py b/src/kimchi/server.py
index b820263..08dfde2 100644
--- a/src/kimchi/server.py
+++ b/src/kimchi/server.py
@@ -74,13 +74,6 @@ class Server(object):
'tools.sessions.storage_type': 'file',
'tools.sessions.storage_path': config.get_session_path(),
'tools.kimchiauth.on': False},
- '/host': {'tools.kimchiauth.on': True},
- '/vms': {'tools.kimchiauth.on': True},
- '/templates': {'tools.kimchiauth.on': True},
- '/networks': {'tools.kimchiauth.on': True},
- '/storagepools': {'tools.kimchiauth.on': True},
- '/tasks': {'tools.kimchiauth.on': True},
- '/debugreports': {'tools.kimchiauth.on': True},
'/css': {
'tools.staticdir.on': True,
'tools.staticdir.dir': 'ui/css',
--
Thanks and best regards!
Sheldon Feng(冯少合)<shaohef(a)linux.vnet.ibm.com>
IBM Linux Technology Center
10 years, 10 months
[PATCHv7 0/8] storage server and targets support
by lvroyce0210@gmail.com
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
v6>v7, adopt lxml to parse xml, move parse params to get() to avoid duplicate code,
fix bugs when one server support multiple target type.
v5>v6, change GET param support to cover more scenario of filter collected results.
v4>v5, remove storage server list reload function,
merge storage server and targets
v3>v4, fix inconsistency between doc and json schema
v1>v3, fix racing problem, fix style.
Royce Lv (8):
Support params for GET method
Add testcase for GET param
Storage server: Update API.md
storage server: update controller.py
storage server: Update model and mockmodel
storage target: Update API.md
storage target: Update controller and json schema
storage target: Add model support
docs/API.md | 22 ++++++++++
src/kimchi/API.json | 20 +++++++++
src/kimchi/control/base.py | 28 +++++++++----
src/kimchi/control/storagepools.py | 4 +-
src/kimchi/control/storageserver.py | 62 ++++++++++++++++++++++++++++
src/kimchi/control/storagevolumes.py | 2 +-
src/kimchi/control/utils.py | 2 +
src/kimchi/mockmodel.py | 30 ++++++++++++++
src/kimchi/model.py | 78 ++++++++++++++++++++++++++++++++++++
src/kimchi/root.py | 2 +
tests/test_rest.py | 34 ++++++++++++++++
11 files changed, 273 insertions(+), 11 deletions(-)
create mode 100644 src/kimchi/control/storageserver.py
--
1.8.1.2
10 years, 10 months
[PATCHv5 0/2] NFS prevalidation support
by lvroyce@linux.vnet.ibm.com
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Note, this patchset depends on:
[PATCH V3] add a synchronous function with timeout to execute command
v1>v4, Address naming comments,
integrate run_command patch and use context manager to deal with umount
Royce Lv (2):
utils: Add nfs prevalication
Integrate nfs path check before create nfs pool
src/kimchi/model.py | 29 +++++++++++++++++++++++++++--
src/kimchi/utils.py | 8 ++++++++
2 files changed, 35 insertions(+), 2 deletions(-)
--
1.8.1.2
10 years, 10 months
[PATCH 1/3] Plugins: Fix plugins framework in kimchi
by Rodrigo Trujillo
If the plugin tab name string is not found in kimchi i18n file, the
tab name is set as 'unknown'. This patch fixes this problem and also
adds routines to add tab html file in cherrypy configuration automati
cally.
Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo(a)linux.vnet.ibm.com>
---
src/kimchi/server.py | 38 ++++++++++++++++++++++++++++++++++++--
ui/js/src/kimchi.main.js | 2 +-
2 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/src/kimchi/server.py b/src/kimchi/server.py
index b820263..919e2e0 100644
--- a/src/kimchi/server.py
+++ b/src/kimchi/server.py
@@ -28,6 +28,10 @@ import logging.handlers
import os
import sslcert
+
+from xml.etree import ElementTree
+
+
from kimchi import auth
from kimchi import config
from kimchi import model
@@ -208,13 +212,43 @@ class Server(object):
script_name = plugin_config['kimchi']['uri']
del plugin_config['kimchi']
+ tabs_extra_file = config.get_plugin_tab_xml(plugin_name)
plugin_config['/ui/config/tab-ext.xml'] = {
'tools.staticfile.on': True,
- 'tools.staticfile.filename':
- config.get_plugin_tab_xml(plugin_name),
+ 'tools.staticfile.filename': tabs_extra_file,
'tools.nocache.on': True}
+
+ # Providing plugin tabs htmls
+ et = ElementTree.ElementTree(file=tabs_extra_file)
+
+ tabs = et.findall('tab')
+ for tab in tabs:
+ html = tab.find('path').text
+ tabs_extra_file = os.path.join(config.get_prefix(), html)
+ if html.startswith('/'):
+ html = html.replace(script_name,'')
+ else:
+ html = html.replace(script_name[1:],'')
+ plugin_config[html] = {
+ 'tools.staticfile.on': True,
+ 'tools.staticfile.filename': tabs_extra_file,
+ 'tools.nocache.on': True}
+
except KeyError:
continue
+ except IOError as e:
+ msg = "Failed to load plugin tabs file %s" %tabs_extra_file
+ cherrypy.log.error_log.error(msg)
+ cherrypy.log.error_log.error('Ignoring plugin "%s"',
+ plugin_name)
+ continue
+ except ElementTree.ParseError as e:
+ msg = "XML parse error in file %s: %s" %(
+ tabs_extra_file, e.msg)
+ cherrypy.log.error_log.error(msg)
+ cherrypy.log.error_log.error('Ignoring plugin "%s"',
+ plugin_name)
+ continue
try:
plugin_app = import_class(plugin_class)()
diff --git a/ui/js/src/kimchi.main.js b/ui/js/src/kimchi.main.js
index cc8afee..8b84a34 100644
--- a/ui/js/src/kimchi.main.js
+++ b/ui/js/src/kimchi.main.js
@@ -211,7 +211,7 @@ kimchi.getTabHtml = function(url) {
$(xmlData).find('tab').each(function() {
var $tab = $(this);
var titleKey = $tab.find('title').text();
- var title = i18n[titleKey];
+ var title = i18n[titleKey] || titleKey;
var path = $tab.find('path').text();
tabsHtml += "<li><a class='item' href=" + path + ">" + title + "</a></li>";
});
--
1.8.1.4
10 years, 10 months