Would be nice to add your signed by to the patch!


On 12/26/2016 04:15 PM, bianca@linux.vnet.ibm.com wrote:
From: Socorro <socorro@linux.vnet.ibm.com>

This patch adds the UI portion for supporting changing the guest boot order
via edit guest panel.  This was based off of what Samuel had prototyped.

Issue found in backend during test:
When updating the VM even with just changing the name, the bootorder gets reset to 'hd' only.
I tested this using the curl command and confirmed that indeed it does get reset to one entry only.
Issue written to address this:  https://github.com/kimchi-project/kimchi/issues/1012

Signed-off-by: Socorro <socorro@linux.vnet.ibm.com>
---
 ui/css/kimchi.css                    | 55 +++++++++++++++++++++++++++++
 ui/css/src/modules/_edit-guests.scss | 54 ++++++++++++++++++++++++++++
 ui/js/src/kimchi.guest_edit_main.js  | 68 ++++++++++++++++++++++++++++++++++--
 ui/pages/guest-edit.html.tmpl        | 18 ++++++++--
 4 files changed, 191 insertions(+), 4 deletions(-)

diff --git a/ui/css/kimchi.css b/ui/css/kimchi.css
index fff3279..ae5e37b 100644
--- a/ui/css/kimchi.css
+++ b/ui/css/kimchi.css
@@ -1557,6 +1557,61 @@ body.wok-gallery {
   overflow: visible;
 }

