ovirt mailbox continues to block mails
by Yu Xin Huo
Aline,
I am focusing on patch review these days, but mail blocking issue is
really troublesome.
For a patchset, I can only see one of them.
Hong Liang even did not get this patch at all.
Please check why they are blocked and if it is due to mail size, please
increase the upper limit of mail size.
10 years, 10 months
[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, 10 months
Re: [Kimchi-devel] [WIP PATCH 0/2] Hosts Management & Host Repository Management
by Aline Manera
On 01/13/2014 05:43 AM, Hongliang Wang wrote:
> On 01/10/2014 10:13 PM, Aline Manera wrote:
>>
>> Some comments:
>>
>> 1) Make sure to have Makefile.am files updated as you are adding new
>> files
> ACK
>>
>> 2) Always use 4 spaces for indentation
> ACK
>>
>> 3) About API:
>> - For federation: I suggest to use /peers instead of /hosts
>> In addition to list, add, remove actions we also
>> need a discover function to find the peers automatically for the user.
>> - For host repositories: from the previous backend patches sent o
>> former mail list, it should be /host/repositories instead of
>> /repositories
>>
> ACK
>> 4) About UI:
>> I prefer to have the "Federation" section listed like the other ones.
>> So, when opening the "Federation" section, we display a table
>> (like those used) with peers information and actions buttons.
> Peers are not in a subset of host, so they are not put in a
> "Federation" Section like those used.
>
> What's more, we need a trade-off here.
>
> Federated peers are in the same level of localhost, that means peers
> including current host are all within a tree structure with same level:
>
> - Federation
> - localhost
> - Peer 1
> - Peer 2
> - ...
>
> When clicking one of the federated peers, user will be guided to the
> corresponding page of that peer.
>
> This leads to 2 types of design:
>
> 1) Flatten
>
> ======================================
> Kimchi Logo
> _____________________________________________________________
>
> Peers | Guests | Templates | Storage | Network
> ___/\_________________________________________________________
>
> localhost 0.0.0.0 1 VMs, 2 Templates, 3 Pools
>
> Peer 1 9.1.2.1 Go >
> Peer 2 9.1.2.2 Go >
> Peer 3 9.1.2.3 Go >
> ======================================
>
> 2) Hierarchy
>
> ==========================================
> Kimchi Logo
> ___________________________________________________________________
> (Floating Menu) |
> Federated Peers | Host | Guests | Templates | Storage | Network
> - localhost |___/\_____________________________________________
> - Peer 1 > |
> - Peer 2 > |
> - Peer 3 > |
> ==========================================
>
> The difference between the 2 types is usage frequency of federated
> peers. If the user jumps to other peers frequently, Option 1 is
> better; otherwise, the user rarely jumps to other peers, Option 2 is
> better. In this patch, user is supposed to rarely jump to other peers.
>
I'd say I prefer the option 2.
That way we can have the host info in a tab and all the peers in a
separated one.
> Welcome more discussions.
>>
>>
>> On 12/30/2013 05:57 AM, Hongliang Wang wrote:
>>> 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
>>>
>>
>
10 years, 10 months
[PATCH V6] Add nfs server and target UI in create storage pool
by zhoumeina
v5-v6 Fix bug in IE10.
Fix bug in Firefox 17.
v4-v5 Change some html nits.
V3-V4 add value in jquery widget.
move all storage all page style to css files.
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.
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 | 28 ++++--
ui/css/theme-default/form.css | 6 ++
ui/css/theme-default/popover.css | 1 +
ui/css/theme-default/storage.css | 29 ++++++-
ui/js/Makefile.am | 4 +-
ui/js/src/kimchi.api.js | 27 ++++++-
ui/js/src/kimchi.popable.js | 2 +-
ui/js/src/kimchi.storagepool_add_main.js | 65 +++++++++++---
ui/js/src/kimchi.utils.js | 11 +++
ui/js/widgets/combobox.js | 130 ++++++++++++++++++++++++++++
ui/js/widgets/filter-select.js | 139 ++++++++++++++++++++++++++++++
ui/js/widgets/select-menu.js | 86 ++++++++++++++++++
ui/pages/i18n.html.tmpl | 6 +-
ui/pages/storagepool-add.html.tmpl | 59 +++++++------
14 files changed, 538 insertions(+), 55 deletions(-)
create mode 100644 ui/js/widgets/combobox.js
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..4d1a808 100644
--- a/ui/css/theme-default/button.css
+++ b/ui/css/theme-default/button.css
@@ -247,30 +247,38 @@
.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;
- box-shadow: -1px -1px 1px #666, 1px 1px 1px #fff, 2px 2px 2px rgba(0, 0, 0, .15) inset;
+ background: #fff;
+ box-shadow: -1px -1px 1px #666, 1px 1px 1px #fff, 1px 1px 1px rgba(0, 0, 0, .15) inset;
font-size: 13px;
- line-height: 38px;
+ line-height: 30px;
text-align: left;
cursor: pointer;
}
-.btn-select .text {
- padding: 0 10px;
+.btn-select .input {
+ border: 0 solid #CCCCCC;
+ margin-right: 10px;
+ font-size: 16px;
+ height: 30px;
+ line-height: 30px;
+ width: 100%;
+ position: absolute;
+ padding: 0 5px;
}
+.btn-select input.invalid-field {
+ border: 1px solid #FF4444;
+}
.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 28e30a5..d1a3885 100644
--- a/ui/css/theme-default/form.css
+++ b/ui/css/theme-default/form.css
@@ -49,4 +49,10 @@
.form-section input.invalid-field[type="text"] {
border-color: #FF4444;
+}
+
+.text-help {
+ font-size: 12px;
+ color: #333;
+ margin: 0 0 5px 5px;
}
\ No newline at end of file
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/css/theme-default/storage.css b/ui/css/theme-default/storage.css
index d81dc75..62e1540 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,11 +548,36 @@
.storage-type-wrapper-controls > .dropdown {
margin: 5px 0 0 1px;
- width: 250px;
+ width: 150px;
}
.storage-type-wrapper-controls input[type="text"][disabled] {
color: #bbb;
background-color: #fafafa;
cursor: not-allowed;
+}
+
+.storage-add-input-width {
+ width: 285px;
+}
+
+.form-section .storage-field {
+ overflow: visible;
+}
+
+.storage-base-input-width {
+ width: 300px;
+}
+
+.storage-window {
+ width: 600px;
+ height: 700px;
+}
+
+.storage-port-width {
+ width:40px;
+}
+
+.storage-auth-width {
+ width: 150px;
}
\ No newline at end of file
diff --git a/ui/js/Makefile.am b/ui/js/Makefile.am
index 6808226..65254da 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
@@ -31,7 +31,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 a4608ff..8d006d2 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -683,5 +683,30 @@ 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',
+ timeout: 2000,
+ dataType : 'json',
+ success : suc,
+ error : err
+ });
}
-};
+};
\ No newline at end of file
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 24de979..a4d4648 100644
--- a/ui/js/src/kimchi.storagepool_add_main.js
+++ b/ui/js/src/kimchi.storagepool_add_main.js
@@ -23,12 +23,13 @@
kimchi.storagepool_add_main = function() {
kimchi.initStorageAddPage();
$('#form-pool-add').on('submit', kimchi.addPool);
- $('#form-nfs-pool-add').on('submit', kimchi.addnfsPool);
$('#pool-doAdd').on('click', kimchi.addPool);
- $('#pool-nfs-doAdd').on('click', kimchi.addnfsPool);
};
kimchi.initStorageAddPage = function() {
+ $('#poolTypeId').selectMenu();
+ $('#serverComboboxId').combobox();
+ $('#targetFilterSelectId').filterselect();
var options = [ {
label : "DIR",
value : "dir"
@@ -54,8 +55,53 @@ kimchi.initStorageAddPage = function() {
});
$('.host-partition').html(listHtml);
}
- kimchi.select('storagePool-list', options);
- $('#poolType').change(function() {
+ $('#poolTypeId').selectMenu("setData", options);
+ kimchi.getStorageServers('netfs', function(data) {
+ var serverContent = [];
+ if (data.length > 0) {
+ $.each(data, function(index, value) {
+ serverContent.push({
+ label : value.addr,
+ value : value.addr
+ });
+ });
+ }
+ $('#serverComboboxId').combobox("setData", serverContent);
+ $('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');
+ }
+ });
+ $('#nfsserverId').on("change",function() {
+ if ($(this).val() !== '' && kimchi.isServer($(this).val())) {
+ $('#nfspathId').prop('disabled',false);
+ $(this).removeClass("invalid-field");
+ } else {
+ $(this).addClass("invalid-field");
+ $('#nfspathId').prop( "disabled",true);
+ }
+ $('#targetFilterSelectId').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
+ });
+ });
+ }
+ $('#targetFilterSelectId').filterselect("setData", targetContent);
+ });
+ });
+ });
+ $('#poolTypeInputId').change(function() {
if ($(this).val() === 'dir') {
$('.path-section').removeClass('tmpl-html');
$('.logical-section').addClass('tmpl-html');
@@ -93,7 +139,7 @@ kimchi.initStorageAddPage = function() {
kimchi.validateForm = function() {
var name = $('#poolId').val();
- var poolType = $("#poolType").val();
+ var poolType = $("#poolTypeInputId").val();
if ('' === name) {
kimchi.message.error(i18n['msg.pool.edit.name.blank']);
return false;
@@ -111,7 +157,6 @@ kimchi.validateForm = function() {
} else {
return kimchi.validateLogicalForm();
}
-
};
kimchi.validateDirForm = function () {
@@ -162,11 +207,7 @@ kimchi.validateServer = function(serverField) {
kimchi.message.error(i18n['msg.pool.edit.server.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(serverField)) {
+ if(!kimchi.isServer(serverField)) {
kimchi.message.error(i18n['msg.validate.pool.edit.server']);
return false;
}
@@ -186,7 +227,7 @@ kimchi.addPool = function(event) {
if (kimchi.validateForm()) {
var formData = $('#form-pool-add').serializeObject();
delete formData.authname;
- var poolType = $("#poolType").val();
+ var poolType = $('#poolTypeId').selectMenu('value');
if (poolType === 'dir') {
formData.path = $('#pathId').val();
} else if (poolType === 'logical') {
diff --git a/ui/js/src/kimchi.utils.js b/ui/js/src/kimchi.utils.js
index a23bf51..3cf36b9 100644
--- a/ui/js/src/kimchi.utils.js
+++ b/ui/js/src/kimchi.utils.js
@@ -168,3 +168,14 @@ kimchi.isUnsignedNumeric = function(number) {
var reg = /^d+(.d+)?$/
return reg.test(number);
}
+
+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;
+ }
+};
diff --git a/ui/js/widgets/combobox.js b/ui/js/widgets/combobox.js
new file mode 100644
index 0000000..2782f62
--- /dev/null
+++ b/ui/js/widgets/combobox.js
@@ -0,0 +1,130 @@
+/*
+ * 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.target.width(this.selectDiv.width()+10);
+ this.listControl.addClass('select-list');
+ this.listControl.parent().addClass('popover');
+ },
+
+ setData : function(options) {
+ var that = this;
+ var value = this.target.val();
+ var selectedClass = 'active';
+ var itemTag = 'li';
+ if (options.length > 0) {
+ that.target.after($('<span class="arrow"></span>'));
+ that.listControl.on('click', itemTag, function(e) {
+ that.listControl.children().removeClass(selectedClass);
+ $(this).addClass(selectedClass);
+ 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.text().indexOf(that.target.val()) == 0) {
+ that.listControl.append(item);
+ temp++;
+ }
+ });
+ if (temp > 0 && that.listControl.html() !== '') {
+ that._open();
+ } else {
+ that._close();
+ }
+ });
+ }
+ },
+
+ value : function(value) {
+ if (value === undefined) {
+ return this.target.val();
+ }
+ this.target.val(value);
+ },
+
+ _dataList : function(options) {
+ var item;
+ var itemTag = 'li';
+ var selectedClass = 'active';
+ var items = [];
+ var that = this;
+ $.each(options, function(index, option) {
+ item = $('<' + itemTag + '>' + option.label +'</' + itemTag + '>');
+ 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
new file mode 100644
index 0000000..e636820
--- /dev/null
+++ b/ui/js/widgets/filter-select.js
@@ -0,0 +1,139 @@
+/*
+ * 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', {
+ _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.target.width(this.selectDiv.width()+10);
+ this.listControl.addClass('select-list');
+ this.listControl.parent().addClass('popover');
+ },
+
+ setData : function(options) {
+ var that = this;
+ var value = this.target.val();
+ var selectedClass = 'active';
+ var itemTag = 'li';
+ if (options.length > 0) {
+ that.target.after($('<span class="arrow"></span>'));
+ that.listControl.on('click', itemTag, function(e) {
+ that.listControl.children().removeClass(selectedClass);
+ $(this).addClass(selectedClass);
+ that.target.val($(this).data('value'));
+ 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);
+ if (items.length === 0) {
+ that.listControl.html(i18n['msg.no.mapping.result']);
+ } else {
+ $.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.text().indexOf(that.target.val()) == 0) {
+ that.listControl.append(item);
+ temp++;
+ }
+ });
+ if (that.listControl.html() === '') {
+ that.target.addClass("invalid-field");
+ that.listControl.html(i18n['msg.no.mapping.result']);
+ } else {
+ that.target.removeClass("invalid-field");
+ }
+ if (temp > 0) {
+ that._open();
+ }
+ });
+ }
+ },
+
+ value : function(value) {
+ if (value === undefined) {
+ return this.target.val();
+ }
+ this.target.val(value);
+ },
+
+ _dataList : function(options) {
+ var item;
+ var itemTag = 'li';
+ var selectedClass = 'active';
+ var items = [];
+ var that = this;
+ $.each(options, function(index, option) {
+ item = $('<' + itemTag + '>' + option.label +'</' + itemTag + '>');
+ 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/select-menu.js b/ui/js/widgets/select-menu.js
new file mode 100644
index 0000000..c9a1b87
--- /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', {
+
+ _create : function() {
+ 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');
+ },
+
+ setData : function (options) {
+ var that = this;
+ var value = this.target.val();
+ var selectedClass = 'active';
+ var itemTag = 'li';
+ var item;
+ if (options.length > 0) {
+ $.each(options, function(index, option) {
+ item = $('<' + itemTag + '>' + option.label +'</' + itemTag + '>');
+ 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);
+ $(this).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();
+ }
+ });
+ } else {
+ kimchi.message.error(i18n['selectmenu.data.error']);
+ }
+ },
+
+ value : function(data) {
+ if (data === undefined) {
+ return this.target.val();
+ }
+ this.target.val(data.value);
+ this.label.val(data.label);
+ },
+
+ 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);
+ }
+ });
+}(jQuery));
\ No newline at end of file
diff --git a/ui/pages/i18n.html.tmpl b/ui/pages/i18n.html.tmpl
index 603f8d7..37b4114 100644
--- a/ui/pages/i18n.html.tmpl
+++ b/ui/pages/i18n.html.tmpl
@@ -122,7 +122,11 @@ var i18n = {
" there, are you sure to continue? ")",
'msg.pool.edit.iscsitarget.blank': "$_("The iSCSI target can not be blank.")",
'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.")"
+ 'msg.validate.pool.edit.server':"$_("This is not a valid Server Name or IP. please, modify it.")",
+ 'select_default': "$_("Please choose")",
+ 'msg.no.mapping.result': "$_("No such data exsit.")",
+ 'msg.no.result' : "$_("No valid result")",
+ 'selectmenu.data.error' : "$_("options needed.")"
};
</script>
</body>
diff --git a/ui/pages/storagepool-add.html.tmpl b/ui/pages/storagepool-add.html.tmpl
index e8dac43..714da3c 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: 700px;">
+ <div class="window storage-window">
<header>
<h1 class="title">$_("Define a New Storage Pool")</h1>
<div class="close">X</div>
@@ -40,18 +40,17 @@
<p class="text-help">
$_("The name used to identify the storage pools, and it should not be empty.")
</p>
- <input id="poolId" required="required" type="text" class="text" style="width: 300px"
- name="name">
+ <input id="poolId" required="required" type="text" class="text storage-base-input-width" name="name">
</div>
</section>
<section class="form-section">
<h2>2. $_("Storage Pool Type")</h2>
<div class="storage-type-wrapper-controls">
- <div class="btn dropdown popable">
- <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%">
- <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>
@@ -65,30 +64,38 @@
$_("The path of the Storage Pool. Each Storage Pool must have a unique path.")</p>
<p class="text-help">
$_("Kimchi will try to create the directory when it does not already exist in your system.")</p>
- <input id="pathId" type="text" class="text" required="required" style="width: 300px">
+ <input id="pathId" type="text" class="text storage-base-input-width">
</div>
<div class="clear"></div>
</section>
</div>
<div class="nfs-section tmpl-html">
<section class="form-section">
- <h2>3. $_("NFS server IP")</h2>
- <div class="field">
+ <h2>3. $_("NFS Server IP")</h2>
+ <div class="field storage-field">
<p class="text-help">
- $_("NFS server IP or hostname. It should not be empty.")</p>
- <input id="nfsserverId" required="required" type="text" class="text"
- style="width: 300px">
+ $_("NFS server IP or hostname. It can be input or chosen from history.")</p>
+ <div id="serverComboboxId" class="storage-add-input-width">
+ <input id="nfsserverId"/>
+ <div>
+ <ul id="nfs-server-used">
+ </ul>
+ </div>
+ </div>
</div>
</section>
<section class="form-section">
<h2>4. $_("NFS Path")</h2>
- <div class="field">
- <p class="text-help">$_("The nfs exported path on nfs server")</p>
- <input id="nfspathId" required="required" type="text" class="text"
- style="width: 300px">
- <input type="hidden" id="localpathId" class="text" value="none">
- </div>
- <div class="clear"></div>
+ <div class="field storage-field">
+ <p class="text-help">$_("The nfs exported path on nfs server.")</p>
+ <div id="targetFilterSelectId" class="storage-add-input-width">
+ <input id="nfspathId" class="input" disabled/>
+ <div>
+ <ul id="nfs-server-target">
+ </ul>
+ </div>
+ </div>
+ </div>
</section>
</div>
<div class="logical-section tmpl-html">
@@ -103,15 +110,15 @@
<div class="field">
<p class="text-help">
$_("iSCSI server IP or hostname. It should not be empty.")</p>
- <input id="iscsiserverId" placeholder="$_("Server")" type="text" class="text" style="width: 300px">
- <input id="iscsiportId" placeholder="$_("Port")" type="text" class="text" style="width:40px" maxlength='4'>
+ <input id="iscsiserverId" placeholder="$_("Server")" type="text" class="text storage-base-input-width">
+ <input id="iscsiportId" placeholder="$_("Port")" type="text" class="text storage-port-width" maxlength="4">
</div>
</section>
<section class="form-section">
<h2>4. $_("Target")</h2>
<div class="field">
<p class="text-help">$_("The iSCSI target on iSCSI server")</p>
- <input id="iscsiTargetId" type="text" class="text" style="width: 300px">
+ <input id="iscsiTargetId" type="text" class="text storage-base-input-width>
</div>
</section>
<section class="form-section">
@@ -123,8 +130,8 @@
<section class="authenticationfield form-section tmpl-html">
<h2>5. $_("iSCSI Authentication")</h2>
<div class="field">
- <input id="usernameId" placeholder="$_("User Name")" type="text" class="text" style="width: 150px">
- <input id="passwordId" placeholder="$_("Password")" type="text" class="text" style="width: 150px">
+ <input id="usernameId" placeholder="$_("User Name")" type="text" class="text storage-auth-width">
+ <input id="passwordId" placeholder="$_("Password")" type="text" class="text storage-auth-width">
</div>
</section>
</div>
--
1.7.1
10 years, 10 months
[PATCH 0/5] cdrom: support add and query cdrom
by lvroyce@linux.vnet.ibm.com
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Add support for cdrom query and add a new cdrom:
list:
GET /vms/vm1/cdroms
--> [{u'path': u'/home/royce/isorepo/Fedora-19-x86_64-DVD.iso', u'name': u'hdc'}]
add:
POST /vms/vm1/cdroms
{'name':'hde', 'path': 'path-of-your-iso'}
get detial:
GET /vms/vm1/cdroms/hdc
-->{u'path': u'/home/royce/isorepo/Fedora-19-x86_64-DVD.iso', u'name': u'hdc'}
REF: https://github.com/kimchi-project/kimchi/wiki/customize-VM
NOTE: Change media will be covered in cdrom update patch. This only covers query and
add a new cdrom device.
Royce Lv (5):
cdrom: Update API.md for add cdrom and query cdrom
cdrom: update controller
cdrom: Add convinient functions to deal with xml parse
cdrom: update model.py
cdrom: Add model test to check cdrom operations
docs/API.md | 15 ++++++++
src/kimchi/API.json | 16 +++++++++
src/kimchi/control/vms.py | 22 ++++++++++++
src/kimchi/model.py | 90 +++++++++++++++++++++++++++++++++++++++++++++--
src/kimchi/xmlutils.py | 5 +++
tests/test_model.py | 29 +++++++++++++++
6 files changed, 175 insertions(+), 2 deletions(-)
--
1.8.1.2
10 years, 10 months
[PATCHv4 0/2] NFS prevalidation
by lvroyce@linux.vnet.ibm.com
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Note, this patchset depends on:
[PATCH V3] add a synchronous function with timeout to execute command
v1>v4, Address naming comments,
integrate run_command patch and use context manager to deal with umount
Royce Lv (2):
utils: Add nfs prevalication
Integrate nfs path check before create nfs pool
src/kimchi/model.py | 30 ++++++++++++++++++++++++++++--
src/kimchi/utils.py | 8 ++++++++
2 files changed, 36 insertions(+), 2 deletions(-)
--
1.8.1.2
10 years, 10 months
[PATCH V2 0/2] Debugreport tool test enhancement
by Shu Ming
V2->V1:
Addressed Shaohe's comment
V1:
1)We need a way to tune the debugreport timeout value
2)Skip the test if there is not debugreport tool
Shu Ming (2):
Skip the debug report test if there is no tool avaible
Add a timeout tunning environment variable for debug report test
tests/test_model.py | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
--
1.8.1.4
10 years, 10 months
[PATCHv3 0/2] nfs prevalidation
by lvroyce@linux.vnet.ibm.com
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Add nfs prevalidation to prevent mount hang for long time
for unreachable export path.
Royce Lv (2):
utils: Add nfs prevalication
Integrate nfs path check before create nfs pool
src/kimchi/model.py | 37 ++++++++++++++++++++++++++++++++++---
src/kimchi/utils.py | 8 ++++++++
2 files changed, 42 insertions(+), 3 deletions(-)
--
1.8.1.2
10 years, 10 months
[PATCH V5 0/5] Add spice backend support for kimchi
by apporc
v5-v4:
1. Rebase to upstream
2. Change the code to coordinate with new websockify mechanism
3. Add test code for ipv6 (Thanks Aline)
v4-v3:
1. Remove not used module "copy" in vmtemplate.py(Thanks Aline)
2. Fix alignment problem in model.py(Thanks Aline)
3. Use type property of jsonschema to validate both ipv4 and ipv6(Thanks Aline)
REF: http://stackoverflow.com/questions/14550235/json-schema-away-to-specify-a...
4. Use "$ref" to simply API.json, remove dumplicate content(Thanks Rodrigo)
v3-v2:
1. Rebase to upstream
2. Improve/simplify some code according to reviewers' advice(Thanks Royce, Markwu and Aline).
3. Reimplement parameters validation using jsonschema.
4. Remove unnecessary test code in model.py.
5. Split patch to several smaller commits according to logic(Thanks Royce).
v2-v1: Rebased to upstream and resend
v1: Add spice backend support for kimchi
apporc (5):
Add spice backend support for kimchi
Validate graphics parameters input by users
Update mockmodel for spice support
Update test case for graphics support
Add graphics parameters description in API.md
docs/API.md | 43 ++++++++++++++-
src/kimchi/API.json | 30 +++++++++--
src/kimchi/control/templates.py | 6 ++-
src/kimchi/control/utils.py | 4 +-
src/kimchi/control/vms.py | 4 +-
src/kimchi/mockmodel.py | 13 +++--
src/kimchi/model.py | 34 +++++++-----
src/kimchi/osinfo.py | 7 +--
src/kimchi/vmtemplate.py | 31 ++++++++++-
tests/test_mockmodel.py | 2 +
tests/test_model.py | 27 +++++++++-
tests/test_rest.py | 111 +++++++++++++++++++++++++++++++++++++--
tests/test_vmtemplate.py | 40 ++++++++++++--
13 files changed, 313 insertions(+), 39 deletions(-)
--
1.7.9.5
10 years, 10 months
[PATCH V1 0/2] Debugreport tool test enhancement
by Shu Ming
1)We need a way to tune the debugreport timeout value
2)Skip the test if there is not debugreport tool
Shu Ming (2):
Skip the debug report test if there is no tool avaible
Add a timeout tunning environment variable for debug report test
tests/test_model.py | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
--
1.8.1.4
10 years, 10 months