[PATCH 0/5 V3] Download and upload UI

- Set dataType (dataType: 'json') instead of add Accept header - Use .show() and .hide() to display or not the "Add Volume button" - Allow any type of file to be uploaded - Change upload/download handlers to query for running Tasks while listing storage volumes in a pool That way all users get the same view when a storage volume is being downloaded or uploaded - Disable upload option until we get all issues fixed Aline Manera (1): Disable upload option while adding a volume to a pool Hongliang Wang (4): Storage Pool Add Volume UI: Add APIs to kimchi.api.js Storage Pool Add Volume UI: Add i18n Strings Storage Pool Add Volume UI: Implement Download/Upload Volume Function Storage Pool Add Volume UI: Connect the Feature in Storage Tab ui/css/theme-default/storage.css | 31 +++- ui/css/theme-default/storagepool-add-volume.css | 36 +++++ ui/js/src/kimchi.api.js | 35 +++++ ui/js/src/kimchi.storage_main.js | 196 +++++++++++++++++++++--- ui/js/src/kimchi.storagepool_add_volume_main.js | 107 +++++++++++++ ui/pages/i18n.json.tmpl | 2 + ui/pages/storagepool-add-volume.html.tmpl | 80 ++++++++++ ui/pages/tabs/storage.html.tmpl | 12 +- 8 files changed, 473 insertions(+), 26 deletions(-) create mode 100644 ui/css/theme-default/storagepool-add-volume.css create mode 100644 ui/js/src/kimchi.storagepool_add_volume_main.js create mode 100644 ui/pages/storagepool-add-volume.html.tmpl -- 1.9.3

From: Hongliang Wang <hlwang@linux.vnet.ibm.com> Add API to handle downloand and upload features. Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- ui/js/src/kimchi.api.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js index 681f573..3398bd4 100644 --- a/ui/js/src/kimchi.api.js +++ b/ui/js/src/kimchi.api.js @@ -1142,5 +1142,40 @@ var kimchi = { kimchi.message.error(data.responseJSON.reason); } }); + }, + + /** + * Add a volume to a given storage pool. + */ + uploadVolumeToSP: function(settings, suc, err) { + var fd = settings['formData']; + var sp = encodeURIComponent(settings['sp']); + kimchi.requestJSON({ + url : kimchi.url + 'storagepools/' + sp + '/storagevolumes', + type : 'POST', + data : fd, + processData : false, + contentType : false, + dataType: 'json', + success : suc, + error : err + }); + }, + + /** + * Add a volume to a given storage pool by URL. + */ + downloadVolumeToSP: function(settings, suc, err) { + var sp = encodeURIComponent(settings['sp']); + delete settings['sp']; + kimchi.requestJSON({ + url : kimchi.url + 'storagepools/' + sp + '/storagevolumes', + type : 'POST', + data : JSON.stringify(settings), + contentType : 'application/json', + dataType : 'json', + success : suc, + error : err + }); } }; -- 1.9.3

On 09/16/2014 05:28 AM, Aline Manera wrote:
From: Hongliang Wang <hlwang@linux.vnet.ibm.com>
Add API to handle downloand and upload features.
Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> Reviewed-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> --- ui/js/src/kimchi.api.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js index 681f573..3398bd4 100644 --- a/ui/js/src/kimchi.api.js +++ b/ui/js/src/kimchi.api.js @@ -1142,5 +1142,40 @@ var kimchi = { kimchi.message.error(data.responseJSON.reason); } }); + }, + + /** + * Add a volume to a given storage pool. + */ + uploadVolumeToSP: function(settings, suc, err) { + var fd = settings['formData']; + var sp = encodeURIComponent(settings['sp']); + kimchi.requestJSON({ + url : kimchi.url + 'storagepools/' + sp + '/storagevolumes', + type : 'POST', + data : fd, + processData : false, + contentType : false, + dataType: 'json', + success : suc, + error : err + }); + }, + + /** + * Add a volume to a given storage pool by URL. + */ + downloadVolumeToSP: function(settings, suc, err) { + var sp = encodeURIComponent(settings['sp']); + delete settings['sp']; + kimchi.requestJSON({ + url : kimchi.url + 'storagepools/' + sp + '/storagevolumes', + type : 'POST', + data : JSON.stringify(settings), + contentType : 'application/json', + dataType : 'json', + success : suc, + error : err + }); } };

From: Hongliang Wang <hlwang@linux.vnet.ibm.com> Add i18n strings for volume download/upload feature. Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- ui/pages/i18n.json.tmpl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/pages/i18n.json.tmpl b/ui/pages/i18n.json.tmpl index b552101..659bec8 100644 --- a/ui/pages/i18n.json.tmpl +++ b/ui/pages/i18n.json.tmpl @@ -169,6 +169,8 @@ "KCHPOOL6011M": "$_("No available partitions found.")", "KCHPOOL6012M": "$_("This storage pool is not persistent. Instead of deactivate, this action will permanently delete it. Would you like to continue?")", "KCHPOOL6013M": "$_("Unable to retrieve partitions information.")", + "KCHPOOL6014M": "$_("In progress...")", + "KCHPOOL6015M": "$_("Failed!")", "KCHVMSTOR0001E": "$_("CDROM path needs to be a valid local/remote path and cannot be blank.")", "KCHVMSTOR0002E": "$_("Disk pool or volume cannot be blank.")" -- 1.9.3

On 09/16/2014 05:28 AM, Aline Manera wrote:
From: Hongliang Wang <hlwang@linux.vnet.ibm.com>
Add i18n strings for volume download/upload feature.
Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> Reviewed-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> --- ui/pages/i18n.json.tmpl | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/ui/pages/i18n.json.tmpl b/ui/pages/i18n.json.tmpl index b552101..659bec8 100644 --- a/ui/pages/i18n.json.tmpl +++ b/ui/pages/i18n.json.tmpl @@ -169,6 +169,8 @@ "KCHPOOL6011M": "$_("No available partitions found.")", "KCHPOOL6012M": "$_("This storage pool is not persistent. Instead of deactivate, this action will permanently delete it. Would you like to continue?")", "KCHPOOL6013M": "$_("Unable to retrieve partitions information.")", + "KCHPOOL6014M": "$_("In progress...")", + "KCHPOOL6015M": "$_("Failed!")",
"KCHVMSTOR0001E": "$_("CDROM path needs to be a valid local/remote path and cannot be blank.")", "KCHVMSTOR0002E": "$_("Disk pool or volume cannot be blank.")"