+ul {
+  cursor: default;
+}
+
+.boot-order {
+  display: block;
+  width: 85%;
+  font-size: 14px;
+  line-height: 1.42857;
+  color: #444;
+  overflow: hidden;
+  background-color: #fff;
+  background-image: none;
+  border: 1px solid #ccc;
+  border-radius: 3px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+  -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+  -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+  transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+}
+
+.boot-order:focus,
+.boot-order.focus {
+  border-color: #66afe9;
+  outline: 0;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+
+.boot-order > li {
+  cursor: move;
+  /* fallback if grab cursor is unsupported */
+  cursor: grab;
+  cursor: -moz-grab;
+  cursor: -webkit-grab;
+  border-left: 0;
+  border-right: 0;
+}
+
+.boot-order > li:first-child {
+  border-top: 0;
+}
+
+.boot-order > li:last-child {
+  border-bottom: 0;
+}
+
+.boot-order > li.ui-sortable-helper {
+  cursor: grabbing;
+  cursor: -moz-grabbing;
+  cursor: -webkit-grabbing;
+  border: 1px solid #ccc !important;
+}
+
 /* Add Template Modal Window */
 .templates-modal .modal-dialog {
   width: 1100px;
diff --git a/ui/css/src/modules/_edit-guests.scss b/ui/css/src/modules/_edit-guests.scss
index 25d4d65..ea3ee9d 100644
--- a/ui/css/src/modules/_edit-guests.scss
+++ b/ui/css/src/modules/_edit-guests.scss
@@ -429,3 +429,57 @@
 #form-guest-storage-add .form-section .field {
     overflow: visible;
 }
+
+ul {
+  cursor: default;
+}
+
+.boot-order {
+  display: block;
+  width: 85%;
+  font-size: 14px;
+  line-height: 1.42857;
+  color: #444;
+  overflow: hidden;
+  background-color: #fff;
+  background-image: none;
+  border: 1px solid #ccc;
+  border-radius: 3px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+  -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+  -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+  transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+}
+
+.boot-order:focus,
+.boot-order.focus {
+  border-color: #66afe9;
+  outline: 0;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+
+.boot-order > li {
+  cursor: move; /* fallback if grab cursor is unsupported */
+  cursor: grab;
+  cursor: -moz-grab;
+  cursor: -webkit-grab;
+  border-left: 0;
+  border-right: 0;
+}
+
+.boot-order > li:first-child {
+  border-top: 0;
+}
+
+.boot-order > li:last-child {
+  border-bottom: 0;
+}
+
+.boot-order > li.ui-sortable-helper {
+  cursor: grabbing;
+  cursor: -moz-grabbing;
+  cursor: -webkit-grabbing;
+  border: 1px solid #ccc !important;
+}
diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js
index bb82077..12c0770 100644
--- a/ui/js/src/kimchi.guest_edit_main.js
+++ b/ui/js/src/kimchi.guest_edit_main.js
@@ -26,6 +26,7 @@ kimchi.guest_edit_main = function() {
     var networkOptions = "";

     clearTimeout(kimchi.vmTimeout);
+    var bootOrderOptions = [];

     $('#modalWindow').on('hidden.bs.modal', function() {
         kimchi.setListVMAutoTimeout();
@@ -45,11 +46,12 @@ kimchi.guest_edit_main = function() {

     var submitForm = function(event) {

-        // tap map, "general": 0, "storage": 1, "interface": 2, "permission": 3, "password": 4
+        // tap map, "general": 0, "storage": 1, "interface": 2, "permission": 3, "pci": 4, "snapshot": 5, "processor": 6, "bootOrder": 7
         var submit_map = {
             0: generalSubmit,
             3: permissionSubmit,
-            6: processorSubmit
+            6: processorSubmit,
+            7: bootOrderSubmit
         };
         var currentTab = $('#guest-edit-window li.active a[data-toggle="tab"]').data('id');
         var toSubmit = parseInt($('#'+currentTab).index());
@@ -967,6 +969,42 @@ kimchi.guest_edit_main = function() {
         }
     };

+    var setupBootOrder = function(guest) {
+        var guestBootOrder = guest['bootorder'];
+        $("#myList").empty();
+        $.each(guestBootOrder, function(index, value) {
+           var itemNode = $.parseHTML("<li class='list-group-item' " + "data-value=" + value + ">" + value + "</li>");
+           $("#myList").append(itemNode);
+        });
+
+        $('.boot-order').sortable({
+            items: 'li',
+            cursor: 'move',
+            opacity: 0.6,
+            containment: "parent",
+            start: function(event, ui) {
+                $(this).addClass('focus');
+            },
+            stop: function(event, ui) {
+                $(this).removeClass('focus');
+            },
+            change: function(event, ui) {
+                // callback once started changing order
+            },
+            update: function(event, ui) {
+                // callback once finished order
+                $(saveButton).prop('disabled', false);
+                bootOrderOptions = [];
+                $("#myList li").each(function() {
+                    bootOrderOptions.push($(this).text())
+                });
+                bootOrderOptions.forEach(function(entry) {
+                    console.log(entry);
+                });
+            }
+        });
+    };
+
     var initContent = function(guest) {
         guest['icon'] = guest['icon'] || 'plugins/kimchi/images/icon-vm.png';
         $('#form-guest-edit-general').fillWithObject(guest);
@@ -1032,6 +1070,7 @@ kimchi.guest_edit_main = function() {
         setupPermission();
         setupPCIDevice();
         setupSnapshot();
+        setupBootOrder(guest);

         kimchi.init_processor_tab(guest.cpu_info, $(saveButton));
         if ((kimchi.thisVMState === "running") || (kimchi.thisVMState === "paused")) {
@@ -1221,4 +1260,29 @@ kimchi.guest_edit_main = function() {
     if(kimchi.hostarch === s390xArch){
         $('#guest-edit-window ul li a[data-id="form-guest-edit-pci"],a[data-id="form-guest-edit-snapshot"]').parent().hide();
     }
+
+    var bootOrderSubmit = function(event) {
+        //Format the strings to go in the array before passing in to the API
+        //"hd", "network", "cdrom"
+        var formattedBootOrderOptions = [];
+        for (var i=0; i<bootOrderOptions.length; i++) {
+            var str = bootOrderOptions[i].trim();
+            str = str.toLowerCase();
+            if (str === "hdd") {
+                str = "hd";
+            } else if (str === "cd-rom") {
+                str = "cdrom";
+            }
+            formattedBootOrderOptions.push(str);
+        }
+        var data = {
+            bootorder: formattedBootOrderOptions
+        };
+        kimchi.updateVM(kimchi.selectedGuest, data, function() {
+            wok.window.close();
+        }, function(err) {
+            wok.message.error(err.responseJSON.reason,'#alert-modal-container');
+        });
+    };
+
 };
diff --git a/ui/pages/guest-edit.html.tmpl b/ui/pages/guest-edit.html.tmpl
index d8a482c..5424250 100644
--- a/ui/pages/guest-edit.html.tmpl
+++ b/ui/pages/guest-edit.html.tmpl
@@ -30,7 +30,7 @@
     </div>
     <div class="modal-body">
     <span id="alert-modal-container"></span>
-<ul class="nav nav-tabs" role="tablist">
+  <ul class="nav nav-tabs" role="tablist">
     <li role="presentation" class="active"><a href="#form-guest-edit-general" aria-controls="form-guest-edit-general" role="tab" data-id="form-guest-edit-general" data-toggle="tab">$_("General")</a></li>
     <li role="presentation"><a href="#form-guest-edit-storage" aria-controls="form-guest-edit-storage" role="tab" data-id="form-guest-edit-storage" data-toggle="tab">$_("Storage")</a></li>
     <li role="presentation"><a href="#form-guest-edit-interface" aria-controls="form-guest-edit-interface" role="tab" data-id="form-guest-edit-interface" data-toggle="tab">$_("Interface")</a></li>
@@ -38,6 +38,7 @@
     <li role="presentation"><a href="#form-guest-edit-pci" aria-controls="form-guest-edit-pci" role="form-guest-edit-pci" data-id="form-guest-edit-pci" data-toggle="tab">$_("Pci")</a></li>
     <li role="presentation"><a href="#form-guest-edit-snapshot" aria-controls="form-guest-edit-snapshot" role="tab" data-id="form-guest-edit-snapshot" data-toggle="tab">$_("Snapshot")</a></li>
     <li role="presentation"><a href="#form-edit-processor" aria-controls="form-edit-processor" role="tab" data-id="form-edit-processor" data-toggle="tab">$_("Processor")</a></li>
+    <li role="presentation"><a href="#form-guest-edit-boot-order" aria-controls="form-guest-edit-boot-order" role="tab" data-id="form-guest-edit-boot-order" data-toggle="tab">Boot Order</a></li>
   </ul>
         <div class="tab-content" id="guest-edit-tabs">
             <form role="tabpanel" class="tab-pane active" id="form-guest-edit-general">
@@ -197,7 +198,6 @@
                             $_("Current CPU must be equal or lower than the Maximum CPU value. If a topology is set, it must be also be a multiple of the 'threads' value.")
                         </p>
                     </div>
-
                     <div id="guest-max-processor-panel" class="form-group">
                         <label for="guest-edit-max-processor-textbox">$_("Max CPU")</label>
                         <p id="settings-readonly-help" class="hidden">$_("Unable to edit maximum CPU or CPU topology when editing a running or paused virtual machine.")</p>
@@ -231,6 +231,20 @@
                     </div>
                 </div>
             </form>
+            <form role="tabpanel" class="tab-pane" id="form-guest-edit-boot-order">
+                <div class="form-group">
+                    <div id="bootOrder">
+                      <ul id="myList" class="list-group boot-order">
+                          <li class="list-group-item" data-value="CD-ROM">CD-ROM</li>
+                          <li class="list-group-item" data-value="HDD">HDD</li>
+                          <li class="list-group-item" data-value="Network">Network</li>
+                      </ul>
+                      <p class="help-block">
+                          <i class="fa fa-info-circle"></i> $_("Change the boot order by dragging the items on the list.")</p>
+                      </p>
+                    </div>
+                </div>
+            </form>
         </div>
     </div>
     <div class="modal-footer">

-- 

Ramon Nunes Medeiros
Kimchi Developer
Linux Technology Center Brazil
IBM Systems & Technology Group
Phone : +55 19 2132 7878
ramonn@br.ibm.com