From: Samuel Guimarães <sguimaraes943(a)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(a)gmail.com>
---
model/storagevolumes.py | 2 +-
ui/css/kimchi.css | 436 ++++++++++++++++--
ui/css/src/modules/_storage.scss | 406 +++++++++++++++--
ui/js/src/kimchi.api.js | 50 ++
ui/js/src/kimchi.storage_main.js | 506 +++++++++++++++++----
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 | 5 +
ui/pages/storagepool-resize-volume.html.tmpl | 51 +++
ui/pages/tabs/storage.html.tmpl | 157 ++++---
10 files changed, 1413 insertions(+), 261 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 70cad4f..4bea724 100644
--- a/model/storagevolumes.py
+++ b/model/storagevolumes.py
@@ -440,7 +440,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..d68211b 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,68 @@ body.wok-gallery {
display: none;
}
+#storage-root-container .volumes .tooltip > .tooltip-inner {
+ width: 150px;
+}
+
+#storage-root-container .volumes input[type=checkbox][disabled].wok-checkbox +
label:before {
+ content: '';
+}
+
+#storage-root-container .volumes .toggle-gallery {
+ left: 202px;
+}
+
+@media (min-width: 1200px) {
+ #storage-root-container .volumes .toggle-gallery {
+ left: 282px;
+ }
+}
+
#storage-root-container .volumes > .footer {
z-index: 100;
}
#storage-root-container .volumes .volumeslist {
- padding: 11px;
- max-height: 285px;
+ padding: 22px;
min-height: 136px;
- overflow: auto;
+ max-height: 505px;
+ overflow: hidden;
}
-#storage-root-container .volumes .volume-box {
- background: #fff;
- padding: 4px 20px;
- margin: 11px;
- display: inline-block;
- width: 409px;
- height: 110px;
+#storage-root-container .volumes .volumeslist .row {
+ font-size: 0;
+ margin-bottom: 22px;
}
-#storage-root-container .volumes .volume-title {
- height: 46px;
- width: 100%;
- border-bottom: 1px solid #ccc;
- position: relative;
+#storage-root-container .volumes .volumeslist .filter {
+ width: 344px;
+ height: 38px;
+ margin-top: 1px;
}
-#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;
+@media (min-width: 992px) {
+ #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 +2300,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 +2343,354 @@ 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;
+ overflow-y: auto;
+ overflow-x: hidden;
+ max-height: 400px;
+}
+
+#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;
+ 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-width: 3px;
+ border-style: solid;
+ border-color: transparent;
+ border-color: rgba(255, 255, 255, 0);
+ 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-width: 1px;
+ border-style: solid;
+ border-color: #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: 270px;
+ order: 1;
+}
+
+#storage-root-container .volumes .wok-gallery span.column-used {
+ width: 105px;
+ order: 2;
+}
+
+#storage-root-container .volumes .wok-gallery span.column-used-by {
+ width: 20px;
+ height: 20px;
+ order: 3;
+ position: absolute;
+ right: 32px;
+ top: 20px;
+}
+
+#storage-root-container .volumes .wok-gallery span.column-used-by .fa {
+ display: block;
+ color: #424242;
+}
+
+#storage-root-container .volumes .wok-gallery span.column-used-by .format-text {
+ display: none !important;
+}
+
+#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 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, #storage-root-container
.volumes .wok-list .volume-progress * {
+ display: none !important;
+}
+
+#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 {
+ overflow-y: auto;
+ overflow-x: hidden;
+ max-height: 350px;
+}
+
+#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 .volume-box-border {
+ border-color: rgba(255, 255, 255, 0);
+ border-width: 0px;
+ border-style: solid;
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body >
.wok-datagrid-row .volume-box-inner {
+ border-color: rgba(255, 255, 255, 0);
+ border-width: 0px;
+ border-style: solid;
+}
+
+#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: 57px;
+}
+
+@media (min-width: 992px) {
+ #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: 95px;
+ }
+}
+
+@media (min-width: 1200px) {
+ #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 {
+ left: 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-header >
span.column-progress,
+#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,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body >
.wok-datagrid-row > div > div > div > span.column-progress {
+ width: 79px;
+ text-transform: capitalize;
+}
+
+@media (min-width: 992px) {
+ #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-header >
span.column-progress,
+ #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,
+ #storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body >
.wok-datagrid-row > div > div > div > span.column-progress {
+ width: 95px;
+ }
+}
+
+@media (min-width: 1200px) {
+ #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-header >
span.column-progress,
+ #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,
+ #storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body >
.wok-datagrid-row > div > div > div > span.column-progress {
+ left: 165px;
+ }
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header >
span.column-used-by,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body >
.wok-datagrid-row > div > div > div > span.column-used-by {
+ width: 69px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ padding-right: 5px;
+}
+
+@media (min-width: 992px) {
+ #storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header >
span.column-used-by,
+ #storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body >
.wok-datagrid-row > div > div > div > span.column-used-by {
+ width: 85px;
+ }
+}
+
+@media (min-width: 1200px) {
+ #storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header >
span.column-used-by,
+ #storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body >
.wok-datagrid-row > div > div > div > span.column-used-by {
+ width: 155px;
+ }
+}
+
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-header >
span.column-used-by .fa,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body >
.wok-datagrid-row > div > div > div > span.column-used-by .fa {
+ display: none !important;
+}
+
+#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: 202px;
+}
+
+@media (min-width: 992px) {
+ #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: 333px;
+ }
+}
+
+@media (min-width: 1200px) {
+ #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 .volumes .wok-list.wok-datagrid > .wok-datagrid-header >
span.column-progress,
+#storage-root-container .volumes .wok-list.wok-datagrid > .wok-datagrid-body >
.wok-datagrid-row > div > div > div > span.column-progress {
+ white-space: nowrap;
}
#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..3316a92 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,63 @@
width: 100%;
background: $navbar-default-toggle-hover-bg;
display: none;
+
+ .tooltip > .tooltip-inner {
+ width: 150px;
+ }
+
+ input[type=checkbox][disabled].wok-checkbox + label:before {
+ content: '';
+ }
+
+ .toggle-gallery {
+ left: 202px;
+ @media (min-width: $screen-lg) {
+ left: 282px;
+ }
+ }
+
.footer {
z-index: 100;
}
+
.volumeslist {
- padding: 11px;
- max-height: 285px;
+ padding: 22px;
min-height: 136px;
- overflow: auto;
- }
- .volume-box {
- background: $navbar-inverse-toggle-icon-bar-bg;
- padding: 4px 20px;
- margin: 11px;
- display: inline-block;
- width: 409px;
- height: 110px;
+ max-height: 505px;
+ overflow: hidden;
}
- .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: 344px;
+ height: 38px;
+ margin-top: 1px;
+ @media (min-width: $screen-md) {
+ 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 +126,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 +146,7 @@
width: 100%;
}
}
+
.volume-data {
margin: 0;
padding: 0;
@@ -164,10 +166,318 @@
}
}
}
- .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;
+ overflow-y: auto;
+ overflow-x: hidden;
+ max-height: 400px;
+ }
+
+ &.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;
+ border-color: rgba($guests-color,1);
+ }
+
+ &.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-width: 3px;
+ border-style: solid;
+ border-color: transparent;
+ border-color: rgba(255,255,255,0);
+ 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-width: 1px;
+ border-style: solid;
+ border-color: #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: 270px;
+ order: 1;
+ }
+
+ span.column-used {
+ width: 105px;
+ order: 2;
+ }
+
+ span.column-used-by {
+ width: 20px;
+ height: 20px;
+ order: 3;
+ position: absolute;
+ right: 32px;
+ top: 20px;
+
+ .fa {
+ display: block;
+ color: #424242;
+ }
+
+ .format-text {
+ display: none !important;
+ }
+
+ }
+
+ 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 {
+
+ 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, .volume-progress * {
+ display: none !important;
+ }
+
+ .volume-box-inner {
+ font-size: 0;
+ }
+
+ &.wok-datagrid > .wok-datagrid-header {
+
+ > span.column-name {
+ padding-left: 41px;
+ }
+
+ }
+
+ &.wok-datagrid > .wok-datagrid-body {
+ overflow-y: auto;
+ overflow-x: hidden;
+ max-height: 350px;
+ }
+
+ &.wok-datagrid > .wok-datagrid-body > .wok-datagrid-row {
+ position: relative;
+ cursor: pointer;
+
+ .volume-box-border {
+ border-color: rgba(255,255,255,0);
+ border-width: 0px;
+ border-style: solid;
+ }
+
+ .volume-box-inner {
+ border-color: rgba(255,255,255,0);
+ border-width: 0px;
+ border-style: solid;
+ }
+
+ }
+
+ &.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: 57px;
+ @media (min-width: $screen-md) {
+ width: 95px;
+ }
+ @media (min-width: $screen-lg) {
+ left: 173px;
+ }
+ }
+
+ > span.column-used,
+ > span.column-type,
+ > span.column-capacity,
+ > span.column-allocated,
+ > span.column-progress {
+ width: 79px;
+ text-transform: capitalize;
+ @media (min-width: $screen-md) {
+ width: 95px;
+ }
+ @media (min-width: $screen-lg) {
+ left: 165px;
+ }
+ }
+
+ > span.column-used-by {
+ width: 69px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ padding-right: 5px;
+ @media (min-width: $screen-md) {
+ width: 85px;
+ }
+ @media (min-width: $screen-lg) {
+ width: 155px;
+ }
+
+ .fa {
+ display: none !important;
+ }
+ }
+
+ > span.column-name {
+ width: 202px;
+ @media (min-width: $screen-md) {
+ width: 333px;
+ }
+ @media (min-width: $screen-lg) {
+ 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;
+ }
+ }
+
+ > span.column-progress {
+ white-space: nowrap;
+ }
+ }
+
+ }
+
+
}
.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..257eac3 100644
--- a/ui/js/src/kimchi.storage_main.js
+++ b/ui/js/src/kimchi.storage_main.js
@@ -65,6 +65,202 @@ 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() {
+ $('[data-name="'+kimchi.selectedSP+'"]
input:checkbox:checked').prop('disabled',true);
+ $.each(kimchi.selectedVolumes, function(i,j) {
+ $('[data-volume-name="'+j+'"]
.volume-inline-progress').removeClass('hidden');
+ volumes = jQuery.grep(volumes, function(value) {
+ return value != j;
+ });
+ kimchi.deleteStoragePoolVolume(kimchi.selectedSP,j,function(){
+ 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['KCHPOOL6017M'].replace('%1','<ul>'+formatedVolumes+'</ul>'+i18n['KCHPOOL6009M']);
+ var settings = {
+ title : i18n['KCHPOOL6018M'],
+ content : confirmMessage,
+ confirm : i18n['KCHAPI6002M'],
+ cancel : i18n['KCHAPI6003M']
+ };
+ wok.confirm(settings, function() {
+ $('[data-name="'+kimchi.selectedSP+'"]
input:checkbox:checked').prop('disabled',true);
+ $.each(kimchi.selectedVolumes, function(i,j) {
+ $('[data-volume-name="'+j+'"]
.volume-inline-progress').removeClass('hidden');
+ volumes = jQuery.grep(volumes, function(value) {
+ return value != j;
+ });
+ kimchi.wipeStoragePoolVolume(kimchi.selectedSP,j,function(){
+ 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 +299,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();
}
});
@@ -230,6 +426,9 @@ kimchi._generateVolumeHTML = function(volume) {
return '';
}
var volumeHtml = $('#volumeTmpl').html();
+ volume.used_by_formatted = '';
+ volume.used_by_text = '';
+ volume.checkbox =
volume.name.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi,'-'),
volume.capacityLevel = Math.round(volume.allocation / volume.capacity * 100) || 0;
if (volume.capacityLevel > 100) {
volume.capacityIcon = 'icon-high';
@@ -241,87 +440,186 @@ kimchi._generateVolumeHTML = function(volume) {
} else {
volume.capacityIcon = 'icon-low';
}
+ if(volume.used_by.length){
+ for (var i = 0; i < volume.used_by.length; i++) {
+ (i + 1 < volume.used_by.length) ? volume.used_by_text +=
volume.used_by[i] +', ' : volume.used_by_text += volume.used_by[i];
+ (i + 1 < volume.used_by.length) ? volume.used_by_formatted +=
volume.used_by[i] +'<br />' : volume.used_by_formatted +=
volume.used_by[i];
+ }
+ }else {
+ volume.used_by_formatted = i18n['KCHPOOL6019M'];
+ volume.used_by_text = '--';
+ }
volume.capacity = wok.changetoProperUnit(volume.capacity,1);
volume.allocation = wok.changetoProperUnit(volume.allocation,1);
return wok.substitute(volumeHtml, volume);
};
+kimchi.doUpdateStoragePool = function(poolObj){
+ var poolName = poolObj.data('name');
+ kimchi.getStoragePool(poolName, function(result) {
+ result.usage = Math.round(result.allocated / result.capacity * 100) || 0;
+ if (result.usage <= 100 && result.usage >= 85) {
+ result.icon = 'icon-high';
+ }else if (result.usage <= 85 && result.usage >= 75 ) {
+ result.icon = 'icon-med';
+ } else {
+ result.icon = 'icon-low';
+ }
+ result.allocated = wok.changetoProperUnit(result.allocated,1);
+ $('> .column-usage > .usage-icon',poolObj).attr('class',
'usage-icon').addClass(result.icon).text(result.usage);
+ $('>
.column-allocated',poolObj).attr('val',result.allocated).text(result.allocated);
+ },function(){
+ return false;
+ });
+};
+
kimchi.doListVolumes = function(poolObj) {
var poolName = poolObj.data('name');
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');
+
+ $(window).resize(function() {
+ $('.pool-action.open', volumeDiv).removeClass('open');
+ });
+
+ $('.pool-action', volumeDiv).on('show.bs.dropdown', function ()
{
+ $(volumeDiv).scrollTop(0);
+ $(this).css('position','absolute');
+ $('.toggle-gallery',volumeDiv).css({
+ 'position':'absolute',
+ 'margin-top': '1px'
+ });
+ $(volumeDiv).bind('mousewheel DOMMouseScroll', function(e) {
+ e.preventDefault();
+ });
+ });
+
+ $('.pool-action', volumeDiv).on('hide.bs.dropdown', function ()
{
+ $(volumeDiv).unbind('mousewheel DOMMouseScroll');
+ $(this).removeAttr( 'style' );
+ $('.toggle-gallery',volumeDiv).removeAttr( 'style' );
+ });
+
+ kimchi.doUpdateStoragePool(poolObj);
+
+ $('[data-toggle="tooltip"]', volumeDiv).tooltip();
+
+ 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 +627,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,19 +693,43 @@ 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];
var downloaded = sizeArray[1];
+ var total = sizeArray[2];
var percent = 0;
if(downloaded) {
- var total = sizeArray[2];
if(!isNaN(total)) {
percent = downloaded / total * 100;
}
}
- var formatted = wok.formatMeasurement(downloaded);
- var size = (1.0 * formatted['v']).toFixed(1) +
formatted['s'];
+ var formatted = wok.formatMeasurement(downloaded, { base: 10, converter:
wok.localeConverters["number-locale-converter"]});
+ var formattedTotal = !isNaN(total) ? wok.formatMeasurement(total, { base: 10,
converter: wok.localeConverters["number-locale-converter"]}) : '';
+ var size = (1.0 * formatted['v']).toFixed(1) + formatted['s']
+ ( formattedTotal !== '' ? ' / '+ (1.0 *
formattedTotal['v']).toFixed(1) + formattedTotal['s'] : formattedTotal );
return {
size: size,
percent: percent
@@ -467,22 +742,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 +790,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..13c7479 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,9 @@
"KCHPOOL6014M": "$_("In progress...")",
"KCHPOOL6015M": "$_("Failed!")",
"KCHPOOL6016M": "$_("No LVM found in the system.")",
+ "KCHPOOL6017M": "$_("This will permanently wipe the following
storage volumes: %1")",
+ "KCHPOOL6018M": "$_("Wipe Confirmation")",
+ "KCHPOOL6019M": "$_("None")",
"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..9bc0ebb 100644
--- a/ui/pages/tabs/storage.html.tmpl
+++ b/ui/pages/tabs/storage.html.tmpl
@@ -102,90 +102,103 @@
</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-by">$_('Used
By')</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="volumeTmpl" 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-by volume-used-by-filter"
data-toggle="tooltip" title="$_('Used by the following VMs:')
{used_by_formatted}" data-placement="bottom"
data-original-title="$_('Used by the following VMs:')
{used_by_formatted}"><span class="sr-only" title="$_('Used
by the following VMs:')"></span><i class="fa
fa-exclamation-circle" role="presentation"></i><span
class="format-text">{used_by_text}</span></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