diff --git a/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb b/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb index f8240be10d..de4c6a4c1a 100644 --- a/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb +++ b/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb @@ -67,6 +67,8 @@ module OpenNebulaJSON when "resubmit" then self.resubmit when "chown" then self.chown(action_hash['params']) when "chmod" then self.chmod_octet(action_hash['params']) + when "attachdisk" then self.attachdisk(action_hash['params']) + when "detachdisk" then self.detachdisk(action_hash['params']) else error_msg = "#{action_hash['perform']} action not " << " available for this resource" @@ -101,5 +103,15 @@ module OpenNebulaJSON def chmod_octet(params=Hash.new) super(params['octet']) end + + def attachdisk(params=Hash.new) + template_json = params['disk_template'] + template = template_to_str(template_json) + super(template) + end + + def detachdisk(params=Hash.new) + super(params['disk_id'].to_i) + end end end diff --git a/src/sunstone/public/css/application.css b/src/sunstone/public/css/application.css index 36feb13fbd..6b023a1a80 100644 --- a/src/sunstone/public/css/application.css +++ b/src/sunstone/public/css/application.css @@ -665,7 +665,8 @@ ul.action_list li a:hover{ vertical-align:middle; } -.quota_edit_icon:hover, .quota_remove_icon:hover { +.quota_edit_icon:hover, .quota_remove_icon:hover, +.detach_disk:hover, .attach_disk:hover{ cursor: pointer; } diff --git a/src/sunstone/public/js/opennebula.js b/src/sunstone/public/js/opennebula.js index 893772121b..0f79839ac3 100644 --- a/src/sunstone/public/js/opennebula.js +++ b/src/sunstone/public/js/opennebula.js @@ -679,6 +679,16 @@ var OpenNebula = { }, "monitor_all" : function(params){ OpenNebula.Action.monitor(params,OpenNebula.VM.resource,true); + }, + "attachdisk" : function(params){ + var action_obj = {"disk_template": params.data.extra_param}; + OpenNebula.Action.simple_action(params,OpenNebula.VM.resource, + "attachdisk",action_obj); + }, + "detachdisk" : function(params){ + var action_obj = {"disk_id": params.data.extra_param}; + OpenNebula.Action.simple_action(params,OpenNebula.VM.resource, + "detachdisk",action_obj); } }, diff --git a/src/sunstone/public/js/plugins/vms-tab.js b/src/sunstone/public/js/plugins/vms-tab.js index 872ad1e38f..8782c478ac 100644 --- a/src/sunstone/public/js/plugins/vms-tab.js +++ b/src/sunstone/public/js/plugins/vms-tab.js @@ -88,6 +88,9 @@ var vms_tab_content = '\

\ '+tr("VNC console requires previous install of the noVNC addon. Check Sunstone documentation for more information.")+'\

\ +

\ +'+tr("You can hotplug and detach existing disks from running VMs from the Disks & Hotplugging tab in the VM information dialog.")+'\ +

