[PATCH V1] Have a meaningful description for the exception test #81
by Shu Ming
This is what the case trys to test if a faked
exception can be caught properly by the task thread.
So a meaningful description is added to avoid confusing
---
tests/test_rest.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tests/test_rest.py b/tests/test_rest.py
index ca96dc0..06ceeaf 100644
--- a/tests/test_rest.py
+++ b/tests/test_rest.py
@@ -73,7 +73,8 @@ class RestTests(unittest.TestCase):
def _except_op(self, cb, opaque):
time.sleep(1)
- raise Exception("Oops")
+ raise Exception("Oops, this is an exception handle test."
+ " You can ignore it safely")
cb('success', True)
def _intermid_op(self, cb, opaque):
--
1.8.1.4
10 years, 10 months
[PATCH] bug fix: check all Red Hat distributions for yum package management
by shaohef@linux.vnet.ibm.com
From: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
There are several Red Hat distributions.
use startswith("red hat") to check this is a Red Hat distributions.
Signed-off-by: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
---
src/kimchi/repositories.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/kimchi/repositories.py b/src/kimchi/repositories.py
index 0ab0b1a..f0c6762 100644
--- a/src/kimchi/repositories.py
+++ b/src/kimchi/repositories.py
@@ -27,9 +27,7 @@ from kimchi.basemodel import Singleton
from kimchi.exception import InvalidOperation, InvalidParameter
from kimchi.exception import OperationFailed, NotFoundError, MissingParameter
-YUM_DISTROS = ['fedora', 'red hat enterprise linux',
- 'red hat enterprise linux server', 'opensuse ',
- 'suse linux enterprise server ']
+YUM_DISTROS = ['fedora', 'opensuse ', 'suse linux enterprise server ']
APT_DISTROS = ['debian', 'ubuntu']
@@ -52,7 +50,7 @@ class Repositories(object):
self._repo_storage = {}
self._distro = platform.linux_distribution()[0].lower()
- if (self._distro in YUM_DISTROS):
+ if (self._distro in YUM_DISTROS or self._distro.startswith('red hat')):
self._pkg_mnger = YumRepo()
elif (self._distro in APT_DISTROS):
self._pkg_mnger = AptRepo()
--
1.8.4.2
10 years, 10 months
[PATCH V2] Debug report file can not be found when downloading
by Shu Ming
Patchset 8bc4dded9 re-organized the various path generation for Kimchi.
Unfortunately, the root static dir was changed which caused the static
dir for debugreport file broken. To the user, he can not download the
debugreport file generated.
---
src/kimchi/mockmodel.py | 5 ++++-
src/kimchi/model/debugreports.py | 5 ++++-
src/kimchi/server.py | 12 ++++++++++--
3 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py
index b23a024..7aaf54d 100644
--- a/src/kimchi/mockmodel.py
+++ b/src/kimchi/mockmodel.py
@@ -305,7 +305,10 @@ class MockModel(object):
ctime = os.stat(file_target).st_ctime
ctime = time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime(ctime))
file_target = os.path.split(file_target)[-1]
- file_target = os.path.join("/data/debugreports", file_target)
+
+ prefix = '/data/debugreports'
+ file_target = os.path.join(prefix, file_target)
+
return {'file': file_target,
'ctime': ctime}
diff --git a/src/kimchi/model/debugreports.py b/src/kimchi/model/debugreports.py
index 7573a5b..64ed8e8 100644
--- a/src/kimchi/model/debugreports.py
+++ b/src/kimchi/model/debugreports.py
@@ -164,7 +164,10 @@ class DebugReportModel(object):
ctime = os.stat(file_target).st_ctime
ctime = time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime(ctime))
file_target = os.path.split(file_target)[-1]
- file_target = os.path.join("/data/debugreports", file_target)
+
+ prefix = '/data/debugreports'
+ file_target = os.path.join(prefix, file_target)
+
return {'file': file_target,
'ctime': ctime}
diff --git a/src/kimchi/server.py b/src/kimchi/server.py
index ef8e701..401136f 100644
--- a/src/kimchi/server.py
+++ b/src/kimchi/server.py
@@ -108,11 +108,10 @@ class Server(object):
},
'/data/debugreports': {
'tools.staticdir.on': True,
- 'tools.staticdir.dir': 'data/debugreports',
'tools.nocache.on': False,
'tools.kimchiauth.on': True,
'tools.staticdir.content_types': {'xz': 'application/x-xz'}
- },
+ },
'/config/ui/tabs.xml': {
'tools.staticfile.on': True,
'tools.staticfile.filename': 'config/ui/tabs.xml',
@@ -129,7 +128,16 @@ class Server(object):
}
}
+ def __update_debugreport_config(self):
+ debug_dict = self.configObj['/data/debugreports']
+ if paths.installed:
+ debug_path = os.path.join(paths.state_dir, 'debugreports')
+ debug_dict.update({'tools.staticdir.dir': debug_path})
+ else:
+ debug_dict.update({'tools.staticdir.dir': 'data/debugreports'})
+
def __init__(self, options):
+ self.__update_debugreport_config()
make_dirs = [
os.path.dirname(os.path.abspath(options.access_log)),
os.path.dirname(os.path.abspath(options.error_log)),
--
1.8.1.4
10 years, 10 months
[PATCH V3] Fix Add Network window
by Rodrigo Trujillo
VLans and Interfaces must only be available for selection if network
type Bridge is selected. This restriction was not implemented in the UI.
This patch fixes this problem.
Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo(a)linux.vnet.ibm.com>
---
ui/js/src/kimchi.network.js | 22 +++++++++++++++++++++-
ui/pages/tabs/network.html.tmpl | 20 +++++++++++---------
2 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/ui/js/src/kimchi.network.js b/ui/js/src/kimchi.network.js
index faf1285..c0fe4ff 100644
--- a/ui/js/src/kimchi.network.js
+++ b/ui/js/src/kimchi.network.js
@@ -210,11 +210,28 @@ kimchi.openNetworkDialog = function(okCallback) {
$("#networkConfig").dialog("open");
};
+kimchi.enableBridgeOptions = function(enable) {
+ if (!enable) {
+ $("#enableVlan").attr("checked", false);
+ $("#networkVlanID").prop("disabled", true);
+ $("#networkVlanID").val("");
+ $("#networkInterface").val("");
+ $("#bridge-options").slideUp(100);
+ } else if (!$("#networkInterface").val()){
+ $("#networkInterface").prop("selectedIndex", 0);
+ $("#bridge-options").slideDown(100);
+ }
+};
+
kimchi.setDefaultNetworkType = function(isInterfaceAvail) {
$("#networkTypeBri").prop("checked", isInterfaceAvail);
$("#networkTypeBri").prop("disabled", !isInterfaceAvail);
- $("#networkInterface").prop("disabled", !isInterfaceAvail);
$("#networkTypeNat").prop("checked", !isInterfaceAvail);
+ if (!isInterfaceAvail) {
+ kimchi.enableBridgeOptions(false);
+ } else {
+ $("#bridge-options").slideDown(100);
+ }
};
kimchi.getNetworkDialogValues = function() {
@@ -250,12 +267,15 @@ kimchi.setupNetworkFormEvent = function() {
});
$("#networkTypeIso").on("click", function(event) {
$("#networkInterface").prop("disabled", true);
+ kimchi.enableBridgeOptions(false);
});
$("#networkTypeNat").on("click", function(event) {
$("#networkInterface").prop("disabled", true);
+ kimchi.enableBridgeOptions(false);
});
$("#networkTypeBri").on("click", function(event) {
$("#networkInterface").prop("disabled", false);
+ kimchi.enableBridgeOptions(true);
});
};
diff --git a/ui/pages/tabs/network.html.tmpl b/ui/pages/tabs/network.html.tmpl
index 83c1d7e..4340e19 100644
--- a/ui/pages/tabs/network.html.tmpl
+++ b/ui/pages/tabs/network.html.tmpl
@@ -71,15 +71,17 @@
<input type="radio" id="networkTypeBri" name="networkType" value="bridged">
<label for="networkTypeBri">$_("Bridged: Virtual machines are connected to physical network directly")</label>
</div>
- <div class="destination">
- <label>$_("Destination"): </label>
- <select id="networkInterface"></select>
- </div>
- <div class="VLAN">
- <label for="enableVlan">$_("Enable VLAN"): </label>
- <input id="enableVlan" type="checkbox" value=""/>
- <label>$_("VLAN ID"): </label>
- <input type="text" id="networkVlanID" disabled>
+ <div id=bridge-options>
+ <div class="destination">
+ <label>$_("Destination"): </label>
+ <select id="networkInterface"></select>
+ </div>
+ <div class="VLAN">
+ <label for="enableVlan">$_("Enable VLAN"): </label>
+ <input id="enableVlan" type="checkbox" value=""/>
+ <label>$_("VLAN ID"): </label>
+ <input type="text" id="networkVlanID" disabled>
+ </div>
</div>
</div>
</div>
--
1.8.5.3
10 years, 10 months
[PATCH] Set default combo box style to storage pool type list
by Aline Manera
From: Aline Manera <alinefm(a)br.ibm.com>
While creating a new storage pool the supported types are listed in a
combo box which does not have the default style used in Kimchi.
Fix it.
Signed-off-by: Aline Manera <alinefm(a)br.ibm.com>
---
ui/css/theme-default/button.css | 4 ++++
ui/js/widgets/select-menu.js | 4 ++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/ui/css/theme-default/button.css b/ui/css/theme-default/button.css
index 014ad20..3437c62 100644
--- a/ui/css/theme-default/button.css
+++ b/ui/css/theme-default/button.css
@@ -121,6 +121,10 @@
right: 10px;
}
+.btn .input {
+ margin-left: 10px;
+}
+
/* Generated at http://colorzilla.com/gradient-editor/ */
.btn-tool {
display: inline-block;
diff --git a/ui/js/widgets/select-menu.js b/ui/js/widgets/select-menu.js
index c213f3c..449104d 100644
--- a/ui/js/widgets/select-menu.js
+++ b/ui/js/widgets/select-menu.js
@@ -27,7 +27,7 @@
this.listControl.html('');
this.target = this.selectDiv.find('input').first();
this.label = this.selectDiv.find('span').first();
- this.selectDiv.addClass('btn-select dropdown popable');
+ this.selectDiv.addClass('btn dropdown popable');
this.target.addClass('input');
this.label.addClass('input');
this.listControl.addClass('select-list');
@@ -75,7 +75,7 @@
},
destroy : function() {
- this.selectDiv.removeClass('btn-select dropdown popable');
+ this.selectDiv.removeClass('btn dropdown popable');
this.target.removeClass('input');
this.label.removeClass('input');
this.listControl.removeClass('select-list');
--
1.7.10.4
10 years, 10 months
[PATCHv2 0/3] Fix vm creation on readonly pool type
by lvroyce@linux.vnet.ibm.com
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Some pool types (scsi, iscsi, mpath) do not allow create/delete
storage volume, so it is wrong to delete these volumes when vm delete.
Fix it by just delete non read only pool types.
Royce Lv (3):
Fix vm creation storage rollback clean
Prevent volume create and delete for certain pool types
Clear pep8 failure in make check
src/kimchi/config.py.in | 3 +++
src/kimchi/control/base.py | 2 ++
src/kimchi/i18n.py | 1 +
src/kimchi/isoinfo.py | 4 ++--
src/kimchi/model/storageservers.py | 4 ++--
src/kimchi/model/storagevolumes.py | 18 +++++++++++++++---
src/kimchi/model/vms.py | 14 ++++++--------
tests/test_model.py | 8 ++++----
8 files changed, 35 insertions(+), 19 deletions(-)
--
1.8.1.2
10 years, 10 months
[PATCH] Don't allow templates to be created with ISOs that won't be usable.
by Christy Perez
qemu can't use an ISO if 'other' can't execute all the directories
containing the file. Return an error explaning this, and suggest
the way to fix it.
Signed-off-by: Christy Perez <christy(a)linux.vnet.ibm.com>
---
po/en_US.po | 6 ++++++
src/kimchi/exception.py | 4 ++++
src/kimchi/i18n.py | 2 ++
src/kimchi/utils.py | 9 +++++++++
src/kimchi/vmtemplate.py | 7 +++++--
5 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/po/en_US.po b/po/en_US.po
index ca1fe86..38af64c 100644
--- a/po/en_US.po
+++ b/po/en_US.po
@@ -674,6 +674,12 @@ msgid "Bad format while reading volume descriptor in ISO %(filename)s"
msgstr ""
#, python-format
+msgid "The hypervisor doesn't have permission to use this ISO %(filename)s. \
+ Consider moving it under /var/lib/libvirt, or \
+ (not recommended) 'chmod -R o+x 'path_to_iso'."
+msgstr ""
+
+#, python-format
msgid "Virtual machine %(name)s already exists"
msgstr ""
diff --git a/src/kimchi/exception.py b/src/kimchi/exception.py
index 2d974a8..263bd0c 100644
--- a/src/kimchi/exception.py
+++ b/src/kimchi/exception.py
@@ -75,6 +75,10 @@ class InvalidParameter(KimchiException):
pass
+class InvalidPermission(KimchiException):
+ pass
+
+
class InvalidOperation(KimchiException):
pass
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index fea0184..05b347c 100644
--- a/src/kimchi/i18n.py
+++ b/src/kimchi/i18n.py
@@ -57,6 +57,8 @@ messages = {
"KCHISO0005E": _("Invalid El Torito boot indicator in ISO %(filename)s"),
"KCHISO0006E": _("Unexpected volume type for primary volume in ISO %(filename)s"),
"KCHISO0007E": _("Bad format while reading volume descriptor in ISO %(filename)s"),
+ "KCHISO0008E": _("The hypervisor doesn't have permission to use this ISO %(filename)s. \
+ Consider moving it under /var/lib/libvirt, or (not recommended) 'chmod -R o+x 'path_to_iso'." ),
"KCHVM0001E": _("Virtual machine %(name)s already exists"),
"KCHVM0002E": _("Virtual machine %(name)s does not exist"),
diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
index 6be1c04..c325be3 100644
--- a/src/kimchi/utils.py
+++ b/src/kimchi/utils.py
@@ -27,6 +27,7 @@ import psutil
import re
import subprocess
import urllib2
+import stat
from threading import Timer
from cherrypy.lib.reprconf import Parser
@@ -234,3 +235,11 @@ def run_setfacl_set_attr(path, attr="r", user=""):
set_user = ["setfacl", "--modify", "user:%s:%s" % (user, attr), path]
out, error, ret = run_command(set_user)
return ret == 0
+
+def check_iso_path_perm(path):
+ """
+ libvirt requires that all parent dirs have o+x
+ """
+ if path == '/': return True
+ return os.stat(path).st_mode & stat.S_IXOTH and \
+ check_iso_path_perm(os.path.dirname(path))
diff --git a/src/kimchi/vmtemplate.py b/src/kimchi/vmtemplate.py
index af07ee3..76ac772 100644
--- a/src/kimchi/vmtemplate.py
+++ b/src/kimchi/vmtemplate.py
@@ -29,9 +29,9 @@ import urlparse
from kimchi import isoinfo
from kimchi import osinfo
-from kimchi.exception import InvalidParameter, IsoFormatError
+from kimchi.exception import InvalidParameter, IsoFormatError, InvalidPermission
from kimchi.isoinfo import IsoImage
-
+from kimchi.utils import check_iso_path_perm
QEMU_NAMESPACE = "xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'"
@@ -55,6 +55,9 @@ class VMTemplate(object):
iso_distro = iso_version = 'unknown'
iso = args.get('cdrom', '')
+ if iso.startswith('/') and \
+ not check_iso_path_perm(os.path.dirname(iso)):
+ raise InvalidPermission("KCHISO0008E", {'filename': iso})
if scan and len(iso) > 0:
iso_distro, iso_version = self.get_iso_info(iso)
if not iso.startswith('/'):
--
1.8.5.3
10 years, 10 months
[PATCH] bug fix: Make URI parameter is not None before encoding it
by Aline Manera
From: Aline Manera <alinefm(a)br.ibm.com>
The following error is raised when the user tried to reboot the host
system:
Request Headers:
AUTHORIZATION: Basic YWxpbmVmbTowaG5lKjI4ZGljSA==
Content-Length: 2
HOST: localhost:8000
Remote-Addr: 127.0.0.1
ACCEPT: application/json
USER-AGENT: curl/7.27.0
Content-Type: application/json
[25/Feb/2014:14:05:28] HTTP Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/cherrypy/_cprequest.py", line 656, in respond
response.body = self.handler()
File "/usr/lib/python2.7/dist-packages/cherrypy/lib/encoding.py", line 188, in __call__
self.body = self.oldhandler(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/cherrypy/_cpdispatch.py", line 34, in __call__
return self.callable(*self.args, **self.kwargs)
File "/home/alinefm/kimchi/src/kimchi/control/base.py", line 79, in wrapper
for arg in self.model_args])
AttributeError: 'NoneType' object has no attribute 'encode'
It is because /host resource has no parameter and fails to encode() the
None value.
So fix it by verifying the parameter is not None in order to make the
encode() call.
Signed-off-by: Aline Manera <alinefm(a)br.ibm.com>
---
src/kimchi/control/base.py | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/kimchi/control/base.py b/src/kimchi/control/base.py
index 91a70ae..5d1f380 100644
--- a/src/kimchi/control/base.py
+++ b/src/kimchi/control/base.py
@@ -75,9 +75,13 @@ class Resource(object):
fn = getattr(self.model, model_fn(self, action_name))
ident = fn(*model_args)
self._redirect(ident)
- uri_params = tuple([urllib2.quote(arg.encode('utf-8'), safe="")
- for arg in self.model_args])
- raise internal_redirect(self.uri_fmt % uri_params)
+ uri_params = []
+ for arg in self.model_args:
+ if arg is None:
+ arg = ''
+ uri_params.append(urllib2.quote(arg.encode('utf-8'),
+ safe=""))
+ raise internal_redirect(self.uri_fmt % tuple(uri_params))
except MissingParameter, e:
raise cherrypy.HTTPError(400, e.message)
except InvalidParameter, e:
--
1.7.10.4
10 years, 10 months
[PATCH] run_command: log error messages using higher log level when return code is non-zero
by zhshzhou@linux.vnet.ibm.com
From: Zhou Zheng Sheng <zhshzhou(a)linux.vnet.ibm.com>
run_command logs stdout and stderr output using the "debug" level. In
this patch, if returncode is non-zero, it logs stderr output using the
"error" level. It's helpful for diagnosing underlying command errors.
Signed-off-by: Zhou Zheng Sheng <zhshzhou(a)linux.vnet.ibm.com>
---
src/kimchi/utils.py | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
index d4ab1a1..e89a93f 100644
--- a/src/kimchi/utils.py
+++ b/src/kimchi/utils.py
@@ -169,8 +169,13 @@ def run_command(cmd, timeout=None):
out, error = proc.communicate()
kimchi_log.debug("Run command: '%s'", " ".join(cmd))
- if out or error:
- kimchi_log.debug("out:\n %s\nerror:\n %s", out, error)
+ if out:
+ kimchi_log.debug("out:\n%s", out)
+
+ if proc.returncode != 0:
+ kimchi_log.error("rc: %s\nerror:\n%s", proc.returncode, error)
+ elif error:
+ kimchi_log.debug("error:\n%s", error)
if timeout_flag[0]:
msg = ("subprocess is killed by signal.SIGKILL for "
--
1.8.5.3
10 years, 10 months
[PATCH] Fix tests: restore the monkey patch after testing Paths
by Mark Wu
To test path vars, we monkey patched the method get_prefix of
Paths, but not restored. Because of it, the other test cases, like
test_plugin, fail to pass. This patch restores the change on teardown.
Reported-by: Zhou Zheng Sheng <zhshzhou(a)linux.vnet.ibm.com>
Signed-off-by: Mark Wu <wudxw(a)linux.vnet.ibm.com>
---
tests/test_config.py.in | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/tests/test_config.py.in b/tests/test_config.py.in
index 3b9ebdc..0400645 100644
--- a/tests/test_config.py.in
+++ b/tests/test_config.py.in
@@ -25,6 +25,17 @@ import unittest
from kimchi.config import Paths, PluginPaths
+get_prefix = None
+
+
+def setUpModule():
+ global get_prefix
+ get_prefix = Paths.get_prefix
+
+
+def tearDownModule():
+ Paths.get_prefix = PluginPaths.get_prefix = get_prefix
+
class ConfigTests(unittest.TestCase):
def assertInstalledPath(self, actual, expected):
--
1.8.4.2
10 years, 10 months