From: Hongliang Wang <hlwang@linux.vnet.ibm.com> Implemented download and upload volumes functions. Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- ui/css/theme-default/storagepool-add-volume.css | 36 ++++++++ ui/js/src/kimchi.storagepool_add_volume_main.js | 107 ++++++++++++++++++++++++ ui/pages/storagepool-add-volume.html.tmpl | 80 ++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 ui/css/theme-default/storagepool-add-volume.css create mode 100644 ui/js/src/kimchi.storagepool_add_volume_main.js create mode 100644 ui/pages/storagepool-add-volume.html.tmpl diff --git a/ui/css/theme-default/storagepool-add-volume.css b/ui/css/theme-default/storagepool-add-volume.css new file mode 100644 index 0000000..6e8a551 --- /dev/null +++ b/ui/css/theme-default/storagepool-add-volume.css @@ -0,0 +1,36 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * 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. + */ +#sp-add-volume-window { + height: 400px; + width: 500px; +} + +#sp-add-volume-window .textbox-wrapper input[type="text"] { + box-sizing: border-box; + width: 100%; +} + +#sp-add-volume-window .textbox-wrapper label { + vertical-align: middle; +} + +#sp-add-volume-window input[type="text"][disabled] { + color: #bbb; + background-color: #fafafa; + cursor: not-allowed; +} diff --git a/ui/js/src/kimchi.storagepool_add_volume_main.js b/ui/js/src/kimchi.storagepool_add_volume_main.js new file mode 100644 index 0000000..590ccde --- /dev/null +++ b/ui/js/src/kimchi.storagepool_add_volume_main.js @@ -0,0 +1,107 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * 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_add_volume_main = function() { + // download from remote server or upload from local file + var type = 'download'; + + var addButton = $('#sp-add-volume-button'); + var remoteURLBox = $('#volume-remote-url'); + var localFileBox = $('#volume-input-file'); + var typeRadios = $('input.volume-type'); + + var isValidURL = function() { + var url = $(remoteURLBox).val(); + return kimchi.template_check_url(url); + }; + + var isValidFile = function() { + var fileName = $(localFileBox).val(); + return fileName.length > 0; + }; + + $(typeRadios).change(function(event) { + $('.volume-input').prop('disabled', true); + $('.volume-input.' + this.value).prop('disabled', false); + type = this.value; + if(type == 'download') { + $(addButton).prop('disabled', !isValidURL()); + } + else { + $(addButton).prop('disabled', !isValidFile()); + } + }); + + $(remoteURLBox).on('input propertychange', function(event) { + $(addButton).prop('disabled', !isValidURL()); + }); + + $(localFileBox).on('change', function(event) { + $(addButton).prop('disabled', !isValidFile()); + }); + + var onError = function(result) { + $(this).prop('disabled', false); + $(typeRadios).prop('disabled', false); + if(!result) { + return; + } + var msg = result['message'] || ( + result['responseJSON'] && result['responseJSON']['reason'] + ); + kimchi.message.error(msg); + }; + + var fetchRemoteFile = function() { + var volumeURL = remoteURLBox.val(); + var volumeName = volumeURL.split(/(\\|\/)/g).pop(); + kimchi.downloadVolumeToSP({ + sp: kimchi.selectedSP, + url: volumeURL + }, function(result) { + kimchi.window.close(); + kimchi.topic('kimchi/storageVolumeAdded').publish(); + }, onError); + }; + + var uploadFile = function() { + var blobFile = $(localFileBox)[0].files[0]; + var fileName = blobFile.name; + var fd = new FormData(); + fd.append('name', fileName); + fd.append('file', blobFile); + kimchi.uploadVolumeToSP({ + sp: kimchi.selectedSP, + formData: fd + }, function(result) { + kimchi.window.close(); + kimchi.topic('kimchi/storageVolumeAdded').publish(); + }, onError); + }; + + $(addButton).on('click', function(event) { + $(this).prop('disabled', true); + $(typeRadios).prop('disabled', true); + if(type === 'download') { + fetchRemoteFile(); + } + else { + uploadFile(); + } + event.preventDefault(); + }); +}; diff --git a/ui/pages/storagepool-add-volume.html.tmpl b/ui/pages/storagepool-add-volume.html.tmpl new file mode 100644 index 0000000..b01c942 --- /dev/null +++ b/ui/pages/storagepool-add-volume.html.tmpl @@ -0,0 +1,80 @@ +#* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * Authors: + * Hongliang Wang <hlwang@linux.vnet.ibm.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *# +#unicode UTF-8 +#import gettext +#from kimchi.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang) +#silent _ = t.gettext +#silent _t = t.gettext +<div id="sp-add-volume-window" class="window"> + <form id="form-sp-add-volume"> + <header class="window-header"> + <h1 class="title">$_("Add a Volume to Storage Pool")</h1> + <div class="close">X</div> + </header> + <section> + <div class="content"> + <div class="form-section"> + <h2> + <input type="radio" id="volume-type-download" class="volume-type" name="volumeType" value="download" checked="checked" /> + <label for="volume-type-download"> + $_("Fetch from remote URL") + </label> + </h2> + <div class="field"> + <p class="text-help"> + $_("Enter the remote URL here.") + </p> + <div class="textbox-wrapper"> + <input type="text" id="volume-remote-url" class="text volume-input download" name="volumeRemoteURL" /> + </div> + </div> + </div> + <div class="form-section"> + <h2> + <input type="radio" id="volume-type-upload" class="volume-type" name="volumeType" value="upload"/> + <label for="volume-type-upload"> + $_("Upload an file") + </label> + </h2> + <div class="field"> + <p class="text-help"> + $_("Choose the ISO file (with .iso suffix) you want to upload.") + </p> + <div class="textbox-wrapper"> + <input type="file" class="volume-input upload" id="volume-input-file" name="volumeLocalFile" disabled="disabled" /> + </div> + </div> + </div> + </div> + </section> + <footer> + <div class="btn-group"> + <button type="submit" id="sp-add-volume-button" class="btn-normal" disabled="disabled"> + <span class="text">$_("Add")</span> + </button> + </div> + </footer> + </form> +</div> +<script type="text/javascript"> + kimchi.sp_add_volume_main(); +</script> -- 1.9.3

