[PATCH v3 0/5] [UI] CDROM Management in a VM

Allow user to manipulate CDROM(s) in a VM: 1) Attach one or more CDROM(s); 2) Replace a CDROM with another ISO file path; 3) Detach a CDROM from a VM. Tested on Chrome. Please apply the following patch first: * [UI] Window - Correct Footer Height v2 -> v3: 3a) Keep the edit window silver instead of white (Aline's comment) 3b) Added information after CDROM manipulations to avoid confusion (Aline & Adam King's comment) v1 -> v2: 2a) Separate one patch into 4 small ones to make it easier to review (Thanks to Ramon Medeiros's comment) 2b) Updated API calling to list CDROM (Thanks to Aline's comment) 2c) Separated VM updating window into 2 parts: general and storage (Thanks to Aline's comment) 2d) Enhanced UI to allow user trigger replace CDROM window by clicking ISO file path text box 2e) Changed uneditable fields from readonly to disabled 2f) Removed authors infomation (Thanks to Aline's comment) Hongliang Wang (5): [UI] kimchi.message - Enhancement [UI] Add CDROM-related APIs [UI] Add i18n Variables for CDROM-related Function [UI] Add/Edit CDROM Support [UI] Attach/Replace/Detach a CDROM to/in/from a VM ui/css/theme-default/guest-cdrom-add.css | 62 +++++++++++ ui/css/theme-default/guest-cdrom-edit.css | 62 +++++++++++ ui/css/theme-default/guest-edit.css | 133 +++++++++++++++++++--- ui/images/theme-default/guest-icon-sprite.png | Bin 0 -> 6748 bytes ui/js/src/kimchi.api.js | 74 +++++++++++++ ui/js/src/kimchi.guest_cdrom_add_main.js | 79 +++++++++++++ ui/js/src/kimchi.guest_cdrom_edit_main.js | 88 +++++++++++++++ ui/js/src/kimchi.guest_edit_main.js | 86 +++++++++++++- ui/js/src/kimchi.message.js | 27 +++-- ui/pages/guest-cdrom-add.html.tmpl | 73 ++++++++++++ ui/pages/guest-cdrom-edit.html.tmpl | 73 ++++++++++++ ui/pages/guest-edit.html.tmpl | 154 +++++++++++++++++--------- ui/pages/i18n.html.tmpl | 11 ++ 13 files changed, 837 insertions(+), 85 deletions(-) create mode 100644 ui/css/theme-default/guest-cdrom-add.css create mode 100644 ui/css/theme-default/guest-cdrom-edit.css create mode 100644 ui/images/theme-default/guest-icon-sprite.png create mode 100644 ui/js/src/kimchi.guest_cdrom_add_main.js create mode 100644 ui/js/src/kimchi.guest_cdrom_edit_main.js create mode 100644 ui/pages/guest-cdrom-add.html.tmpl create mode 100644 ui/pages/guest-cdrom-edit.html.tmpl -- 1.8.1.4

