[RFC] define REST API for guest Network Interfaces.
by Sheldon
now we have support network get/create/delete/activate/deactivate
Now we need to support the attach/detach/
<https://github.com/kimchi-project/kimchi/wiki/customize-VM#organization-o...>
a Network to a guest.
And get the info of Network attached to a guest.
libvirt supports several types of network interfaces:
'bridge','network','user','ethernet','direct','hostdev','mcast',
'server', 'client'
but there is not a unique "name" attribute for "interface" element.(more
libvirt network interfaces info
<http://libvirt.org/formatdomain.html#elementsNICS>)
That is not good to define our REST API.
But for "network" type resource, there is a "network" attribute of
"source" resource.
And the value of "network" attribute is the name of network that we
defined by /networks POST method.
the "network" type + "network" attribute is unique.
We can define the Network Interfaces like this to support "network" type
Interfaces:
GET /vms/*name*/Interfaces?type=network&network="default"
But this is not RESTFUL.
Maybe We can also name a Network Interface by the Interface mac.
The mac is unique.
GET /vms/*name*/Interfaces/mac
The best way for user is get the NICS name in guest. such as eth0, eth1....
GET /vms/*name*/Interfaces/eth0
GET /vms/*name*/Interfaces/eth1
But there is a problem, we need get the nic name and mac from guest.
and Make a map in kimchi DB.
also the nic name may change, we need make the map consistence with
guest nic name.
--
Sheldon Feng(???)<shaohef(a)linux.vnet.ibm.com>
IBM Linux Technology Center
10 years, 11 months
[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, 11 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, 11 months
[PATCH V2] Add nfs server and target UI in create storage pool
by zhoumeina
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 | 11 +--
ui/css/theme-default/form.css | 6 ++
ui/css/theme-default/storage.css | 4 +-
ui/js/Makefile.am | 4 +-
ui/js/src/kimchi.api.js | 26 ++++++-
ui/js/src/kimchi.storagepool_add_main.js | 73 +++++++++++++++--
ui/js/src/kimchi.utils.js | 11 +++
ui/js/widgets/filter-select.js | 137 ++++++++++++++++++++++++++++++
ui/js/widgets/select-menu.js | 86 +++++++++++++++++++
ui/pages/i18n.html.tmpl | 5 +-
ui/pages/storagepool-add.html.tmpl | 41 +++++++--
11 files changed, 376 insertions(+), 28 deletions(-)
create mode 100644 ui/js/widgets/filter-select.js
create mode 100644 ui/js/widgets/select-menu.js
diff --git a/ui/css/theme-default/button.css b/ui/css/theme-default/button.css
index c7ed3f6..f99679a 100644
--- a/ui/css/theme-default/button.css
+++ b/ui/css/theme-default/button.css
@@ -247,17 +247,16 @@
.btn-select {
display: inline-block;
position: relative;
- height: 38px;
+ height: 30px;
padding-right: 20px;
margin: 5px;
vertical-align: top;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
- border-radius: 5px;
- background: #eee;
+ background: #fff;
box-shadow: -1px -1px 1px #666, 1px 1px 1px #fff, 2px 2px 2px rgba(0, 0, 0, .15) inset;
font-size: 13px;
- line-height: 38px;
+ line-height: 30px;
text-align: left;
cursor: pointer;
}
@@ -269,8 +268,8 @@
.btn-select .arrow {
position: absolute;
width: 15px;
- height: 38px;
- line-height: 38px;
+ height: 30px;
+ line-height: 30px;
top: 0;
right: 5px;
background: url(../images/theme-default/arrow-down-black.png) no-repeat center center;
diff --git a/ui/css/theme-default/form.css b/ui/css/theme-default/form.css
index c24b277..9db4bba 100644
--- a/ui/css/theme-default/form.css
+++ b/ui/css/theme-default/form.css
@@ -45,3 +45,9 @@
line-height: 30px;
padding: 0 5px;
}
+
+.text-help {
+ font-size: 12px;
+ color: #333;
+ margin: 0 0 5px 5px;
+}
diff --git a/ui/css/theme-default/storage.css b/ui/css/theme-default/storage.css
index d81dc75..ae89f1b 100644
--- a/ui/css/theme-default/storage.css
+++ b/ui/css/theme-default/storage.css
@@ -529,7 +529,7 @@
width: 300px;
display: inline-block;
vertical-align: top;
- padding: 5px 5px 5px 20px;
+ padding: 5px 5px 5px 22px;
}
.storage-type-wrapper-controls input[type="text"] {
@@ -548,7 +548,7 @@
.storage-type-wrapper-controls > .dropdown {
margin: 5px 0 0 1px;
- width: 250px;
+ width: 150px;
}
.storage-type-wrapper-controls input[type="text"][disabled] {
diff --git a/ui/js/Makefile.am b/ui/js/Makefile.am
index 337e369..8dfd4d6 100644
--- a/ui/js/Makefile.am
+++ b/ui/js/Makefile.am
@@ -20,7 +20,7 @@
SUBDIRS = novnc
-EXTRA_DIST = src
+EXTRA_DIST = src widgets
jsdir = $(datadir)/kimchi/ui/js
@@ -32,7 +32,7 @@ dist_js_DATA = \
modernizr.custom.2.6.2.min.js \
$(NULL)
-kimchi.min.js: src/*.js
+kimchi.min.js: widgets/*.js src/*.js
cat $(sort $^) > $@
CLEANFILES = kimchi.min.js
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index fbcf4a2..f6115a8 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -681,5 +681,29 @@ var kimchi = {
success : suc,
error : err
});
+ },
+
+ getStorageServers: function(type, suc, err) {
+ var url = kimchi.url + 'storageservers?target_type=' + type;
+ kimchi.requestJSON({
+ url : url,
+ type : 'GET',
+ contentType : 'application/json',
+ dataType : 'json',
+ success : suc,
+ error : err
+ });
+ },
+
+ getStorageTargets: function(server,type, suc, err) {
+ var url = kimchi.url + 'storageservers/' + server + '/storagetargets?target_type=' + type;
+ kimchi.requestJSON({
+ url : url,
+ type : 'GET',
+ contentType : 'application/json',
+ dataType : 'json',
+ success : suc,
+ error : err
+ });
}
-};
+};
\ No newline at end of file
diff --git a/ui/js/src/kimchi.storagepool_add_main.js b/ui/js/src/kimchi.storagepool_add_main.js
index b31610a..7955352 100644
--- a/ui/js/src/kimchi.storagepool_add_main.js
+++ b/ui/js/src/kimchi.storagepool_add_main.js
@@ -51,7 +51,72 @@ kimchi.initStorageAddPage = function() {
});
$('.host-partition').html(listHtml);
}
- kimchi.select('storagePool-list', options);
+ $('#storagePool-list').selectMenu();
+ $('#storagePool-list').selectMenu("setData", options);
+ kimchi.getStorageServers('netfs', function(data) {
+ var serverContent = [];
+ serverContent.push({
+ label : i18n['select_default'],
+ value : ''
+ });
+ if (data.length > 0) {
+ $.each(data, function(index, value) {
+ serverContent.push({
+ label : value,
+ value : value
+ });
+ });
+ }
+ $('#nfs-server-used').selectMenu();
+ $('#nfs-server-used').selectMenu("setData", serverContent);
+ $('#nfs-server-target').filterselect();
+ $('input[name=nfsServerType]').change(function() {
+ if ($(this).val() === 'input') {
+ $('#nfsServerInputDiv').removeClass('tmpl-html');
+ $('#nfsServerChooseDiv').addClass('tmpl-html');
+ } else {
+ $('#nfsServerInputDiv').addClass('tmpl-html');
+ $('#nfsServerChooseDiv').removeClass('tmpl-html');
+ }
+ });
+ $('#nfsServerSelect').change(function() {
+ $('#nfsserverId').val($(this).val());
+ $('#nfsserverId').trigger("keydown");
+ });
+ $('#nfsserverId').on("keydown",function() {
+ if ($(this).val() !== '' && kimchi.isServer($(this).val())) {
+ $('#nfspathId').removeAttr('disabled');
+ } else {
+ $('#nfspathId').attr('disabled','disabled');
+ }
+ $('#nfs-server-target').filterselect('clear');
+ });
+ $('#nfspathId').focus(function() {
+ var targetContent = [];
+ kimchi.getStorageTargets($('#nfsserverId').val(), 'netfs', function(data) {
+ if (data.length > 0) {
+ $.each(data, function(index, value) {
+ targetContent.push({
+ label : value.target,
+ value : value.target
+ });
+ });
+ } else {
+ targetContent.push({
+ label : i18n['msg.no.result'],
+ value : ''
+ });
+ }
+ $('#nfs-server-target').filterselect("setData", targetContent);
+ },function() {
+ targetContent.push({
+ label : i18n['msg.no.result'],
+ value : ''
+ });
+ $('#nfs-server-target').filterselect("setData", targetContent);
+ });
+ });
+ });
$('#poolType').change(function() {
if ($(this).val() === 'dir') {
$('.path-section').removeClass('tmpl-html');
@@ -88,7 +153,6 @@ kimchi.validateForm = function() {
} else {
return kimchi.validateLogicalForm();
}
-
};
kimchi.validateDirForm = function () {
@@ -116,11 +180,8 @@ kimchi.validateNfsForm = function () {
kimchi.message.error(i18n['msg.pool.edit.nfspath.blank']);
return false;
}
- var domain = "([0-9a-z_!~*'()-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6}"
- var ip = "(\\d{1,3}\.){3}\\d{1,3}"
- regex = new RegExp('^' + domain + '|' + ip + '$')
- if(!regex.test(nfsserver)) {
+ if(kimchi.isServer(nfsserver)) {
kimchi.message.error(i18n['msg.validate.pool.edit.nfsserver']);
return false;
}
diff --git a/ui/js/src/kimchi.utils.js b/ui/js/src/kimchi.utils.js
index 8af6a11..6439db6 100644
--- a/ui/js/src/kimchi.utils.js
+++ b/ui/js/src/kimchi.utils.js
@@ -163,3 +163,14 @@ kimchi.changetoProperUnit = function(numOrg, digits, base) {
kimchi.formatMeasurement = format;
})();
+
+kimchi.isServer = function(server) {
+ var domain = "([0-9a-z_!~*'()-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6}"
+ var ip = "(\\d{1,3}\.){3}\\d{1,3}"
+ regex = new RegExp('^' + domain + '|' + ip + '$');
+ if(!regex.test(server)) {
+ return false;
+ } else {
+ return true;
+ }
+};
\ No newline at end of file
diff --git a/ui/js/widgets/filter-select.js b/ui/js/widgets/filter-select.js
new file mode 100644
index 0000000..02fe5d9
--- /dev/null
+++ b/ui/js/widgets/filter-select.js
@@ -0,0 +1,137 @@
+/*
+ * 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.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.addClass('btn-select dropdown popable');
+ this.listControl.parent().addClass('popover');
+ },
+
+ _setOption : function(key, value) {
+ },
+
+ setData : function(options) {
+ this.element.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);
+ })
+ 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) {
+ 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.storagepool.unvalid.path']);
+ }
+ 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() {
+ // call the base destroy function
+ $.Widget.prototype.destroy.call(this);
+ }
+ });
+}(jQuery));
\ No newline at end of file
diff --git a/ui/js/widgets/select-menu.js b/ui/js/widgets/select-menu.js
new file mode 100644
index 0000000..4124096
--- /dev/null
+++ b/ui/js/widgets/select-menu.js
@@ -0,0 +1,86 @@
+/*
+ * 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.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.addClass('btn-select dropdown popable');
+ this.listControl.parent().addClass('popover');
+ var that = this;
+ },
+
+ _setOption : function(key,value) {},
+
+ setData : function (options) {
+ var that = this;
+ var value = this.target.val();
+ var selectedClass = 'active';
+ var itemTag = 'li';
+ $.each(options, function(index, option) {
+ item = $('<' + itemTag + '></' + itemTag + '>');
+ item.text(option.label);
+ item.data('value', option.value);
+ if(option.value === value) {
+ item.addClass(selectedClass);
+ that.label.text(option.label);
+ }
+ that.listControl.append(item);
+ });
+ that.listControl.on('click', itemTag, function() {
+ that.listControl.children().removeClass(selectedClass);
+ that.listControl.addClass(selectedClass);
+ that.label.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) {
+ 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
+ $.Widget.prototype.destroy.call(this);
+ }
+ });
+}(jQuery));
\ No newline at end of file
diff --git a/ui/pages/i18n.html.tmpl b/ui/pages/i18n.html.tmpl
index c1fc3d1..c95da9b 100644
--- a/ui/pages/i18n.html.tmpl
+++ b/ui/pages/i18n.html.tmpl
@@ -121,7 +121,10 @@ var i18n = {
'action_create': "$_("Create")",
'msg_warning': "$_("Warning")",
'msg.logicalpool.confirm.delete': "$_("It will format your disk and you will loose any data in"
- " there, are you sure to continue? ")"
+ " there, are you sure to continue? ")",
+ 'select_default': "$_("Please choose")",
+ 'msg.storagepool.unvalid.path': "$_("This is not a valid path")",
+ 'msg.no.result' : "$_("No valid result")"
};
</script>
</body>
diff --git a/ui/pages/storagepool-add.html.tmpl b/ui/pages/storagepool-add.html.tmpl
index 5a2dd45..3a73390 100644
--- a/ui/pages/storagepool-add.html.tmpl
+++ b/ui/pages/storagepool-add.html.tmpl
@@ -27,7 +27,7 @@
<!DOCTYPE html>
<html>
<body>
- <div class="window" style="width: 600px; height: 600px;">
+ <div class="window" style="width: 800px; height: 650px;">
<header>
<h1 class="title">$_("Define a New Storage Pool")</h1>
<div class="close">X</div>
@@ -47,10 +47,10 @@
<section class="form-section">
<h2>2. $_("Storage Pool Type")</h2>
<div class="storage-type-wrapper-controls">
- <div class="btn dropdown popable">
+ <div>
<input id="poolType" name="type" type="hidden" value="dir"/>
<span class="text" id="pool-type-label"></span><span class="arrow"></span>
- <div class="popover" style="width: 100%">
+ <div style="width: 100%">
<ul class="select-list" id="storagePool-list" data-target="poolType" data-label="pool-type-label">
</ul>
</div>
@@ -74,22 +74,43 @@
<section class="form-section">
<h2>3. $_("NFS server IP")</h2>
<div class="field">
+ <input type="radio" id="nfsServerInput" value="input" name="nfsServerType" checked="true">
+ <label>$_("I want to input the server myself.")</label>
+ <input type="radio" id="nfsServerChoose" value="choose" name="nfsServerType">
+ <label>$_("I want to choose a server I used before.")</label>
+ </div>
+ <div id="nfsServerInputDiv" class="field">
<p class="text-help">
$_("NFS server IP or hostname. It should not be empty.")</p>
<input id="nfsserverId" type="text" class="text"
style="width: 300px">
</div>
+ <div id="nfsServerChooseDiv" class="field tmpl-html" style="overflow:visible">
+ <p class="text-help">
+ $_("Please choose the nfs server you want to create storage pool.")</p>
+ <div style="width: 285px">
+ <input id="nfsServerSelect" type="hidden"/>
+ <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="nfsServerSelect" data-label="nfs-server-label">
+ </ul>
+ </div>
+ </div>
+ </div>
</section>
<section class="form-section">
<h2>4. $_("NFS Path")</h2>
- <div class="field">
+ <div class="field" style="overflow:visible">
<p class="text-help">$_("The nfs exported path on nfs server")</p>
- <input id="nfspathId" type="text" class="text"
- style="width: 300px">
- <input type="hidden" id="localpathId" class="text"
- value="none">
- </div>
- <div class="clear"></div>
+ <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">
+ </ul>
+ </div>
+ </div>
+ </div>
</section>
</div>
<div class="logical-section tmpl-html">
--
1.7.1
10 years, 11 months
[PATCH V2 0/2] Add UI support of iscsi
by zhoumeina
v1-v2 modify some of translation messages
Include create storage pool UI and translation files.
zhoumeina (2):
Add UI support of iscsi
Add the ISCSI translation po files
po/en_US.po | 31 +++++++++++++----
po/kimchi.pot | 30 ++++++++++++----
po/pt_BR.po | 31 +++++++++++++----
po/zh_CN.po | 31 +++++++++++++----
ui/js/src/kimchi.storagepool_add_main.js | 54 ++++++++++++++++++++++++-----
ui/pages/i18n.html.tmpl | 7 ++--
ui/pages/storagepool-add.html.tmpl | 22 +++++++++++-
7 files changed, 159 insertions(+), 47 deletions(-)
mode change 100644 => 100755 po/kimchi.pot
10 years, 11 months
[PATCH] pep8 cleanup for distroloader.py
by Aline Manera
From: Aline Manera <alinefm(a)br.ibm.com>
This patch cleans up pep8 style issue in distroloader.py
Signed-off-by: Aline Manera <alinefm(a)br.ibm.com>
---
Makefile.am | 1 +
src/kimchi/distroloader.py | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 0fd92c8..5460240 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,6 +43,7 @@ PEP8_WHITELIST = \
src/kimchi/cachebust.py \
src/kimchi/config.py.in \
src/kimchi/disks.py \
+ src/kimchi/distroloader.py \
src/kimchi/root.py \
src/kimchi/server.py \
plugins/__init__.py \
diff --git a/src/kimchi/distroloader.py b/src/kimchi/distroloader.py
index 6310644..98fd764 100644
--- a/src/kimchi/distroloader.py
+++ b/src/kimchi/distroloader.py
@@ -18,7 +18,7 @@
#
# 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
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
import glob
@@ -46,7 +46,7 @@ class DistroLoader(object):
data = json.load(f)
return data
except ValueError:
- msg = "DistroLoader: failed to parse json from distro file: %s" % fname
+ msg = "DistroLoader: failed to parse distro file: %s" % fname
kimchi_log.error(msg)
raise OperationFailed(msg)
--
1.7.10.4
10 years, 11 months
[PATCH] pep8 cleanup for exception.py
by Aline Manera
From: Aline Manera <alinefm(a)br.ibm.com>
This patch cleans up pep8 style issue in exception.py
Signed-off-by: Aline Manera <alinefm(a)br.ibm.com>
---
Makefile.am | 1 +
src/kimchi/exception.py | 7 ++++++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 0fd92c8..3b8e494 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,6 +43,7 @@ PEP8_WHITELIST = \
src/kimchi/cachebust.py \
src/kimchi/config.py.in \
src/kimchi/disks.py \
+ src/kimchi/exception.py \
src/kimchi/root.py \
src/kimchi/server.py \
plugins/__init__.py \
diff --git a/src/kimchi/exception.py b/src/kimchi/exception.py
index d7a2835..df9619f 100644
--- a/src/kimchi/exception.py
+++ b/src/kimchi/exception.py
@@ -18,19 +18,24 @@
#
# 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
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
class NotFoundError(Exception):
pass
+
class OperationFailed(Exception):
pass
+
class MissingParameter(Exception):
pass
+
class InvalidParameter(Exception):
pass
+
class InvalidOperation(Exception):
pass
--
1.7.10.4
10 years, 11 months
[PATCH 0/6] Refactore isoinfo.py
by Aline Manera
From: Aline Manera <alinefm(a)br.ibm.com>
Aline Manera (6):
isoinfo: Add ignore_list paramter to main program
isoinfo: Use absolute path only for local ISO files
Move IsoFormatError() from isoinfo.py to exception.py
Move ISO path validation to IsoImage()
isoinfo: Move _probe_iso() to IsoImage()
pep8 cleanup for isoinfo.py
Makefile.am | 1 +
src/kimchi/exception.py | 4 ++
src/kimchi/isoinfo.py | 138 +++++++++++++++++++++++-----------------------
src/kimchi/model.py | 11 ++--
src/kimchi/scan.py | 5 +-
src/kimchi/vmtemplate.py | 8 ++-
6 files changed, 87 insertions(+), 80 deletions(-)
--
1.7.10.4
10 years, 11 months
[PATCH] plugin: fix dynamic import mechanism
by Zhou Zheng Sheng
The current kimchi plugin subsystem implement a dynamic discovery and
import mechanism. It uses the Python builtin function __import__() to
actually import a plugin module by name. However it turns out it only
works when we start kimchi from the project source directory, not work
when it is started from the installed path.
This is because the __import__() accepts a "global" arugment and it
needs "__name__", "__path__" and "__package__" in this "global" dict to
determine the package context [1][2]. When in kimchi/utils.py it runs
"import plugins.XXX", it actually fetch the "__package__" from utils.py,
which is "kimchi", then it imports "kimchi.plugins.XXX" under the hood
[3].
The current import_module() function calls __import__() without giving a
global dict. When kimchid is started from /usr/bin, without the package
context, __import__() can not find "plugins.sample".
This patch provides the full package context to __import__() to mimic
the standard "import" statement behavior.
[1] http://docs.python.org/2/library/functions.html#__import__
[2] http://hg.python.org/cpython/file/990d7647ea51/Python/import.c
[3] http://docs.python.org/2/reference/simple_stmts.html#import
Signed-off-by: Zhou Zheng Sheng <zhshzhou(a)linux.vnet.ibm.com>
---
src/kimchi/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
index f7eda93..b6d84fd 100644
--- a/src/kimchi/utils.py
+++ b/src/kimchi/utils.py
@@ -83,4 +83,4 @@ def import_class(class_path):
def import_module(module_name):
- return __import__(module_name, fromlist=[''])
+ return __import__(module_name, globals(), locals(), [''])
--
1.7.11.7
10 years, 11 months
[PATCH] Add jquery widget dropDown button
by zhoumeina
This patch is working for make dropDown button a jquery
widget.
We can create a dropdown button simply with:
$('#buttonId').dropdownButton();
And in html:
<div id="buttonId">
<span class="text">$_("Button label")</span><span class="arrow"></span>
<div>
<button><span class="text">$_("dropdownbutton1")</span></button>
<button><span class="text">$_("dropdownbutton2")</span></button>
</div>
</div>
If we need some other style, you can add it to html, and bind action in js.
Not a perfect widget, but a beginning.
Signed-off-by: zhoumeina <zhoumein(a)linux.vnet.ibm.com>
---
ui/js/widgets/button-dropDown.js | 42 ++++++++++++++++++++++++++++++++++++++
1 files changed, 42 insertions(+), 0 deletions(-)
create mode 100644 ui/js/widgets/button-dropDown.js
diff --git a/ui/js/widgets/button-dropDown.js b/ui/js/widgets/button-dropDown.js
new file mode 100644
index 0000000..49259e3
--- /dev/null
+++ b/ui/js/widgets/button-dropDown.js
@@ -0,0 +1,42 @@
+/*
+ * 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.dropdownButton', {
+ options: {
+ key: 0,
+ value: 0
+ },
+
+ _create : function() {
+ this.actionDiv = this.element;
+ this.actionDiv.addClass('btn dropdown popable');
+ this.actionDiv.find('div').addClass('popover');
+ this.actionDiv.find('button').addClass('button-big');
+ },
+
+ _setOption : function(key,value) {},
+
+ destroy : function() {
+ // call the base destroy function
+ $.Widget.prototype.destroy.call(this);
+ }
+ });
+}(jQuery));
\ No newline at end of file
--
1.7.1
10 years, 11 months