On 09/16/2014 05:28 AM, Aline Manera wrote:
From: Hongliang Wang <hlwang@linux.vnet.ibm.com>
Implemented download and upload volumes functions.
Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com>
--- ui/css/theme-default/storagepool-add-volume.css | 36 ++++++++ ui/js/src/kimchi.storagepool_add_volume_main.js | 107 ++++++++++++++++++++++++ ui/pages/storagepool-add-volume.html.tmpl | 80 ++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 ui/css/theme-default/storagepool-add-volume.css create mode 100644 ui/js/src/kimchi.storagepool_add_volume_main.js create mode 100644 ui/pages/storagepool-add-volume.html.tmpl
diff --git a/ui/css/theme-default/storagepool-add-volume.css b/ui/css/theme-default/storagepool-add-volume.css new file mode 100644 index 0000000..6e8a551 --- /dev/null +++ b/ui/css/theme-default/storagepool-add-volume.css @@ -0,0 +1,36 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * 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. + */ +#sp-add-volume-window { + height: 400px; + width: 500px; +} + +#sp-add-volume-window .textbox-wrapper input[type="text"] { + box-sizing: border-box; + width: 100%; +} + +#sp-add-volume-window .textbox-wrapper label { + vertical-align: middle; +} + +#sp-add-volume-window input[type="text"][disabled] { + color: #bbb; + background-color: #fafafa; + cursor: not-allowed; +} diff --git a/ui/js/src/kimchi.storagepool_add_volume_main.js b/ui/js/src/kimchi.storagepool_add_volume_main.js new file mode 100644 index 0000000..590ccde --- /dev/null +++ b/ui/js/src/kimchi.storagepool_add_volume_main.js @@ -0,0 +1,107 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * 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_add_volume_main = function() { + // download from remote server or upload from local file + var type = 'download'; + + var addButton = $('#sp-add-volume-button'); + var remoteURLBox = $('#volume-remote-url'); + var localFileBox = $('#volume-input-file'); + var typeRadios = $('input.volume-type'); + + var isValidURL = function() { + var url = $(remoteURLBox).val(); + return kimchi.template_check_url(url); + }; + + var isValidFile = function() { + var fileName = $(localFileBox).val(); + return fileName.length > 0; + }; + + $(typeRadios).change(function(event) { + $('.volume-input').prop('disabled', true); + $('.volume-input.' + this.value).prop('disabled', false); + type = this.value; + if(type == 'download') { + $(addButton).prop('disabled', !isValidURL()); + } + else { + $(addButton).prop('disabled', !isValidFile()); + } + }); + + $(remoteURLBox).on('input propertychange', function(event) { + $(addButton).prop('disabled', !isValidURL()); + }); + + $(localFileBox).on('change', function(event) { + $(addButton).prop('disabled', !isValidFile()); + }); + + var onError = function(result) { + $(this).prop('disabled', false); + $(typeRadios).prop('disabled', false); + if(!result) { + return; + } + var msg = result['message'] || ( + result['responseJSON'] && result['responseJSON']['reason'] + ); + kimchi.message.error(msg); + }; + + var fetchRemoteFile = function() { + var volumeURL = remoteURLBox.val(); + var volumeName = volumeURL.split(/(\\|\/)/g).pop(); + kimchi.downloadVolumeToSP({ + sp: kimchi.selectedSP, + url: volumeURL + }, function(result) { + kimchi.window.close(); + kimchi.topic('kimchi/storageVolumeAdded').publish(); + }, onError); + }; + + var uploadFile = function() { + var blobFile = $(localFileBox)[0].files[0]; + var fileName = blobFile.name; + var fd = new FormData(); + fd.append('name', fileName); + fd.append('file', blobFile); + kimchi.uploadVolumeToSP({ + sp: kimchi.selectedSP, + formData: fd + }, function(result) { + kimchi.window.close(); + kimchi.topic('kimchi/storageVolumeAdded').publish(); + }, onError); + }; + + $(addButton).on('click', function(event) { + $(this).prop('disabled', true); + $(typeRadios).prop('disabled', true); + if(type === 'download') { + fetchRemoteFile(); + } + else { + uploadFile(); + } + event.preventDefault(); + }); +}; diff --git a/ui/pages/storagepool-add-volume.html.tmpl b/ui/pages/storagepool-add-volume.html.tmpl new file mode 100644 index 0000000..b01c942 --- /dev/null +++ b/ui/pages/storagepool-add-volume.html.tmpl @@ -0,0 +1,80 @@ +#* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * Authors: + * Hongliang Wang <hlwang@linux.vnet.ibm.com> Sorry I forgot to remove author line. + * + * 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 kimchi.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang) +#silent _ = t.gettext +#silent _t = t.gettext +<div id="sp-add-volume-window" class="window"> + <form id="form-sp-add-volume"> + <header class="window-header"> + <h1 class="title">$_("Add a Volume to Storage Pool")</h1> + <div class="close">X</div> + </header> + <section> + <div class="content"> + <div class="form-section"> + <h2> + <input type="radio" id="volume-type-download" class="volume-type" name="volumeType" value="download" checked="checked" /> + <label for="volume-type-download"> + $_("Fetch from remote URL") + </label> + </h2> + <div class="field"> + <p class="text-help"> + $_("Enter the remote URL here.") + </p> + <div class="textbox-wrapper"> + <input type="text" id="volume-remote-url" class="text volume-input download" name="volumeRemoteURL" /> + </div> + </div> + </div> + <div class="form-section"> + <h2> + <input type="radio" id="volume-type-upload" class="volume-type" name="volumeType" value="upload"/> + <label for="volume-type-upload"> + $_("Upload an file") + </label> + </h2> + <div class="field"> + <p class="text-help"> + $_("Choose the ISO file (with .iso suffix) you want to upload.") + </p> + <div class="textbox-wrapper"> + <input type="file" class="volume-input upload" id="volume-input-file" name="volumeLocalFile" disabled="disabled" /> + </div> + </div> + </div> + </div> + </section> + <footer> + <div class="btn-group"> + <button type="submit" id="sp-add-volume-button" class="btn-normal" disabled="disabled"> + <span class="text">$_("Add")</span> + </button> + </div> + </footer> + </form> +</div> +<script type="text/javascript"> + kimchi.sp_add_volume_main(); +</script>