\ \ '; @@ -479,6 +482,22 @@ var vm_actions = { error: onError, notify: true }, + "VM.attachdisk" : { + type: "single", + call: OpenNebula.VM.attachdisk, + callback: vmShow, + error: onError, + notify: true + }, + "VM.detachdisk" : { + type: "single", + call: OpenNebula.VM.detachdisk, + callback: function(req,res){ + setTimeout(vmShow,1000,req); + }, + error: onError, + notify: true + }, "VM.help" : { type: "custom", call: function() { @@ -631,6 +650,10 @@ var vm_info_panel = { title: tr("Virtual Machine information"), content: "" }, + "vm_hotplugging_tab" : { + title: tr("Disks & Hotplugging"), + content: "" + }, "vm_template_tab" : { title: tr("VM template"), content: "" @@ -821,6 +844,11 @@ function updateVMachineElement(request, vm_json){ var id = vm_json.VM.ID; var element = vMachineElementArray(vm_json); updateSingleElement(element,dataTable_vMachines,'#vm_'+id) + + //we update this too, even if it is not shown. + var $hotplugging_tab = $('div#vm_info_panel div#vm_hotplugging_tab'); + $('#hotplugging_form',$hotplugging_tab).replaceWith(printDisks(vm_json.VM)); + $('tr.at_volatile',$hotplugging_tab).hide(); } // Callback to delete a single element from the list @@ -1014,6 +1042,11 @@ function updateVMInfo(request,vm){ ' }; + var hotplugging_tab = { + title: tr("Disks & Hotplugging"), + content: printDisks(vm_info) + }; + var template_tab = { title: tr("VM Template"), content: @@ -1039,6 +1072,7 @@ function updateVMInfo(request,vm){ }; Sunstone.updateInfoPanelTab("vm_info_panel","vm_info_tab",info_tab); + Sunstone.updateInfoPanelTab("vm_info_panel","vm_hotplugging_tab",hotplugging_tab); Sunstone.updateInfoPanelTab("vm_info_panel","vm_template_tab",template_tab); Sunstone.updateInfoPanelTab("vm_info_panel","vm_log_tab",log_tab); Sunstone.updateInfoPanelTab("vm_info_panel","vm_history_tab",history_tab); @@ -1050,6 +1084,187 @@ function updateVMInfo(request,vm){ for (var i=0; i reference by name! + 4, //name col + [10,10,10], + [tr("DISABLED"),tr("LOCKED"),tr("ERROR")] + ); + var html ='\ +
\ + \ + \ + \ + \ + \ + '; + + + var disks = [] + if ($.isArray(vm_info.TEMPLATE.DISK)) + disks = vm_info.TEMPLATE.DISK + else if (!$.isEmptyObject(vm_info.TEMPLATE.DISK)) + disks = [vm_info.TEMPLATE.DISK] + + if (!disks.length){ + html += ''; + html += '
'+tr("Disks information")+'
\ + '+tr("No disks to show")+'\ +
'; + return html; + } + + for (var i = 0; i < disks.length; i++){ + var disk = disks[i]; + html += ''; + html += disk.DISK_ID + ' - ' + + (disk.IMAGE ? disk.IMAGE : "Volatile") + ''; + html += ''+disk.TYPE+''; + html += ' '; + } + + html += '\ + '; + + if (vm_info.STATE != "3"){ + html +=''; + return html; + } + + html += '\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
'+tr("Attach disk to running VM")+'
\ + \ +
\ + \ +
\ + \ +
\ + \ +
\ + \ +
\ + \ +
\ + \ +
\ + \ +
\ + \ +
'; + + return html; +} + +function hotpluggingOps(){ + $('i.detach_disk').live('click', function(){ + var i = $(this); + var vm_id = i.parents('form').attr('vmid'); + var disk_id = i.parents('tr').attr('disk_id'); + var parent = i.parent(); + + Sunstone.runAction('VM.detachdisk', vm_id, disk_id); + + i.remove(); + parent.append(spinner); + return false; + }); + + $('select#attach_disk_type').live('change',function(){ + var context = $(this).parents('form'); + switch ($(this).val()){ + case "image": + $('tr.at_volatile',context).hide(); + $('tr.at_image',context).show(); + break; + case "volatile": + $('tr.at_image',context).hide(); + $('tr.at_volatile',context).show(); + break; + }; + }); + + $('#hotplugging_form').live('submit',function(){ + var vm_id = $(this).attr('vmid'); + var disk_obj = {}; + switch($('select#attach_disk_type',this).val()){ + case "image": + var im_id = $('select[name="IMAGE_ID"]',this).val(); + if (!im_id) { + notifyError(tr("Please select an image to attach")); + return false; + } + disk_obj.IMAGE_ID = $('select[name="IMAGE_ID"]',this).val(); + disk_obj.DEV_PREFIX = $('input[name="DEV_PREFIX"]',this).val(); + disk_obj.BUS = 'scsi'; + break; + case "volatile": + disk_obj.SIZE = $('input[name="SIZE"]',this).val(); + disk_obj.FORMAT = $('input[name="FORMAT"]',this).val(); + disk_obj.TYPE = $('select[name="TYPE"]',this).val(); + disk_obj.DEV_PREFIX = $('input[name="DEV_PREFIX"]',this).val(); + disk_obj.READONLY = $('select[name="READONLY"]',this).val(); + disk_obj.SAVE = $('save[name="SAVE"]',this).val(); + break; + } + + var obj = { DISK : disk_obj }; + Sunstone.runAction("VM.attachdisk", vm_id, obj); + return false; + }); } // Sets up the create-template dialog and all the processing associated to it, @@ -1526,6 +1741,7 @@ $(document).ready(function(){ setupSaveasDialog(); setVMAutorefresh(); setupVNC(); + hotpluggingOps(); initCheckAllBoxes(dataTable_vMachines); tableCheckboxesListener(dataTable_vMachines); diff --git a/src/sunstone/public/js/plugins/vnets-tab.js b/src/sunstone/public/js/plugins/vnets-tab.js index f593349851..530dcf2cdc 100644 --- a/src/sunstone/public/js/plugins/vnets-tab.js +++ b/src/sunstone/public/js/plugins/vnets-tab.js @@ -617,8 +617,6 @@ function updateVNetworkInfo(request,vn){ ''; - var leases_tab_content = printLeases(vn_info); - var info_tab = { title: tr("Virtual Network information"), content: info_tab_content @@ -626,7 +624,7 @@ function updateVNetworkInfo(request,vn){ var leases_tab = { title: "Lease management", - content: leases_tab_content + content: printLeases(vn_info) }; Sunstone.updateInfoPanelTab("vnet_info_panel","vnet_info_tab",info_tab); @@ -675,6 +673,7 @@ function printLeases(vn_info){ \ \ '; + html += ''; return html; } else if (leases.constructor != Array) //>1 lease