[RFC][PATCH] VM supports interfaces
by shaohef@linux.vnet.ibm.com
From: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
now kimchi support supports network get/create/delete/activate/deactivate
REST API.
Now we need to support the attach/detach/ a Network to a VM.
https://github.com/kimchi-project/kimchi/wiki/customize-VM#organization-o...
And get the info of Network attached to a VM.
more libvirt network interfaces info:
http://libvirt.org/formatdomain.html#elementsNICS
Signed-off-by: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
---
docs/API.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/docs/API.md b/docs/API.md
index 9edc551..2d3ce11 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -127,6 +127,55 @@ Represents a snapshot of the Virtual Machine's primary monitor.
* volume: A volume name that contains the initial disk contents
+### Sub-Collection: Virtual Machine Network Interfaces
+
+**URI:** /vms/*:name*/interfaces
+
+Represents all network interfaces attached to a Virtual Machine.
+
+**Methods:**
+
+* **GET**: Retrieve a summarized list of all network interfaces attached to a Virtual Machine.
+
+* **POST**: attach a network interface to VM
+ * type: The type of VM network interface that libvirt supports.
+ It can be one of these types: 'network', 'bridge', 'user','ethernet',
+ 'direct', 'hostdev', 'mcast', 'server' and 'client'.
+ Now kimchi just supports 'network' type.
+ * network *(optional)*: the name of resource network, it is required when the
+ interface type is network.
+ * model *(optional)*: model of emulated network interface card. It can be one of these models:
+ ne2k_pci, i82551, i82557b, i82559er, rtl8139, e1000, pcnet and virtio.
+ when model is missing, but already some interfaces is attached to VM, then will choose
+ one of model of the exist interfaces.
+ if on interface is attached to VM, then 'virtio' is default.
+
+### Sub-Resource: Virtual Machine Network Interface
+
+**URI:** /vms/*:name*/interfaces/*:name*
+
+A interface represents available network interface on VM.
+
+**Methods:**
+
+* **GET**: Retrieve the full description of the VM network interface
+ * name: The identifier of the network interface.
+ * type: The type of VM network interface that libvirt supports.
+ It will be one of these types: 'network', 'bridge', 'user','ethernet',
+ 'direct', 'hostdev', 'mcast', 'server' and 'client'.
+ * network *(optional)*: the name of resource network, only be available when the
+ interface type is network.
+ * bridge *(optional)*: the name of resource bridge, only be available when the
+ interface type is bridge.
+ * mac: Media Access Control Address of the VM interface.
+
+* **DELETE**: detach the network interface from VM
+
+**Actions (POST):**
+
+*No actions defined*
+
+
### Resource: Template
**URI:** /templates/*:name*
--
1.8.4.2
10 years, 10 months
[PATCH V3] Add nfs server and target UI in create storage pool
by zhoumeina
v2-v3 Make nfs server inputbox to combobox
Edit jquery widgets to fix some small nits in it.
change some parameter according to the changes from
back end.
v1-v2 Fix some bug in this patch, make it working and retest
This patch is working adding a select box in create nfs pool,
when user don't want to input the server ip or name, he can
simply select "used the server I have used before" and choose
a server in a select box, this is more convinent.
Add a new jquery filter-select widget
In order to show server target I did a select box in UI, but sometimes
maybe the export path number is large. So I made a filter-select
widget to make user easier to choose the export path he want.
This is the first jquery widget. And let us make all common widget to
jquery widget from now on.
Signed-off-by: zhoumeina <zhoumein(a)linux.vnet.ibm.com>
---
ui/css/theme-default/button.css | 12 +++-
ui/css/theme-default/popover.css | 1 +
ui/js/src/kimchi.popable.js | 2 +-
ui/js/src/kimchi.storagepool_add_main.js | 26 +++----
ui/js/widgets/combobox.js | 124 ++++++++++++++++++++++++++++++
ui/js/widgets/filter-select.js | 37 +++------
ui/js/widgets/select-menu.js | 37 +++------
ui/pages/i18n.html.tmpl | 2 +-
ui/pages/storagepool-add.html.tmpl | 32 ++++----
9 files changed, 189 insertions(+), 84 deletions(-)
create mode 100644 ui/js/widgets/combobox.js
diff --git a/ui/css/theme-default/button.css b/ui/css/theme-default/button.css
index f99679a..693ed59 100644
--- a/ui/css/theme-default/button.css
+++ b/ui/css/theme-default/button.css
@@ -261,8 +261,16 @@
cursor: pointer;
}
-.btn-select .text {
- padding: 0 10px;
+.btn-select .input {
+ border: 0 solid #CCCCCC;
+ padding: 0 10px;
+ margin-right: 10px;
+ font-size: 16px;
+ height: 30px;
+ line-height: 30px;
+ width: 100%;
+ position: absolute;
+ background: transparent;
}
.btn-select .arrow {
diff --git a/ui/css/theme-default/popover.css b/ui/css/theme-default/popover.css
index 95eb183..e91ccc0 100644
--- a/ui/css/theme-default/popover.css
+++ b/ui/css/theme-default/popover.css
@@ -31,6 +31,7 @@
left: 0;
display: none;
cursor: default;
+ width: 100%;
}
.popover:BEFORE {
diff --git a/ui/js/src/kimchi.popable.js b/ui/js/src/kimchi.popable.js
index 153d32c..2a843be 100644
--- a/ui/js/src/kimchi.popable.js
+++ b/ui/js/src/kimchi.popable.js
@@ -25,7 +25,7 @@ kimchi.popable = function() {
$(document).on("click", ".popable", function(e) {
var isOpen = $(this).hasClass('open');
$(".popable").removeClass('open');
- if (!isOpen) {
+ if (!isOpen && $(this).find('ul').html() !== '') {
$(this).addClass('open');
}
diff --git a/ui/js/src/kimchi.storagepool_add_main.js b/ui/js/src/kimchi.storagepool_add_main.js
index 134d13f..4192649 100644
--- a/ui/js/src/kimchi.storagepool_add_main.js
+++ b/ui/js/src/kimchi.storagepool_add_main.js
@@ -54,8 +54,8 @@ kimchi.initStorageAddPage = function() {
});
$('.host-partition').html(listHtml);
}
- $('#storagePool-list').selectMenu();
- $('#storagePool-list').selectMenu("setData", options);
+ $('#poolTypeId').selectMenu();
+ $('#poolTypeId').selectMenu("setData", options);
kimchi.getStorageServers('netfs', function(data) {
var serverContent = [];
serverContent.push({
@@ -65,14 +65,14 @@ kimchi.initStorageAddPage = function() {
if (data.length > 0) {
$.each(data, function(index, value) {
serverContent.push({
- label : value,
- value : value
+ label : value.addr,
+ value : value.addr
});
});
}
- $('#nfs-server-used').selectMenu();
- $('#nfs-server-used').selectMenu("setData", serverContent);
- $('#nfs-server-target').filterselect();
+ $('#serverComboboxId').combobox();
+ $('#serverComboboxId').combobox("setData", serverContent);
+ $('#targetFilterSelectId').filterselect();
$('input[name=nfsServerType]').change(function() {
if ($(this).val() === 'input') {
$('#nfsServerInputDiv').removeClass('tmpl-html');
@@ -82,17 +82,13 @@ kimchi.initStorageAddPage = function() {
$('#nfsServerChooseDiv').removeClass('tmpl-html');
}
});
- $('#nfsServerSelect').change(function() {
- $('#nfsserverId').val($(this).val());
- $('#nfsserverId').trigger("keydown");
- });
- $('#nfsserverId').on("keydown",function() {
+ $('#nfsserverId').on("change",function() {
if ($(this).val() !== '' && kimchi.isServer($(this).val())) {
$('#nfspathId').removeAttr('disabled');
} else {
$('#nfspathId').attr('disabled','disabled');
}
- $('#nfs-server-target').filterselect('clear');
+ $('#targetFilterSelectId').filterselect('clear');
});
$('#nfspathId').focus(function() {
var targetContent = [];
@@ -110,7 +106,7 @@ kimchi.initStorageAddPage = function() {
value : ''
});
}
- $('#nfs-server-target').filterselect("setData", targetContent);
+ $('#targetFilterSelectId').filterselect("setData", targetContent);
},function() {
targetContent.push({
label : i18n['msg.no.result'],
@@ -120,7 +116,7 @@ kimchi.initStorageAddPage = function() {
});
});
});
- $('#poolType').change(function() {
+ $('#poolTypeInputId').change(function() {
if ($(this).val() === 'dir') {
$('.path-section').removeClass('tmpl-html');
$('.logical-section').addClass('tmpl-html');
diff --git a/ui/js/widgets/combobox.js b/ui/js/widgets/combobox.js
new file mode 100644
index 0000000..dfa6566
--- /dev/null
+++ b/ui/js/widgets/combobox.js
@@ -0,0 +1,124 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * Authors:
+ * zhoumeina <zhoumein(a)linux.vnet.ibm.com>
+ *
+ * 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.
+ */
+(function($) {
+ $.widget('kimchi.combobox', {
+ _create : function() {
+ this.selectDiv = this.element;
+ this.listControl = this.selectDiv.find('ul').first();
+ this.listControl.html('');
+ this.target = this.selectDiv.find('input').first();
+ this.selectDiv.addClass('btn-select dropdown popable');
+ this.target.addClass('input');
+ this.listControl.addClass('select-list');
+ this.listControl.parent().addClass('popover');
+ },
+
+ setData : function(options) {
+ this.listControl.html('');
+ var that = this;
+ var value = this.target.val();
+ var selectedClass = 'active';
+ var itemTag = 'li';
+
+ that.listControl.on('click', itemTag, function(e) {
+ that.listControl.children().removeClass(selectedClass);
+ that.listControl.addClass(selectedClass);
+ that.target.text($(this).text());
+ var oldValue = that.target.val();
+ var newValue = $(this).data('value');
+ that.target.val(newValue);
+ if (oldValue !== newValue) {
+ that.target.change();
+ }
+ });
+
+ that.selectDiv.click(function(e) {
+ that.listControl.html('');
+ var items = that._dataList(options);
+ $.each(items, function(index, item) {
+ that.listControl.append(item);
+ })
+ });
+
+ that.target.keyup(function(event) {
+ that.listControl.html('');
+ var items = that._dataList(options);
+ var temp = 0;
+ $.each(items, function(index, item) {
+ if (item.html().indexOf(that.target.val()) >= 0) {
+ that.listControl.append(item);
+ temp++;
+ }
+ });
+ if (that.listControl.html() === '') {
+ that.listControl.html(i18n['msg.no.mapping.result']);
+ }
+ if (temp > 0) {
+ that._open();
+ }
+ });
+ },
+
+ _dataList : function(options) {
+ var item;
+ var itemTag = 'li';
+ var selectedClass = 'active';
+ var items = [];
+ var that = this;
+ $.each(options, function(index, option) {
+ item = $('<' + itemTag + '></' + itemTag + '>');
+ item.text(option.label);
+ item.data('value', option.value);
+ if (option.value === that.target.val()) {
+ item.addClass(selectedClass);
+ }
+ items.push(item);
+ });
+ return items;
+ },
+
+ clear : function() {
+ this.target.val("");
+ },
+
+ _open : function() {
+ var isOpen = this.selectDiv.hasClass('open');
+ if (!isOpen) {
+ this.selectDiv.addClass('open');
+ }
+ },
+
+ _close : function() {
+ var isOpen = this.selectDiv.hasClass('open');
+ if (isOpen) {
+ this.selectDiv.removeClass('open');
+ }
+ },
+
+ destroy : function() {
+ this.selectDiv.removeClass('btn-select dropdown popable');
+ this.target.removeClass('input');
+ this.listControl.removeClass('select-list');
+ this.listControl.parent().removeClass('popover');
+ $.Widget.prototype.destroy.call(this);
+ }
+ });
+}(jQuery));
\ No newline at end of file
diff --git a/ui/js/widgets/filter-select.js b/ui/js/widgets/filter-select.js
index 02fe5d9..0686aa2 100644
--- a/ui/js/widgets/filter-select.js
+++ b/ui/js/widgets/filter-select.js
@@ -20,28 +20,19 @@
*/
(function($) {
$.widget('kimchi.filterselect', {
- options : {
- key : 0,
- value : 0
- },
-
_create : function() {
- this.listControl = this.element;
- this.element.html('');
- var targetId = this.listControl.data('target');
- var labelId = this.listControl.data('label');
- this.target = $('#' + targetId);
- this.label = $('#' + labelId);
- this.selectDiv = this.listControl.parent().parent();
+ this.selectDiv = this.element;
+ this.listControl = this.selectDiv.find('ul').first();
+ this.listControl.html('');
+ this.target = this.selectDiv.find('input').first();
this.selectDiv.addClass('btn-select dropdown popable');
+ this.target.addClass('input');
+ this.listControl.addClass('select-list');
this.listControl.parent().addClass('popover');
},
- _setOption : function(key, value) {
- },
-
setData : function(options) {
- this.element.html('');
+ this.listControl.html('');
var that = this;
var value = this.target.val();
var selectedClass = 'active';
@@ -65,13 +56,6 @@
$.each(items, function(index, item) {
that.listControl.append(item);
})
- var isOpen = that.selectDiv.hasClass('open');
- that.selectDiv.removeClass('open');
- if (!isOpen && items.length > 0) {
- that.selectDiv.addClass('open');
- }
- e.preventDefault();
- e.stopPropagation();
});
that.target.keyup(function(event) {
@@ -85,7 +69,7 @@
}
});
if (that.listControl.html() === '') {
- that.listControl.html(i18n['msg.storagepool.unvalid.path']);
+ that.listControl.html(i18n['msg.no.mapping.result']);
}
if (temp > 0) {
that._open();
@@ -130,7 +114,10 @@
},
destroy : function() {
- // call the base destroy function
+ this.selectDiv.removeClass('btn-select dropdown popable');
+ this.target.removeClass('input');
+ this.listControl.removeClass('select-list');
+ this.listControl.parent().removeClass('popover')
$.Widget.prototype.destroy.call(this);
}
});
diff --git a/ui/js/widgets/select-menu.js b/ui/js/widgets/select-menu.js
index 454fe3c..c2ced7e 100644
--- a/ui/js/widgets/select-menu.js
+++ b/ui/js/widgets/select-menu.js
@@ -20,26 +20,20 @@
*/
(function($) {
$.widget('kimchi.selectMenu', {
- options: {
- key: 0,
- value: 0
- },
_create : function() {
- this.listControl = this.element;
- this.element.html('');
- var targetId = this.listControl.data('target');
- var labelId = this.listControl.data('label');
- this.target = $('#' + targetId);
- this.label = $('#' + labelId);
- this.selectDiv = this.listControl.parent().parent();
+ this.selectDiv = this.element;
+ this.listControl = this.selectDiv.find('ul').first();
+ 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.target.addClass('input');
+ this.label.addClass('input');
+ this.listControl.addClass('select-list');
this.listControl.parent().addClass('popover');
- var that = this;
},
- _setOption : function(key,value) {},
-
setData : function (options) {
var that = this;
var value = this.target.val();
@@ -67,19 +61,14 @@
}
});
- that.selectDiv.click(function(e) {
- var isOpen = that.selectDiv.hasClass('open');
- that.selectDiv.removeClass('open');
- if (!isOpen) {
- that.selectDiv.addClass('open');
- }
- e.preventDefault();
- e.stopPropagation();
- });
},
destroy : function() {
- // call the base destroy function
+ this.selectDiv.removeClass('btn-select dropdown popable');
+ this.target.removeClass('input');
+ this.label.removeClass('input');
+ this.listControl.removeClass('select-list');
+ this.listControl.parent().removeClass('popover');
$.Widget.prototype.destroy.call(this);
}
});
diff --git a/ui/pages/i18n.html.tmpl b/ui/pages/i18n.html.tmpl
index 3047fdc..9727eba 100644
--- a/ui/pages/i18n.html.tmpl
+++ b/ui/pages/i18n.html.tmpl
@@ -124,7 +124,7 @@ var i18n = {
'msg.pool.edit.server.blank':"$_("Server name can not be blank.")",
'msg.validate.pool.edit.server':"$_("This is not a valid Server Name or IP. please, modify it.")",
'select_default': "$_("Please choose")",
- 'msg.storagepool.unvalid.path': "$_("This is not a valid path")",
+ 'msg.no.mapping.result': "$_("No such data exsit.")",
'msg.no.result' : "$_("No valid result")"
};
</script>
diff --git a/ui/pages/storagepool-add.html.tmpl b/ui/pages/storagepool-add.html.tmpl
index 4276bf0..00f21d5 100644
--- a/ui/pages/storagepool-add.html.tmpl
+++ b/ui/pages/storagepool-add.html.tmpl
@@ -47,11 +47,11 @@
<section class="form-section">
<h2>2. $_("Storage Pool Type")</h2>
<div class="storage-type-wrapper-controls">
- <div>
- <input id="poolType" name="type" type="hidden" value="dir"/>
- <span class="text" id="pool-type-label"></span><span class="arrow"></span>
- <div style="width: 100%">
- <ul class="select-list" id="storagePool-list" data-target="poolType" data-label="pool-type-label">
+ <div id="poolTypeId">
+ <input id="poolTypeInputId" name="type" type="hidden" value="dir"/>
+ <span id="pool-type-label"></span><span class="arrow"></span>
+ <div>
+ <ul id="storagePool-list">
</ul>
</div>
</div>
@@ -73,14 +73,14 @@
<div class="nfs-section tmpl-html">
<section class="form-section">
<h2>3. $_("NFS server IP")</h2>
- <div class="field">
+ <div class="field" style="overflow:visible">
<p class="text-help">
- $_("NFS server IP or hostname. It should not be empty.")</p>
- <div style="width: 285px">
+ $_("NFS server IP or hostname. It can be input or choose from history.")</p>
+ <div id="serverComboboxId" style="width: 285px">
<input id="nfsserverId"/>
- <span class="text" id="nfs-server-label"></span><span class="arrow"></span>
- <div style="width: 100%">
- <ul class="select-list" id="nfs-server-used" data-target="nfsserverId" data-label="nfs-server-label">
+ <span class="arrow"></span>
+ <div>
+ <ul id="nfs-server-used">
</ul>
</div>
</div>
@@ -90,11 +90,11 @@
<h2>4. $_("NFS Path")</h2>
<div class="field" style="overflow:visible">
<p class="text-help">$_("The nfs exported path on nfs server")</p>
- <div style="width: 285px">
- <input id="nfspathId" class="text" disabled="disabled" style="width:293px;"/>
- <span class="text" id="nfs-target-label"></span><span class="arrow"></span>
- <div style="width: 100%">
- <ul class="select-list" id="nfs-server-target" data-target="nfspathId" data-label="nfs-target-label">
+ <div id="targetFilterSelectId" style="width: 285px">
+ <input id="nfspathId" class="input" disabled="disabled"/>
+ <span class="arrow"></span>
+ <div>
+ <ul id="nfs-server-target">
</ul>
</div>
</div>
--
1.7.1
10 years, 10 months
[PATCH V1] add a synchronous function with timeout to execute command
by shaohef@linux.vnet.ibm.com
From: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
We need a common function to execute shell command.
We also need timeout when execute shell command.
A threading.Timer is used to send signal.SIGKILL to kill the command
when timeout.
Signed-off-by: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Signed-off-by: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
---
src/kimchi/utils.py | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
index af245c6..94097ad 100644
--- a/src/kimchi/utils.py
+++ b/src/kimchi/utils.py
@@ -23,6 +23,7 @@
import cherrypy
import os
+import subprocess
import urllib2
@@ -30,6 +31,7 @@ from cherrypy.lib.reprconf import Parser
from kimchi import config
+from threading import Timer
kimchi_log = cherrypy.log.error_log
@@ -96,3 +98,40 @@ def check_url_path(path):
return False
return True
+
+
+def run_command(cmd, timeout=None):
+ def kill_proc(proc, timeout_flag):
+ timeout_flag[0] = True
+ proc.kill()
+
+ proc = None
+ timer = None
+ timeout_flag = [False]
+
+ try:
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ if timeout is not None:
+ timer = Timer(timeout, kill_proc, [proc, timeout_flag])
+ timer.start()
+
+ 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)
+
+ return out, error, proc.returncode, timeout_flag[0]
+ except Exception as e:
+ msg = "Failed to run command: %s." % " ".join(cmd)
+ msg = msg if proc is None else msg + "\n error code: %s."
+ kimchi_log.error("%s\n %s", msg, e)
+
+ if proc:
+ return out, error, proc.returncode, timeout_flag[0]
+ else:
+ return None, None, None, timeout_flag[0]
+ finally:
+ if timer and not timeout_flag[0]:
+ timer.cancel()
--
1.8.4.2
10 years, 10 months
[PATCH] Fix break of deep scanning
by lvroyce@linux.vnet.ibm.com
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Commit 265de8d7 forgetted to add type 'kimchi-iso' to storage pool
type, which prevent deep scannning to execute.
Add it to API.json to fix this break.
Signed-off-by: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
---
src/kimchi/API.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/kimchi/API.json b/src/kimchi/API.json
index 3a3c48f..268287b 100644
--- a/src/kimchi/API.json
+++ b/src/kimchi/API.json
@@ -16,7 +16,7 @@
"type": {
"description": "The type of the defined Storage Pool",
"type": "string",
- "pattern": "^dir|netfs|logical$",
+ "pattern": "^dir|netfs|logical|kimchi-iso$",
"required": true
},
"path": {
--
1.8.1.2
10 years, 10 months
[Fwd: Fw: Is this SSL error an issue, or expected behavior?]
by Christy Perez
Rodrigo,
Not to beat a dead horse here (hopefully you've all heard that
expression before, heh), but my question wasn't about how to get it
working or why it's happening -- but rather if we should handle the
error instead of having it shown to users. See:
] ENGINE socket.error 1
Traceback (most recent call last):
File
"/usr/lib/python2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py",
line 1292, in communicate
req.parse_request()
File
"/usr/lib/python2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py",
line 580, in parse_request
success = self.read_request_line()
File
"/usr/lib/python2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py",
line 611, in read_request_line
request_line = self.rfile.readline()
File
"/usr/lib/python2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py",
line 274, in readline
data = self.rfile.readline(256)
File
"/usr/lib/python2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py",
line 1114, in readline
data = self.recv(self._rbufsize)
File
"/usr/lib/python2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py",
line 990, in recv
data = self._sock.recv(size)
File "/usr/lib64/python2.7/ssl.py", line 241, in recv
return self.read(buflen)
File "/usr/lib64/python2.7/ssl.py", line 160, in read
return self._sslobj.read(len)
SSLError: [Errno 1] _ssl.c:1419: error:14094418:SSL
routines:SSL3_READ_BYTES:tlsv1 alert unknown ca
If we're all okay with that showing up in the kimchi command output --
fine. I just wanted to be sure.
Regards,
-------- Forwarded Message --------
From: Christy L Norman Perez <clnperez(a)us.ibm.com>
To: christy(a)linux.vnet.ibm.com
Subject: Fw: Is this SSL error an issue, or expected behavior?
Date: Fri, 3 Jan 2014 16:42:55 -0600
----- Forwarded by Christy L Norman Perez/Austin/IBM on 01/03/2014 04:01 PM
-----
From: Rodrigo Trujillo/Brazil/IBM@IBMBR
To: Christy L Norman Perez/Austin/IBM@IBMUS, Rodrigo
Trujillo/Brazil/IBM, Daniel Henrique Barboza/Brazil/IBM@IBMBR,
Adriano Araujo dos Reis Botega/Brazil/IBM@IBMBR, Scott
Garfinkle/Austin/IBM@IBMUS, Christy L Norman
Perez/Austin/IBM@IBMUS, De Xin AD Wu/China/IBM@IBMCN, Zheng
Sheng ZS Zhou/China/IBM@IBMCN
Cc: kimchi-ginger-dev@IBMUS
Date: 12/27/2013 05:06 AM
Subject: Re: Is this SSL error an issue, or expected behavior?
Like Mark said, this problem is caused by the CA which signed the Kimchi
certificate ... actually, it is an auto signed certificate....
you can see running:
openssl x509 -text -in src/kimchi-cert.pem
notice that the issuer is kimchi itself.
The error is caused because by kimchi actually. It happens because the
browser or url requester does not accept the certificate.
So, if you use curl for testing, use the option "-k" (insecure) ... if you
are using browser , they usually ask if you would like to trust the
certificate.
Regards
Rodrigo Trujillo
Staff Software Engineer
Linux Technology Center - Brasil
From: Christy L Norman Perez/Austin/IBM@IBMUS
To: kimchi
Date: 19/12/2013 16:11
Subject: Is this SSL error an issue, or expected behavior?
To pick up from the e-mail I started yesterday...
The ca error does go away if I go in and "forget about the site," create an
exception for the certificate, then try again. I also played with this a
bit to see if I can get the regular kimchi build to give me the same error,
and I could. So, I think this could be discussed as an issue with kimchi
(not just kimchi-ginger).
Regards,
Christy Norman Perez <clnperez(a)us.ibm.com>
Software Engineer
IBM KVM Assistance Program
Linux Technology Center
512.286.7821 (T/L 363.7821)
10 years, 10 months
[WIP PATCH 0/2] Hosts Management & Host Repository Management
by Hongliang Wang
Added federated hosts;
Added host repository management.
There is a bug in kimchi.widget.Grid widget: when there are more than one
Grid instances in the page, column resizing function will work incorrectly.
I'll send another patch to fix it.
Hongliang Wang (2):
Federated Hosts Management
Host Repositories Management UI
src/kimchi/model.py | 1 +
ui/css/theme-default/host-add.css | 29 +++++++
ui/css/theme-default/host-edit.css | 29 +++++++
ui/css/theme-default/host.css | 80 +++++++++++++++---
ui/css/theme-default/hosts.css | 24 ++++++
ui/css/theme-default/repository-edit.css | 29 +++++++
ui/css/theme-default/window.css | 6 +-
ui/images/theme-default/host-icon-sprite.png | Bin 1034 -> 1163 bytes
ui/js/src/kimchi.api.js | 110 +++++++++++++++++++++++++
ui/js/src/kimchi.grid.js | 2 +-
ui/js/src/kimchi.host.js | 93 +++++++++++++++++++++
ui/js/src/kimchi.host_add_main.js | 62 ++++++++++++++
ui/js/src/kimchi.host_edit_main.js | 62 ++++++++++++++
ui/js/src/kimchi.hosts.js | 116 +++++++++++++++++++++++++++
ui/js/src/kimchi.repository_edit_main.js | 62 ++++++++++++++
ui/pages/guest-add.html.tmpl | 2 +-
ui/pages/guest-edit.html.tmpl | 2 +-
ui/pages/host-add.html.tmpl | 66 +++++++++++++++
ui/pages/host-edit.html.tmpl | 66 +++++++++++++++
ui/pages/hosts.html.tmpl | 41 ++++++++++
ui/pages/i18n.html.tmpl | 16 ++++
ui/pages/login-window.html.tmpl | 2 +-
ui/pages/report-add.html.tmpl | 2 +-
ui/pages/repository-edit.html.tmpl | 66 +++++++++++++++
ui/pages/storagepool-add.html.tmpl | 2 +-
ui/pages/tabs/host.html.tmpl | 40 ++++++++-
ui/pages/template-add.html.tmpl | 2 +-
ui/pages/template-edit.html.tmpl | 2 +-
28 files changed, 989 insertions(+), 25 deletions(-)
create mode 100644 ui/css/theme-default/host-add.css
create mode 100644 ui/css/theme-default/host-edit.css
create mode 100644 ui/css/theme-default/hosts.css
create mode 100644 ui/css/theme-default/repository-edit.css
create mode 100644 ui/js/src/kimchi.host_add_main.js
create mode 100644 ui/js/src/kimchi.host_edit_main.js
create mode 100644 ui/js/src/kimchi.hosts.js
create mode 100644 ui/js/src/kimchi.repository_edit_main.js
create mode 100644 ui/pages/host-add.html.tmpl
create mode 100644 ui/pages/host-edit.html.tmpl
create mode 100644 ui/pages/hosts.html.tmpl
create mode 100644 ui/pages/repository-edit.html.tmpl
--
1.8.1.4
10 years, 10 months
[PATCH V2 0/3] Removal of developer UI
by Shu Ming
V1->V2: Add the patch to update po files
[RFC] Removal of of developer UI
Shu Ming (3):
Remove the legacy files from automake and package configurations
Remove the legacy files
Update the po files
contrib/kimchi.spec.fedora.in | 3 -
contrib/kimchi.spec.suse.in | 3 -
po/POTFILES.in | 1 -
po/en_US.po | 97 +-
po/kimchi.pot | 97 +-
po/pt_BR.po | 97 +-
po/zh_CN.po | 97 +-
ui/css/Makefile.am | 2 +-
ui/css/dev.base.css | 3999 -----------------------------------------
ui/css/dev.jquery-ui.css | 1173 ------------
ui/css/dev.main.css | 131 --
ui/css/dev.style.css | 164 --
ui/images/Makefile.am | 2 +-
ui/images/bg-footer-noise.jpg | Bin 6916 -> 0 bytes
ui/images/chosen-sprite.png | Bin 646 -> 0 bytes
ui/images/gauze.png | Bin 6045 -> 0 bytes
ui/images/gtk-directory.png | Bin 2759 -> 0 bytes
ui/images/image-missing.png | Bin 2856 -> 0 bytes
ui/images/jq-global-nav.png | Bin 6738 -> 0 bytes
ui/images/jq-nav-icons.png | Bin 9804 -> 0 bytes
ui/js/Makefile.am | 1 -
ui/js/dev.main.js | 464 -----
ui/pages/Makefile.am | 1 -
ui/pages/dev-ui.html.tmpl | 170 --
24 files changed, 86 insertions(+), 6416 deletions(-)
delete mode 100644 ui/css/dev.base.css
delete mode 100644 ui/css/dev.jquery-ui.css
delete mode 100644 ui/css/dev.main.css
delete mode 100644 ui/css/dev.style.css
delete mode 100644 ui/images/bg-footer-noise.jpg
delete mode 100644 ui/images/chosen-sprite.png
delete mode 100644 ui/images/gauze.png
delete mode 100644 ui/images/gtk-directory.png
delete mode 100644 ui/images/image-missing.png
delete mode 100644 ui/images/jq-global-nav.png
delete mode 100644 ui/images/jq-nav-icons.png
delete mode 100644 ui/js/dev.main.js
delete mode 100644 ui/pages/dev-ui.html.tmpl
--
1.8.1.4
10 years, 10 months
[PATCH V5 0/3] network improvment: add vms field
by shaohef@linux.vnet.ibm.com
From: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
V4 -> V5
fix typo in subject.
V3 -> V4
the subject of patch V3 3/3 is wrong.
fix it.
V2 -> V3
update mockmodel and test case
V1 -> V2
set the flags argument of listAllDomains as 0 explicitly.
For in some distros:
$ pydoc libvirt.virConnect.listAllDomains
libvirt.virConnect.listAllDomains = listAllDomains(self, flags) \
unbound libvirt.virConnect method
And in other distros:
$ pydoc libvirt.virConnect.listAllDomains
libvirt.virConnect.listAllDomains = listAllDomains(self, flags=0) \
unbound libvirt.virConnect method
ShaoHe Feng (3):
network improvement: add vms field
network improvement: update mockmodel to support vms field
network improvement: update test case to support vms field
docs/API.md | 1 +
src/kimchi/control/networks.py | 1 +
src/kimchi/mockmodel.py | 9 +++++++++
src/kimchi/model.py | 15 +++++++++++++++
tests/test_model.py | 1 +
tests/test_rest.py | 3 +++
6 files changed, 30 insertions(+)
--
1.8.4.2
10 years, 10 months
[PATCH v4 1/3] Generate libvirt's interface XML definition for vlan tagged bridge
by Mark Wu
To support vlan tagged virtual network, kimchi needs create the underlying
vlan and bridge interface. Libvirt's interface driver can do it with
a given XML definition. This patch targets to generate the XML according
to the interface and vlan id.
Signed-off-by: Mark Wu <wudxw(a)linux.vnet.ibm.com>
---
src/kimchi/networkxml.py | 19 +++++++++++++++++++
tests/test_networkxml.py | 22 ++++++++++++++++++++++
tests/utils.py | 6 ++++++
3 files changed, 47 insertions(+)
diff --git a/src/kimchi/networkxml.py b/src/kimchi/networkxml.py
index 786cb69..63cb210 100644
--- a/src/kimchi/networkxml.py
+++ b/src/kimchi/networkxml.py
@@ -21,6 +21,10 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import ipaddr
+import lxml.etree as ET
+
+
+from lxml.builder import E
# FIXME, do not support ipv6
@@ -109,3 +113,18 @@ def to_network_xml(**kwargs):
</network>
""" % params
return xml
+
+
+def create_vlan_tagged_bridge_xml(bridge, interface, vlan_id):
+ vlan = E.vlan(E.interface(name=interface))
+ vlan.set('tag', vlan_id)
+ m = E.interface(
+ E.start(mode='onboot'),
+ E.bridge(
+ E.interface(
+ vlan,
+ type='vlan',
+ name='.'.join([interface, vlan_id]))),
+ type='bridge',
+ name=bridge)
+ return ET.tostring(m)
diff --git a/tests/test_networkxml.py b/tests/test_networkxml.py
index 3073bce..42b3ea9 100644
--- a/tests/test_networkxml.py
+++ b/tests/test_networkxml.py
@@ -25,6 +25,9 @@ import unittest
import kimchi.networkxml as nxml
+import utils
+
+
from kimchi.xmlutils import xpath_get_text
@@ -151,3 +154,22 @@ class NetworkXmlTests(unittest.TestCase):
netmask = xpath_get_text(xml, "/network/ip/@netmask")[0]
self.assertEquals(netmask,
str(ipaddr.IPNetwork(params["net"]).netmask))
+
+
+class InterfaceXmlTests(unittest.TestCase):
+
+ def test_vlan_tagged_bridge_no_ip(self):
+ expected_xml = """
+ <interface type='bridge' name='br10'>
+ <start mode='onboot'/>
+ <bridge>
+ <interface type='vlan' name='em1.10'>
+ <vlan tag='10'>
+ <interface name='em1'/>
+ </vlan>
+ </interface>
+ </bridge>
+ </interface>
+ """
+ actual_xml = nxml.create_vlan_tagged_bridge_xml('br10', 'em1', '10')
+ self.assertEquals(actual_xml, utils.normalize_xml(expected_xml))
diff --git a/tests/utils.py b/tests/utils.py
index 008f668..79fc2e2 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -32,6 +32,7 @@ import unittest
from contextlib import closing
+from lxml import etree
import kimchi.server
@@ -159,3 +160,8 @@ def patch_auth():
import kimchi.auth
kimchi.auth.authenticate = _authenticate
+
+
+def normalize_xml(xml_str):
+ return etree.tostring(etree.fromstring(xml_str,
+ etree.XMLParser(remove_blank_text=True)))
--
1.8.4.2
10 years, 10 months
[PATCH v4 2/3] Support creating vlan tagged virtual network
by Mark Wu
It creates a vlan interface on top of the given nic or bond interface,
and bridge the vlan interface to a new created bridge, which is used to
forward VM's traffic. So all packets transmitted from VM will be tagged
before it departs from the physical network interface.
Signed-off-by: Mark Wu <wudxw(a)linux.vnet.ibm.com>
---
src/kimchi/API.json | 6 ++++++
src/kimchi/model.py | 47 ++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 50 insertions(+), 3 deletions(-)
diff --git a/src/kimchi/API.json b/src/kimchi/API.json
index 3a3c48f..19b1c51 100644
--- a/src/kimchi/API.json
+++ b/src/kimchi/API.json
@@ -125,6 +125,12 @@
"interface": {
"description": "The name of a network interface on the host",
"type": "string"
+ },
+ "vlan_id": {
+ "description": "Network's VLAN ID",
+ "type": "integer",
+ "maximum": 4094,
+ "minimum": 1
}
}
},
diff --git a/src/kimchi/model.py b/src/kimchi/model.py
index ed613b1..5281979 100644
--- a/src/kimchi/model.py
+++ b/src/kimchi/model.py
@@ -57,6 +57,7 @@ except ImportError:
from kimchi import config
from kimchi import netinfo
from kimchi import network as knetwork
+from kimchi import networkxml
from kimchi import vnc
from kimchi import xmlutils
from kimchi.asynctask import AsyncTask
@@ -66,7 +67,6 @@ from kimchi.exception import MissingParameter, NotFoundError, OperationFailed
from kimchi.featuretests import FeatureTests
from kimchi.iscsi import TargetClient
from kimchi.isoinfo import IsoImage
-from kimchi.networkxml import to_network_xml
from kimchi.objectstore import ObjectStore
from kimchi.scan import Scanner
from kimchi.screenshot import VMScreenshot
@@ -819,7 +819,12 @@ class Model(object):
if netinfo.is_bridge(iface):
params['bridge'] = iface
elif netinfo.is_bare_nic(iface) or netinfo.is_bonding(iface):
- params['forward']['dev'] = iface
+ if params.get('vlan_id') is None:
+ params['forward']['dev'] = iface
+ else:
+ params['bridge'] = \
+ self._create_vlan_tagged_bridge(str(iface),
+ str(params['vlan_id']))
else:
raise InvalidParameter("the interface should be bare nic, "
"bonding or bridge device.")
@@ -843,7 +848,7 @@ class Model(object):
if connection == 'bridge':
self._set_network_bridge(params)
- xml = to_network_xml(**params)
+ xml = networkxml.to_network_xml(**params)
try:
network = conn.networkDefineXML(xml)
@@ -901,8 +906,44 @@ class Model(object):
if network.isActive():
raise InvalidOperation(
"Unable to delete the active network %s" % name)
+ self._remove_vlan_tagged_bridge(network)
network.undefine()
+ def _get_vlan_tagged_bridge_name(self, interface, vlan_id):
+ return '-'.join(('kimchi', interface, vlan_id))
+
+ def _is_vlan_tagged_bridge(self, bridge):
+ return bridge.startswith('kimchi-')
+
+ def _create_vlan_tagged_bridge(self, interface, vlan_id):
+ br_name = self._get_vlan_tagged_bridge_name(interface, vlan_id)
+ br_xml = networkxml.create_vlan_tagged_bridge_xml(br_name, interface,
+ vlan_id)
+ conn = self.conn.get()
+ conn.changeBegin()
+ try:
+ vlan_tagged_br = conn.interfaceDefineXML(br_xml)
+ vlan_tagged_br.create()
+ except libvirt.libvirtError as e:
+ conn.changeRollback()
+ raise OperationFailed(e.message)
+ else:
+ conn.changeCommit()
+ return br_name
+
+ def _remove_vlan_tagged_bridge(self, network):
+ try:
+ bridge = network.bridgeName()
+ except libvirt.libvirtError:
+ pass
+ else:
+ if self._is_vlan_tagged_bridge(bridge):
+ conn = self.conn.get()
+ iface = conn.interfaceLookupByName(bridge)
+ if iface.isActive():
+ iface.destroy()
+ iface.undefine()
+
def add_task(self, target_uri, fn, opaque=None):
id = self.next_taskid
self.next_taskid = self.next_taskid + 1
--
1.8.4.2
10 years, 10 months