[PATCH] Add support to RHEL 7
by abotega@linux.vnet.ibm.com
From: Adriano Botega <abotega(a)linux.vnet.ibm.com>
RHEL 7 is the next Red Hat Enterprise distro version and because of a difference in the distro name in Volume Descriptor Table on it's ISO file, Kimchi is not recognizing as a RHEL distro.
This patch adds the correct regex to add support to RHEL 7
Signed-off-by: Adriano Botega <abotega(a)linux.vnet.ibm.com>
---
src/kimchi/isoinfo.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/kimchi/isoinfo.py b/src/kimchi/isoinfo.py
index 7e6d733..06bc6d8 100644
--- a/src/kimchi/isoinfo.py
+++ b/src/kimchi/isoinfo.py
@@ -111,6 +111,7 @@ iso_dir = [
'openSUSE-DVD-i586-Build0167|openSUSE-DVD-x86_640167'),
('rhel', '4.8', 'RHEL/4-U8'),
('rhel', lambda m: m.group(1), 'RHEL[_/](\d+\.\d+)'),
+ ('rhel', lambda m: m.group(1), 'RHEL[-](\d+\.\d+)'),
('debian', lambda m: m.group(1), 'Debian (\d+\.\d+)'),
('ubuntu', lambda m: m.group(2), '[Uu]buntu(-Server)? (\d+\.\d+)'),
('fedora', lambda m: m.group(1), 'Fedora[ -](\d+)'),
--
1.8.4.2
10 years, 11 months
[PATCH] Add a control.vm module
by shaohef@linux.vnet.ibm.com
From: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
All vm devices should be in this module
Signed-off-by: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
Signed-off-by: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
---
Makefile.am | 1 +
configure.ac | 1 +
contrib/kimchi.spec.fedora.in | 1 +
contrib/kimchi.spec.suse.in | 1 +
src/kimchi/control/Makefile.am | 2 ++
src/kimchi/control/vm/Makefile.am | 32 ++++++++++++++++++++++++++++++++
src/kimchi/control/vm/__init__.py | 22 ++++++++++++++++++++++
7 files changed, 60 insertions(+)
create mode 100644 src/kimchi/control/vm/Makefile.am
create mode 100644 src/kimchi/control/vm/__init__.py
diff --git a/Makefile.am b/Makefile.am
index 04ad696..c9a880c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -46,6 +46,7 @@ PEP8_WHITELIST = \
src/kimchi/cachebust.py \
src/kimchi/config.py.in \
src/kimchi/control/*.py \
+ src/kimchi/control/vm/*.py \
src/kimchi/disks.py \
src/kimchi/distroloader.py \
src/kimchi/exception.py \
diff --git a/configure.ac b/configure.ac
index e4ccb83..5148f12 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,6 +54,7 @@ AC_CONFIG_FILES([
src/distros.d/Makefile
src/kimchi/Makefile
src/kimchi/control/Makefile
+ src/kimchi/control/vm/Makefile
plugins/Makefile
plugins/sample/Makefile
plugins/sample/ui/Makefile
diff --git a/contrib/kimchi.spec.fedora.in b/contrib/kimchi.spec.fedora.in
index cc8c298..4fa94d4 100644
--- a/contrib/kimchi.spec.fedora.in
+++ b/contrib/kimchi.spec.fedora.in
@@ -113,6 +113,7 @@ rm -rf $RPM_BUILD_ROOT
%{_bindir}/kimchid
%{python_sitelib}/kimchi/*.py*
%{python_sitelib}/kimchi/control/*.py*
+%{python_sitelib}/kimchi/control/vm/*.py*
%{python_sitelib}/kimchi/API.json
%{_datadir}/kimchi/doc/API.md
%{_datadir}/kimchi/doc/README.md
diff --git a/contrib/kimchi.spec.suse.in b/contrib/kimchi.spec.suse.in
index d1aec7b..9f16dfb 100644
--- a/contrib/kimchi.spec.suse.in
+++ b/contrib/kimchi.spec.suse.in
@@ -60,6 +60,7 @@ rm -rf $RPM_BUILD_ROOT
%{_bindir}/kimchid
%{python_sitelib}/kimchi/*.py*
%{python_sitelib}/kimchi/control/*.py*
+%{python_sitelib}/kimchi/control/vm/*.py*
%{python_sitelib}/kimchi/API.json
%{_datadir}/kimchi/doc/API.md
%{_datadir}/kimchi/doc/README.md
diff --git a/src/kimchi/control/Makefile.am b/src/kimchi/control/Makefile.am
index 925c593..42f62c3 100644
--- a/src/kimchi/control/Makefile.am
+++ b/src/kimchi/control/Makefile.am
@@ -20,6 +20,8 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+SUBDIRS = vm
+
control_PYTHON = *.py
controldir = $(pythondir)/kimchi/control
diff --git a/src/kimchi/control/vm/Makefile.am b/src/kimchi/control/vm/Makefile.am
new file mode 100644
index 0000000..17340af
--- /dev/null
+++ b/src/kimchi/control/vm/Makefile.am
@@ -0,0 +1,32 @@
+#
+# Kimchi
+#
+# Copyright IBM Corp, 2013
+#
+# Authors:
+# ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
+# Royce Lv <lvroyce(a)linux.vnet.ibm.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+vm_PYTHON = \
+ __init__.py
+
+
+vmdir = $(pythondir)/kimchi/control/vm
+
+install-data-local:
+ $(MKDIR_P) $(DESTDIR)$(vmdir)
diff --git a/src/kimchi/control/vm/__init__.py b/src/kimchi/control/vm/__init__.py
new file mode 100644
index 0000000..f22e568
--- /dev/null
+++ b/src/kimchi/control/vm/__init__.py
@@ -0,0 +1,22 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2013
+#
+# Authors:
+# ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
+# Royce Lv <lvroyce(a)linux.vnet.ibm.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
--
1.8.4.2
10 years, 11 months
[PATCH V2] UI: template supports networks
by Xin Ding
V1 ->V2 use combo box
Add network to edit Template.
Signed-off-by: Xin Ding <xinding(a)linux.vnet.ibm.com>
---
ui/css/theme-default/template-edit.css | 34 +++++++++++++++++++++++++++++++++-
ui/js/src/kimchi.template_edit_main.js | 29 +++++++++++++++++++++++++++++
ui/pages/template-edit.html.tmpl | 21 +++++++++++++++++++--
3 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/ui/css/theme-default/template-edit.css b/ui/css/theme-default/template-edit.css
index e61b2fb..ecc9106 100644
--- a/ui/css/theme-default/template-edit.css
+++ b/ui/css/theme-default/template-edit.css
@@ -20,7 +20,7 @@
*/
#template-edit-window {
font-size: 13px;
- height: 400px;
+ height: 420px;
width: 1000px;
}
@@ -73,3 +73,35 @@
.hidden-area {
display: none;
}
+
+.template-edit-wrapper-controls .select-list-box {
+ width: 272px;
+ max-height: 168px;
+ overflow: auto;
+ margin-top: 5px;
+ border: 1px solid #ccc;
+}
+
+.template-edit-wrapper-controls .select-list-box>li>label {
+ display: block;
+}
+
+.template-edit-wrapper-controls .select-list-box>li>label>input[type="checkbox"] {
+ display: none;
+}
+
+.template-edit-wrapper-controls .select-list-box>li>label>.item {
+ display: block;
+ height: 41px;
+ line-height: 41px;
+ padding: 0 20px 0 40px;
+ border-bottom: 1px solid #ccc;
+ box-shadow: 0px 1px 1px #fff;
+ text-shadow: -1px -1px 1px #ddd, 1px 1px 1px #fff;
+ color: #222;
+ font-size: 12px;
+}
+
+.template-edit-wrapper-controls .select-list-box>li>label>input[type="checkbox"]:CHECKED+.item {
+ background: #f8f8f8 url(../images/theme-default/check-green.png) no-repeat 10px center;
+}
diff --git a/ui/js/src/kimchi.template_edit_main.js b/ui/js/src/kimchi.template_edit_main.js
index efe4a6f..ad535ee 100644
--- a/ui/js/src/kimchi.template_edit_main.js
+++ b/ui/js/src/kimchi.template_edit_main.js
@@ -43,6 +43,26 @@ kimchi.template_edit_main = function() {
}
kimchi.select('template-edit-storagePool-list', options);
});
+ kimchi.listNetworks(function(result) {
+ if(result && result.length > 0) {
+ var html = '';
+ var tmpl = $('#tmpl-network').html();
+ $.each(result, function(index, network) {
+ html += kimchi.template(tmpl, network);
+ });
+ $('#template-edit-network-list').html(html).show();
+ if(template.networks && template.networks.length > 0) {
+ $('input[name="networks"]', templateEditForm).each(function(index, element) {
+ var value = $(element).val();
+ if(template.networks.indexOf(value) >= 0) {
+ $(element).prop('checked', true);
+ }
+ });
+ }
+ } else {
+ $('#template-edit-network-list').hide();
+ }
+ });
});
$('#tmpl-edit-button-cancel').on('click', function() {
@@ -64,6 +84,15 @@ kimchi.template_edit_main = function() {
});
data['memory'] = Number(data['memory']);
data['cpus'] = Number(data['cpus']);
+ var networks = templateEditForm.serializeObject().networks;
+ if (networks instanceof Array) {
+ data.networks = networks;
+ } else if (networks != null) {
+ data.networks = [networks];
+ } else {
+ data.networks = [];
+ }
+
kimchi.updateTemplate($('#template-name').val(), data, function() {
kimchi.doListTemplates();
kimchi.window.close();
diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl
index fe7314d..f7921d6 100644
--- a/ui/pages/template-edit.html.tmpl
+++ b/ui/pages/template-edit.html.tmpl
@@ -75,8 +75,6 @@
<input id="template-edit-memory-textbox" name="memory" type="text" />
</div>
</div>
- </fieldset>
- <fieldset class="template-edit-fieldset">
<div>
<div class="template-edit-wrapper-label">
<label>$_("Disk (GB)")</label>
@@ -85,6 +83,8 @@
<input id="template-edit-version-textbox" name="disks" type="text" />
</div>
</div>
+ </fieldset>
+ <fieldset class="template-edit-fieldset">
<div>
<div class="template-edit-wrapper-label">
<label>$_("CDROM")</label>
@@ -108,6 +108,23 @@
</div>
</div>
</div>
+ <div>
+ <div class="template-edit-wrapper-label">
+ <label>$_("Network")</label>
+ </div>
+ <div class="template-edit-wrapper-controls">
+ <ul class="select-list-box" id="template-edit-network-list">
+ </ul>
+ <script id="tmpl-network" type="text/html">
+ <li>
+ <label>
+ <input name="networks" type="checkbox" value="{name}" />
+ <span class="item">{name}</span>
+ </label>
+ </li>
+ </script>
+ </div>
+ </div>
</fieldset>
</form>
</div>
--
1.8.3.2
10 years, 11 months
[PATCH] Deep scan: listing 'unknown' bootable isos after deep scan
by Daniel Barboza
From: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
When the iso distro and version can't be recognized, but the iso is
bootable, we shoud add it to the iso list after the deep scan.
Signed-off-by: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
---
src/kimchi/isoinfo.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/kimchi/isoinfo.py b/src/kimchi/isoinfo.py
index 7e6d733..64c1bb2 100644
--- a/src/kimchi/isoinfo.py
+++ b/src/kimchi/isoinfo.py
@@ -285,9 +285,11 @@ def probe_iso(status_helper, params):
ignore_list = params.get('ignore_list', [])
def update_result(iso, ret):
+ path = os.path.abspath(iso) if os.path.isfile(iso) else iso
if ret != ('unknown', 'unknown'):
- path = os.path.abspath(iso) if os.path.isfile(iso) else iso
updater({'path': path, 'distro': ret[0], 'version': ret[1]})
+ else:
+ updater({'path': path, 'distro': 'unknown', 'version': 'unknown'})
if os.path.isdir(loc):
for root, dirs, files in os.walk(loc):
--
1.8.3.1
10 years, 11 months
[PATCH v2] Fix break of deep scanning
by Daniel Barboza
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Commit 265de8d7 forgot to add type 'kimchi-iso' to storage pool
type, which prevents deep scannning to execute.
Add it to API.json to fix this break.
Signed-off-by: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Signed-off-by: Daniel Henrique Barboza <danielhb(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 19b1c51..3281d2e 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.3.1
10 years, 11 months
[PATCH v2] Deep scan: listing 'unknown' bootable isos after deep scan
by Daniel Barboza
From: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
When the iso distro and version can't be recognized, but the iso is
bootable, we shoud add it to the iso list after the deep scan.
Signed-off-by: Daniel Henrique Barboza <danielhb(a)linux.vnet.ibm.com>
---
src/kimchi/isoinfo.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/kimchi/isoinfo.py b/src/kimchi/isoinfo.py
index 7e6d733..417aae0 100644
--- a/src/kimchi/isoinfo.py
+++ b/src/kimchi/isoinfo.py
@@ -285,9 +285,8 @@ def probe_iso(status_helper, params):
ignore_list = params.get('ignore_list', [])
def update_result(iso, ret):
- if ret != ('unknown', 'unknown'):
- path = os.path.abspath(iso) if os.path.isfile(iso) else iso
- updater({'path': path, 'distro': ret[0], 'version': ret[1]})
+ path = os.path.abspath(iso) if os.path.isfile(iso) else iso
+ updater({'path': path, 'distro': ret[0], 'version': ret[1]})
if os.path.isdir(loc):
for root, dirs, files in os.walk(loc):
--
1.8.3.1
10 years, 11 months
[PATCH] UI bug fix: Set vlan_id value only if 'Enable VLAN' is checked
by Aline Manera
From: Aline Manera <alinefm(a)br.ibm.com>
Commit 2f54aaba added a checkbox to provide choice of enabling vlan tagging
while creating a bridged network, but it doesn't check the checkbox before
setting the vlan_id to send server request.
Because that when the user tries to create a bridged network without enabling
VLAN the following error is raised:
Invalid parameter: 'None is not of type u'integer''
Fix it by setting vlan_id only if the vlan checkbox is checked.
Signed-off-by: Aline Manera <alinefm(a)br.ibm.com>
---
ui/js/src/kimchi.network.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/ui/js/src/kimchi.network.js b/ui/js/src/kimchi.network.js
index 65479b2..9bd0cb5 100644
--- a/ui/js/src/kimchi.network.js
+++ b/ui/js/src/kimchi.network.js
@@ -136,12 +136,14 @@ kimchi.initNetworkCreation = function() {
var data = {
name : network.name,
connection: network.type,
- vlan_id: network.vlan_id,
};
if (network.type === kimchi.NETWORK_TYPE_BRIDGE) {
data.connection = "bridge";
data.interface = network.interface;
- data.vlan_id = network.vlan_id;
+ if ($("#enableVlan").prop("checked")) {
+ alert('está checked')
+ data.vlan_id = network.vlan_id;
+ }
}
kimchi.createNetwork(data, function(result) {
network.state = result.state === "active" ? "up" : "down";
--
1.7.10.4
10 years, 11 months
[PATCH V2] add a synchronous function with timeout to execute command
by shaohef@linux.vnet.ibm.com
From: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
V1 -> V2
check timeout happens and report a specific error
+ if proc.returncode == -9 and timeout_flag[0] is True:
+ kimchi_log.error("subprocess is killed by signal.SIGKILL "
+ "for timeout %s seconds", timeout)
ShaoHe Feng (1):
add a synchronous function with timeout to execute command
src/kimchi/utils.py | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
--
1.8.4.2
10 years, 11 months
[PATCHv6 0/8] Add support of storage server and target
by lvroyce0210@gmail.com
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
v5>v6, change GET param support to cover more scenario of filter collected results.
v4>v5, remove storage server list reload function,
merge storage server and targets
v3>v4, fix inconsistency between doc and json schema
v1>v3, fix racing problem, fix style.
Add parameters to GET request so that we will query storage server as:
/storageservers?target_type=netfs
Query all servers of any type supported(now only netfs):
/storageservers
Query all storage targets on a server:
/storageservers/host-name/storagetargets
Query a given type of storage targets:
/storageservers/host-name/storagetargets?target_type=netfs
Note: Due to Ubuntu 13.04 bug: ubuntu host report empty list for targets query,
as my solution already accepted and is easy to fix, we will wait it upstream
before 2weeks before release, I'll provide a work around by then if not available yet.
REF:
https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1264955
Royce Lv (8):
Support params for GET method
Add testcase for GET param
Storage server: Update API.md
storage server: update controller.py
storage server: Update model and mockmodel
storage target: Update API.md
storage target: Update controller and json schema
storage target: Add model support
docs/API.md | 22 +++++++++++
src/kimchi/API.json | 20 ++++++++++
src/kimchi/control/base.py | 26 +++++++++----
src/kimchi/control/storagepools.py | 4 +-
src/kimchi/control/storageserver.py | 63 +++++++++++++++++++++++++++++++
src/kimchi/control/utils.py | 2 +
src/kimchi/mockmodel.py | 28 ++++++++++++++
src/kimchi/model.py | 74 +++++++++++++++++++++++++++++++++++++
src/kimchi/root.py | 2 +
tests/test_rest.py | 34 +++++++++++++++++
10 files changed, 266 insertions(+), 9 deletions(-)
create mode 100644 src/kimchi/control/storageserver.py
--
1.8.1.2
10 years, 11 months
[PATCH V4] Add nfs server and target UI in create storage pool
by zhoumeina
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 | 21 +++--
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 | 72 ++++++++++++++--
ui/js/src/kimchi.utils.js | 11 +++
ui/js/widgets/combobox.js | 131 +++++++++++++++++++++++++++++
ui/js/widgets/filter-select.js | 135 ++++++++++++++++++++++++++++++
ui/js/widgets/select-menu.js | 83 ++++++++++++++++++
ui/pages/i18n.html.tmpl | 5 +-
ui/pages/storagepool-add.html.tmpl | 59 ++++++++------
14 files changed, 539 insertions(+), 47 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..dcca6a9 100644
--- a/ui/css/theme-default/button.css
+++ b/ui/css/theme-default/button.css
@@ -247,30 +247,37 @@
.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;
}
-.btn-select .text {
+.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 {
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..85ac70f 100644
--- a/ui/js/src/kimchi.storagepool_add_main.js
+++ b/ui/js/src/kimchi.storagepool_add_main.js
@@ -29,6 +29,9 @@ kimchi.storagepool_add_main = function() {
};
kimchi.initStorageAddPage = function() {
+ $('#poolTypeId').selectMenu();
+ $('#serverComboboxId').combobox();
+ $('#targetFilterSelectId').filterselect();
var options = [ {
label : "DIR",
value : "dir"
@@ -54,8 +57,66 @@ 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 = [];
+ serverContent.push({
+ label : i18n['select_default'],
+ value : ''
+ });
+ 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);
+ } else {
+ $('#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
+ });
+ });
+ } else {
+ targetContent.push({
+ label : i18n['msg.no.result'],
+ value : ''
+ });
+ }
+ $('#targetFilterSelectId').filterselect("setData", targetContent);
+ },function() {
+ targetContent.push({
+ label : i18n['msg.no.result'],
+ value : ''
+ });
+ $('#targetFilterSelectId').filterselect("setData", targetContent);
+ });
+ });
+ });
+ $('#poolTypeInputId').change(function() {
if ($(this).val() === 'dir') {
$('.path-section').removeClass('tmpl-html');
$('.logical-section').addClass('tmpl-html');
@@ -111,7 +172,6 @@ kimchi.validateForm = function() {
} else {
return kimchi.validateLogicalForm();
}
-
};
kimchi.validateDirForm = function () {
@@ -162,11 +222,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(nfsserver)) {
kimchi.message.error(i18n['msg.validate.pool.edit.server']);
return false;
}
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..aa948e6
--- /dev/null
+++ b/ui/js/widgets/combobox.js
@@ -0,0 +1,131 @@
+/*
+ * 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();
+ }
+ });
+ },
+
+ 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 + '></' + 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
new file mode 100644
index 0000000..6eaaa94
--- /dev/null
+++ b/ui/js/widgets/filter-select.js
@@ -0,0 +1,135 @@
+/*
+ * 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.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);
+ 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.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();
+ }
+ });
+ },
+
+ 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 + '></' + 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/select-menu.js b/ui/js/widgets/select-menu.js
new file mode 100644
index 0000000..053eeba
--- /dev/null
+++ b/ui/js/widgets/select-menu.js
@@ -0,0 +1,83 @@
+/*
+ * 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';
+ $.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();
+ }
+ });
+
+ },
+
+ 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..9727eba 100644
--- a/ui/pages/i18n.html.tmpl
+++ b/ui/pages/i18n.html.tmpl
@@ -122,7 +122,10 @@ 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")"
};
</script>
</body>
diff --git a/ui/pages/storagepool-add.html.tmpl b/ui/pages/storagepool-add.html.tmpl
index e8dac43..5b99e20 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,40 @@
$_("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" required="required 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 choose from history.")</p>
+ <div id="serverComboboxId" class="storage-add-input-width">
+ <input id="nfsserverId"/>
+ <span class="arrow"></span>
+ <div>
+ <ul id="nfs-server-used">
+ </ul>
+ </div>
+ </div>
</div>
</section>
<section class="form-section">
<h2>4. $_("NFS Path")</h2>
- <div class="field">
+ <div class="field storage-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 id="targetFilterSelectId" class="storage-add-input-width">
+ <input id="nfspathId" class="input" disabled/>
+ <span class="arrow"></span>
+ <div>
+ <ul id="nfs-server-target">
+ </ul>
+ </div>
+ </div>
+ </div>
</section>
</div>
<div class="logical-section tmpl-html">
@@ -103,15 +112,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 storage-base-input-width" class="text">
+ <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 +132,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, 11 months