On 09/16/2014 06:57 AM, Hongliang Wang wrote:
On 09/16/2014 05:28 AM, Aline Manera wrote:
From: Hongliang Wang <hlwang@linux.vnet.ibm.com>
Implemented download and upload volumes functions.
Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com>
--- ui/css/theme-default/storagepool-add-volume.css | 36 ++++++++ ui/js/src/kimchi.storagepool_add_volume_main.js | 107 ++++++++++++++++++++++++ ui/pages/storagepool-add-volume.html.tmpl | 80 ++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 ui/css/theme-default/storagepool-add-volume.css create mode 100644 ui/js/src/kimchi.storagepool_add_volume_main.js create mode 100644 ui/pages/storagepool-add-volume.html.tmpl
diff --git a/ui/css/theme-default/storagepool-add-volume.css b/ui/css/theme-default/storagepool-add-volume.css new file mode 100644 index 0000000..6e8a551 --- /dev/null +++ b/ui/css/theme-default/storagepool-add-volume.css @@ -0,0 +1,36 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * 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. + */ +#sp-add-volume-window { + height: 400px; + width: 500px; +} + +#sp-add-volume-window .textbox-wrapper input[type="text"] { + box-sizing: border-box; + width: 100%; +} + +#sp-add-volume-window .textbox-wrapper label { + vertical-align: middle; +} + +#sp-add-volume-window input[type="text"][disabled] { + color: #bbb; + background-color: #fafafa; + cursor: not-allowed; +} diff --git a/ui/js/src/kimchi.storagepool_add_volume_main.js b/ui/js/src/kimchi.storagepool_add_volume_main.js new file mode 100644 index 0000000..590ccde --- /dev/null +++ b/ui/js/src/kimchi.storagepool_add_volume_main.js @@ -0,0 +1,107 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * 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_add_volume_main = function() { + // download from remote server or upload from local file + var type = 'download'; + + var addButton = $('#sp-add-volume-button'); + var remoteURLBox = $('#volume-remote-url'); + var localFileBox = $('#volume-input-file'); + var typeRadios = $('input.volume-type'); + + var isValidURL = function() { + var url = $(remoteURLBox).val(); + return kimchi.template_check_url(url); + }; + + var isValidFile = function() { + var fileName = $(localFileBox).val(); + return fileName.length > 0; + }; + + $(typeRadios).change(function(event) { + $('.volume-input').prop('disabled', true); + $('.volume-input.' + this.value).prop('disabled', false); + type = this.value; + if(type == 'download') { + $(addButton).prop('disabled', !isValidURL()); + } + else { + $(addButton).prop('disabled', !isValidFile()); + } + }); + + $(remoteURLBox).on('input propertychange', function(event) { + $(addButton).prop('disabled', !isValidURL()); + }); + + $(localFileBox).on('change', function(event) { + $(addButton).prop('disabled', !isValidFile()); + }); + + var onError = function(result) { + $(this).prop('disabled', false); + $(typeRadios).prop('disabled', false); + if(!result) { + return; + } + var msg = result['message'] || ( + result['responseJSON'] && result['responseJSON']['reason'] + ); + kimchi.message.error(msg); + }; + + var fetchRemoteFile = function() { + var volumeURL = remoteURLBox.val(); + var volumeName = volumeURL.split(/(\\|\/)/g).pop(); + kimchi.downloadVolumeToSP({ + sp: kimchi.selectedSP, + url: volumeURL + }, function(result) { + kimchi.window.close(); + kimchi.topic('kimchi/storageVolumeAdded').publish(); + }, onError); + }; + + var uploadFile = function() { + var blobFile = $(localFileBox)[0].files[0]; + var fileName = blobFile.name; + var fd = new FormData(); + fd.append('name', fileName); + fd.append('file', blobFile); + kimchi.uploadVolumeToSP({ + sp: kimchi.selectedSP, + formData: fd + }, function(result) { + kimchi.window.close(); + kimchi.topic('kimchi/storageVolumeAdded').publish(); + }, onError); + }; + + $(addButton).on('click', function(event) { + $(this).prop('disabled', true); + $(typeRadios).prop('disabled', true); + if(type === 'download') { + fetchRemoteFile(); + } + else { + uploadFile(); + } + event.preventDefault(); + }); +}; diff --git a/ui/pages/storagepool-add-volume.html.tmpl b/ui/pages/storagepool-add-volume.html.tmpl new file mode 100644 index 0000000..b01c942 --- /dev/null +++ b/ui/pages/storagepool-add-volume.html.tmpl @@ -0,0 +1,80 @@ +#* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * Authors: + * Hongliang Wang <hlwang@linux.vnet.ibm.com> Sorry I forgot to remove author line.
No problem. I will remove it before applying.
+ * + * 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 kimchi.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang) +#silent _ = t.gettext +#silent _t = t.gettext +<div id="sp-add-volume-window" class="window"> + <form id="form-sp-add-volume"> + <header class="window-header"> + <h1 class="title">$_("Add a Volume to Storage Pool")</h1> + <div class="close">X</div> + </header> + <section> + <div class="content"> + <div class="form-section"> + <h2> + <input type="radio" id="volume-type-download" class="volume-type" name="volumeType" value="download" checked="checked" /> + <label for="volume-type-download"> + $_("Fetch from remote URL") + </label> + </h2> + <div class="field"> + <p class="text-help"> + $_("Enter the remote URL here.") + </p> + <div class="textbox-wrapper"> + <input type="text" id="volume-remote-url" class="text volume-input download" name="volumeRemoteURL" /> + </div> + </div> + </div> + <div class="form-section"> + <h2> + <input type="radio" id="volume-type-upload" class="volume-type" name="volumeType" value="upload"/> + <label for="volume-type-upload"> + $_("Upload an file") + </label> + </h2> + <div class="field"> + <p class="text-help"> + $_("Choose the ISO file (with .iso suffix) you want to upload.") + </p> + <div class="textbox-wrapper"> + <input type="file" class="volume-input upload" id="volume-input-file" name="volumeLocalFile" disabled="disabled" /> + </div> + </div> + </div> + </div> + </section> + <footer> + <div class="btn-group"> + <button type="submit" id="sp-add-volume-button" class="btn-normal" disabled="disabled"> + <span class="text">$_("Add")</span> + </button> + </div> + </footer> + </form> +</div> +<script type="text/javascript"> + kimchi.sp_add_volume_main(); +</script>