Sometimes we want to show the message at a specific position, other than at the top of the browser. In this patch, we introduced a new parameter to the function with which we can place the message wherever we want. Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> --- ui/js/src/kimchi.message.js | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/ui/js/src/kimchi.message.js b/ui/js/src/kimchi.message.js index f997a73..35e3db9 100644 --- a/ui/js/src/kimchi.message.js +++ b/ui/js/src/kimchi.message.js @@ -15,16 +15,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -kimchi.message = function(msg, level) { - if ($('#messageField').size() < 1) { - $(document.body).append('<div id="messageField"></div>'); +kimchi.message = function(msg, level, node) { + var container = node || $('#messageField'); + if ($(container).size() < 1) { + container = $('<div id="messageField"/>').appendTo(document.body); } var message = '<div class="message ' + (level || '') + '" style="display: none;">'; - message += '<div class="close">X</div>'; + if(!node) { + message += '<div class="close">X</div>'; + } message += '<div class="content">' + msg + '</div>'; message += '</div>'; var $message = $(message); - $('#messageField').append($message); + $(container).append($message); $message.fadeIn(100); setTimeout(function() { @@ -33,7 +36,7 @@ kimchi.message = function(msg, level) { }); }, 4000); - $('#messageField').on("click", ".close", function(e) { + $(container).on("click", ".close", function(e) { $(this).parent().fadeOut(200, function() { $(this).remove(); }); @@ -98,16 +101,16 @@ kimchi.confirm = function(settings, confirmCallback, cancelCallback) { }); }; -kimchi.message.warn = function(msg) { - kimchi.message(msg, 'warn'); +kimchi.message.warn = function(msg, node) { + kimchi.message(msg, 'warn', node); }; -kimchi.message.error = function(msg) { - kimchi.message(msg, 'error'); +kimchi.message.error = function(msg, node) { + kimchi.message(msg, 'error', node); }; kimchi.message.error.code = function(code) { msg = code + ": " + i18n[code] kimchi.message(msg, 'error'); }; -kimchi.message.success = function(msg) { - kimchi.message(msg, 'success'); +kimchi.message.success = function(msg, node) { + kimchi.message(msg, 'success', node); }; -- 1.8.1.4

Add APIs for attaching CDROM to VM in kimchi.api.js. Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> --- ui/js/src/kimchi.api.js | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js index fdd9cfc..691b2a1 100644 --- a/ui/js/src/kimchi.api.js +++ b/ui/js/src/kimchi.api.js @@ -727,5 +727,79 @@ var kimchi = { success : suc, error : err }); + }, + + addVMStorage : function(settings, suc, err) { + var vm = encodeURIComponent(settings['vm']); + delete settings['vm']; + kimchi.requestJSON({ + url : kimchi.url + 'vms/' + vm + '/storages', + type : 'POST', + contentType : 'application/json', + data : JSON.stringify(settings), + dataType : 'json', + success : suc, + error : err + }); + }, + + retrieveVMStorage : function(settings, suc, err) { + var vm = encodeURIComponent(settings['vm']); + var dev = encodeURIComponent(settings['dev']); + kimchi.requestJSON({ + url : kimchi.url + "vms/" + vm + '/storages/' + dev, + type : 'GET', + contentType : 'application/json', + dataType : 'json', + success: suc, + error: err + }); + }, + + replaceVMStorage : function(settings, suc, err) { + var vm = encodeURIComponent(settings['vm']); + var dev = encodeURIComponent(settings['dev']); + kimchi.requestJSON({ + url : kimchi.url + 'vms/' + vm + '/storages/' + dev, + type : 'PUT', + contentType : 'application/json', + data : JSON.stringify({ + path: settings['path'] + }), + dataType : 'json', + success : suc, + error : err + }); + }, + + deleteVMStorage : function(settings, suc, err) { + var vm = settings['vm']; + var dev = settings['dev']; + kimchi.requestJSON({ + url : kimchi.url + 'vms/' + encodeURIComponent(vm) + + '/storages/' + encodeURIComponent(dev), + type : 'DELETE', + contentType : 'application/json', + dataType : 'json', + success : suc, + error : err + }); + }, + + listVMStorages : function(params, suc, err) { + var vm = encodeURIComponent(params['vm']); + var type = params['storageType']; + var url = kimchi.url + 'vms/' + vm + '/storages'; + if(type) { + url += '?type=' + type; + } + kimchi.requestJSON({ + url : url, + type : 'GET', + contentType : 'application/json', + dataType : 'json', + success : suc, + error : err + }); } }; -- 1.8.1.4

Add i18n strings in i18n.html.tmpl. Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> --- ui/pages/i18n.html.tmpl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ui/pages/i18n.html.tmpl b/ui/pages/i18n.html.tmpl index a7dddf4..b671af3 100644 --- a/ui/pages/i18n.html.tmpl +++ b/ui/pages/i18n.html.tmpl @@ -91,6 +91,17 @@ var i18n = { 'KCHVM6001M': "$_("This will delete the virtual machine and its virtual disks. This operation cannot be undone. Would you like to continue?")", + + 'KCHVMCD6001M': "$_("This CDROM will be detached permanently and you can re-attach it. Continue to detach it?")", + 'KCHVMCD6002M': "$_("Attach")", + 'KCHVMCD6003M': "$_("Attaching...")", + 'KCHVMCD6004M': "$_("Replace")", + 'KCHVMCD6005M': "$_("Replacing...")", + 'KCHVMCD6006M': "$_("Successfully attached!")", + 'KCHVMCD6007M': "$_("Successfully replaced!")", + 'KCHVMCD6008M': "$_("Successfully detached!")", + + 'KCHNET6001E': "$_("The VLAN id must be between 1 and 4094.")", 'KCHNET6001M': "$_("unavailable")", -- 1.8.1.4

In this patch, we introduced 2 features: 1) Add CDROM to VM 2) Edit CDROM in VM Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> --- ui/css/theme-default/guest-cdrom-add.css | 62 ++++++++++++++++++++++ ui/css/theme-default/guest-cdrom-edit.css | 62 ++++++++++++++++++++++ ui/js/src/kimchi.guest_cdrom_add_main.js | 79 +++++++++++++++++++++++++++ ui/js/src/kimchi.guest_cdrom_edit_main.js | 88 +++++++++++++++++++++++++++++++ ui/pages/guest-cdrom-add.html.tmpl | 73 +++++++++++++++++++++++++ ui/pages/guest-cdrom-edit.html.tmpl | 73 +++++++++++++++++++++++++ 6 files changed, 437 insertions(+) create mode 100644 ui/css/theme-default/guest-cdrom-add.css create mode 100644 ui/css/theme-default/guest-cdrom-edit.css create mode 100644 ui/js/src/kimchi.guest_cdrom_add_main.js create mode 100644 ui/js/src/kimchi.guest_cdrom_edit_main.js create mode 100644 ui/pages/guest-cdrom-add.html.tmpl create mode 100644 ui/pages/guest-cdrom-edit.html.tmpl diff --git a/ui/css/theme-default/guest-cdrom-add.css b/ui/css/theme-default/guest-cdrom-add.css new file mode 100644 index 0000000..656e328 --- /dev/null +++ b/ui/css/theme-default/guest-cdrom-add.css @@ -0,0 +1,62 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013 + * + * 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. + */ +#guest-cdrom-add-window { + font-size: 13px; + height: 600px; + width: 700px; +} + +.guest-cdrom-add-fieldset { + padding: 1em; +} + +#guest-cdrom-add-window input[type="text"] { + font-size: 16px; + height: 38px; + background: #fff; + -webkit-border-radius: 5px; + border-radius: 5px; + box-shadow: 2px 2px 2px #eee inset; + border-top: 1px solid #bbb; + border-left: 1px solid #bbb; + padding-left: 10px; + width: 600px; +} + +#guest-cdrom-add-window input[type="text"][disabled] { + color: #bbb; + background-color: #fafafa; + cursor: not-allowed; +} + +#cdrom-error-message { + color: red; + padding: 5px; +} + +#vm-cdrom-button-add[disabled] { + background: #c0c0c0; + color: #ddd; + padding-left: 26px; +} + +#vm-cdrom-button-add.loading[disabled] { + background: url("../../images/theme-default/loading.gif") 7px center no-repeat #c0c0c0; + color: #ddd; + padding-left: 26px; +} diff --git a/ui/css/theme-default/guest-cdrom-edit.css b/ui/css/theme-default/guest-cdrom-edit.css new file mode 100644 index 0000000..7008d73 --- /dev/null +++ b/ui/css/theme-default/guest-cdrom-edit.css @@ -0,0 +1,62 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013 + * + * 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. + */ +#guest-cdrom-edit-window { + font-size: 13px; + height: 600px; + width: 700px; +} + +.guest-cdrom-edit-fieldset { + padding: 1em; +} + +#guest-cdrom-edit-window input[type="text"] { + font-size: 16px; + height: 38px; + background: #fff; + -webkit-border-radius: 5px; + border-radius: 5px; + box-shadow: 2px 2px 2px #eee inset; + border-top: 1px solid #bbb; + border-left: 1px solid #bbb; + padding-left: 10px; + width: 600px; +} + +#guest-cdrom-edit-window input[type="text"][disabled] { + color: #bbb; + background-color: #fafafa; + cursor: not-allowed; +} + +#cdrom-error-message { + color: red; + padding: 5px; +} + +#vm-cdrom-button-edit[disabled] { + background: #c0c0c0; + color: #ddd; + padding-left: 26px; +} + +#vm-cdrom-button-edit.loading[disabled] { + background: url("../../images/theme-default/loading.gif") 7px center no-repeat #c0c0c0; + color: #ddd; + padding-left: 26px; +} diff --git a/ui/js/src/kimchi.guest_cdrom_add_main.js b/ui/js/src/kimchi.guest_cdrom_add_main.js new file mode 100644 index 0000000..464c8bf --- /dev/null +++ b/ui/js/src/kimchi.guest_cdrom_add_main.js @@ -0,0 +1,79 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013 + * + * 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.guest_cdrom_add_main = function() { + var cdromAddForm = $('#form-vm-cdrom-add'); + var submitButton = $('#vm-cdrom-button-add'); + var nameTextbox = $('input[name="dev"]', cdromAddForm); + var typeTextbox = $('input[name="type"]', cdromAddForm); + var pathTextbox = $('input[name="path"]', cdromAddForm); + var errorMessage = $('#cdrom-error-message'); + + var submitForm = function(event) { + if(submitButton.prop('disabled')) { + return false; + } + + var dev = nameTextbox.val(); + var type = typeTextbox.val(); + var path = pathTextbox.val(); + if(!path || path === '') { + return false; + } + + var formData = cdromAddForm.serializeObject(); + $.each([submitButton, nameTextbox, pathTextbox], function(i, c) { + $(c).prop('disabled', true); + }); + $(submitButton).addClass('loading').text(i18n['KCHVMCD6003M']); + $(errorMessage).text(''); + + var settings = { + vm: kimchi.selectedGuest, + type: type, + path: path + }; + + if(dev && dev !== '') { + settings['dev'] = dev; + } + + kimchi.addVMStorage(settings, function(result) { + kimchi.window.close(); + kimchi.topic('kimchi/vmCDROMAttached').publish({ + result: result + }); + }, function(result) { + var errText = result['reason'] || + result['responseJSON']['reason']; + $(errorMessage).text(errText); + + $.each([submitButton, nameTextbox, pathTextbox], function(i, c) { + $(c).prop('disabled', false); + }); + $(submitButton).removeClass('loading').text(i18n['KCHVMCD6002M']); + }); + + event.preventDefault(); + }; + + cdromAddForm.on('submit', submitForm); + submitButton.on('click', submitForm); + pathTextbox.on('input propertychange', function(event) { + $(submitButton).prop('disabled', $(this).val() === ''); + }); +}; diff --git a/ui/js/src/kimchi.guest_cdrom_edit_main.js b/ui/js/src/kimchi.guest_cdrom_edit_main.js new file mode 100644 index 0000000..bf608bc --- /dev/null +++ b/ui/js/src/kimchi.guest_cdrom_edit_main.js @@ -0,0 +1,88 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013 + * + * 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.guest_cdrom_edit_main = function() { + var cdromEditForm = $('#form-vm-cdrom-edit'); + var submitButton = $('#vm-cdrom-button-edit'); + var nameTextbox = $('input[name="dev"]', cdromEditForm); + var typeTextbox = $('input[name="type"]', cdromEditForm); + var pathTextbox = $('input[name="path"]', cdromEditForm); + var errorMessage = $('#cdrom-error-message'); + var originalPath = null; + + kimchi.retrieveVMStorage({ + vm: kimchi.selectedGuest, + dev: kimchi.selectedGuestStorage + }, function(storage) { + for(var prop in storage) { + $('input[name="' + prop + '"]', cdromEditForm).val(storage[prop]); + } + + originalPath = storage['path']; + }); + + var submitForm = function(event) { + if(submitButton.prop('disabled')) { + return false; + } + + var path = pathTextbox.val(); + if(!path || path === '') { + return false; + } + + $.each([submitButton, nameTextbox, pathTextbox], function(i, c) { + $(c).prop('disabled', true); + }); + $(submitButton).addClass('loading').text(i18n['KCHVMCD6005M']); + $(errorMessage).text(''); + + var settings = { + vm: kimchi.selectedGuest, + dev: kimchi.selectedGuestStorage, + path: path + }; + + kimchi.replaceVMStorage(settings, function(result) { + kimchi.window.close(); + kimchi.message.success(i18n['KCHVMCD6007M']); + kimchi.topic('kimchi/vmCDROMReplaced').publish({ + result: result + }); + }, function(result) { + var errText = result['reason'] || + result['responseJSON']['reason']; + $(errorMessage).text(errText); + + $.each([submitButton, nameTextbox, pathTextbox], function(i, c) { + $(c).prop('disabled', false); + }); + $(submitButton).removeClass('loading').text(i18n['KCHVMCD6004M']); + }); + + event.preventDefault(); + }; + + cdromEditForm.on('submit', submitForm); + submitButton.on('click', submitForm); + pathTextbox.on('input propertychange', function(event) { + var invalid = + ($(this).val() === originalPath) || + ($(this).val() === ''); + $(submitButton).prop('disabled', invalid); + }); +}; diff --git a/ui/pages/guest-cdrom-add.html.tmpl b/ui/pages/guest-cdrom-add.html.tmpl new file mode 100644 index 0000000..59df474 --- /dev/null +++ b/ui/pages/guest-cdrom-add.html.tmpl @@ -0,0 +1,73 @@ +#* + * Project Kimchi + * + * Copyright IBM, Corp. 2013 + * + * 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="guest-cdrom-add-window" class="window"> + <header> + <h1 class="title">$_("Attach a CDROM to VM")</h1> + <div class="close">X</div> + </header> + <div class="content"> + <form id="form-vm-cdrom-add"> + <section class="form-section"> + <h2>1. $_("Device Name")</h2> + <div class="field"> + <p class="text-help"> + $_("The name used to identify the CDROM. If omitted, a name will be chosen automatically.") + </p> + <input type="text" class="text" name="dev" /> + </div> + </section> + <section class="form-section"> + <h2>2. $_("Device Type")</h2> + <div class="field"> + <p class="text-help"> + $_("The device type. Currently, only \"cdrom\" is supported.") + </p> + <input type="text" class="text" name="type" value="cdrom" disabled="disabled" /> + </div> + </section> + <section class="form-section"> + <h2>3. $_("ISO File Path")</h2> + <div class="field"> + <p class="text-help"> + $_("The ISO file path in the server.") + </p> + <input type="text" class="text" name="path" /> + </div> + </section> + <section class="form-section"> + <div id="cdrom-error-message"></div> + </section> + </form> + </div> + <footer> + <div class="btn-group"> + <button id="vm-cdrom-button-add" class="btn-normal" disabled="disabled"> + <span class="text">$_("Attach")</span> + </button> + </div> + </footer> +</div> +<script type="text/javascript"> + kimchi.guest_cdrom_add_main(); +</script> diff --git a/ui/pages/guest-cdrom-edit.html.tmpl b/ui/pages/guest-cdrom-edit.html.tmpl new file mode 100644 index 0000000..9f07d9f --- /dev/null +++ b/ui/pages/guest-cdrom-edit.html.tmpl @@ -0,0 +1,73 @@ +#* + * Project Kimchi + * + * Copyright IBM, Corp. 2013 + * + * 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="guest-cdrom-edit-window" class="window"> + <header> + <h1 class="title">$_("Replace a CDROM of VM")</h1> + <div class="close">X</div> + </header> + <div class="content"> + <form id="form-vm-cdrom-edit"> + <section class="form-section"> + <h2>1. $_("Device Name")</h2> + <div class="field"> + <p class="text-help"> + $_("The name used to identify the CDROM. Read-only.") + </p> + <input type="text" class="text" name="dev" disabled="disabled" /> + </div> + </section> + <section class="form-section"> + <h2>2. $_("Device Type")</h2> + <div class="field"> + <p class="text-help"> + $_("The device type. Currently, only \"cdrom\" is supported.") + </p> + <input type="text" class="text" name="type" value="cdrom" disabled="disabled" /> + </div> + </section> + <section class="form-section"> + <h2>3. $_("ISO File Path")</h2> + <div class="field"> + <p class="text-help"> + $_("The ISO file path in the server.") + </p> + <input type="text" class="text" name="path" /> + </div> + </section> + <section class="form-section"> + <div id="cdrom-error-message"></div> + </section> + </form> + </div> + <footer> + <div class="btn-group"> + <button id="vm-cdrom-button-edit" class="btn-normal" disabled="disabled"> + <span class="text">$_("Replace")</span> + </button> + </div> + </footer> +</div> +<script type="text/javascript"> + kimchi.guest_cdrom_edit_main(); +</script> -- 1.8.1.4

Allow user to manipulate CDROM(s) in a VM: 1) Attach one or more CDROM(s); 2) Replace a CDROM with another ISO file path; 3) Detach a CDROM from a VM. Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> --- ui/css/theme-default/guest-edit.css | 133 +++++++++++++++++++--- ui/images/theme-default/guest-icon-sprite.png | Bin 0 -> 6748 bytes ui/js/src/kimchi.guest_edit_main.js | 86 +++++++++++++- ui/pages/guest-edit.html.tmpl | 154 +++++++++++++++++--------- 4 files changed, 300 insertions(+), 73 deletions(-) create mode 100644 ui/images/theme-default/guest-icon-sprite.png diff --git a/ui/css/theme-default/guest-edit.css b/ui/css/theme-default/guest-edit.css index f4ccdee..9591092 100644 --- a/ui/css/theme-default/guest-edit.css +++ b/ui/css/theme-default/guest-edit.css @@ -17,36 +17,40 @@ */ #guest-edit-window { font-size: 13px; - height: 380px; - width: 420px; + height: 400px; + width: 600px; +} + +#guest-edit-tabs { + background: transparent; + border: none; + height: 100%; + padding: 0; } .guest-edit-fieldset { - float: left; - padding: 1em; + padding-right: 0; } .guest-edit-wrapper-label, .guest-edit-wrapper-controls { display: inline-block; } -.guest-edit-wrapper-controls input[type="text"][disabled] { - color: #bbb; - background-color: #fafafa; - cursor: not-allowed; -} - .guest-edit-wrapper-label { - width: 10em; + height: 38px; + line-height: 38px; + margin-top: 5px; + vertical-align: top; + width: 80px; } .guest-edit-wrapper-controls { - width: 18em; + width: 470px; } .guest-edit-wrapper-controls input[type="text"] { + font-size: 16px; height: 38px; - line-height: 38px; background: #fff; -webkit-border-radius: 5px; border-radius: 5px; @@ -54,7 +58,7 @@ border-top: 1px solid #bbb; border-left: 1px solid #bbb; padding-left: 10px; - width: 100%; + width: 450px; } .guest-edit-wrapper-controls input[type="text"][disabled] { @@ -62,3 +66,104 @@ background-color: #fafafa; cursor: not-allowed; } + +#guest-edit-cdrom-row-container { + max-height: 180px; + overflow: auto; +} + +#guest-edit-cdrom-row-container input[type="text"] { + width: 390px; +} + +.guest-edit-cdrom-button { + background: url("../images/theme-default/guest-icon-sprite.png") no-repeat left top transparent; + border: none; + height: 25px; + vertical-align: middle; + width: 25px; +} + +.guest-edit-cdrom-button.attach { + margin-top: 5px; +} + +.guest-edit-cdrom-button.attach:hover { + background-position: 0 -27px; +} + +.guest-edit-cdrom-button.attach:focus { + background-position: 0 -54px; +} + +.guest-edit-cdrom-button.attach:active { + background-position: 0 -81px; +} + +.guest-edit-cdrom-button.attach[disabled] { + background-position: 0 -108px; +} + +.guest-edit-cdrom-button.replace { + background-position: -27px 0; +} + +.guest-edit-cdrom-button.replace:hover { + background-position: -27px -27px; +} + +.guest-edit-cdrom-button.replace:focus { + background-position: -27px -54px; +} + +.guest-edit-cdrom-button.replace:active { + background-position: -27px -81px; +} + +.guest-edit-cdrom-button.replace[disabled] { + background-position: -27px -108px; +} + +.guest-edit-cdrom-button.detach { + background-position: -54px 0; +} + +.guest-edit-cdrom-button.detach:hover { + background-position: -54px -27px; +} + +.guest-edit-cdrom-button.detach:focus { + background-position: -54px -54px; +} + +.guest-edit-cdrom-button.detach:active { + background-position: -54px -81px; +} + +.guest-edit-cdrom-button.detach[disabled] { + background-position: -54px -108px; +} + +#message-container { + color: #555; + font-size: 14px; + height: 100%; + line-height: 56px; +} + +#message-container .message { + background: transparent; +} + +#message-container .success { + color: green; +} + +#message-container .error { + color: red; +} + +#message-container .content { + margin: 0; + position: static; +} diff --git a/ui/images/theme-default/guest-icon-sprite.png b/ui/images/theme-default/guest-icon-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..81edb5945d3bd204313a6d53b55cecf17ee97679 GIT binary patch literal 6748 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 Bz#9Mn literal 0 HcmV?d00001 diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js index f32fbb1..2419a50 100644 --- a/ui/js/src/kimchi.guest_edit_main.js +++ b/ui/js/src/kimchi.guest_edit_main.js @@ -16,17 +16,94 @@ * limitations under the License. */ kimchi.guest_edit_main = function() { - var guestEditForm = $('#form-guest-edit'); + var buttonContainer = $('#action-button-container'); + $('#guest-edit-tabs').tabs({ + beforeActivate: function(event, ui) { + var deactivated = ui['oldPanel']; + if($(deactivated).attr('id') === 'form-guest-edit-general') { + $(buttonContainer).addClass('hidden'); + } + else { + $(buttonContainer).removeClass('hidden'); + } + } + }); + + var guestEditForm = $('#form-guest-edit-general'); var saveButton = $('#guest-edit-button-save'); + + var refreshCDROMs = function() { + kimchi.listVMStorages({ + vm: kimchi.selectedGuest, + storageType: 'cdrom' + }, function(storages) { + var rowHTML = $('#cdrom-row-tmpl').html(); + var container = $('#guest-edit-cdrom-row-container'); + $(container).empty(); + + $.each(storages, function(index, storage) { + storage['vm'] = kimchi.selectedGuest; + var templated = kimchi.template(rowHTML, storage); + container.append(templated); + }); + + var replaceCDROM = function(event) { + event.preventDefault(); + kimchi.selectedGuestStorage = $(this).data('dev'); + kimchi.window.open("guest-cdrom-edit.html"); + }; + + $('input[type="text"][name="cdrom"]', container).on('click', replaceCDROM); + $('.replace', container).on('click', replaceCDROM); + + $('.detach', container).on('click', function(e) { + event.preventDefault(); + var settings = { + title : i18n['KCHAPI6004M'], + content : i18n['KCHVMCD6001M'], + confirm : i18n['KCHAPI6002M'], + cancel : i18n['KCHAPI6003M'] + }; + + var dev = $(this).data('dev'); + kimchi.confirm(settings, function() { + kimchi.deleteVMStorage({ + vm: kimchi.selectedGuest, + dev: dev + }, function() { + kimchi.topic('kimchi/vmCDROMDetached').publish(); + }); + }); + }); + }); + }; + kimchi.retrieveVM(kimchi.selectedGuest, function(guest) { guest['icon'] = guest['icon'] || 'images/icon-vm.png'; for ( var prop in guest) { $('input[name="' + prop + '"]', guestEditForm).val(guest[prop]); } - }); - $('#guest-edit-button-cancel').on('click', function() { - kimchi.window.close(); + refreshCDROMs(); + + $('#guest-edit-attach-cdrom-button').on('click', function(event) { + event.preventDefault(); + kimchi.window.open("guest-cdrom-add.html"); + }); + + var messageNode = $('#message-container'); + kimchi.topic('kimchi/vmCDROMAttached').subscribe(function(params) { + kimchi.message.success(i18n['KCHVMCD6006M'], messageNode); + refreshCDROMs(); + }); + kimchi.topic('kimchi/vmCDROMReplaced').subscribe(function(params) { + kimchi.message.success(i18n['KCHVMCD6007M'], messageNode); + refreshCDROMs(); + }); + kimchi.topic('kimchi/vmCDROMDetached').subscribe(function(params) { + kimchi.message.success(i18n['KCHVMCD6008M'], messageNode); + refreshCDROMs(); + }); }); var submitForm = function(event) { @@ -42,6 +119,7 @@ kimchi.guest_edit_main = function() { }, function(err) { kimchi.message.error(err.responseJSON.reason); }); + event.preventDefault(); }; diff --git a/ui/pages/guest-edit.html.tmpl b/ui/pages/guest-edit.html.tmpl index a461031..64e1136 100644 --- a/ui/pages/guest-edit.html.tmpl +++ b/ui/pages/guest-edit.html.tmpl @@ -27,74 +27,118 @@ <div class="close">X</div> </header> <div class="content"> - <form id="form-guest-edit"> - <fieldset class="guest-edit-fieldset"> - <div> - <div class="guest-edit-wrapper-label"> - <label for="guest-edit-id-textbox"> - $_("Name") - </label> + <div id="guest-edit-tabs"> + <ul> + <li> + <a href="#form-guest-edit-general">$_("General")</a> + </li> + <li> + <a href="#form-guest-edit-storage">$_("Storage")</a> + </li> + </ul> + <form id="form-guest-edit-general"> + <fieldset class="guest-edit-fieldset"> + <div> + <div class="guest-edit-wrapper-label"> + <label for="guest-edit-id-textbox"> + $_("Name") + </label> + </div> + <div class="guest-edit-wrapper-controls"> + <input id="guest-edit-id-textbox" + name="name" type="text" /> + </div> </div> - <div class="guest-edit-wrapper-controls"> - <input id="guest-edit-id-textbox" - name="name" type="text" /> + <div> + <div class="guest-edit-wrapper-label"> + <label for="guest-edit-cores-textbox"> + $_("CPUs") + </label> + </div> + <div class="guest-edit-wrapper-controls"> + <input + id="guest-edit-cores-textbox" + name="cpus" + type="text" + disabled="disabled" /> + </div> </div> - </div> - <div> - <div class="guest-edit-wrapper-label"> - <label for="guest-edit-cores-textbox"> - $_("CPUs") - </label> + <div> + <div class="guest-edit-wrapper-label"> + <label for="guest-edit-memory-textbox"> + $_("Memory") + </label> + </div> + <div class="guest-edit-wrapper-controls"> + <input id="guest-edit-memory-textbox" + name="memory" + type="text" + disabled="disabled" /> + </div> </div> - <div class="guest-edit-wrapper-controls"> - <input - id="guest-edit-cores-textbox" - name="cpus" - type="text" - disabled="disabled" /> + <div> + <div class="guest-edit-wrapper-label"> + <label for="guest-edit-icon-textbox"> + $_("Icon") + </label> + </div> + <div class="guest-edit-wrapper-controls"> + <input + id="guest-edit-icon-textbox" + name="icon" + type="text" + disabled="disabled" /> + </div> </div> - </div> - <div> - <div class="guest-edit-wrapper-label"> - <label for="guest-edit-memory-textbox"> - $_("Memory") - </label> + </fieldset> + </form> + <form id="form-guest-edit-storage"> + <fieldset class="guest-edit-fieldset"> + <div> + <div class="guest-edit-wrapper-label"> + <label> + $_("CDROM") + </label> + </div> + <div class="guest-edit-wrapper-controls"> + <div id="guest-edit-cdrom-row-container"></div> + <div> + <button id="guest-edit-attach-cdrom-button" + class="guest-edit-cdrom-button attach" + title="$_("Attach")"> + </button> + </div> + </div> </div> - <div class="guest-edit-wrapper-controls"> - <input id="guest-edit-memory-textbox" - name="memory" - type="text" - disabled="disabled" /> - </div> - </div> - <div> - <div class="guest-edit-wrapper-label"> - <label for="guest-edit-icon-textbox"> - $_("Icon") - </label> - </div> - <div class="guest-edit-wrapper-controls"> - <input - id="guest-edit-icon-textbox" - name="icon" - type="text" - disabled="disabled" /> - </div> - </div> - </fieldset> - </form> + </fieldset> + </form> + </div> </div> <footer> - <div class="btn-group"> - <button id="guest-edit-button-cancel" class="btn-normal"> - <span class="text">$_("Cancel")</span> - </button> + <div id="action-button-container" class="btn-group"> <button id="guest-edit-button-save" class="btn-normal"> <span class="text">$_("Save")</span> </button> </div> + <div id="message-container"></div> </footer> </div> +<script id="cdrom-row-tmpl" type="text/html"> + <div> + <input name="cdrom" type="text" + data-vm="{vm}" data-dev="{dev}" + value="{path}" readonly="readonly" /> + <button class="guest-edit-cdrom-button replace" + data-vm="{vm}" data-dev="{dev}" + title="$_("Replace")"> + </button> + <button class="guest-edit-cdrom-button detach" + data-vm="{vm}" data-dev="{dev}" + title="$_("Detach")"> + </button> + </div> +</script> + <script type="text/javascript"> kimchi.guest_edit_main(); </script> -- 1.8.1.4
participants (1)
-
Hongliang Wang