[PATCH 0/2 V3] Detect and enable help page from plugins tabs
by Rodrigo Trujillo
This patch set changes the way Kimchi loads Help pages of the tabs of
the plugins.
It also changes the Sample plugin, in order to demonstrate and show
properly how to configure the a Help page
Rodrigo Trujillo (2):
Fix problems to open plugin's help pages
Changes in sample plugin to fix and improve help
configure.ac | 1 -
plugins/sample/Makefile.am | 12 +++++
plugins/sample/sample.conf.in | 5 ++
plugins/sample/ui/config/tab-ext.xml | 11 ++++-
plugins/sample/ui/pages/Makefile.am | 2 +-
.../sample/ui/pages/help/en_US/sample-tab1.html | 1 +
.../sample/ui/pages/help/en_US/sample-tab2.html | 1 +
plugins/sample/ui/pages/sample-tab1.html.tmpl | 30 ++++++++++++
plugins/sample/ui/pages/sample-tab2.html.tmpl | 30 ++++++++++++
plugins/sample/ui/pages/tab.html.tmpl | 30 ------------
ui/js/src/kimchi.main.js | 55 +++++++++++++++++-----
11 files changed, 133 insertions(+), 45 deletions(-)
create mode 100644 plugins/sample/ui/pages/help/en_US/sample-tab1.html
create mode 100644 plugins/sample/ui/pages/help/en_US/sample-tab2.html
create mode 100644 plugins/sample/ui/pages/sample-tab1.html.tmpl
create mode 100644 plugins/sample/ui/pages/sample-tab2.html.tmpl
delete mode 100644 plugins/sample/ui/pages/tab.html.tmpl
--
1.9.3
10 years, 2 months
[PATCH 1/1] add sub-makefile in src/kimchi/xmlutils
by Simon Jin
Signed-off-by: Simon Jin <simonjin(a)linux.vnet.ibm.com>
---
configure.ac | 1 +
src/kimchi/Makefile.am | 2 +-
src/kimchi/xmlutils/Makefile.am | 25 +++++++++++++++++++++++++
3 files changed, 27 insertions(+), 1 deletion(-)
create mode 100644 src/kimchi/xmlutils/Makefile.am
diff --git a/configure.ac b/configure.ac
index d64ddc2..1b476c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -84,6 +84,7 @@ AC_CONFIG_FILES([
src/kimchi/control/Makefile
src/kimchi/control/vm/Makefile
src/kimchi/model/Makefile
+ src/kimchi/xmlutils/Makefile
plugins/Makefile
plugins/sample/Makefile
plugins/sample/po/Makefile.in
diff --git a/src/kimchi/Makefile.am b/src/kimchi/Makefile.am
index 84def58..5c204e0 100644
--- a/src/kimchi/Makefile.am
+++ b/src/kimchi/Makefile.am
@@ -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
-SUBDIRS = control model
+SUBDIRS = control model xmlutils
kimchi_PYTHON = $(filter-out config.py, $(wildcard *.py))
diff --git a/src/kimchi/xmlutils/Makefile.am b/src/kimchi/xmlutils/Makefile.am
new file mode 100644
index 0000000..5c246cb
--- /dev/null
+++ b/src/kimchi/xmlutils/Makefile.am
@@ -0,0 +1,25 @@
+#
+# Kimchi
+#
+# Copyright IBM Corp, 2014
+#
+# 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
+
+model_PYTHON = *.py
+
+modeldir = $(pythondir)/kimchi/xmlutils
+
+install-data-local:
+ $(MKDIR_P) $(DESTDIR)$(modeldir)
--
1.9.3
10 years, 2 months
[PATCH] UI: Clone Guest
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/list.css | 18 ++++++++++
ui/js/src/kimchi.api.js | 13 +++++++
ui/js/src/kimchi.guest_main.js | 68 +++++++++++++++++++++++++++++++++++-----
ui/pages/guest.html.tmpl | 4 ++
4 files changed, 95 insertions(+), 8 deletions(-)
diff --git a/ui/css/theme-default/list.css b/ui/css/theme-default/list.css
index 8ffee69..fc3017b 100644
--- a/ui/css/theme-default/list.css
+++ b/ui/css/theme-default/list.css
@@ -275,3 +275,21 @@
text-shadow: -1px -1px 1px #ccc, 1px 1px 1px #fff;
padding-left: 10px;
}
+
+.guest-clone {
+ margin: 10px;
+}
+
+.guest-clone .icon {
+ background: url('../../images/theme-default/loading.gif') no-repeat;
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ vertical-align: middle;
+}
+
+.guest-clone .text {
+ color: #666666;
+ margin-left: 5px;
+ text-shadow: -1px -1px 1px #CCCCCC, 1px 1px 1px #FFFFFF;
+}
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 5895a07..216a7dd 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -1233,5 +1233,18 @@ var kimchi = {
success : suc,
error : err
});
+ },
+
+ cloneGuest: function(vm, suc, err) {
+ kimchi.requestJSON({
+ url : kimchi.url + 'vms/'+encodeURIComponent(vm)+"/clone",
+ type : 'POST',
+ contentType : 'application/json',
+ dataType : 'json',
+ success : suc,
+ error : err ? err : function(data) {
+ kimchi.message.error(data.responseJSON.reason);
+ }
+ });
}
};
diff --git a/ui/js/src/kimchi.guest_main.js b/ui/js/src/kimchi.guest_main.js
index dbe8753..113ddfb 100644
--- a/ui/js/src/kimchi.guest_main.js
+++ b/ui/js/src/kimchi.guest_main.js
@@ -15,6 +15,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+kimchi.sampleGuestObject = {
+ "name": "",
+ "uuid": "",
+ "state": "shutoff",
+ "persistent": true,
+ "icon": null,
+ "cpus": 0,
+ "memory": 0,
+ "stats": {
+ "net_throughput": 0,
+ "io_throughput_peak": 100,
+ "cpu_utilization": 0,
+ "io_throughput": 0,
+ "net_throughput_peak": 100
+ },
+ "screenshot": null,
+ "graphics": {
+ "passwd": null,
+ "passwdValidTo": null,
+ "type": "vnc",
+ "port": null,
+ "listen": "127.0.0.1"
+ },
+ "users": [],
+ "groups": [],
+ "access": "full"
+};
+
kimchi.vmstart = function(event) {
var button=$(this);
@@ -173,8 +201,20 @@ kimchi.listVmsAuto = function() {
if (kimchi.vmTimeout) {
clearTimeout(kimchi.vmTimeout);
}
+ var getCloningGuests = function(){
+ var guests = [];
+ kimchi.getTasksByFilter('status=running&target_uri='+encodeURIComponent('^/vms/*'), function(tasks) {
+ for(var i=0;i<tasks.length;i++){
+ var guestUri = tasks[i].target_uri;
+ var guestName = guestUri.substring(guestUri.lastIndexOf('/')+1, guestUri.length);
+ guests.push($.extend({}, kimchi.sampleGuestObject, {name: guestName, isCloning: true}));
+ }
+ }, null, true);
+ return guests;
+ };
kimchi.listVMs(function(result, textStatus, jqXHR) {
if (result && textStatus=="success") {
+ result = getCloningGuests().concat(result);
if(result.length) {
var listHtml = '';
var guestTemplate = kimchi.guestTemplate;
@@ -233,14 +273,16 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
imgLoad.attr('src',load_src);
//Link the stopped tile to the start action, the running tile to open the console
- if (vmRunningBool) {
- liveTile.off("click", kimchi.vmstart);
- liveTile.on("click", kimchi.openVmConsole);
- }
- else {
- liveTile.off("click", kimchi.openVmConsole);
- liveTile.on("click", kimchi.vmstart);
- liveTile.hover(function(event){$(this).find('.overlay').show()}, function(event){$(this).find('.overlay').hide()});
+ if(!vmObject.isCloning){
+ if (vmRunningBool) {
+ liveTile.off("click", kimchi.vmstart);
+ liveTile.on("click", kimchi.openVmConsole);
+ }
+ else {
+ liveTile.off("click", kimchi.openVmConsole);
+ liveTile.on("click", kimchi.vmstart);
+ liveTile.hover(function(event){$(this).find('.overlay').show()}, function(event){$(this).find('.overlay').hide()});
+ }
}
@@ -286,6 +328,11 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
}
guestActions.find("[name=vm-edit]").on({click : kimchi.vmedit});
guestActions.find("[name=vm-delete]").on({click : kimchi.vmdelete});
+ guestActions.find("[name=vm-clone]").click(function(){
+ kimchi.cloneGuest($(this).closest('li[name=guest]').attr("id"), function(data){
+ kimchi.listVmsAuto();
+ });
+ });
//Maintain menu open state
var actionMenu=guestActions.find("div[name=actionmenu]");
@@ -293,6 +340,11 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
$('.popover', actionMenu).toggle();
}
+ if(vmObject.isCloning){
+ guestActions.children().hide();
+ result.find('.guest-clone').removeClass('hide-content');
+ }
+
return result;
};
diff --git a/ui/pages/guest.html.tmpl b/ui/pages/guest.html.tmpl
index 43fb350..304749c 100644
--- a/ui/pages/guest.html.tmpl
+++ b/ui/pages/guest.html.tmpl
@@ -26,6 +26,9 @@
<div class="guest-general">
<h2 class="title" title="{name}">{name}</h2>
</div>
+ <div class="guest-clone hide-content">
+ <span class="icon"></span><span class="text">$_("Cloning") ...</span>
+ </div>
</div>
<div name="cpu_utilization" class="sortable">
<div class="circleGauge"></div>
@@ -56,6 +59,7 @@
<span class="text">$_("Actions")</span><span class="arrow"></span>
<div class="popover actionsheet right-side" style="width: 250px">
<button class="button-big shutoff-disabled" name="vm-console" ><span class="text">$_("Connect")</span></button>
+ <button class="button-big running-hidden" name="vm-clone"><span class="text">$_("Clone")</span></button>
<button class="button-big running-disabled" name="vm-edit"><span class="text">$_("Edit")</span></button>
<button class="button-big shutoff-hidden" name="vm-reset"><span class="text">$_("Reset")</span></button>
<button class="button-big shutoff-hidden" name="vm-shutdown"><span class="text">$_("Shut Down")</span></button>
--
1.7.1
10 years, 2 months
[PATCH] UI: Clone Guest
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/list.css | 18 ++++++++++
ui/js/src/kimchi.api.js | 17 ++++++++-
ui/js/src/kimchi.guest_main.js | 72 +++++++++++++++++++++++++++++++++++----
ui/pages/guest.html.tmpl | 4 ++
4 files changed, 101 insertions(+), 10 deletions(-)
diff --git a/ui/css/theme-default/list.css b/ui/css/theme-default/list.css
index 8ffee69..fc3017b 100644
--- a/ui/css/theme-default/list.css
+++ b/ui/css/theme-default/list.css
@@ -275,3 +275,21 @@
text-shadow: -1px -1px 1px #ccc, 1px 1px 1px #fff;
padding-left: 10px;
}
+
+.guest-clone {
+ margin: 10px;
+}
+
+.guest-clone .icon {
+ background: url('../../images/theme-default/loading.gif') no-repeat;
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ vertical-align: middle;
+}
+
+.guest-clone .text {
+ color: #666666;
+ margin-left: 5px;
+ text-shadow: -1px -1px 1px #CCCCCC, 1px 1px 1px #FFFFFF;
+}
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 5895a07..2f90219 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -695,10 +695,10 @@ var kimchi = {
}, 2000);
break;
case 'finished':
- suc(result);
+ suc && suc(result);
break;
case 'failed':
- err(result);
+ err && err(result);
break;
default:
break;
@@ -1233,5 +1233,18 @@ var kimchi = {
success : suc,
error : err
});
+ },
+
+ cloneGuest: function(vm, suc, err) {
+ kimchi.requestJSON({
+ url : kimchi.url + 'vms/'+encodeURIComponent(vm)+"/clone",
+ type : 'POST',
+ contentType : 'application/json',
+ dataType : 'json',
+ success : suc,
+ error : err ? err : function(data) {
+ kimchi.message.error(data.responseJSON.reason);
+ }
+ });
}
};
diff --git a/ui/js/src/kimchi.guest_main.js b/ui/js/src/kimchi.guest_main.js
index dbe8753..8c2e8fa 100644
--- a/ui/js/src/kimchi.guest_main.js
+++ b/ui/js/src/kimchi.guest_main.js
@@ -15,6 +15,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+kimchi.sampleGuestObject = {
+ "name": "",
+ "uuid": "",
+ "state": "shutoff",
+ "persistent": true,
+ "icon": null,
+ "cpus": 0,
+ "memory": 0,
+ "stats": {
+ "net_throughput": 0,
+ "io_throughput_peak": 100,
+ "cpu_utilization": 0,
+ "io_throughput": 0,
+ "net_throughput_peak": 100
+ },
+ "screenshot": null,
+ "graphics": {
+ "passwd": null,
+ "passwdValidTo": null,
+ "type": "vnc",
+ "port": null,
+ "listen": "127.0.0.1"
+ },
+ "users": [],
+ "groups": [],
+ "access": "full"
+};
+
kimchi.vmstart = function(event) {
var button=$(this);
@@ -173,8 +201,24 @@ kimchi.listVmsAuto = function() {
if (kimchi.vmTimeout) {
clearTimeout(kimchi.vmTimeout);
}
+ var getCloningGuests = function(){
+ var guests = [];
+ kimchi.getTasksByFilter('status=running&target_uri='+encodeURIComponent('^/vms/*'), function(tasks) {
+ for(var i=0;i<tasks.length;i++){
+ var guestUri = tasks[i].target_uri;
+ var guestName = guestUri.substring(guestUri.lastIndexOf('/')+1, guestUri.length);
+ guests.push($.extend({}, kimchi.sampleGuestObject, {name: guestName, isCloning: true}));
+ if(kimchi.trackingTasks.indexOf(tasks[i].id)==-1)
+ kimchi.trackTask(tasks[i].id, null, function(err){
+ kimchi.message.error(err.message);
+ }, null);
+ }
+ }, null, true);
+ return guests;
+ };
kimchi.listVMs(function(result, textStatus, jqXHR) {
if (result && textStatus=="success") {
+ result = getCloningGuests().concat(result);
if(result.length) {
var listHtml = '';
var guestTemplate = kimchi.guestTemplate;
@@ -233,14 +277,16 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
imgLoad.attr('src',load_src);
//Link the stopped tile to the start action, the running tile to open the console
- if (vmRunningBool) {
- liveTile.off("click", kimchi.vmstart);
- liveTile.on("click", kimchi.openVmConsole);
- }
- else {
- liveTile.off("click", kimchi.openVmConsole);
- liveTile.on("click", kimchi.vmstart);
- liveTile.hover(function(event){$(this).find('.overlay').show()}, function(event){$(this).find('.overlay').hide()});
+ if(!vmObject.isCloning){
+ if (vmRunningBool) {
+ liveTile.off("click", kimchi.vmstart);
+ liveTile.on("click", kimchi.openVmConsole);
+ }
+ else {
+ liveTile.off("click", kimchi.openVmConsole);
+ liveTile.on("click", kimchi.vmstart);
+ liveTile.hover(function(event){$(this).find('.overlay').show()}, function(event){$(this).find('.overlay').hide()});
+ }
}
@@ -286,6 +332,11 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
}
guestActions.find("[name=vm-edit]").on({click : kimchi.vmedit});
guestActions.find("[name=vm-delete]").on({click : kimchi.vmdelete});
+ guestActions.find("[name=vm-clone]").click(function(){
+ kimchi.cloneGuest($(this).closest('li[name=guest]').attr("id"), function(data){
+ kimchi.listVmsAuto();
+ });
+ });
//Maintain menu open state
var actionMenu=guestActions.find("div[name=actionmenu]");
@@ -293,6 +344,11 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
$('.popover', actionMenu).toggle();
}
+ if(vmObject.isCloning){
+ guestActions.children().hide();
+ result.find('.guest-clone').removeClass('hide-content');
+ }
+
return result;
};
diff --git a/ui/pages/guest.html.tmpl b/ui/pages/guest.html.tmpl
index 43fb350..ffdabe8 100644
--- a/ui/pages/guest.html.tmpl
+++ b/ui/pages/guest.html.tmpl
@@ -26,6 +26,9 @@
<div class="guest-general">
<h2 class="title" title="{name}">{name}</h2>
</div>
+ <div class="guest-clone hide-content">
+ <span class="icon"></span><span class="text">$_("Cloning")...</span>
+ </div>
</div>
<div name="cpu_utilization" class="sortable">
<div class="circleGauge"></div>
@@ -56,6 +59,7 @@
<span class="text">$_("Actions")</span><span class="arrow"></span>
<div class="popover actionsheet right-side" style="width: 250px">
<button class="button-big shutoff-disabled" name="vm-console" ><span class="text">$_("Connect")</span></button>
+ <button class="button-big running-disabled" name="vm-clone"><span class="text">$_("Clone")</span></button>
<button class="button-big running-disabled" name="vm-edit"><span class="text">$_("Edit")</span></button>
<button class="button-big shutoff-hidden" name="vm-reset"><span class="text">$_("Reset")</span></button>
<button class="button-big shutoff-hidden" name="vm-shutdown"><span class="text">$_("Shut Down")</span></button>
--
1.7.1
10 years, 2 months
[PATCH 0/5] Power (ppc) support patches
by Paulo Vital
This patch set enables Power(ppc) support by default on Kimchi.
Whithout them, the upstream code of Kimchi is not fully compatible
with the Power architecture.
Eli Qiao (2):
Add tablet to vmtemplate,to provides an absolute pointer device which
often helps with getting a consistent mouse cursor position in VNC.
Fix Bug 110927 - Sosreport throwing kimchi error Signed-off-by: Eli
Qiao <taget(a)linux.vnet.ibm.com>
Mark Wu (1):
Add sos plugin for kimchi
Paulo Vital (2):
PowerKVM: Workaround of numpy byte order bug on PowerPC
Add PowerKVM information as ISO otpion to installation.
contrib/kimchi.spec.fedora.in | 3 +++
src/kimchi/Makefile.am | 4 +++-
src/kimchi/isoinfo.py | 1 +
src/kimchi/osinfo.py | 5 +++--
src/kimchi/sos.py | 37 +++++++++++++++++++++++++++++++++++++
src/kimchi/vmtemplate.py | 5 +++++
src/kimchi/websocket.py | 7 +++++--
7 files changed, 57 insertions(+), 5 deletions(-)
create mode 100644 src/kimchi/sos.py
--
1.9.3
10 years, 2 months
[PATCH] Guest disk hot plug UI
by Wen Wang
From: Wen Wang <wenwang(a)linux.vnet.ibm.com>
Enable users add and detach disk when vm is running.
Signed-off-by: Wen Wang <wenwang(a)linux.vnet.ibm.com>
---
ui/js/src/kimchi.guest_edit_main.js | 29 ++++++++++++-----------------
1 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js
index 030e112..eb0254e 100644
--- a/ui/js/src/kimchi.guest_edit_main.js
+++ b/ui/js/src/kimchi.guest_edit_main.js
@@ -57,17 +57,14 @@ kimchi.guest_edit_main = function() {
text: false
});
- if(kimchi.thisVMState != "running") {
- $('.detach', container).button({
- icons: {
- primary: 'ui-icon-trash'
- },
- text: false
- });
+ $('.detach', container).button({
+ icons: {
+ primary: 'ui-icon-trash'
+ },
+ text: false
+ });
- } else {
- $('.detach', container).remove();
- }
+ $('.view .detach', container).remove();
$('.save', container).button({
icons: {
@@ -443,14 +440,8 @@ kimchi.guest_edit_main = function() {
guest['icon'] = guest['icon'] || 'images/icon-vm.png';
$('#form-guest-edit-general').fillWithObject(guest);
kimchi.thisVMState = guest['state'];
-
refreshCDROMs();
- if(kimchi.thisVMState === "running") {
- $("#form-guest-edit-general input").prop("disabled", "disabled");
- $("#guest-edit-attach-cdrom-button").remove();
- $("#form-guest-edit-interface .header button").remove();
- } else {
- $('#guest-edit-attach-cdrom-button').button({
+ $('#guest-edit-attach-cdrom-button').button({
icons: {
primary: "ui-icon-plusthick"
},
@@ -459,6 +450,10 @@ kimchi.guest_edit_main = function() {
event.preventDefault();
kimchi.window.open("guest-storage-add.html");
});
+ if(kimchi.thisVMState === "running") {
+ $("#form-guest-edit-general input").prop("disabled", "disabled");
+ $("#form-guest-edit-interface .header button").remove();
+ } else {
$("#action-button-container").removeClass("hidden");
}
--
1.7.1
10 years, 2 months
[RFC] LDAP integration in kimchi
by Royce Lv
LDAP supports connect to it (bind) for authentication, usr/group/role
add/delete for authorization.
For kimchi-LDAP integration we need to address following issues:
1. LDAP set up scripts for kimchi:
We need to add initial users: guest, admin; roles: netadmin,
hostadmin, guestadmin in LDAP server.
Adding these schema for user maybe a burden, we may supply a script
to init LDAP server configuration
2. Configuration of using LDAP:
Configured to use PAM/LDAP, Connecting to a dedicate LDAP server
address(As we may use an LDAP to store information of clustered machine,
address can be modified).
If this LDAP server does not exist, ask user if they want to setup
one, and help them with setup scripts.
For this release just support one LDAP per host.
3. Module for LDAP operation wrapping:
A dedicate module to encapsulate LDAP operations, such as
bind/unbind, adding, deleting, query groups/roles.
4. authentication:
We need to abstract authenticate class to be compatible with both
PAM and LDAP, and call bind/unbind to implement authentication.
5. authorization:
Abstract authentication module to distiguish PAM and LDAP, user name
still from cherrypy session, when using LDAP, user/role information are
all retrieved from LDAP server.
6. user/role maintenance:
Manipulate LDAP to add user, delete user, authorize user with a
role, add role/delete role, and so on.
This part will not be covered in this release.
10 years, 2 months
[PATCHv1 0/4] LDAP authentication
by lvroyce0210@gmail.com
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
How to test:
1. set an LDAP based on PAM:
http://www.debuntu.org/how-to-set-up-a-ldap-server-and-its-clients/
2. uncommented ldap section in config
Tested:
1. authentication with valid user/password
2. wrong password
3. non-existent user
4. wrong ldap settings
Royce Lv (4):
Add configuration of LDAP
Split PAM and LDAP authentication
Add LDAP authentication
Fix test cases for authentication
contrib/DEBIAN/control.in | 1 +
contrib/kimchi.spec.fedora.in | 1 +
contrib/kimchi.spec.suse.in | 1 +
src/kimchi.conf.in | 9 +++
src/kimchi/auth.py | 153 +++++++++++++++++++++++++++++++-----------
src/kimchi/config.py.in | 5 ++
tests/utils.py | 43 ++++++++----
7 files changed, 159 insertions(+), 54 deletions(-)
--
1.8.3.2
10 years, 2 months
[RFC: PATCH v1] Prevent disks from being added more than once
by Christy Perez
The concept of a ref count for disks had been added, but this count
was dependant upon the pool name for a disk. However, the pool name
wasn't being stored in the VM XML so it wasn't possible to retreive
the pool for the disk in order to update the ref count.
To fix this, this patch changes the way that disks are added when
created in libvirt storage pools. Instead of files, they are treated
as volumes in pools.
Note: Because of this modification, a small inconsistency in the API,
which states that the pool for a vm's "storages" is returned, is
corrected. The pool is returned as an empty string if the disk or
volume was not create from a pool (e.g. a remote ISO).
Signed-off-by: Christy Perez <christy(a)linux.vnet.ibm.com>
---
src/kimchi/model/storagevolumes.py | 13 ++++++--
src/kimchi/model/vmstorages.py | 68 +++++++++++++++++++++++++++++++++++---
src/kimchi/vmdisks.py | 33 ++++++++++++++----
src/kimchi/vmtemplate.py | 41 ++++++++++++++++-------
4 files changed, 129 insertions(+), 26 deletions(-)
diff --git a/src/kimchi/model/storagevolumes.py b/src/kimchi/model/storagevolumes.py
index f9f226f..af97748 100644
--- a/src/kimchi/model/storagevolumes.py
+++ b/src/kimchi/model/storagevolumes.py
@@ -249,19 +249,26 @@ def _get_ref_cnt(self, pool, name, path):
try:
ref_cnt = session.get('storagevolume', vol_id)['ref_cnt']
except NotFoundError:
+ kimchi_log.info('Volume %s not found in obj store.' % vol_id)
# Fix storage volume created outside kimchi scope
ref_cnt = 0
- # try to find this volume in exsisted vm
+ # try to find this volume in exsisting vm
vms = VMsModel.get_vms(self.conn)
for vm in vms:
dom = VMModel.get_vm(vm, self.conn)
storages = get_vm_disk_list(dom)
for disk in storages:
- d_info = get_vm_disk(dom, disk)
+ d_info = get_vm_disk(dom, disk, self.conn)
if path == d_info['path']:
ref_cnt = ref_cnt + 1
- session.store('storagevolume', vol_id,
+ try:
+ session.store('storagevolume', vol_id,
{'ref_cnt': ref_cnt})
+ except Exception as e:
+ # Just log an error if the obj store fails:
+ kimchi_log.warning('Unable to store storage volume id in '
+ 'objectstore due error: %s', 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
diff --git a/src/kimchi/model/vmstorages.py b/src/kimchi/model/vmstorages.py
index 4d6c0b2..1b2c0fe 100644
--- a/src/kimchi/model/vmstorages.py
+++ b/src/kimchi/model/vmstorages.py
@@ -32,7 +32,7 @@
from kimchi.model.vms import DOM_STATE_MAP, VMModel
from kimchi.model.storagevolumes import StorageVolumeModel
from kimchi.model.utils import get_vm_config_flag
-from kimchi.utils import check_url_path
+from kimchi.utils import check_url_path, kimchi_log
from kimchi.osinfo import lookup
from kimchi.vmdisks import get_device_xml, get_vm_disk, get_vm_disk_list
from kimchi.vmdisks import DEV_TYPE_SRC_ATTR_MAP
@@ -73,6 +73,11 @@ def _get_storage_xml(params, ignore_source=False):
source = E.source(protocol=output.scheme, name=output.path)
source.append(host)
disk.append(source)
+ elif src_type == 'volume':
+ source = E.source()
+ source.set('pool', params.get('pool'))
+ source.set('volume', params.get('vol'))
+ disk.append(source)
else:
# Fixing source attribute
source = E.source()
@@ -138,6 +143,8 @@ def create(self, vm_name, params):
# Path will never be blank due to API.json verification.
# There is no need to cover this case here.
params['format'] = 'raw'
+ vol_info = None
+ vol_store_name = None
if not ('vol' in params) ^ ('path' in params):
raise InvalidParameter("KCHVMSTOR0017E")
if params.get('vol'):
@@ -146,6 +153,7 @@ def create(self, vm_name, params):
vol_info = StorageVolumeModel(
conn=self.conn,
objstore=self.objstore).lookup(pool, params['vol'])
+ vol_store_name = '%s:%s' % (pool, params['vol'])
except KeyError:
raise InvalidParameter("KCHVMSTOR0012E")
except Exception as e:
@@ -158,6 +166,10 @@ def create(self, vm_name, params):
params['format'] = vol_info['format']
params['path'] = vol_info['path']
params['src_type'] = _check_path(params['path'])
+ if params['src_type'] is 'file' and params.get('pool') and \
+ params.get('vol'):
+ params['src_type'] = 'volume'
+ # change from 'file' to volume if in a pool ^^
if (params['bus'] not in HOTPLUG_TYPE
and DOM_STATE_MAP[dom.info()[0]] != 'shutoff'):
raise InvalidOperation('KCHVMSTOR0011E')
@@ -171,6 +183,16 @@ def create(self, vm_name, params):
dom.attachDeviceFlags(dev_xml, get_vm_config_flag(dom, 'all'))
except Exception as e:
raise OperationFailed("KCHVMSTOR0008E", {'error': e.message})
+
+ try:
+ new_ref_cnt = vol_info['ref_cnt'] + 1
+ with self.objstore as session:
+ session.store('storagevolume', vol_store_name, {'ref_cnt': new_ref_cnt})
+ except Exception as e:
+ # Just log an error if the obj store fails:
+ kimchi_log.warning('Unable to store storage volume id in '
+ 'objectstore due error: %s', e.message)
+
return params['dev']
def _get_storage_device_name(self, vm_name, params):
@@ -192,25 +214,41 @@ def get_list(self, vm_name):
dom = VMModel.get_vm(vm_name, self.conn)
return get_vm_disk_list(dom)
-
class VMStorageModel(object):
def __init__(self, **kargs):
self.conn = kargs['conn']
+ self.objstore = kargs['objstore']
def lookup(self, vm_name, dev_name):
# Retrieve disk xml and format return dict
dom = VMModel.get_vm(vm_name, self.conn)
- return get_vm_disk(dom, dev_name)
+ disk = get_vm_disk(dom, dev_name, self.conn)
+ # Also include the pool and volume
+ pool_name = ''
+ vol_name = ''
+ try:
+ pool_name = disk.get('pool')
+ vol_name = disk.get('volume')
+ except Exception as e:
+ kimchi_log.warning('VMDisk lookup error: %s' % e.message)
+
+ disk['pool'] = pool_name
+ disk['volume'] = vol_name
+ return disk
def delete(self, vm_name, dev_name):
# Get storage device xml
dom = VMModel.get_vm(vm_name, self.conn)
+ disk_info = None
+ disk_xml = None
+ pool_name = ''
+ vol_name = ''
try:
- bus_type = self.lookup(vm_name, dev_name)['bus']
+ disk_info = self.lookup(vm_name, dev_name)
+ bus_type = disk_info['bus']
except NotFoundError:
raise
- dom = VMModel.get_vm(vm_name, self.conn)
if (bus_type not in HOTPLUG_TYPE and
DOM_STATE_MAP[dom.info()[0]] != 'shutoff'):
raise InvalidOperation('KCHVMSTOR0011E')
@@ -224,10 +262,30 @@ def delete(self, vm_name, dev_name):
except Exception as e:
raise OperationFailed("KCHVMSTOR0010E", {'error': e.message})
+ # Get the pool and vol of a disk so we can
+ # decrement its ref_cnt in the obj store
+ pool_name = disk_info.get('pool')
+ vol_name = disk_info.get('volume')
+
+ if(pool_name and vol_name):
+ try:
+ vol_id = '%s:%s' % (pool_name, vol_name)
+ with self.objstore as session:
+ vol = session.get('storagevolume', vol_id)
+ if vol:
+ ref_cnt = vol['ref_cnt']
+ if ref_cnt > 0:
+ ref_cnt = ref_cnt - 1
+ session.store('storagevolume', vol_id, {'ref_cnt': ref_cnt})
+ except Exception as e:
+ kimchi_log.warning('Unable to decrement volume ref count due to %s.'
+ % e.message)
+
def update(self, vm_name, dev_name, params):
path = params.get('path')
if path and len(path) != 0:
params['src_type'] = _check_path(path)
+ # change from 'file' to 'volume' if pool ^^
ignore_source = False
else:
params['src_type'] = 'file'
diff --git a/src/kimchi/vmdisks.py b/src/kimchi/vmdisks.py
index 6012ada..185a499 100644
--- a/src/kimchi/vmdisks.py
+++ b/src/kimchi/vmdisks.py
@@ -17,6 +17,8 @@
# 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 libvirt
+import os
from lxml import objectify
from kimchi.exception import NotFoundError
@@ -34,37 +36,56 @@ def get_device_xml(dom, dev_name):
return None
return disk[0]
+def get_pool_xml(conn, pool_name):
+ conn = conn.get()
+ return objectify.fromstring(conn.\
+ storagePoolLookupByName(pool_name).XMLDesc(0))
-def get_vm_disk(dom, dev_name):
+def get_vm_disk(dom, dev_name, conn):
# Retrieve disk xml and format return dict
disk = get_device_xml(dom, dev_name)
if disk is None:
raise NotFoundError(
"KCHVMSTOR0007E",
{'dev_name': dev_name, 'vm_name': dom.name()})
- path = ""
+ path = ''
dev_bus = 'ide'
+ pool_name = ''
+ vol_name = ''
try:
source = disk.source
if source is not None:
- src_type = disk.attrib['type']
+ src_type = disk.get('type')
if src_type == 'network':
host = source.host
path = (source.attrib['protocol'] + '://' +
host.attrib['name'] + ':' +
host.attrib['port'] + source.attrib['name'])
+ elif src_type == 'volume':
+ pool_name = disk.source.get('pool')
+ pool = get_pool_xml(conn, pool_name)
+ pool_path = str(pool.target.path)
+ vol_name = disk.source.attrib['volume']
+ path = os.path.join(pool_path, vol_name)
else:
path = source.attrib[DEV_TYPE_SRC_ATTR_MAP[src_type]]
# Retrieve storage bus type
dev_bus = disk.target.attrib['bus']
- except:
- pass
+ except Exception as e:
+ kimchi_log.warning("get_vm_disk exception: %s " % e.message)
+
dev_type = disk.attrib['device']
+
+ # Pool and volume may be empty strings, if the user passed a disk name.
+ # If the disk was from a storage pool, let's use that so we can keep track
+ # of its ref_cnt in the objects store.
return {'dev': dev_name,
'type': dev_type,
'path': path,
'format': disk.driver.attrib['type'],
- 'bus': dev_bus}
+ 'bus': dev_bus,
+ 'pool': pool_name,
+ 'volume': vol_name}
def get_vm_disk_list(dom):
diff --git a/src/kimchi/vmtemplate.py b/src/kimchi/vmtemplate.py
index 5f22db9..1940911 100644
--- a/src/kimchi/vmtemplate.py
+++ b/src/kimchi/vmtemplate.py
@@ -187,24 +187,41 @@ def _get_cdrom_xml(self, libvirt_stream_protocols, qemu_stream_dns):
return network_file % (params)
def _get_disks_xml(self, vm_uuid):
- storage_path = self._get_storage_path()
+ def TYPE(v):
+ return {'type': v}
+
+ #storage_path = self._get_storage_path()
+ _pool = pool_name_from_uri(self.info['storagepool'])
ret = ""
for i, disk in enumerate(self.info['disks']):
index = disk.get('index', i)
- volume = "%s-%s.img" % (vm_uuid, index)
- src = os.path.join(storage_path, volume)
+ _volume = "%s-%s.img" % (vm_uuid, index)
+ #src = os.path.join(storage_path, volume)
dev = "%s%s" % (self._bus_to_dev[self.info['disk_bus']],
string.lowercase[index])
fmt = 'raw' if self._get_storage_type() in ['logical'] else 'qcow2'
- params = {'src': src, 'dev': dev, 'bus': self.info['disk_bus'],
- 'type': fmt}
- ret += """
- <disk type='file' device='disk'>
- <driver name='qemu' type='%(type)s' cache='none'/>
- <source file='%(src)s' />
- <target dev='%(dev)s' bus='%(bus)s' />
- </disk>
- """ % params
+ #params = {'src': src, 'dev': dev, 'bus': self.info['disk_bus'],
+ # 'type': fmt}
+ #ret += """
+ #<disk type='file' device='disk'>
+ # <driver name='qemu' type='%(type)s' cache='none'/>
+ # <source file='%(src)s' />
+ # <target dev='%(dev)s' bus='%(bus)s' />
+ #</disk>
+ #""" % params
+
+ # Instead do:
+ #<disk type='volume'>
+ # <driver name='qemu' type='%(type)s' cache='none'/>
+ # <source pool='%(pool)s' volume='%(volume)s' />
+ # <target dev='%(dev)s' bus='%(bus)s />
+ #</disk>
+ disk = E.disk(
+ E.driver(TYPE(fmt), name='qemu', cache='none'),
+ E.source(pool=_pool, volume=_volume),
+ E.target(dev=dev, bus=self.info['disk_bus']),
+ TYPE('volume'))
+ ret += etree.tostring(disk)
return ret
def _get_graphics_xml(self, params):
--
1.9.3
10 years, 2 months
RFC: Add serial as a valid graphics type
by Yu Xin Huo
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/...
Per my understanding:
1. To enable the serial console, it needs configuration on guest OS.
/ You must configure the virtualized operating system to output
information to the virtual serial port.//
// The serial port is called //|ttyS0|//on Linux or //|COM1|//on
Windows./
It need to modify the |/boot/grub/grub.conf| file on guest OS and
reboot guest.
So VM must have OS already installed, seems like it needs the guest
to be running.
2. The serial console can be accessed with 'virsh console' or 'use
|virt-manager| to display the virtual text console'.
So the target of this work item is to add a 'web command line
console' in kimchi UI to access the 'serial console'?
||||
10 years, 2 months