[Kimchi-devel] [PATCH] [Kimchi] Storage Volume management
sguimaraes943 at gmail.com
sguimaraes943 at gmail.com
Mon May 23 12:30:01 UTC 2016
From: Samuel Guimarães <sguimaraes943 at gmail.com>
This commit adds Storage Volume management functions Wipe, Clone, Resize and Delete with multiple selection. It also includes a filter input for each Storage Pool and Gallery View for Storage Volumes.
Signed-off-by: Samuel Guimarães <sguimaraes943 at gmail.com>
---
model/storagevolumes.py | 2 +-
ui/css/kimchi.css | 287 ++++++++++---
ui/css/src/modules/_storage.scss | 309 +++++++++++---
ui/js/src/kimchi.api.js | 50 +++
ui/js/src/kimchi.storage_main.js | 443 ++++++++++++++++-----
ui/js/src/kimchi.storagepool_add_volume_main.js | 2 +-
ui/js/src/kimchi.storagepool_resize_volume_main.js | 59 +++
ui/pages/i18n.json.tmpl | 6 +
ui/pages/storagepool-resize-volume.html.tmpl | 51 +++
ui/pages/tabs/storage.html.tmpl | 155 +++----
10 files changed, 1107 insertions(+), 257 deletions(-)
create mode 100644 ui/js/src/kimchi.storagepool_resize_volume_main.js
create mode 100644 ui/pages/storagepool-resize-volume.html.tmpl
diff --git a/model/storagevolumes.py b/model/storagevolumes.py
index da42e85..0b34c5b 100644
--- a/model/storagevolumes.py
+++ b/model/storagevolumes.py
@@ -435,7 +435,7 @@ class StorageVolumeModel(object):
'name': name,
'new_pool': new_pool,
'new_name': new_name}
- taskid = add_task(u'/plugins/kimchi/storagepools/%s/storagevolumes/%s'
+ taskid = add_task(u'/plugins/kimchi/storagepools/%s/storagevolumes/%s/clone'
% (pool, new_name), self._clone_task, self.objstore,
params)
return self.task.lookup(taskid)
diff --git a/ui/css/kimchi.css b/ui/css/kimchi.css
index 49ea39a..130d64e 100644
--- a/ui/css/kimchi.css
+++ b/ui/css/kimchi.css
@@ -2183,6 +2183,8 @@ body.wok-gallery {
}
#storage-root-container .wok-datagrid-body .handle {
+ -webkit-user-select: none;
+ -moz-user-select: none;
user-select: none;
position: relative;
}
@@ -2221,74 +2223,47 @@ body.wok-gallery {
display: none;
}
+#storage-root-container .volumes input[type=checkbox][disabled].wok-checkbox + label:before {
+ content: '';
+}
+
#storage-root-container .volumes > .footer {
z-index: 100;
}
#storage-root-container .volumes .volumeslist {
- padding: 11px;
+ padding: 22px;
max-height: 285px;
min-height: 136px;
+ max-height: 505px;
overflow: auto;
}
-#storage-root-container .volumes .volume-box {
- background: #fff;
- padding: 4px 20px;
- margin: 11px;
- display: inline-block;
- width: 409px;
- height: 110px;
-}
-
-#storage-root-container .volumes .volume-title {
- height: 46px;
- width: 100%;
- border-bottom: 1px solid #ccc;
- position: relative;
+#storage-root-container .volumes .volumeslist .row {
+ font-size: 0;
+ margin-bottom: 22px;
}
-#storage-root-container .volumes .volume-name {
- font-size: 15pt;
- font-weight: 300;
- width: 274px;
- line-height: 46px;
- display: inline-block;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
+#storage-root-container .volumes .volumeslist .filter {
+ width: 514px;
}
-#storage-root-container .volumes .volume-utilization {
- vertical-align: top;
- text-align: right;
+#storage-root-container .volumes .pool-action {
display: inline-block;
- width: 90px;
- height: 46px;
- line-height: 46px;
+ margin-right: 20px;
}
#storage-root-container .volumes .volume-icon {
display: inline-block;
+ vertical-align: middle;
width: 27px;
- height: 46px;
- line-height: 46px;
+ height: 27px;
+ line-height: 27px;
background-repeat: no-repeat;
background-position: 50%;
background-color: transparent;
}
-#storage-root-container .volumes .volume-usage {
- vertical-align: top;
- font-size: 15pt;
- font-weight: 400;
- display: inline-block;
- text-align: right;
- line-height: 46px;
- padding-left: 0;
- margin-left: 5px;
-}
-
#storage-root-container .volumes .volume-icon.icon-high {
background-image: url("/images/theme-default/high.png");
}
@@ -2304,13 +2279,13 @@ body.wok-gallery {
#storage-root-container .volumes .volume-progress {
position: absolute;
margin: 0;
- width: 409px;
- top: -4px;
- left: -20px;
+ width: 407px;
+ top: 4px;
+ left: 4px;
}
#storage-root-container .volumes .volume-progress .progress-bar-outer {
- background: transparent;
+ background: #ddd;
height: 6px;
overflow: hidden;
width: 100%;
@@ -2347,8 +2322,226 @@ body.wok-gallery {
}
#storage-root-container .volumes .pool-empty {
+ width: 100%;
+ cursor: default !important;
+}
+
+#storage-root-container .volumes .pool-empty > span {
+ width: 100%;
text-align: center;
line-height: 136px;
+ vertical-align: middle !important;
+}
+
+#storage-root-container .volumes .wok-gallery.wok-datagrid {
+ background: transparent;
+ margin-top: -12px;
+}
+
+#storage-root-container .volumes .wok-gallery.wok-datagrid > .wok-datagrid-header {
+ display: none;
+}
+
+#storage-root-container .volumes .wok-gallery.wok-datagrid > .wok-datagrid-body {
+ margin-left: -3px;
+}
+
+#storage-root-container .volumes .wok-gallery.wok-datagrid .wok-datagrid-body > .wok-datagrid-row {
+ position: relative;
+ cursor: pointer;
+ background: #fff !important;
+ border: 0 !important;
+ display: inline-block !important;
+ width: 415px !important;
+ margin: 12px 4px 0;
+}
+
+#storage-root-container .volumes .wok-gallery.wok-datagrid .wok-datagrid-body > .wok-datagrid-row, #storage-root-container .volumes .wok-gallery.wok-datagrid .wok-datagrid-body > .wok-datagrid-row * {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+}
+
+#storage-root-container .volumes .wok-gallery.wok-datagrid .wok-datagrid-body > .wok-datagrid-row.selected .volume-box-border {
+ border-color: #8cc63f;
+}
+
+#storage-root-container .volumes .wok-gallery.wok-datagrid .wok-datagrid-body > .wok-datagrid-row.selected .volume-box-inner {
+ border-color: #000;
+}
+
+#storage-root-container .volumes .wok-gallery .volume-box-outer {
+ border-radius: 3px;
+ overflow: hidden;
+}
+
+#storage-root-container .volumes .wok-gallery .volume-box-border {
+ display: block;
+ border: 3px solid transparent;
+ transition: border-color .1s ease-in-out;
+}
+
+#storage-root-container .volumes .wok-gallery .volume-box-inner {
+ padding: 0 16px;
+ width: 409px;
+ height: 110px;
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: space-around;
+ border: 1px solid #fff;
+ background: #fff;
+ transition: border-color .1s ease-in-out;
+}
+
+#storage-root-container .volumes .wok-gallery span.column-name,
+#storage-root-container .volumes .wok-gallery span.column-used {
+ height: 52px;
+ line-height: 52px;
+ border-bottom: 1px solid #ccc;
+}
+
+#storage-root-container .volumes .wok-gallery span.column-name {
+ width: 303px;
+ order: 1;
+}
+
+#storage-root-container .volumes .wok-gallery span.column-used {
+ width: 72px;
+ order: 2;
+}
+
+#storage-root-container .volumes .wok-gallery span.column-name label.volume-name {
+ width: 100%;
+ height: 52px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ display: block;
+ margin: 0;
+ padding-right: 6px;
+}
+
+#storage-root-container .volumes .wok-gallery span.column-allocated,
+#storage-root-container .volumes .wok-gallery span.column-capacity,
+#storage-root-container .volumes .wok-gallery span.column-format,
+#storage-root-container .volumes .wok-gallery span.column-type {
+ order: 3;
+ width: 72px;
+ margin-top: -5px;
+}
+
+#storage-root-container .volumes .wok-gallery span.gallery-header {
+ font-weight: 600;
+ display: block;
+}
+
+#storage-root-container .volumes .wok-gallery span.column-progress {
+ display: none;
+}
+
+#storage-root-container .volumes .wok-gallery .tooltip-iner {
+ font-size: 11pt;
+ padding: 6px 12px;
+}
+
+#storage-root-container .volumes .wok-list .tooltip {
+ display: none !important;
+}
+
+#storage-root-container .volumes .wok-list span.gallery-header {
+ display: none;
+}
+
+#storage-root-container .volumes .wok-list .volume-inline-progress {
+ vertical-align: middle;
+ display: inline-block;
+ margin-right: 7px;
+}
+
+#storage-root-container .volumes .wok-list .volume-inline-progress > span.wok-loading-icon {
+ margin-right: 0;
+}
+
+#storage-root-container .volumes .wok-list .volume-progress {
+ width: 100%;
+ top: 0px;
+ left: 0px;
+}
+
+#storage-root-container .volumes .wok-list .volume-progress .progress-bar-outer {
+ height: 3px;
+}
+
+#storage-root-container .volumes .wok-list .volume-box-inner {
+ font-size: 0;
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header > span.column-name {
+ padding-left: 41px;
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row {
+ position: relative;
+ cursor: pointer;
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row.selected {
+ background: #ddd !important;
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div > span {
+ font-family: "Open Sans", Helvetica, Arial, "Lucida Grande", sans-serif;
+ line-height: 2.42857;
+ vertical-align: top;
+ font-size: 12.5pt;
+ font-weight: 400;
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div > span.column-name {
+ padding-left: 15px;
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header > span,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div > span {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header span.column-format,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div span.column-format {
+ width: 173px;
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header span.column-used,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header span.column-type,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header span.column-capacity,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header span.column-allocated,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div span.column-used,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div span.column-type,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div span.column-capacity,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div span.column-allocated {
+ width: 165px;
+ text-transform: capitalize;
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header > span.column-name,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div > span.column-name {
+ width: 444px;
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header > span.column-name label,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div > span.column-name label {
+ padding: 0 5px 0 0;
+ margin-right: 0;
+ margin-bottom: 0;
+ font-size: inherit;
+ font-weight: inherit;
+ width: 100%;
+ display: block;
+ height: auto;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
#storage-root-container .wok-datagrid > .wok-datagrid-body > .wok-datagrid-row[data-stat="inactive"] {
diff --git a/ui/css/src/modules/_storage.scss b/ui/css/src/modules/_storage.scss
index 4a9f9e1..f90d4d8 100644
--- a/ui/css/src/modules/_storage.scss
+++ b/ui/css/src/modules/_storage.scss
@@ -25,6 +25,8 @@
position: relative;
}
.handle {
+ -webkit-user-select: none;
+ -moz-user-select: none;
user-select: none;
position: relative;
}
@@ -58,66 +60,48 @@
width: 100%;
background: $navbar-default-toggle-hover-bg;
display: none;
+
+ input[type=checkbox][disabled].wok-checkbox + label:before {
+ content: '';
+ }
+
> .footer {
z-index: 100;
}
+
.volumeslist {
- padding: 11px;
+ padding: 22px;
max-height: 285px;
min-height: 136px;
+ max-height: 505px;
overflow: auto;
}
- .volume-box {
- background: $navbar-inverse-toggle-icon-bar-bg;
- padding: 4px 20px;
- margin: 11px;
- display: inline-block;
- width: 409px;
- height: 110px;
- }
- .volume-title {
- height: 46px;
- width: 100%;
- border-bottom: 1px solid $input-border;
- position: relative;
+
+ .volumeslist .row {
+ font-size: 0;
+ margin-bottom: 22px;
}
- .volume-name {
- font-size: 15pt;
- font-weight: 300;
- width: 274px;
- line-height: 46px;
- display: inline-block;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
+
+ .volumeslist .filter {
+ width: 514px;
}
- .volume-utilization {
- vertical-align: top;
- text-align: right;
+
+ .pool-action {
display: inline-block;
- width: 90px;
- height: 46px;
- line-height: 46px;
+ margin-right: 20px;
}
+
.volume-icon {
display: inline-block;
+ vertical-align: middle;
width: 27px;
- height: 46px;
- line-height: 46px;
+ height: 27px;
+ line-height: 27px;
background-repeat: no-repeat;
background-position: 50%;
background-color: transparent;
}
- .volume-usage {
- vertical-align: top;
- font-size: 15pt;
- font-weight: 400;
- display: inline-block;
- text-align: right;
- line-height: 46px;
- padding-left: 0;
- margin-left: 5px;
- }
+
.volume-icon.icon-high {
background-image: url('#{$wok-icon-path}/high.png');
}
@@ -127,14 +111,16 @@
.volume-icon.icon-low {
background-image: url('#{$wok-icon-path}/low.png');
}
+
.volume-progress {
position: absolute;
margin: 0;
- width: 409px;
- top: -4px;
- left: -20px;
+ width: 407px;
+ top: 4px;
+ left: 4px;
+
.progress-bar-outer {
- background: transparent;
+ background: $table-bg-hover;
height: 6px;
overflow: hidden;
width: 100%;
@@ -145,6 +131,7 @@
width: 100%;
}
}
+
.volume-data {
margin: 0;
padding: 0;
@@ -164,10 +151,240 @@
}
}
}
- .pool-empty {
+ .pool-empty{
+ width: 100%;
+ cursor: default !important;
+ > span {
+ width: 100%;
text-align: center;
line-height: 136px;
+ vertical-align: middle !important;
+ }
+ }
+
+ .wok-gallery {
+
+ &.wok-datagrid {
+ background: transparent;
+ margin-top: -12px;
}
+
+ &.wok-datagrid > .wok-datagrid-header {
+ display: none;
+ }
+
+ &.wok-datagrid > .wok-datagrid-body {
+ margin-left: -3px;
+ }
+
+ &.wok-datagrid .wok-datagrid-body > .wok-datagrid-row {
+ position: relative;
+ cursor: pointer;
+ background: $body-bg !important;
+ border: 0 !important;
+ display: inline-block !important;
+ width: 415px !important;
+ margin: 12px 4px 0;
+ &, * {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+ }
+ }
+
+ &.wok-datagrid .wok-datagrid-body > .wok-datagrid-row.selected .volume-box-border {
+ border-color: $guests-color;
+ }
+
+ &.wok-datagrid .wok-datagrid-body > .wok-datagrid-row.selected .volume-box-inner {
+ border-color: $gray-base;
+ }
+
+ .volume-box-outer {
+ border-radius: 3px;
+ overflow: hidden;
+ }
+
+ .volume-box-border {
+ display: block;
+ border: 3px solid transparent;
+ transition: border-color .1s ease-in-out
+ }
+
+ .volume-box-inner {
+ padding: 0 16px;
+ width: 409px;
+ height: 110px;
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: space-around;
+ border: 1px solid #fff;
+ background: #fff;
+ transition: border-color .1s ease-in-out;
+ }
+
+ span.column-name,
+ span.column-used {
+ height: 52px;
+ line-height: 52px;
+ border-bottom: 1px solid $input-border;
+ }
+
+ span.column-name {
+ width: 303px;
+ order: 1;
+ }
+
+ span.column-used {
+ width: 72px;
+ order: 2;
+ }
+
+ span.column-name label.volume-name {
+ width: 100%;
+ height: 52px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ display: block;
+ margin: 0;
+ padding-right: 6px;
+ }
+
+ span.column-allocated,
+ span.column-capacity,
+ span.column-format,
+ span.column-type {
+ order: 3;
+ width: 72px;
+ margin-top: -5px;
+ }
+
+ span.gallery-header {
+ font-weight: 600;
+ display: block;
+ }
+
+ span.column-progress {
+ display: none;
+ }
+
+ .tooltip-iner {
+ font-size: 11pt;
+ padding: 6px 12px;
+ }
+
+ }
+
+ .wok-list {
+
+ .tooltip {
+ display: none !important;
+ }
+
+ span.gallery-header {
+ display: none;
+ }
+
+ .volume-inline-progress {
+ vertical-align: middle;
+ display: inline-block;
+ margin-right: 7px;
+ }
+
+ .volume-inline-progress > span.wok-loading-icon {
+ margin-right: 0;
+ }
+
+ .volume-progress {
+ width: 100%;
+ top: 0px;
+ left: 0px;
+
+ .progress-bar-outer {
+ height: 3px;
+ }
+ }
+
+ .volume-box-inner {
+ font-size: 0;
+ }
+
+ &.wok-datagrid > .wok-datagrid-header {
+
+ > span.column-name {
+ padding-left: 41px;
+ }
+
+ }
+
+ &.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row {
+ position: relative;
+ cursor: pointer;
+ }
+
+ &.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row.selected {
+ background: $table-bg-hover !important;
+ }
+
+ &.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div {
+
+ > span {
+ font-family: $font-family-sans-serif;
+ line-height: (1 + $line-height-base);
+ vertical-align: top;
+ font-size: 12.5pt;
+ font-weight: 400;
+ }
+
+ > span.column-name {
+ padding-left: 15px;
+ }
+
+ }
+
+ &.wok-datagrid > .wok-datagrid-header,
+ &.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row > div > div > div {
+
+ >span {
+ display: inline-block;
+ vertical-align: middle;
+ }
+
+ span.column-format {
+ width: 173px;
+ }
+
+ span.column-used,
+ span.column-type,
+ span.column-capacity,
+ span.column-allocated {
+ width: 165px;
+ text-transform: capitalize;
+ }
+
+ > span.column-name {
+ width: 444px;
+
+ label {
+ padding: 0 5px 0 0;
+ margin-right: 0;
+ margin-bottom: 0;
+ font-size: inherit;
+ font-weight: inherit;
+ width: 100%;
+ display: block;
+ height: auto;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ }
+ }
+
+ }
+
+
}
.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row[data-stat="inactive"] {
color: $gray-light !important;
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 1ef3649..ce93d7d 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -760,6 +760,56 @@ var kimchi = {
});
},
+ cloneStoragePoolVolume: function(poolName, volumeName, data, suc, err) {
+ var url = 'plugins/kimchi/storagepools/' + encodeURIComponent(poolName) + '/storagevolumes/' + encodeURIComponent(volumeName) + '/clone';
+ wok.requestJSON({
+ url : url,
+ type : 'POST',
+ data : JSON.stringify(data),
+ contentType : 'application/json',
+ dataType : 'json',
+ success : suc,
+ error : err
+ });
+ },
+
+ resizeStoragePoolVolume: function(poolName, volumeName, data, suc, err) {
+ var url = 'plugins/kimchi/storagepools/' + encodeURIComponent(poolName) + '/storagevolumes/' + encodeURIComponent(volumeName) + '/resize';
+ wok.requestJSON({
+ url : url,
+ type : 'POST',
+ data : JSON.stringify(data),
+ contentType : 'application/json',
+ dataType : 'json',
+ success : suc,
+ error : err
+ });
+ },
+
+ wipeStoragePoolVolume: function(poolName, volumeName, suc, err) {
+ var url = 'plugins/kimchi/storagepools/' + encodeURIComponent(poolName) + '/storagevolumes/' + encodeURIComponent(volumeName) + '/wipe';
+ wok.requestJSON({
+ url : url,
+ type : 'POST',
+ contentType : 'application/json',
+ dataType : 'json',
+ success : suc,
+ error : err
+ });
+ },
+
+ deleteStoragePoolVolume: function(poolName, volumeName, suc, err) {
+ var url = 'plugins/kimchi/storagepools/' + encodeURIComponent(poolName) + '/storagevolumes/' + encodeURIComponent(volumeName);
+ wok.requestJSON({
+ url : url,
+ type : 'DELETE',
+ contentType : 'application/json',
+ dataType : 'json',
+ success : suc,
+ error : err
+ });
+ },
+
getHostVgs: function(suc, err) {
var url = 'plugins/kimchi/host/vgs/';
wok.requestJSON({
diff --git a/ui/js/src/kimchi.storage_main.js b/ui/js/src/kimchi.storage_main.js
index 5312388..a8e4255 100644
--- a/ui/js/src/kimchi.storage_main.js
+++ b/ui/js/src/kimchi.storage_main.js
@@ -65,6 +65,200 @@ kimchi.doListStoragePools = function() {
kimchi.storageBindClick = function() {
+ $('.volumes').on('click','.toggle-gallery',function(e){
+ e.preventDefault();
+ e.stopPropagation();
+ var button = $(this);
+ var volumeBlock = $(this).parent().parent().parent();
+ var text = $('span.text', button).text();
+ $(".wok-list, .wok-gallery",volumeBlock).toggleClass("wok-list wok-gallery");
+ $('span.text', button).text(text == i18n['KCHTMPL6005M'] ? i18n['KCHTMPL6004M'] : i18n['KCHTMPL6005M']);
+ });
+
+ if(wok.tabMode['storage'] === 'admin') {
+
+ $('.volumes').on('click','.volume-delete',function(e){
+ e.preventDefault();
+ e.stopPropagation();
+ var button = $(this);
+ $('.dropdown.pool-action.open .dropdown-toggle').dropdown('toggle');
+ kimchi.selectedSP = $(this).data('name');
+ var volumeBlock = $(this).data('name');
+ var volumes = $('[data-name="'+kimchi.selectedSP+'"] input:checkbox:checked').map(function(){
+ return this.value;
+ }).get();
+ kimchi.selectedVolumes = volumes.slice();
+ var formatedVolumes = '';
+ if(kimchi.selectedVolumes.length && !button.parent().is('disabled')){
+ for (i = 0; i < kimchi.selectedVolumes.length; i++) {
+ formatedVolumes += "<li>" + kimchi.selectedVolumes[i] + "</li>";
+ }
+ var confirmMessage = i18n['KCHPOOL6010M'].replace('%1','<ul>'+formatedVolumes+'</ul>'+i18n['KCHPOOL6009M']);
+ var settings = {
+ title : i18n['KCHAPI6001M'],
+ content : confirmMessage,
+ confirm : i18n['KCHAPI6002M'],
+ cancel : i18n['KCHAPI6003M']
+ };
+ wok.confirm(settings, function() {
+ $.each(kimchi.selectedVolumes, function(i,j) {
+ volumes = jQuery.grep(volumes, function(value) {
+ return value != j;
+ });
+ kimchi.deleteStoragePoolVolume(kimchi.selectedSP,j,function(){
+ wok.message.success(i18n['KCHPOOL6017M'].replace('%1','<strong>'+j+'</strong>'));
+ wok.topic('kimchi/storageVolumeDeleted').publish();
+ },function(err){
+ wok.message.error(err.responseJSON.reason);
+ });
+ if(volumes.length === 0){
+ kimchi.selectedVolumes = '';
+ wok.topic('kimchi/storageVolumeDeleted').publish();
+ }
+ });
+ });
+ }else {
+ return false;
+ }
+ });
+
+ $('.volumes').on('click','.volume-wipe',function(e){
+ e.preventDefault();
+ e.stopPropagation();
+ var button = $(this);
+ $('.dropdown.pool-action.open .dropdown-toggle').dropdown('toggle');
+ kimchi.selectedSP = $(this).data('name');
+ var volumeBlock = $(this).data('name');
+ var volumes = $('[data-name="'+kimchi.selectedSP+'"] input:checkbox:checked').map(function(){
+ return this.value;
+ }).get();
+ kimchi.selectedVolumes = volumes.slice();
+ var formatedVolumes = '';
+ if(kimchi.selectedVolumes.length && !button.parent().is('disabled')){
+ for (i = 0; i < kimchi.selectedVolumes.length; i++) {
+ formatedVolumes += "<li>" + kimchi.selectedVolumes[i] + "</li>";
+ }
+ var confirmMessage = i18n['KCHPOOL6018M'].replace('%1','<ul>'+formatedVolumes+'</ul>'+i18n['KCHPOOL6009M']);
+ var settings = {
+ title : i18n['KCHPOOL6019M'],
+ content : confirmMessage,
+ confirm : i18n['KCHAPI6002M'],
+ cancel : i18n['KCHAPI6003M']
+ };
+ wok.confirm(settings, function() {
+ $.each(kimchi.selectedVolumes, function(i,j) {
+ volumes = jQuery.grep(volumes, function(value) {
+ return value != j;
+ });
+ kimchi.wipeStoragePoolVolume(kimchi.selectedSP,j,function(){
+ wok.message.success(i18n['KCHPOOL6017M'].replace('%1','<strong>'+j+'</strong>'));
+ wok.topic('kimchi/storageVolumeWiped').publish();
+ },function(err){
+ wok.message.error(err.responseJSON.reason);
+ });
+ if(volumes.length === 0){
+ kimchi.selectedVolumes = '';
+ wok.topic('kimchi/storageVolumeWiped').publish();
+ }
+ });
+ });
+ }else {
+ return false;
+ }
+ });
+
+ $('.volumes').on('click','.volume-resize',function(e){
+ e.preventDefault();
+ e.stopPropagation();
+ var button = $(this);
+ $('.dropdown.pool-action.open .dropdown-toggle').dropdown('toggle');
+ kimchi.selectedSP = $(this).data('name');
+ var volumes = $('[data-name="'+kimchi.selectedSP+'"] input:checkbox:checked').map(function(){
+ return this.value;
+ }).get();
+ kimchi.selectedVolumes = volumes.slice(0,1);
+ if(kimchi.selectedVolumes.length && !button.parent().is('disabled')){
+ wok.window.open('plugins/kimchi/storagepool-resize-volume.html');
+ }else {
+ return false;
+ }
+ });
+
+ $('.volumes').on('click','.volume-clone',function(e){
+ e.preventDefault();
+ e.stopPropagation();
+ var button = $(this);
+ $('.dropdown.pool-action.open .dropdown-toggle').dropdown('toggle');
+ kimchi.selectedSP = $(this).data('name');
+ var volumeBlock = $(this).data('name');
+ var volumes = $('[data-name="'+kimchi.selectedSP+'"] input:checkbox:checked').map(function(){
+ return this.value;
+ }).get();
+ kimchi.volumesToClone = volumes.slice();
+ var formatedVolumes = '';
+ if(kimchi.volumesToClone.length && !button.parent().is('disabled')){
+ $.each(kimchi.volumesToClone, function(i,j) {
+ volumes = jQuery.grep(volumes, function(value) {
+ return value != j;
+ });
+ var data = {};
+ data = {
+ pool: kimchi.selectedSP
+ }
+ kimchi.cloneStoragePoolVolume(kimchi.selectedSP,j,data,function(){
+ wok.topic('kimchi/storageVolumeCloned').publish();
+ },function(err){
+ wok.message.error(err.responseJSON.reason);
+ });
+ if(volumes.length === 0){
+ kimchi.volumesToClone = '';
+ wok.topic('kimchi/storageVolumeCloned').publish();
+ }
+ });
+ }else {
+ return false;
+ }
+ });
+
+ $('.volumes').on('click','.wok-datagrid-row',function(e){
+ if (!$(e.target).is("input[type='checkbox']") && !$(e.target).is("label")) {
+ var volumeBlock = $(this);
+ var checkbox = volumeBlock.find('[name="selected-volume[]"]');
+ checkbox.trigger('click');
+ }
+ });
+
+ $('.volumes').on('change','[name="selected-volume[]"]',function(e){
+ var checkbox = $(this);
+ var volumeBlock = $(this).closest('.wok-datagrid-row');
+ var volumesBlock = $(this).closest('.volumeslist');
+ var disabled = [];
+ if($('[name="selected-volume[]"]:checked',volumesBlock).length > 1) {
+ disabled = ['volume-clone','volume-wipe','volume-delete'];
+ $('.volume-resize',volumesBlock).parent().addClass('disabled');
+ for (i = 0; i < disabled.length; i++) {
+ $('.'+disabled[i],volumesBlock).parent().removeClass('disabled');
+ }
+ }else if($('[name="selected-volume[]"]:checked',volumesBlock).length === 1){
+ disabled = ['volume-resize','volume-clone','volume-wipe','volume-delete'];
+ for (i = 0; i < disabled.length; i++) {
+ $('.'+disabled[i],volumesBlock).parent().removeClass('disabled');
+ }
+ }else {
+ disabled = ['volume-resize','volume-clone','volume-wipe','volume-delete'];
+ for (i = 0; i < disabled.length; i++) {
+ $('.'+disabled[i],volumesBlock).parent().addClass('disabled');
+ }
+ }
+ if(checkbox.is(":checked")){
+ volumeBlock.addClass('selected');
+ }else {
+ volumeBlock.removeClass('selected');
+ }
+ });
+
+ }
+
$('.inactive').each(function(index) {
if ('active' === $(this).data('state')) {
$(this).hide();
@@ -103,10 +297,10 @@ kimchi.storageBindClick = function() {
$(this).data('type') !== 'iscsi' &&
$(this).data('type') !== 'scsi';
if(canAddVolume) {
- $(this).show();
+ $(this).parent().show();
}
else {
- $(this).hide();
+ $(this).parent().hide();
}
});
@@ -229,7 +423,8 @@ kimchi._generateVolumeHTML = function(volume) {
if(volume['type'] === 'kimchi-iso') {
return '';
}
- var volumeHtml = $('#volumeTmpl').html();
+ var volumeHtml = $('#volumeTmpl2').html();
+ volume.checkbox = volume.name.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi,'-'),
volume.capacityLevel = Math.round(volume.allocation / volume.capacity * 100) || 0;
if (volume.capacityLevel > 100) {
volume.capacityIcon = 'icon-high';
@@ -251,77 +446,122 @@ kimchi.doListVolumes = function(poolObj) {
var getOngoingVolumes = function() {
var result = {};
+ var clone = 'status=running&target_uri=' + encodeURIComponent('^/plugins/kimchi/storagepools/.+/storagevolumes/.+/clone');
var filter = 'status=running&target_uri=' + encodeURIComponent('^/plugins/kimchi/storagepools/' + poolName + '/*');
kimchi.getTasksByFilter(filter, function(tasks) {
for(var i = 0; i < tasks.length; i++) {
- var volumeName = tasks[i].target_uri.split('/').pop();
- result[volumeName] = tasks[i];
+ if(tasks[i].message !== 'cloning volume') {
+ var volumeName = tasks[i].target_uri.split('/').pop();
+ result[volumeName] = tasks[i];
+
+ if(kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) {
+ continue;
+ }
- if(kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) {
- continue;
+ kimchi.trackTask(tasks[i].id, function(result) {
+ wok.topic('kimchi/volumeTransferFinished').publish(result);
+ }, function(result) {
+ wok.topic('kimchi/volumeTransferError').publish(result);
+ }, function(result) {
+ wok.topic('kimchi/volumeTransferProgress').publish(result);
+ });
}
+ }
+ }, null, true);
+ kimchi.getTasksByFilter(clone, function(tasks) {
+ for(var i = 0; i < tasks.length; i++) {
+ if(tasks[i].message === 'cloning volume') {
+ var volumeName = tasks[i].target_uri.split('/')[6];
+ result[volumeName] = tasks[i];
- kimchi.trackTask(tasks[i].id, function(result) {
- wok.topic('kimchi/volumeTransferFinished').publish(result);
- }, function(result) {
- wok.topic('kimchi/volumeTransferError').publish(result);
- }, function(result) {
- wok.topic('kimchi/volumeTransferProgress').publish(result);
- });
+ if(kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) {
+ continue;
+ }
+
+ kimchi.trackTask(tasks[i].id, function(result) {
+ wok.topic('kimchi/volumeCloneFinished').publish(result);
+ }, function(result) {
+ wok.topic('kimchi/volumeCloneError').publish(result);
+ }, function(result) {
+ wok.topic('kimchi/volumeCloneProgress').publish(result);
+ });
+ }
}
}, null, true);
return result;
};
- var volumeDiv = $('#volume' + poolName);
- $(volumeDiv).empty();
+ var volumeDiv = $('#volume-' + poolName);
+ var volumeDatatable = $('.wok-datagrid > .wok-datagrid-body',volumeDiv);
var slide = $('.volumes', poolObj);
var handleArrow = $('.arrow-down', poolObj);
-
kimchi.listStorageVolumes(poolName, function(result) {
var listHtml = '';
var ongoingVolumes = [];
var ongoingVolumesMap = getOngoingVolumes();
$.each(ongoingVolumesMap, function(volumeName, task) {
ongoingVolumes.push(volumeName);
- var volume = {
- poolName: poolName,
- used_by: [],
- capacity: 0,
- name: volumeName,
- format: '',
- bootable: null,
- os_distro: '',
- allocation: 0,
- os_version: '',
- path: '',
- type: 'file',
- capacityLevel: 0,
- capacityIcon: ''
- };
- listHtml += kimchi._generateVolumeHTML(volume);
+ var volume = {
+ poolName: poolName,
+ used_by: [],
+ capacity: 0,
+ name: volumeName,
+ format: '',
+ bootable: null,
+ os_distro: '',
+ allocation: 0,
+ os_version: '',
+ path: '',
+ type: 'file',
+ capacityLevel: 0,
+ capacityIcon: ''
+ };
+ listHtml += kimchi._generateVolumeHTML(volume);
});
$.each(result, function(index, value) {
if (ongoingVolumes.indexOf(value.name) === -1) {
+ $(volumeDatatable).empty();
value.poolname = poolName;
listHtml += kimchi._generateVolumeHTML(value);
}
});
if (listHtml.length > 0) {
- volumeDiv.html(listHtml);
+ $(volumeDatatable).empty();
+ $('.filter',volumeDiv).prop('disabled',false);
+ $('.toggle-gallery',volumeDiv).prop('disabled',false);
+ $(volumeDatatable).html(listHtml);
+
} else {
- volumeDiv.html("<div class='pool-empty'>" + i18n['KCHPOOL6002M'] + "</div>");
+ $(volumeDatatable).empty();
+ $('.filter',volumeDiv).prop('disabled',true);
+ $('.toggle-gallery',volumeDiv).prop('disabled',true);
+ $(volumeDatatable).html("<div class='pool-empty wok-datagrid-row'><span class='volume-empty'>" + i18n['KCHPOOL6002M'] + "</span></div>");
}
$.each(ongoingVolumesMap, function(volumeName, task) {
wok.topic('kimchi/volumeTransferProgress').publish(task);
});
+ var checkbox = volumeDiv.find('[name="selected-volume[]"]');
+ checkbox.trigger('change');
+ checkbox.prop('checked',false);
poolObj.removeClass('in');
kimchi.changeArrow(handleArrow);
slide.slideDown('slow');
+
+ volumeDivId = volumeDiv.attr('id');
+
+ volumeOptions = {
+ valueNames: ['volume-name-filter', 'volume-format-filter', 'volume-type-filter']
+ };
+ volumeFilterList = new List(volumeDivId, volumeOptions);
+
+ volumeFilterList.sort('volume-name-filter', {
+ order: "asc"
+ });
+
}, function(err) {
wok.message.error(err.responseJSON.reason);
}, false);
@@ -329,53 +569,6 @@ kimchi.doListVolumes = function(poolObj) {
kimchi.initLogicalPoolExtend = function() {
- // $("#logicalPoolExtend").dialog({
- // autoOpen : false,
- // modal : true,
- // width : 600,
- // resizable : false,
- // closeText: "X",
- // open : function(){
- // $('#loading-info', '#logicalPoolExtend').removeClass('hidden');
- // $(".ui-dialog-titlebar-close", $("#logicalPoolExtend").parent()).removeAttr("title");
- // kimchi.listHostPartitions(function(data) {
- // $('#loading-info', '#logicalPoolExtend').addClass('hidden');
- // if (data.length > 0) {
- // for(var i=0;i<data.length;i++){
- // if (data[i].type === 'part' || data[i].type === 'disk') {
- // $('.host-partition', '#logicalPoolExtend').append(wok.substitute($('#logicalPoolExtendTmpl').html(), data[i]));
- // }
- // }
- // } else {
- // $('.host-partition').html(i18n['KCHPOOL6011M']);
- // $('.host-partition').addClass('text-help');
- // }
- // }, function(err) {
- // $('#loading-info', '#logicalPoolExtend').addClass('hidden');
- // $('.host-partition').html(i18n['KCHPOOL6013M'] + '<br/>(' + err.responseJSON.reason + ')');
- // $('.host-partition').addClass('text-help');
- // });
- // },
- // beforeClose : function() { $('.host-partition', '#logicalPoolExtend').empty(); },
- // buttons : [{
- // class: "ui-button-primary",
- // text: i18n.KCHAPI6007M,
- // click: function(){
- // var devicePaths = [];
- // $("input[type='checkbox']:checked", "#logicalPoolExtend").each(function(){
- // devicePaths.push($(this).prop('value'));
- // })
- // kimchi.updateStoragePool($("#logicalPoolExtend").dialog("option", "poolName"),{disks: devicePaths},function(data){
- // var item = $("#"+$("#logicalPoolExtend").dialog("option", "poolName"));
- // $(".usage", $(".storage-name", item)).text((Math.round(data.allocated/data.capacity*100)||0)+"%");
- // $(".storage-text", $(".storage-capacity", item)).text(wok.changetoProperUnit(data.capacity,1));
- // $(".storage-text", $(".storage-allocate", item)).text(wok.changetoProperUnit(data.allocated,1));
- // });
- // $(this).dialog("close");
- // }
- // }]
- // });
-
$('#logicalPoolExtend').on('hidden.bs.modal', function () {
$('.host-partition', '#logicalPoolExtend').empty();
});
@@ -442,6 +635,29 @@ kimchi.storage_main = function() {
kimchi.doListVolumes(poolNode);
});
+ wok.topic('kimchi/storageVolumeDeleted').subscribe(function() {
+ pool = kimchi.selectedSP;
+ var poolNode = $('.storage-li[data-name="' + pool + '"]');
+ kimchi.doListVolumes(poolNode);
+ });
+
+ wok.topic('kimchi/storageVolumeWiped').subscribe(function() {
+ pool = kimchi.selectedSP;
+ var poolNode = $('.storage-li[data-name="' + pool + '"]');
+ kimchi.doListVolumes(poolNode);
+ });
+ wok.topic('kimchi/storageVolumeCloned').subscribe(function() {
+ pool = kimchi.selectedSP;
+ var poolNode = $('.storage-li[data-name="' + pool + '"]');
+ kimchi.doListVolumes(poolNode);
+ });
+
+ wok.topic('kimchi/storageVolumeResized').subscribe(function() {
+ pool = kimchi.selectedSP;
+ var poolNode = $('.storage-li[data-name="' + pool + '"]');
+ kimchi.doListVolumes(poolNode);
+ });
+
wok.topic('kimchi/volumeTransferProgress').subscribe(function(result) {
var extractProgressData = function(data) {
var sizeArray = /(\d+)\/(\d+)/g.exec(data) || [0, 0, 0];
@@ -467,22 +683,32 @@ kimchi.storage_main = function() {
var progress = extractProgressData(result['message']);
var size = progress['size'];
var percent = progress['percent'];
-
- volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]');
- $('.progress-bar-inner', volumeBox).css({
- width: percent + '%'
- });
- $('.progress-transferred', volumeBox).text(size);
+ volumeBox = $('#volume-' + poolName + ' [data-volume-name="' + volumeName + '"]').closest('.wok-datagrid-row');
$('.volume-progress', volumeBox).removeClass('hidden');
+ $('.column-progress', volumeBox).removeClass('hidden');
+ $('.column-progress', '.wok-datagrid-header').removeClass('hidden');
+ $('.volume-inline-progress', volumeBox).removeClass('hidden');
+ $('.column-format > .format-text', volumeBox).text('--');
+ $('.progress-bar', volumeBox).attr('aria-valuenow',percent+'%').css('width',percent+'%');
+ $('input[type="checkbox"]',volumeBox).prop('disabled',true);
+ $(volumeBox).addClass('in-progress')
+ $('.volume-box-inner', volumeBox).attr({'data-toggle':'tooltip','data-original-title': i18n['KCHPOOL6014M'] + ' ' +size});
+ $('.tooltip-inner', volumeBox).text(i18n['KCHPOOL6014M']+' '+size);
+ $('.progress-transferred', volumeBox).text(size);
$('.progress-status', volumeBox).text(i18n['KCHPOOL6014M']);
+ $('[data-toggle="tooltip"]',volumeBox).tooltip();
});
wok.topic('kimchi/volumeTransferFinished').subscribe(function(result) {
var uriElements = result.target_uri.split('/');
var poolName = uriElements[4];
var volumeName = uriElements.pop();
- var volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]');
+ volumeBox = $('#volume-' + poolName + ' [data-volume-name="' + volumeName + '"]').closest('.wok-datagrid-row');
+ $(volumeBox).removeClass('in-progress')
$('.volume-progress', volumeBox).addClass('hidden');
+ $('.column-progress', volumeBox).addClass('hidden');
+ $('.column-progress', '.wok-datagrid-header').addClass('hidden');
+ $('.volume-inline-progress', volumeBox).addClass('hidden');
kimchi.getStoragePoolVolume(poolName, volumeName, function(volume) {
var html = kimchi._generateVolumeHTML(volume);
$(volumeBox).replaceWith(html);
@@ -505,9 +731,46 @@ kimchi.storage_main = function() {
var uriElements = result.target_uri.split('/');
var poolName = uriElements[4];
var volumeName = uriElements.pop();
- volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]');
+ volumeBox = $('#volume-' + poolName + ' [data-volume-name="' + volumeName + '"]').closest('.wok-datagrid-row');
$('.progress-status', volumeBox).text(i18n['KCHPOOL6015M']);
});
+
+ wok.topic('kimchi/volumeCloneFinished').subscribe(function(result) {
+ var uriElements = result.target_uri.split('/');
+ var poolName = uriElements[4];
+ var poolNode = $('.storage-li[data-name="' + poolName + '"]');
+ kimchi.doListVolumes(poolNode);
+ });
+
+ wok.topic('kimchi/volumeCloneProgress').subscribe(function(result) {
+ var uriElements = result.target_uri.split('/');
+ var poolName = uriElements[4];
+ var volumeName = uriElements[6];
+ volumeBox = $('#volume-' + poolName + ' [data-volume-name="' + volumeName + '"]').closest('.wok-datagrid-row');
+ $('.column-progress', volumeBox).removeClass('hidden');
+ $('.column-progress', '.wok-datagrid-header').removeClass('hidden');
+ $('.volume-inline-progress', volumeBox).removeClass('hidden');
+ $('.column-format > .format-text', volumeBox).text('--');
+ $('input[type="checkbox"]',volumeBox).prop('disabled',true);
+ $(volumeBox).addClass('in-progress')
+ $('.volume-box-inner', volumeBox).attr({'data-toggle':'tooltip','data-original-title': i18n['KCHPOOL6014M'] });
+ $('.tooltip-inner', volumeBox).text(i18n['KCHPOOL6014M']);
+ $('.progress-status', volumeBox).text(i18n['KCHPOOL6014M']);
+ $('[data-toggle="tooltip"]',volumeBox).tooltip();
+ });
+
+ wok.topic('kimchi/volumeCloneError').subscribe(function(result) {
+ // Error message from Async Task status
+ if (result['message']) {
+ var errText = result['message'];
+ }
+ // Error message from standard kimchi exception
+ else {
+ var errText = result['responseJSON']['reason'];
+ }
+ result && wok.message.error(errText);
+ });
+
};
kimchi.changeArrow = function(obj) {
diff --git a/ui/js/src/kimchi.storagepool_add_volume_main.js b/ui/js/src/kimchi.storagepool_add_volume_main.js
index c398369..e167a20 100644
--- a/ui/js/src/kimchi.storagepool_add_volume_main.js
+++ b/ui/js/src/kimchi.storagepool_add_volume_main.js
@@ -180,6 +180,6 @@ kimchi.sp_add_volume_main = function() {
uploadFile();
}
event.preventDefault();
- $('#modalWindow').modal.close();
+ wok.window.close();
});
};
diff --git a/ui/js/src/kimchi.storagepool_resize_volume_main.js b/ui/js/src/kimchi.storagepool_resize_volume_main.js
new file mode 100644
index 0000000..791cc1d
--- /dev/null
+++ b/ui/js/src/kimchi.storagepool_resize_volume_main.js
@@ -0,0 +1,59 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM Corp, 2016
+ *
+ * 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.
+ */
+
+kimchi.sp_resize_volume_main = function() {
+
+ var addButton = $('#sp-resize-volume-button');
+ var size = $('#volume-size');
+ var form = $('form#form-sp-resize-volume');
+
+ $(addButton).prop('disabled',true);
+ $(size).on('keyup', function(){
+ if($(this).val().length !==0) {
+ addButton.prop('disabled', false);
+ } else{
+ addButton.prop('disabled',true);
+ }
+ });
+ $(addButton).on('click',function(e){
+ e.preventDefault();
+ e.stopPropagation();
+ $(form).submit();
+ });
+ $(form).on('submit',function(e){
+ e.preventDefault();
+ e.stopPropagation();
+ var newsize = parseInt($(size).val());
+ var bytes = newsize * 1048576;
+ var data = {};
+ data = {
+ size: bytes
+ };
+ kimchi.resizeStoragePoolVolume(kimchi.selectedSP, kimchi.selectedVolumes[0], data, function() {
+ $(size).prop('disabled', true);
+ $(addButton).prop('disabled',true);
+ wok.topic('kimchi/storageVolumeResized').publish();
+ wok.window.close();
+ }, function(err) {
+ wok.message.error(err.responseJSON.reason, '#alert-modal-container');
+ $(size).prop('disabled', false);
+ $(addButton).prop('disabled',false);
+ $(size).focus();
+ });
+ });
+}
diff --git a/ui/pages/i18n.json.tmpl b/ui/pages/i18n.json.tmpl
index e152989..a1f43d3 100644
--- a/ui/pages/i18n.json.tmpl
+++ b/ui/pages/i18n.json.tmpl
@@ -98,6 +98,8 @@
"KCHPOOL6006M": "$_("Loading iSCSI targets...")",
"KCHPOOL6007M": "$_("No iSCSI found. Please input one.")",
"KCHPOOL6008M": "$_("Failed to load iSCSI targets.")",
+ "KCHPOOL6009M": "$_("Would you like to continue?")",
+ "KCHPOOL6010M": "$_("This will permanently delete the following storage volumes: %1")",
"KCHPOOL6005E": "$_("Invalid NFS mount path.")",
"KCHPOOL6006E": "$_("No logical device selected.")",
@@ -108,6 +110,10 @@
"KCHPOOL6014M": "$_("In progress...")",
"KCHPOOL6015M": "$_("Failed!")",
"KCHPOOL6016M": "$_("No LVM found in the system.")",
+ "KCHPOOL6017M": "$_("Volume %1 was successfully removed.")",
+ "KCHPOOL6018M": "$_("This will permanently wipe the following storage volumes: %1")",
+ "KCHPOOL6019M": "$_("Wipe Confirmation")",
+ "KCHPOOL6020M": "$_("Volume %1 is cloning.")",
"KCHVMSTOR0001E": "$_("CDROM path needs to be a valid local/remote path and cannot be blank.")",
"KCHVMSTOR0002E": "$_("Disk pool or volume cannot be blank.")"
diff --git a/ui/pages/storagepool-resize-volume.html.tmpl b/ui/pages/storagepool-resize-volume.html.tmpl
new file mode 100644
index 0000000..7a8c7d4
--- /dev/null
+++ b/ui/pages/storagepool-resize-volume.html.tmpl
@@ -0,0 +1,51 @@
+#*
+ * Project Kimchi
+ *
+ * Copyright IBM Corp, 2016
+ *
+ * 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.
+ *#
+#unicode UTF-8
+#import gettext
+#from wok.cachebust import href
+#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True)
+#silent _ = t.gettext
+#silent _t = t.gettext
+<html>
+<body>
+<div id="sp-add-volume-window" class="window modal-content">
+ <form id="form-sp-resize-volume">
+ <div class="modal-header">
+ <h4 class="modal-title">$_("Resize Volume")</h4>
+ </div>
+ <div class="modal-body">
+ <span id="alert-modal-container"></span>
+ <div class="form-group">
+ <label for="volume-size">$_("Size")</label>
+ <input type="number" id="volume-size" class="form-control" name="size" />
+ <p class="help-block">
+ <i class="fa fa-info-circle"></i> $_("The total space which can be used to store data. The unit is megabytes.")
+ </p>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="submit" id="sp-resize-volume-button" class="btn btn-default" disabled="disabled">$_("Ok")</button>
+ <button type="button" class="btn btn-default" data-dismiss="modal">$_("Cancel")</button>
+ </div>
+ </form>
+</div>
+<script type="text/javascript">
+ kimchi.sp_resize_volume_main();
+</script>
+</body>
+</html>
diff --git a/ui/pages/tabs/storage.html.tmpl b/ui/pages/tabs/storage.html.tmpl
index fa51e48..cf1eac7 100644
--- a/ui/pages/tabs/storage.html.tmpl
+++ b/ui/pages/tabs/storage.html.tmpl
@@ -102,90 +102,101 @@
</div>
</div>
<script id="storageTmpl" type="html/text">
- <div id="{name}" class="storage-li in" data-name="{name}" data-stat="{state}">
- <span class='column-state' val="{state}">
- <span class='storage-state {state}'>
- <i class="fa fa-power-off"></i>
- </span>
- </span><!--
- --><span class='column-name' title="{name}" val="{name}">{name}</span><!--
- --><span class='column-type' val="{type}">{type}</span><!--
- --><span class='column-location' val="{path}">{path}</span><!--
- --><span class='column-usage {state}' val="{usage}" ><span class='usage-icon {icon}'>{usage}</span>%</span><!--
- --><span class='column-allocated' val="{allocated}">{allocated}</span><!--
- --><span class='column-capacity' val="{capacity}">{capacity}</span><!--
- --><span class="column-disks {state}">
- <div class="handle arrow-down"></div>
- </span><!--
- --><span class="column-action storage-button" style="display:none">
- <span class="pull-right">
+<div id="{name}" class="storage-li in" data-name="{name}" data-stat="{state}">
+ <span class='column-state' val="{state}"><span class='storage-state {state}'><i class="fa fa-power-off"></i></span></span><!--
+ --><span class='column-name' title="{name}" val="{name}">{name}</span><!--
+ --><span class='column-type' val="{type}">{type}</span><!--
+ --><span class='column-location' val="{path}">{path}</span><!--
+ --><span class='column-usage {state}' val="{usage}" ><span class='usage-icon {icon}'>{usage}</span>%</span><!--
+ --><span class='column-allocated' val="{allocated}">{allocated}</span><!--
+ --><span class='column-capacity' val="{capacity}">{capacity}</span><!--
+ --><span class="column-disks {state}"><div class="handle arrow-down"></div></span><!--
+ --><span class="column-action storage-button" style="display:none">
+ <span class="pull-right">
<div class="dropdown menu-flat storage-action" data-state="{state}" data-type="{type}" data-name="{name}">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false" aria-haspopup="true"><span class="edit-alt"></span>$_("Actions")<span class="caret"></span></button>
<ul class="dropdown-menu actionsheet">
- <li role="presentation">
- <a href="#" class="pool-deactivate" data-inuse="{in_use}" data-stat="{state}" data-name="{name}" data-persistent="{persistent}" href="#"><i class="fa fa-minus-circle"></i>$_("Deactivate")</a>
- </li>
- <li role="presentation">
- <a href="#" class="pool-activate" data-stat="{state}" data-name="{name}"><i class="fa fa-power-off"></i>$_("Activate")</a>
- </li>
- <li role="presentation">
- <a href="#" class="pool-add-volume" data-stat="{state}" data-name="{name}" data-type="{type}"><i class="fa fa-plus-circle"></i>$_("Add Volume")</a>
- </li>
- <li role="presentation" class="{enableExt}">
- <a href="#" class="pool-extend" data-stat="{state}" data-name="{name}" data-toggle="modal" data-target="#logicalPoolExtend"><i class="fa fa-external-link-square"></i>$_("Extend")</a>
- </li>
- <li role="presentation" class="critical">
- <a href="#" class="pool-delete" data-inuse="{in_use}" data-stat="{state}" data-name="{name}"><i class="fa fa-ban"></i>$_("Undefine")</a>
- </li>
+ <li><a href="#" class="pool-deactivate" data-inuse="{in_use}" data-stat="{state}" data-name="{name}" data-persistent="{persistent}"><i class="fa fa-minus-circle"></i>$_("Deactivate")</a></li>
+ <li><a href="#" class="pool-activate" data-stat="{state}" data-name="{name}"><i class="fa fa-power-off"></i>$_("Activate")</a></li>
+ <li class="{enableExt}"><a href="#" class="pool-extend" data-stat="{state}" data-name="{name}" data-toggle="modal" data-target="#logicalPoolExtend"><i class="fa fa-external-link-square"></i>$_("Extend")</a></li>
+ <li class="critical"><a href="#" class="pool-delete" data-inuse="{in_use}" data-stat="{state}" data-name="{name}"><i class="fa fa-ban"></i>$_("Undefine")</a></li>
</ul>
</div>
- </span>
</span>
- <div class="volumes">
- <div id="volume{name}" class="volumeslist" data-name="{name}" ></div>
- <div class="clear"></div>
- </div>
- </div>
-</script>
-<script id="volumeTmpl" type="html/text">
- <div class="volume-box" data-volume-name="{name}">
- <div class="volume-title">
- <div class="volume-name" title="{name}">{name}</div>
- <div class="volume-utilization">
- <span class="volume-icon {capacityIcon}"></span>
- <span class="volume-usage">{capacityLevel}%</span>
+ </span>
+ <div class="volumes">
+ <div id="volume-{name}" class="volumeslist" data-name="{name}">
+ <div class="row">
+ <div class="pull-left">
+ <div class="dropdown menu-flat pool-action">
+ <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false" aria-haspopup="true"><span class="edit-alt"></span>$_("Actions")<span class="caret"></span></button>
+ <ul class="dropdown-menu actionsheet">
+ <li><a href="#" class="pool-add-volume" data-stat="{state}" data-name="{name}" data-type="{type}"><i class="fa fa-plus-circle"></i> $_("Add Volume")</a></li>
+ <li class="disabled"><a href="#" class="volume-resize" data-name="{name}"><i class="fa fa-external-link-square"></i> $_("Resize")</a></li>
+ <li class="disabled"><a href="#" class="volume-clone" data-name="{name}"><i class="fa fa-copy"></i> $_("Clone")</a></li>
+ <li class="disabled"><a href="#" class="volume-wipe" data-name="{name}"><i class="fa fa-eraser"></i> $_("Wipe")</a></li>
+ <li class="disabled critical"><a href="#" class="volume-delete" data-name="{name}"><i class="fa fa-minus-circle"></i> $_("Delete")</a></li>
+ </ul>
+ </div>
+ <button type="button" class="btn btn-default toggle-gallery"><span class="text">$_('View Gallery')</span> <i class="fa fa-angle-right"></i><i class="fa fa-angle-right"></i><i class="fa fa-angle-right"></i></button>
+ </div>
+ <div class="pull-right">
+ <label><span class="sr-only">$_('Filter:')</span>
+ <input type="text" class="filter form-control search" placeholder="$_('Filter')">
+ </label>
+ </div>
</div>
- <div class="volume-progress hidden">
- <div class="progress-bar-outer">
- <div class="progress-bar-inner"></div>
+ <div class="wok-datagrid wok-list">
+ <div class="wok-datagrid-header">
+ <span class="column-name">$_('Name')</span><!--
+ --><span class="column-format">$_('Format')</span><!--
+ --><span class="column-type">$_('Type')</span><!--
+ --><span class="column-used">$_('Used')</span><!--
+ --><span class="column-allocated">$_('Allocated')</span><!--
+ --><span class="column-capacity">$_('Capacity')</span><!--
+ --><span class="column-progress hidden">$_('Progress')</span>
</div>
- <div class="progress-label">
- <span class="progress-status"></span>
- <span class="progress-transferred"></span>
+ <ul class="wok-datagrid-body list" id="volume-{name}-table">
+ </ul>
+ </div>
+ <div class="wok-mask hidden">
+ <div class="wok-mask-loader-container">
+ <div class="wok-mask-loading">
+ <div class="wok-mask-loading-icon"></div>
+ <div class="wok-mask-loading-text">$_("Loading...")</div>
+ </div>
</div>
</div>
</div>
- <div class="volume-setting">
+ <div class="clear"></div>
+ </div>
+</div>
+</script>
+<script id="volumeTmpl2" type="html/text">
+<li class="wok-datagrid-row">
+ <div class="volume-progress hidden">
+ <div class="progress-bar-outer progress">
+ <div class="progress-bar-inner progress-bar" role="progressbar" aria-valuenow="0%" aria-valuemin="0%" aria-valuemax="100%" ></div>
+ </div>
+ </div>
+ <div class="volume-box-outer">
+ <div class="volume-box-border">
+ <div class="volume-box-inner" data-volume-name="{name}">
+ <span class="column-name" title="{name}">
+ <input type="checkbox" class="wok-checkbox" name="selected-volume[]" id="{checkbox}" value="{name}">
+ <label class="volume-name volume-name-filter" for="{checkbox}"><span class="volume-inline-progress hidden"><span class="wok-loading-icon"></span></span> {name}</label><!--
+ --></span><!--
+ --><span class="column-format volume-format-filter"><span class="gallery-header">$_('Format')</span><span class="format-text">{format}</span></span><!--
+ --><span class="column-type volume-type-filter"><span class="gallery-header">$_('Type')</span>{type}</span><!--
+ --><span class="column-used"><span role="presentation" class="volume-icon {capacityIcon}"></span> {capacityLevel}%</span><!--
+ --><span class="column-allocated"><span class="gallery-header">$_('Allocation')</span>{allocation}</span><!--
+ --><span class="column-capacity"><span class="gallery-header">$_('Capacity')</span>{capacity}</span><!--
+ --><span class="column-progress hidden"><span class="progress-status"></span> <span class="progress-transferred"></span>
+ </span>
</div>
- <ul class="volume-data">
- <li>
- <span class="value" title="{format}">{format}</span>
- <span class="key">$_("Format")</span>
- </li>
- <li>
- <span class="value" title="{type}">{type}</span>
- <span class="key">$_("Type")</span>
- </li>
- <li>
- <span class="value" title="{allocation}">{allocation}</span>
- <span class="key">$_("Allocation")</span>
- </li>
- <li>
- <span class="value" title="{capacity}">{capacity}</span>
- <span class="key">$_("Capacity")</span>
- </li>
- </ul>
- </div>
+ </div>
+ </div>
+</li>
</script>
<script id="logicalPoolExtendTmpl" type="html/text">
<div>
--
1.9.3
More information about the Kimchi-devel
mailing list