From: Hongliang Wang <hlwang@linux.vnet.ibm.com> Connect download/upload volume window with storage pool add button. Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- ui/css/theme-default/storage.css | 31 ++++++- ui/js/src/kimchi.storage_main.js | 196 ++++++++++++++++++++++++++++++++++----- ui/pages/tabs/storage.html.tmpl | 12 ++- 3 files changed, 213 insertions(+), 26 deletions(-) diff --git a/ui/css/theme-default/storage.css b/ui/css/theme-default/storage.css index f635c2f..e0ab290 100644 --- a/ui/css/theme-default/storage.css +++ b/ui/css/theme-default/storage.css @@ -336,7 +336,6 @@ float: left; padding: 4px; margin-bottom: 5px; - height: 40px; width: 130px; } @@ -622,3 +621,33 @@ #iSCSITarget input { width: 493px; } + +/* Progress bar */ +.volume-progress { + clear: both; + width: 140px; +} + +.volume-progress .progress-bar-outer { + background: #ccc; + height: 4px; + overflow: hidden; + width: 100%; +} + +.volume-progress .progress-bar-inner { + background: #090; + height: 100%; + width: 0%; +} + +.volume-progress .progress-label { + color: #999; + font-size: 10px; + line-height: 16px; +} + +.volume-progress .progress-transferred { + float: right; +} +/* End of Progress bar */ diff --git a/ui/js/src/kimchi.storage_main.js b/ui/js/src/kimchi.storage_main.js index ae3f963..28b2b58 100644 --- a/ui/js/src/kimchi.storage_main.js +++ b/ui/js/src/kimchi.storage_main.js @@ -42,7 +42,6 @@ kimchi.doListStoragePools = function() { }, function(err) { kimchi.message.error(err.responseJSON.reason); }); - } kimchi.storageBindClick = function() { @@ -79,6 +78,19 @@ kimchi.storageBindClick = function() { } }); + $('.pool-add-volume').each(function(index) { + var canAddVolume = + $(this).data('stat') === 'active' && + $(this).data('type') !== 'iscsi' && + $(this).data('type') !== 'scsi'; + if(canAddVolume) { + $(this).show(); + } + else { + $(this).hide(); + } + }); + if(kimchi.tabMode['storage'] === 'admin') { $('.pool-delete').on('click', function(event) { var $pool = $(this); @@ -135,6 +147,12 @@ kimchi.storageBindClick = function() { } }); + $('.pool-add-volume').on('click', function(event) { + var poolName = $(this).data('name'); + kimchi.selectedSP = poolName; + kimchi.window.open('storagepool-add-volume.html'); + }); + $('.storage-action').on('click', function() { var storage_action = $(this); var deleteButton = storage_action.find('.pool-delete'); @@ -149,10 +167,6 @@ kimchi.storageBindClick = function() { $("#logicalPoolExtend").dialog("option", "poolName", $(this).data('name')); $("#logicalPoolExtend").dialog("open"); }); - - $('#volume-doAdd').on('click', function() { - kimchi.window.open('storagevolume-add.html'); - }); } $('.storage-li').on('click', function(event) { @@ -173,29 +187,90 @@ kimchi.storageBindClick = function() { }); } +kimchi._generateVolumeHTML = function(volume) { + if(volume['type'] === 'kimchi-iso') { + return ''; + } + var volumeHtml = $('#volumeTmpl').html(); + volume.capacity = kimchi.changetoProperUnit(volume.capacity,1); + volume.allocation = kimchi.changetoProperUnit(volume.allocation,1); + return kimchi.substitute(volumeHtml, volume); +}; + kimchi.doListVolumes = function(poolObj) { - var volumeDiv = $('#volume' + poolObj.data('name')); + var poolName = poolObj.data('name') + + var getOngoingVolumes = function() { + var result = {} + var filter = 'status=running&target_uri=' + encodeURIComponent('^/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(kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) { + continue; + } + + kimchi.trackTask(tasks[i].id, function(result) { + kimchi.topic('kimchi/volumeTransferFinished').publish(result); + }, function(result) { + kimchi.topic('kimchi/volumeTransferError').publish(result); + }, function(result) { + kimchi.topic('kimchi/volumeTransferProgress').publish(result); + }); + } + }, null, true); + return result; + }; + + var volumeDiv = $('#volume' + poolName); + $(volumeDiv).empty(); var slide = poolObj.next('.volumes'); var handleArrow = poolObj.children().last().children(); - kimchi.listStorageVolumes(poolObj.data('name'), function(result) { - var volumeHtml = $('#volumeTmpl').html(); - if (result) { - if (result.length) { - var listHtml = ''; - $.each(result, function(index, value) { - value.poolname = poolObj.data('name'); - value.capacity = kimchi.changetoProperUnit(value.capacity,1); - value.allocation = kimchi.changetoProperUnit(value.allocation,1); - listHtml += kimchi.substitute(volumeHtml, value); - }); - volumeDiv.html(listHtml); - } else { - volumeDiv.html("<div class='pool-empty'>" + i18n['KCHPOOL6002M'] + "</div>"); + + kimchi.listStorageVolumes(poolName, function(result) { + var listHtml = ''; + var ongoingVolumes = []; + var ongoingVolumesMap = getOngoingVolumes(); + $.each(ongoingVolumesMap, function(volumeName, task) { + ongoingVolumes.push(volumeName) + var volume = { + poolName: poolName, + ref_cnt: 0, + capacity: 0, + name: volumeName, + format: '', + bootable: null, + os_distro: '', + allocation: 0, + os_version: '', + path: '', + type: 'file' + }; + listHtml += kimchi._generateVolumeHTML(volume); + }); + + $.each(result, function(index, value) { + if (ongoingVolumes.indexOf(value.name) == -1) { + value.poolname = poolName; + listHtml += kimchi._generateVolumeHTML(value); } - poolObj.removeClass('in'); - kimchi.changeArrow(handleArrow); - slide.slideDown('slow'); + }); + + if (listHtml.length > 0) { + volumeDiv.html(listHtml); + } else { + volumeDiv.html("<div class='pool-empty'>" + i18n['KCHPOOL6002M'] + "</div>"); } + + $.each(ongoingVolumesMap, function(volumeName, task) { + kimchi.topic('kimchi/volumeTransferProgress').publish(task); + }); + + poolObj.removeClass('in'); + kimchi.changeArrow(handleArrow); + slide.slideDown('slow'); }, function(err) { kimchi.message.error(err.responseJSON.reason); }); @@ -255,7 +330,80 @@ kimchi.storage_main = function() { } kimchi.doListStoragePools(); kimchi.initLogicalPoolExtend(); -} + + kimchi.topic('kimchi/storageVolumeAdded').subscribe(function() { + pool = kimchi.selectedSP; + var poolNode = $('.storage-li[data-name="' + pool + '"]'); + kimchi.doListVolumes(poolNode); + }); + + kimchi.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 percent = 0; + if(downloaded) { + var total = sizeArray[2]; + if(!isNaN(total)) { + percent = downloaded / total * 100; + } + } + var formatted = kimchi.formatMeasurement(downloaded); + var size = (1.0 * formatted['v']).toFixed(1) + formatted['s']; + return { + size: size, + percent: percent + }; + }; + + var uriElements = result.target_uri.split('/'); + var poolName = uriElements[2]; + var volumeName = uriElements.pop(); + 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); + $('.volume-progress', volumeBox).removeClass('hidden'); + $('.progress-status', volumeBox).text(i18n['KCHPOOL6014M']); + }); + + kimchi.topic('kimchi/volumeTransferFinished').subscribe(function(result) { + var uriElements = result.target_uri.split('/'); + var poolName = uriElements[2]; + var volumeName = uriElements.pop(); + var volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]'); + $('.volume-progress', volumeBox).addClass('hidden'); + kimchi.getStoragePoolVolume(poolName, volumeName, function(volume) { + var html = kimchi._generateVolumeHTML(volume); + $(volumeBox).replaceWith(html); + }, function(err) { + kimchi.message.error(err.responseJSON.reason); + }); + }); + + kimchi.topic('kimchi/volumeTransferError').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 && kimchi.message.error(errText); + + var uriElements = result.target_uri.split('/'); + var poolName = uriElements[2]; + var volumeName = uriElements.pop(); + volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]'); + $('.progress-status', volumeBox).text(i18n['KCHPOOL6015M']); + }); +}; kimchi.changeArrow = function(obj) { if ($(obj).hasClass('arrow-down')) { diff --git a/ui/pages/tabs/storage.html.tmpl b/ui/pages/tabs/storage.html.tmpl index 87205bd..523f480 100644 --- a/ui/pages/tabs/storage.html.tmpl +++ b/ui/pages/tabs/storage.html.tmpl @@ -82,6 +82,7 @@ <div class="popover actionsheet right-side" style="width: 250px"> <button class="button-big pool-deactivate" data-stat="{state}" data-name="{name}" data-persistent="{persistent}"><span class="text">$_("Deactivate")</span></button> <button class="button-big pool-activate" data-stat="{state}" data-name="{name}"><span class="text">$_("Activate")</span></button> + <button class="button-big pool-add-volume" data-stat="{state}" data-name="{name}" data-type="{type}"><span class="text">$_("Add Volume")</span></button> <button class="button-big pool-extend {enableExt}" data-stat="{state}" data-name="{name}"><span class="text">$_("Extend")</span></button> <button class="button-big red pool-delete" data-stat="{state}" data-name="{name}"><span class="text">$_("Undefine")</span></button> </div> @@ -98,11 +99,20 @@ </li> </script> <script id="volumeTmpl" type="html/text"> - <div class="volume-box white-box"> + <div class="volume-box white-box" data-volume-name="{name}"> <div class="storage-icon volume-default icon-{format} "> </div> <div class="volume-title"> <div class="volume-name" title="{name}">{name}</div> + <div class="volume-progress hidden"> + <div class="progress-bar-outer"> + <div class="progress-bar-inner"></div> + </div> + <div class="progress-label"> + <span class="progress-status"></span> + <span class="progress-transferred"></span> + </div> + </div> </div> <div class="volume-setting"> </div> -- 1.9.3

