[PATCH] Handle transient VM requests differently
by Christy Perez
If a transient (or non-persistent) VM is created outside of
Kimchi, it will (expectedly) be deleted when shutdown. However,
Kimchi calls a GET after shutdown and other POST requests. When
the GET fails because the VM has been deleted, a user will get
an error. However, this is not an error condition.
This patch checks to see if a VM is transient, and if so, does not
call the subsequent GET on the VM.
---
src/kimchi/control/base.py | 13 +++++++++----
src/kimchi/control/vms.py | 17 +++++++++++++----
src/kimchi/i18n.py | 1 +
src/kimchi/model/vms.py | 9 ++++++++-
4 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/src/kimchi/control/base.py b/src/kimchi/control/base.py
index 97e789f..8048370 100644
--- a/src/kimchi/control/base.py
+++ b/src/kimchi/control/base.py
@@ -63,7 +63,8 @@ def _redirect(self, ident, code=303):
uri_params += [urllib2.quote(ident.encode('utf-8'), safe="")]
raise cherrypy.HTTPRedirect(self.uri_fmt % tuple(uri_params), code)
- def generate_action_handler(self, action_name, action_args=None):
+ def generate_action_handler(self, action_name, action_args=None,
+ ignore_not_found=False):
def _render_element(self, ident):
self._redirect(ident)
uri_params = []
@@ -75,7 +76,7 @@ def _render_element(self, ident):
raise internal_redirect(self.uri_fmt % tuple(uri_params))
return self._generate_action_handler_base(action_name, _render_element,
- action_args)
+ ignore_not_found, action_args)
def generate_action_handler_task(self, action_name, action_args=None):
def _render_task(self, task):
@@ -86,7 +87,7 @@ def _render_task(self, task):
action_args)
def _generate_action_handler_base(self, action_name, render_fn,
- action_args=None):
+ ignore_not_found, action_args=None):
def wrapper(*args, **kwargs):
validate_method(('POST'), self.role_key, self.admin_methods)
try:
@@ -111,7 +112,11 @@ def wrapper(*args, **kwargs):
except UnauthorizedError, e:
raise cherrypy.HTTPError(403, e.message)
except NotFoundError, e:
- raise cherrypy.HTTPError(404, e.message)
+ if ignore_not_found is True:
+ # Should something be returned instead?
+ pass
+ else:
+ raise cherrypy.HTTPError(404, e.message)
except OperationFailed, e:
raise cherrypy.HTTPError(500, e.message)
except KimchiException, e:
diff --git a/src/kimchi/control/vms.py b/src/kimchi/control/vms.py
index 1a84b6c..82682af 100644
--- a/src/kimchi/control/vms.py
+++ b/src/kimchi/control/vms.py
@@ -21,7 +21,6 @@
from kimchi.control.utils import internal_redirect, UrlSubNode
from kimchi.control.vm import sub_nodes
-
@UrlSubNode('vms', True)
class VMs(Collection):
def __init__(self, model):
@@ -37,12 +36,22 @@ def __init__(self, model, ident):
self.role_key = 'guests'
self.screenshot = VMScreenShot(model, ident)
self.uri_fmt = '/vms/%s'
+ _ignore_not_found = False
+ try:
+ # the test driver causes an exception in is_persistent()
+ _ignore_not_found = \
+ not model.vm_is_persistent(self.ident.decode('utf-8'))
+ except:
+ pass
for ident, node in sub_nodes.items():
setattr(self, ident, node(model, self.ident))
self.start = self.generate_action_handler('start')
- self.poweroff = self.generate_action_handler('poweroff')
- self.shutdown = self.generate_action_handler('shutdown')
- self.reset = self.generate_action_handler('reset')
+ self.poweroff = self.generate_action_handler('poweroff',
+ ignore_not_found = _ignore_not_found)
+ self.shutdown = self.generate_action_handler('shutdown',
+ ignore_not_found = _ignore_not_found)
+ self.reset = self.generate_action_handler('reset',
+ ignore_not_found = _ignore_not_found)
self.connect = self.generate_action_handler('connect')
self.clone = self.generate_action_handler_task('clone')
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index 4eccc3e..4ab08d1 100644
--- a/src/kimchi/i18n.py
+++ b/src/kimchi/i18n.py
@@ -106,6 +106,7 @@
"KCHVM0033E": _("Virtual machine '%(name)s' must be stopped before cloning it."),
"KCHVM0034E": _("Insufficient disk space to clone virtual machine '%(name)s'"),
"KCHVM0035E": _("Unable to clone VM '%(name)s'. Details: %(err)s"),
+ "KCHVM0036E": _("Invalid operation for non-persistent virtual machine %(name)s"),
"KCHVMHDEV0001E": _("VM %(vmid)s does not contain directly assigned host device %(dev_name)s."),
"KCHVMHDEV0002E": _("The host device %(dev_name)s is not allowed to directly assign to VM."),
diff --git a/src/kimchi/model/vms.py b/src/kimchi/model/vms.py
index bae27c1..d3b4f1f 100644
--- a/src/kimchi/model/vms.py
+++ b/src/kimchi/model/vms.py
@@ -760,9 +760,13 @@ def lookup(self, name):
'users': users,
'groups': groups,
'access': 'full',
- 'persistent': True if dom.isPersistent() else False
+ 'persistent': self.is_persistent(name)
}
+ def is_persistent(self, name):
+ dom = self.get_vm(name, self.conn)
+ return True if dom.isPersistent() else False
+
def _vm_get_disk_paths(self, dom):
xml = dom.XMLDesc(0)
xpath = "/domain/devices/disk[@device='disk']/source/@file"
@@ -784,6 +788,9 @@ def get_vm(name, conn):
def delete(self, name):
conn = self.conn.get()
dom = self.get_vm(name, self.conn)
+ if not dom.isPersistent():
+ raise InvalidOperation("KCHVM0036E", {'name': name})
+
self._vmscreenshot_delete(dom.UUIDString())
paths = self._vm_get_disk_paths(dom)
info = self.lookup(name)
--
1.9.3
9 years, 11 months
[PATCH] UI: Customize jQuery UI Tabs Widget
by huoyuxin@linux.vnet.ibm.com
From: Yu Xin Huo <huoyuxin(a)linux.vnet.ibm.com>
Signed-off-by: Yu Xin Huo <huoyuxin(a)linux.vnet.ibm.com>
---
ui/css/theme-default/tabs.css | 28 ++++++++++++++++++++++++++++
ui/css/theme-default/theme.css | 32 ++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 0 deletions(-)
create mode 100644 ui/css/theme-default/tabs.css
create mode 100644 ui/css/theme-default/theme.css
diff --git a/ui/css/theme-default/tabs.css b/ui/css/theme-default/tabs.css
new file mode 100644
index 0000000..7d7dd6c
--- /dev/null
+++ b/ui/css/theme-default/tabs.css
@@ -0,0 +1,28 @@
+.ui-tabs {
+ border: 0 none !important;
+ padding: 0;
+ position: relative;
+}
+
+.ui-tabs .ui-tabs-nav {
+ background: none;
+ border-color: #ededed;
+ border-width: 0 0 2px;
+}
+
+.ui-tabs .ui-tabs-nav li {
+ background: none;
+ border-width: 0;
+ padding: 0 0px 1px;
+}
+
+.ui-tabs .ui-tabs-nav li.ui-tabs-active {
+ border-bottom: 2px solid #008abf;
+ margin-bottom: -2px;
+ font-weight: bold;
+}
+
+.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
+ line-height: 1;
+ padding: 10px 20px 5px;
+}
diff --git a/ui/css/theme-default/theme.css b/ui/css/theme-default/theme.css
new file mode 100644
index 0000000..48df973
--- /dev/null
+++ b/ui/css/theme-default/theme.css
@@ -0,0 +1,32 @@
+/*
+ * Customize jQuery UI default theme
+ */
+
+.ui-widget {
+ font-family: 'Helvetica Neue', Helvetica, Arial;
+}
+
+.ui-widget input,
+.ui-widget select,
+.ui-widget textarea,
+.ui-widget button {
+ font-family: 'Helvetica Neue', Helvetica, Arial;
+}
+
+.ui-state-active a,
+.ui-state-active a:link,
+.ui-state-active a:visited {
+ color: #222222;
+}
+
+.ui-state-default a,
+.ui-state-default a:link,
+.ui-state-default a:visited {
+ color: #222222;
+}
+
+.ui-state-default,
+.ui-widget-content .ui-state-default,
+.ui-widget-header .ui-state-default {
+ font-weight: normal;
+}
--
1.7.1
9 years, 11 months
[PATCH] UI: Add Kimchi message widget for new kimchi UI
by Wen Wang
Signed-off-by: Wen Wang <wenwang(a)linux.vnet.ibm.com>
---
ui/css/theme-default/message-flat.css | 87 +++++++++++++++++++++++++++++++
ui/js/widgets/message-flat.js | 97 +++++++++++++++++++++++++++++++++++
2 files changed, 184 insertions(+)
create mode 100644 ui/css/theme-default/message-flat.css
create mode 100644 ui/js/widgets/message-flat.js
diff --git a/ui/css/theme-default/message-flat.css b/ui/css/theme-default/message-flat.css
new file mode 100644
index 0000000..8281bff
--- /dev/null
+++ b/ui/css/theme-default/message-flat.css
@@ -0,0 +1,87 @@
+/*
+* Project Kimchi
+*
+* Copyright IBM, Corp. 2015
+*
+* Licensed under the Apache License, Version 2.0 (the 'License');
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an 'AS IS' BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+.border-grey {
+ background-clip: border-box;
+ border: 6px solid rgba(170,170,170,0.3);
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ margin: auto;
+ width: 502px;
+ height: 202px;
+ border-radius: 5px;
+}
+
+.message-dialog {
+ border: 3px solid #999999;
+ height: 198px;
+ width: 498px;
+ background: white;
+}
+
+.message-dialog .message-inline {
+ display: inline-block;
+}
+
+.message-dialog .message-type-icon {
+ position: absolute;
+ margin: 20px 20px;
+ color: #008ABF;
+ font-size: 50px;
+}
+
+.message-dialog .message-main {
+ position: relative;
+ margin: 30px 0 0 110px;
+ width: 350px;
+}
+
+.message-dialog .message-confirm-info {
+ margin: 20px 0 0 110px;
+ width: 350px;
+}
+
+.message-dialog .message-footer {
+ position: absolute;
+ left: 3px;
+ right: 1px;
+ bottom: 1px;
+ height: 50px;
+ background-color: #008ABF;
+}
+
+.message-dialog .message-footer .message-button {
+ display: inline-block;
+ background-color: white;
+ width: 75px;
+ height: 30px;
+ line-height: 30px;
+ position: relative;
+ margin-left: 10px;
+ margin-top: 10px;
+ text-align: center;
+ vertical-align: middle;
+}
+
+.message-dialog .message-footer .message-button:hover{
+ background-color: #EEEEEE;
+ cursor: pointer;
+}
\ No newline at end of file
diff --git a/ui/js/widgets/message-flat.js b/ui/js/widgets/message-flat.js
new file mode 100644
index 0000000..1ab6aa3
--- /dev/null
+++ b/ui/js/widgets/message-flat.js
@@ -0,0 +1,97 @@
+/*
+* Project Kimchi
+*
+* Copyright IBM, Corp. 2015
+*
+* Licensed under the Apache License, Version 2.0 (the 'License');
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an 'AS IS' BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/* How to use:
+* $(".selector").messageFlat({
+* contentMain: "This is a test", //Content you are going to add
+* contentConfirm: "Sure?" //Content that inform user whether they want to continue.
+* //Default value is: "Are you sure you want to go on?"
+* confirm: function() {
+* //Function after confirm
+* }
+* });
+*/
+
+(function( $ ) {
+ $.widget("kimchi.messageFlat", {
+ options: {
+ autoOpen: true,
+ contentMain: null,
+ contentConfirm: "Are you sure you want to go on?",
+ confirm: null
+ },
+
+ _create: function() {
+ var that = this;
+ var msg = that.options.contentMain;
+ var cfm = that.options.contentConfirm;
+ $(".body").addClass("style:'opacity:0.5'");
+ that._open();
+ $(".message-type-icon").addClass("icon-help-circled-1");
+ $(".message-dialog .message-content .message-main").text(msg);
+ $(".message-dialog .message-confirm-info").text(cfm);
+ $(".message-dialog .message-cancel").on("click", that.destroy);
+ $(".message-dialog .message-okay").on("click", function() {
+ that._trigger("confirm");
+ that.destroy();
+ });
+ },
+
+ _open: function() {
+ var html =
+ "<div id='overlay'></div>" +
+ "<div class='border-grey'>" +
+ "<div class='message-dialog'>" +
+ "<div class='message-content'>" +
+ "<div class='message-inline message-type-icon'></div>" +
+ "<div class='message-inline message-main'></div>" +
+ "</div>" +
+ "<div class='message-confirm-info'></div>" +
+ "<div class='message-footer'>" +
+ "<div class='message-button message-okay'>Ok</div>" +
+ "<div class='message-button message-cancel'>Cancel</div>" +
+ "</div>" +
+ "</div>" +
+ "</div>";
+ if (this.options.autoOpen) {
+ $(html).appendTo($("body"));
+ var pageWidth = window.screen.width;
+ var pageHeight = window.screen.height;
+ var pageLeft = document.screenLeft
+ var pageTop = document.screenTop;
+ var topOffset = "-" + pageHeight + "px";
+ console.log(topOffset);
+ $("#overlay").css({
+ "opacity": "0.5",
+ "Left": pageLeft,
+ "Top": pageTop,
+ "background-color": "white",
+ "width": pageWidth,
+ "height": pageHeight,
+ "margin-top": topOffset,
+ "overflow": "hidden"
+ });
+ }
+ },
+
+ destroy: function() {
+ $(".border-grey").remove();
+ $("#overlay").remove();
+ }
+ });
+})(jQuery);
\ No newline at end of file
--
2.1.0
9 years, 11 months
[PATCH] UI: Grid Widget
by huoyuxin@linux.vnet.ibm.com
From: Yu Xin Huo <huoyuxin(a)linux.vnet.ibm.com>
Signed-off-by: Yu Xin Huo <huoyuxin(a)linux.vnet.ibm.com>
---
ui/css/theme-default/datagrid.css | 45 ++++++++++++++++++
ui/js/widgets/grid.js | 93 +++++++++++++++++++++++++++++++++++++
2 files changed, 138 insertions(+), 0 deletions(-)
create mode 100644 ui/css/theme-default/datagrid.css
create mode 100644 ui/js/widgets/grid.js
diff --git a/ui/css/theme-default/datagrid.css b/ui/css/theme-default/datagrid.css
new file mode 100644
index 0000000..635c818
--- /dev/null
+++ b/ui/css/theme-default/datagrid.css
@@ -0,0 +1,45 @@
+.grid span {
+ display: inline-block;
+}
+
+.grid .header {
+ padding-bottom: 1px;
+ border-bottom: solid 2px #ededed;
+}
+
+.grid .header span span {
+ vertical-align: middle;
+}
+
+.grid .header .sort-up {
+ margin-bottom: -9px;
+ cursor: pointer;
+}
+
+.grid .header .sort-down {
+ margin-top: -9px;
+ cursor: pointer;
+}
+
+.grid .header > span:first-child,
+.grid .body .row > span:first-child {
+ padding-left: 10px;
+}
+
+.grid .body .row {
+ height: 46px;
+ line-height: 46px;
+ border-bottom: solid 1px #ededed;
+}
+
+.grid .body .row[disabled] {
+ color: #999999;
+}
+
+.grid .body .odd {
+ background-color: #fcfcfc;
+}
+
+.grid .body .even {
+ background-color: #ffffff;
+}
diff --git a/ui/js/widgets/grid.js b/ui/js/widgets/grid.js
new file mode 100644
index 0000000..565caed
--- /dev/null
+++ b/ui/js/widgets/grid.js
@@ -0,0 +1,93 @@
+$(function(){
+$.widget("kimchi.grid", {
+ options: {
+ enableSorting: true
+ },
+ _create: function() {
+ var that = this;
+ this.element.addClass('grid');
+ var head = $(this.element.children().get(0));
+ var body = $(this.element.children().get(1));
+ head.addClass('header c1 bold grey');
+ if(this.options.enableSorting){
+ head.children().each(function(){
+ var addSorting = "<span>"+$(this).html()+"</span>";
+ addSorting += "<span><div class='icon-angle-up sort-up'></div><div class='icon-angle-down sort-down'></div></span>";
+ $(this).empty().append(addSorting);
+ });
+ }
+ $('.icon-angle-up', head).click(function(){
+ that.sort(head.children().index($(this).parent().parent()), true);
+ });
+ $('.icon-angle-down', head).click(function(){
+ that.sort(head.children().index($(this).parent().parent()), false);
+ });
+ body.addClass('body c1 normal dark-grey');
+ body.children().addClass('row');
+ this._setRowBackgroud();
+ },
+ _setRowBackgroud: function(){
+ var i=0, classes=['odd', 'even'];
+ $(this.element.children().get(1)).children().each(function(){
+ $(this).removeClass('odd');
+ $(this).removeClass('even');
+ $(this).addClass(classes[i]);
+ i = i==0?1:0;
+ });
+ },
+ sort: function(column, assending) {
+ var head = $(this.element.children().get(0));
+ $('.icon-up-dir', head).removeClass('icon-up-dir').addClass('icon-angle-up');
+ $('.icon-down-dir', head).removeClass('icon-down-dir').addClass('icon-angle-down');
+ var columnCell = $(head.children().get(column));
+ if(assending){
+ $('.icon-angle-up', columnCell).removeClass('icon-angle-up').addClass('icon-up-dir');
+ }else{
+ $('.icon-angle-down', columnCell).removeClass('icon-angle-down').addClass('icon-down-dir');
+ }
+ var container = $(this.element.children().get(1));
+ var keys = [], map = {};
+ container.children().each(function(){
+ var key = $($(this).children().get(column)).attr('val');
+ keys.push(key);
+ map[key] = $(this);
+ });
+ keys.sort();
+ if(!assending) keys.reverse();
+ container.empty();
+ for(var i=0;i<keys.length;i++){
+ container.append(map[keys[i]]);
+ }
+ this._setRowBackgroud();
+ },
+ filter: function(keyword) {
+ keyword = keyword.toLowerCase();
+ var container = $(this.element.children().get(1));
+ container.children().each(function(){
+ var hide = true;
+ $(this).children().each(function(){
+ if($(this).attr('val').toLowerCase().indexOf(keyword)!=-1){
+ hide = false;
+ return false;
+ }
+ });
+ $(this).css('display', hide?'none':'');
+ });
+ this._setRowBackgroud();
+ },
+ _destroy: function() {
+ this.element.removeClass('grid');
+ var head = $(this.element.children().get(0));
+ var body = $(this.element.children().get(1));
+ head.removeClass('header c1 bold grey');
+ if(this.options.enableSorting){
+ head.children().each(function(){
+ var oriContent = $($(this).children().get(0)).html()
+ $(this).empty().append(oriContent);
+ });
+ }
+ body.removeClass('body c1 normal dark-grey');
+ body.children().removeClass('row odd even');
+ }
+});
+});
--
1.7.1
9 years, 11 months
[PATCH 0/8] Storage pool tests and bug fixes
by Aline Manera
Aline Manera (8):
Rename test_storagepool.py to test_storagepoolxml.py
Storage Pools: Update docs/API.md
Storage pool: Fix encoding/decoding while dealing with storage pools
MockModel: Override storage pool validation
MockModel: Add mock code to list partitions to /host/partitions API
MockModel: Extend logical storage pool
MockModel: Fix devices filter
Storage pool tests
docs/API.md | 5 +-
src/kimchi/mockmodel.py | 45 ++++++++
src/kimchi/model/storagepools.py | 6 +-
tests/test_mock_storagepool.py | 156 ++++++++++++++++++++++++++
tests/test_model.py | 70 ------------
tests/test_rest.py | 120 +-------------------
tests/test_storagepool.py | 236 ++++++++++++++-------------------------
tests/test_storagepoolxml.py | 171 ++++++++++++++++++++++++++++
tests/utils.py | 11 ++
9 files changed, 476 insertions(+), 344 deletions(-)
create mode 100644 tests/test_mock_storagepool.py
create mode 100644 tests/test_storagepoolxml.py
--
2.1.0
9 years, 11 months
[PATCH] UI: Add messagebar widget
by Wen Wang
1) Add sample for widget
2) Add messagebar as widget
Signed-off-by: Wen Wang <wenwang(a)linux.vnet.ibm.com>
---
ui/css/theme-default/messagebar-flat.css | 63 +++++++++++++++++++++++++++++
ui/js/widgets/messagebar-flat.js | 65 ++++++++++++++++++++++++++++++
ui/js/widgets/samples/messagebar-flat.html | 29 +++++++++++++
3 files changed, 157 insertions(+)
create mode 100644 ui/css/theme-default/messagebar-flat.css
create mode 100644 ui/js/widgets/messagebar-flat.js
create mode 100644 ui/js/widgets/samples/messagebar-flat.html
diff --git a/ui/css/theme-default/messagebar-flat.css b/ui/css/theme-default/messagebar-flat.css
new file mode 100644
index 0000000..86605cd
--- /dev/null
+++ b/ui/css/theme-default/messagebar-flat.css
@@ -0,0 +1,63 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2015
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+.messagebar {
+ height: 30px;
+}
+
+.messagebar .messagebar-text {
+ padding-left: 5px;
+ text-align: left;
+ vertical-align: 50%;
+}
+
+.messagebar .messageHead {
+ display: inline-block;
+ width: 5px;
+ height: 30px;
+}
+
+.messagebar-close {
+ padding-top: 6px;
+ padding-right: 10px;
+ cursor: pointer;
+ float: right;
+}
+
+.green {
+ background-color: #DAE6CB;
+}
+
+.dark-green {
+ background-color: #89C53A;
+}
+
+.yellow {
+ background-color: #F1E3C2;
+}
+
+.dark-yellow {
+ background-color: #FDB60D;
+}
+
+.red {
+ background-color: #EAC3C7;
+}
+
+.dark-red {
+ background-color: #D81227;
+}
\ No newline at end of file
diff --git a/ui/js/widgets/messagebar-flat.js b/ui/js/widgets/messagebar-flat.js
new file mode 100644
index 0000000..d72682d
--- /dev/null
+++ b/ui/js/widgets/messagebar-flat.js
@@ -0,0 +1,65 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2015
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ /*
+
+ $(".selector").messagebarFlat({
+ content: "This is a test", //text that is going to be shown to user
+ color: "red" //color that we pre-defined, current are "red", "yellow" and "green"
+ });
+
+ */
+(function($) {
+ $.widget("kimchi.messagebarFlat", {
+ options : {
+ content : null,
+ color : "red",
+ },
+
+ _create: function() {
+ var now = this._getTime();
+ var that = this;
+ $("<div class='messagebar'><span class='messageHead'></span>" +
+ "<span class='messagebar-text'> " + this.options.content +": " + now + "</span></div>")
+ .addClass(this.options.color)
+ .appendTo(that.element);
+ $(".messageHead").addClass("dark-" + this.options.color);
+ $("<span class='messagebar-close icon-cancel-circled'></span>").on("click", function() {
+ that.destroy();
+ }).appendTo($(".messagebar"));
+ setTimeout(function() {
+ that.destroy()
+ }, 3000);
+ },
+
+ _getTime: function() {
+ var CT = new Date();
+ var currentDate = CT.getDate() + "/" + CT.getMonth()+1 + "/" +CT.getFullYear();
+ var currentTime = CT.getHours() + ":" + CT.getMinutes() + ":" + CT.getSeconds();
+ var now = currentDate + " " + currentTime;
+ return now;
+ },
+
+ destroy: function() {
+ var that = this;
+ that.element.fadeOut("normal", function() {
+ that.element.remove();
+ });
+ }
+ });
+})(jQuery);
\ No newline at end of file
diff --git a/ui/js/widgets/samples/messagebar-flat.html b/ui/js/widgets/samples/messagebar-flat.html
new file mode 100644
index 0000000..1b1ce0b
--- /dev/null
+++ b/ui/js/widgets/samples/messagebar-flat.html
@@ -0,0 +1,29 @@
+<!--Sample code -->
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>Kimchi</title>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
+ <link rel="stylesheet" href="../../../libs/themes/base/jquery-ui.min.css">
+ <link rel="stylesheet" href="../../../css/fontello/css/fontello.css">
+ <link rel="stylesheet" href="../../../css/fontello/css/animation.css">
+ <link rel="stylesheet" href="../../../css/theme-default/messagebar-flat.css">
+ <script src="../../../libs/jquery-1.10.0.min.js"></script>
+ <script src="../../../libs/jquery-ui.min.js"></script>
+ <script src="../messagebar-flat.js"></script>
+ </head>
+ <body>
+ <div class="message"></div>
+ <script>
+ $(document).ready(function() {
+ $(".message").messagebarFlat({
+ content: "This is a test",
+ color: "red"
+ });
+ });
+ </script>
+ </body>
+
+</html>
--
2.1.0
9 years, 11 months
[PATCH] UI: Add a new folder that allows adding new kimchi UI design samples
by Wen Wang
Signed-off-by: Wen Wang <wenwang(a)linux.vnet.ibm.com>
---
ui/js/widgets/samples/Readme.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 ui/js/widgets/samples/Readme.md
diff --git a/ui/js/widgets/samples/Readme.md b/ui/js/widgets/samples/Readme.md
new file mode 100644
index 0000000..9c8e425
--- /dev/null
+++ b/ui/js/widgets/samples/Readme.md
@@ -0,0 +1 @@
+This folder contains the usage of Kimchi new UI design widgets.
\ No newline at end of file
--
2.1.0
9 years, 11 months
[PATCH] Issue #563: Delete network button works even disabled
by gouzongmei@ourfuture.cn
From: Zongmei Gou <gouzongmei(a)ourfuture.cn>
---
ui/js/src/kimchi.network.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ui/js/src/kimchi.network.js b/ui/js/src/kimchi.network.js
index 34448f8..bd91d29 100644
--- a/ui/js/src/kimchi.network.js
+++ b/ui/js/src/kimchi.network.js
@@ -157,7 +157,7 @@ kimchi.addNetworkActions = function(network) {
network.state = "down";
}
} else if ($(evt.currentTarget).attr("nwAct") === "delete") {
- if (network.state === "up") {
+ if (network.state === "up" || network.in_use) {
return false;
}
kimchi.confirm({
--
1.8.3.1
9 years, 11 months
[HELP] Problems with lighttpd
by Ramon Medeiros
Hi Team,
i'm trying to switch from nginx to lighttpd as kimchi proxy. I
successfully create the proxy on port 8001, but the problem is the
redirection from http to https.
To try this, do:
1) Install lighttpd
2) Start kimchi, kill nginx process
3) Run lighttpd with this configuration (save to /etc/kimchi/lighttpd.conf):
# Variables
var.log_root = "/var/log/lighttpd"
var.server_root = "/var/www"
var.state_dir = "/var/run"
var.home_dir = "/var/lib/lighttpd"
var.conf_dir = "/etc/lighttpd"
var.vhosts_dir = server_root + "/vhosts"
var.cache_dir = "/var/cache/lighttpd"
var.socket_dir = home_dir + "/sockets"
# Server settings
server.username = "lighttpd"
server.groupname = "lighttpd"
server.document-root = server_root + "/lighttpd"
server.pid-file = state_dir + "/lighttpd.pid"
server.errorlog = log_root + "/error.log"
# Server modules
server.modules = (
"mod_proxy",
"mod_redirect",
"mod_accesslog",
)
# debug settings
debug.log-request-handling = "enable"
debug.log-request-header = "enable"
debug.log-request-header-on-error = "enable"
debug.log-response-header = "enable"
debug.log-file-not-found = "enable"
debug.log-condition-handling = "enable"
# VIRTUAL HOSTS
# Main server
$SERVER["socket"] == ":8001" {
server.port = 8001
ssl.engine = "enable"
ssl.pemfile = "/etc/kimchi/kimchi.pem"
# server.document-root = server_root + "/lighttpd"
proxy.debug = 1
proxy.server = ( "" => ( ( "host" => "127.0.0.1", "port" => 8010 )))
}
# redirect from http to https
$SERVER["socket"] == ":8000" {
server.port = 8000
server.document-root = server_root + "/lighttpd"
$HTTP["host"] =~ "[^0-9:]*" {
url.redirect = ("[^0-9:]*" => "https://%0:8001$0")
}
}
4) Run with /usr/sbin/lighttpd -D -f /etc/kimchi/lighttpd.conf.
You will can access https://localhost:8001 with no problems, but, if you
try to access localhost:8000, you will be redirect to
https://127.0.0.1:8010.
I did not understand why this is happening. Can someone please take a look?
--
Ramon Nunes Medeiros
Kimchi Developer
Software Engineer - Linux Technology Center Brazil
IBM Systems & Technology Group
Phone : +55 19 2132 7878
ramonn(a)br.ibm.com
9 years, 11 months
[PATCH] Issue #569: Deactive logical pool cause vm failed to start
by gouzongmei@ourfuture.cn
From: Zongmei Gou <gouzongmei(a)ourfuture.cn>
Deactive logical pool cause vm failed to start while storage of the vm is in this logical pool.
Storage pool's "deactive" action call libvirt "StoragePoolDestroy" function which causes different result on different pool type.Once the pool is destroyed, the 'dir' type pool remains its target path and images while the 'logical' type pool deletes its target path and images.
This patch make deactive logical pool action failed while exists vm(s) linked to this pool.
---
src/kimchi/i18n.py | 1 +
src/kimchi/model/storagepools.py | 28 ++++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index 4eccc3e..4d84837 100644
--- a/src/kimchi/i18n.py
+++ b/src/kimchi/i18n.py
@@ -187,6 +187,7 @@ messages = {
"KCHPOOL0035E": _("Unable to delete pool %(name)s as it is associated with some templates"),
"KCHPOOL0036E": _("A volume group named '%(name)s' already exists. Please, choose another name to create the logical pool."),
"KCHPOOL0037E": _("Unable to update database with deep scan information due error: %(err)s"),
+ "KCHPOOL0038E": _("Unable to deactivate pool %(name)s. There are some virtual machines %(vms)s linked to this pool."),
"KCHVOL0001E": _("Storage volume %(name)s already exists"),
"KCHVOL0002E": _("Storage volume %(name)s does not exist in storage pool %(pool)s"),
diff --git a/src/kimchi/model/storagepools.py b/src/kimchi/model/storagepools.py
index e03c6bb..6aa2c58 100644
--- a/src/kimchi/model/storagepools.py
+++ b/src/kimchi/model/storagepools.py
@@ -18,6 +18,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import libvirt
+import os
from kimchi.scan import Scanner
from kimchi.exception import InvalidOperation, MissingParameter
@@ -27,6 +28,8 @@ from kimchi.model.host import DeviceModel
from kimchi.model.libvirtstoragepool import StoragePoolDef
from kimchi.utils import add_task, kimchi_log, pool_name_from_uri, run_command
from kimchi.xmlutils.utils import xpath_get_text
+from kimchi.model.vms import VMModel, VMsModel
+from kimchi.xmlutils.disk import get_vm_disk_info, get_vm_disks
ISO_POOL_NAME = u'kimchi_isos'
@@ -230,6 +233,24 @@ class StoragePoolModel(object):
source[key] = res
return source
+ def _get_vms_attach_to_a_storagepool(self, pool_name):
+ # find out vm(s) the vol(s) of this pool attached to.
+ pool = self.get_storagepool(pool_name, self.conn)
+ xml = pool.XMLDesc(0)
+
+ vms = []
+ pool_path = xpath_get_text(xml, "/pool/target/path")[0]
+ vms_list = VMsModel.get_vms(self.conn)
+ for vm in vms_list:
+ dom = VMModel.get_vm(vm, self.conn)
+ storages = get_vm_disks(dom)
+ for disk in storages.keys():
+ d_info = get_vm_disk_info(dom, disk)
+ if pool_path == os.path.split(d_info['path'])[0]:
+ vms.append(vm)
+ break
+ return sorted(vms)
+
def _nfs_status_online(self, pool, poolArgs=None):
if not poolArgs:
xml = pool.XMLDesc(0)
@@ -378,6 +399,13 @@ class StoragePoolModel(object):
raise OperationFailed("KCHPOOL0033E",
{'name': name, 'server': source['addr']})
return
+ elif (pool_type == 'logical' and
+ self._get_storagepool_vols_num(pool) > 0):
+ # can not deactive if vol(s) exists, because destroy
+ # logical pool will cause the vol deleted.
+ vms = self._get_vms_attach_to_a_storagepool(name)
+ raise InvalidOperation('KCHPOOL0038E', {'name': name,
+ 'vms': ', '.join(vms)})
try:
persistent = pool.isPersistent()
pool.destroy()
--
1.8.3.1
9 years, 11 months