On 09/16/2014 05:28 AM, Aline Manera wrote:
From: Hongliang Wang <hlwang@linux.vnet.ibm.com>
Connect download/upload volume window with storage pool add button.
Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> Reviewed-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> --- ui/css/theme-default/storage.css | 31 ++++++- ui/js/src/kimchi.storage_main.js | 196 ++++++++++++++++++++++++++++++++++----- ui/pages/tabs/storage.html.tmpl | 12 ++- 3 files changed, 213 insertions(+), 26 deletions(-)
diff --git a/ui/css/theme-default/storage.css b/ui/css/theme-default/storage.css index f635c2f..e0ab290 100644 --- a/ui/css/theme-default/storage.css +++ b/ui/css/theme-default/storage.css @@ -336,7 +336,6 @@ float: left; padding: 4px; margin-bottom: 5px; - height: 40px; width: 130px; }
@@ -622,3 +621,33 @@ #iSCSITarget input { width: 493px; } + +/* Progress bar */ +.volume-progress { + clear: both; + width: 140px; +} + +.volume-progress .progress-bar-outer { + background: #ccc; + height: 4px; + overflow: hidden; + width: 100%; +} + +.volume-progress .progress-bar-inner { + background: #090; + height: 100%; + width: 0%; +} + +.volume-progress .progress-label { + color: #999; + font-size: 10px; + line-height: 16px; +} + +.volume-progress .progress-transferred { + float: right; +} +/* End of Progress bar */ diff --git a/ui/js/src/kimchi.storage_main.js b/ui/js/src/kimchi.storage_main.js index ae3f963..28b2b58 100644 --- a/ui/js/src/kimchi.storage_main.js +++ b/ui/js/src/kimchi.storage_main.js @@ -42,7 +42,6 @@ kimchi.doListStoragePools = function() { }, function(err) { kimchi.message.error(err.responseJSON.reason); }); - }
kimchi.storageBindClick = function() { @@ -79,6 +78,19 @@ kimchi.storageBindClick = function() { } });
+ $('.pool-add-volume').each(function(index) { + var canAddVolume = + $(this).data('stat') === 'active' && + $(this).data('type') !== 'iscsi' && + $(this).data('type') !== 'scsi'; + if(canAddVolume) { + $(this).show(); + } + else { + $(this).hide(); + } + }); + if(kimchi.tabMode['storage'] === 'admin') { $('.pool-delete').on('click', function(event) { var $pool = $(this); @@ -135,6 +147,12 @@ kimchi.storageBindClick = function() { } });
+ $('.pool-add-volume').on('click', function(event) { + var poolName = $(this).data('name'); + kimchi.selectedSP = poolName; + kimchi.window.open('storagepool-add-volume.html'); + }); + $('.storage-action').on('click', function() { var storage_action = $(this); var deleteButton = storage_action.find('.pool-delete'); @@ -149,10 +167,6 @@ kimchi.storageBindClick = function() { $("#logicalPoolExtend").dialog("option", "poolName", $(this).data('name')); $("#logicalPoolExtend").dialog("open"); }); - - $('#volume-doAdd').on('click', function() { - kimchi.window.open('storagevolume-add.html'); - }); }
$('.storage-li').on('click', function(event) { @@ -173,29 +187,90 @@ kimchi.storageBindClick = function() { }); }
+kimchi._generateVolumeHTML = function(volume) { + if(volume['type'] === 'kimchi-iso') { + return ''; + } + var volumeHtml = $('#volumeTmpl').html(); + volume.capacity = kimchi.changetoProperUnit(volume.capacity,1); + volume.allocation = kimchi.changetoProperUnit(volume.allocation,1); + return kimchi.substitute(volumeHtml, volume); +}; + kimchi.doListVolumes = function(poolObj) { - var volumeDiv = $('#volume' + poolObj.data('name')); + var poolName = poolObj.data('name') + + var getOngoingVolumes = function() { + var result = {} + var filter = 'status=running&target_uri=' + encodeURIComponent('^/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(kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) { + continue; + } + + kimchi.trackTask(tasks[i].id, function(result) { + kimchi.topic('kimchi/volumeTransferFinished').publish(result); + }, function(result) { + kimchi.topic('kimchi/volumeTransferError').publish(result); + }, function(result) { + kimchi.topic('kimchi/volumeTransferProgress').publish(result); + }); + } + }, null, true); + return result; + }; + + var volumeDiv = $('#volume' + poolName); + $(volumeDiv).empty(); var slide = poolObj.next('.volumes'); var handleArrow = poolObj.children().last().children(); - kimchi.listStorageVolumes(poolObj.data('name'), function(result) { - var volumeHtml = $('#volumeTmpl').html(); - if (result) { - if (result.length) { - var listHtml = ''; - $.each(result, function(index, value) { - value.poolname = poolObj.data('name'); - value.capacity = kimchi.changetoProperUnit(value.capacity,1); - value.allocation = kimchi.changetoProperUnit(value.allocation,1); - listHtml += kimchi.substitute(volumeHtml, value); - }); - volumeDiv.html(listHtml); - } else { - volumeDiv.html("<div class='pool-empty'>" + i18n['KCHPOOL6002M'] + "</div>"); + + kimchi.listStorageVolumes(poolName, function(result) { + var listHtml = ''; + var ongoingVolumes = []; + var ongoingVolumesMap = getOngoingVolumes(); + $.each(ongoingVolumesMap, function(volumeName, task) { + ongoingVolumes.push(volumeName) + var volume = { + poolName: poolName, + ref_cnt: 0, + capacity: 0, + name: volumeName, + format: '', + bootable: null, + os_distro: '', + allocation: 0, + os_version: '', + path: '', + type: 'file' + }; + listHtml += kimchi._generateVolumeHTML(volume); + }); + + $.each(result, function(index, value) { + if (ongoingVolumes.indexOf(value.name) == -1) { + value.poolname = poolName; + listHtml += kimchi._generateVolumeHTML(value); } - poolObj.removeClass('in'); - kimchi.changeArrow(handleArrow); - slide.slideDown('slow'); + }); + + if (listHtml.length > 0) { + volumeDiv.html(listHtml); + } else { + volumeDiv.html("<div class='pool-empty'>" + i18n['KCHPOOL6002M'] + "</div>"); } + + $.each(ongoingVolumesMap, function(volumeName, task) { + kimchi.topic('kimchi/volumeTransferProgress').publish(task); + }); + + poolObj.removeClass('in'); + kimchi.changeArrow(handleArrow); + slide.slideDown('slow'); }, function(err) { kimchi.message.error(err.responseJSON.reason); }); @@ -255,7 +330,80 @@ kimchi.storage_main = function() { } kimchi.doListStoragePools(); kimchi.initLogicalPoolExtend(); -} + + kimchi.topic('kimchi/storageVolumeAdded').subscribe(function() { + pool = kimchi.selectedSP; + var poolNode = $('.storage-li[data-name="' + pool + '"]'); + kimchi.doListVolumes(poolNode); + }); + + kimchi.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 percent = 0; + if(downloaded) { + var total = sizeArray[2]; + if(!isNaN(total)) { + percent = downloaded / total * 100; + } + } + var formatted = kimchi.formatMeasurement(downloaded); + var size = (1.0 * formatted['v']).toFixed(1) + formatted['s']; + return { + size: size, + percent: percent + }; + }; + + var uriElements = result.target_uri.split('/'); + var poolName = uriElements[2]; + var volumeName = uriElements.pop(); + 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); + $('.volume-progress', volumeBox).removeClass('hidden'); + $('.progress-status', volumeBox).text(i18n['KCHPOOL6014M']); + }); + + kimchi.topic('kimchi/volumeTransferFinished').subscribe(function(result) { + var uriElements = result.target_uri.split('/'); + var poolName = uriElements[2]; + var volumeName = uriElements.pop(); + var volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]'); + $('.volume-progress', volumeBox).addClass('hidden'); + kimchi.getStoragePoolVolume(poolName, volumeName, function(volume) { + var html = kimchi._generateVolumeHTML(volume); + $(volumeBox).replaceWith(html); + }, function(err) { + kimchi.message.error(err.responseJSON.reason); + }); + }); + + kimchi.topic('kimchi/volumeTransferError').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 && kimchi.message.error(errText); + + var uriElements = result.target_uri.split('/'); + var poolName = uriElements[2]; + var volumeName = uriElements.pop(); + volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]'); + $('.progress-status', volumeBox).text(i18n['KCHPOOL6015M']); + }); +};
kimchi.changeArrow = function(obj) { if ($(obj).hasClass('arrow-down')) { diff --git a/ui/pages/tabs/storage.html.tmpl b/ui/pages/tabs/storage.html.tmpl index 87205bd..523f480 100644 --- a/ui/pages/tabs/storage.html.tmpl +++ b/ui/pages/tabs/storage.html.tmpl @@ -82,6 +82,7 @@ <div class="popover actionsheet right-side" style="width: 250px"> <button class="button-big pool-deactivate" data-stat="{state}" data-name="{name}" data-persistent="{persistent}"><span class="text">$_("Deactivate")</span></button> <button class="button-big pool-activate" data-stat="{state}" data-name="{name}"><span class="text">$_("Activate")</span></button> + <button class="button-big pool-add-volume" data-stat="{state}" data-name="{name}" data-type="{type}"><span class="text">$_("Add Volume")</span></button> <button class="button-big pool-extend {enableExt}" data-stat="{state}" data-name="{name}"><span class="text">$_("Extend")</span></button> <button class="button-big red pool-delete" data-stat="{state}" data-name="{name}"><span class="text">$_("Undefine")</span></button> </div> @@ -98,11 +99,20 @@ </li> </script> <script id="volumeTmpl" type="html/text"> - <div class="volume-box white-box"> + <div class="volume-box white-box" data-volume-name="{name}"> <div class="storage-icon volume-default icon-{format} "> </div> <div class="volume-title"> <div class="volume-name" title="{name}">{name}</div> + <div class="volume-progress hidden"> + <div class="progress-bar-outer"> + <div class="progress-bar-inner"></div> + </div> + <div class="progress-label"> + <span class="progress-status"></span> + <span class="progress-transferred"></span> + </div> + </div> </div> <div class="volume-setting"> </div>

Upload feature has some issues. Disable it until we get them fixed. Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- ui/pages/storagepool-add-volume.html.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/pages/storagepool-add-volume.html.tmpl b/ui/pages/storagepool-add-volume.html.tmpl index b01c942..dad689c 100644 --- a/ui/pages/storagepool-add-volume.html.tmpl +++ b/ui/pages/storagepool-add-volume.html.tmpl @@ -50,7 +50,7 @@ </div> <div class="form-section"> <h2> - <input type="radio" id="volume-type-upload" class="volume-type" name="volumeType" value="upload"/> + <input type="radio" id="volume-type-upload" class="volume-type" name="volumeType" value="upload" disabled/> <label for="volume-type-upload"> $_("Upload an file") </label> -- 1.9.3

On 09/16/2014 05:28 AM, Aline Manera wrote:
Upload feature has some issues. Disable it until we get them fixed.
Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> Reviewed-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> --- ui/pages/storagepool-add-volume.html.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ui/pages/storagepool-add-volume.html.tmpl b/ui/pages/storagepool-add-volume.html.tmpl index b01c942..dad689c 100644 --- a/ui/pages/storagepool-add-volume.html.tmpl +++ b/ui/pages/storagepool-add-volume.html.tmpl @@ -50,7 +50,7 @@ </div> <div class="form-section"> <h2> - <input type="radio" id="volume-type-upload" class="volume-type" name="volumeType" value="upload"/> + <input type="radio" id="volume-type-upload" class="volume-type" name="volumeType" value="upload" disabled/> <label for="volume-type-upload"> $_("Upload an file") </label>
participants (2)
-
Aline Manera
-
Hongliang Wang