From 557124605ed519188840c9460e627005fef5994b Mon Sep 17 00:00:00 2001 From: Hector Sanjuan <hsanjuan@opennebula.org> Date: Mon, 12 Mar 2012 12:45:38 +0100 Subject: [PATCH] Feature #1112: Update Sunstone dashboards, allow DS select on image creation, list images in DS in extended info and various small bugfixes. (cherry picked from commit b20a063d7f13f136f06e97137638dc134262c552) --- .../models/OpenNebulaJSON/ImageJSON.rb | 2 +- src/sunstone/models/SunstoneServer.rb | 15 +++++++- .../public/js/plugins/dashboard-tab.js | 22 ++++++++++-- .../public/js/plugins/dashboard-users-tab.js | 14 +++++++- .../public/js/plugins/datastores-tab.js | 35 +++++++++++++++++-- src/sunstone/public/js/plugins/images-tab.js | 15 ++++++-- src/sunstone/public/js/plugins/vnets-tab.js | 1 + src/sunstone/public/js/sunstone-util.js | 19 +++++++--- 8 files changed, 109 insertions(+), 14 deletions(-) diff --git a/src/sunstone/models/OpenNebulaJSON/ImageJSON.rb b/src/sunstone/models/OpenNebulaJSON/ImageJSON.rb index 11c03966ee..99a0bdf04b 100644 --- a/src/sunstone/models/OpenNebulaJSON/ImageJSON.rb +++ b/src/sunstone/models/OpenNebulaJSON/ImageJSON.rb @@ -37,7 +37,7 @@ module OpenNebulaJSON template = template_to_str(image_hash) end - self.allocate(template,ds_id) + self.allocate(template,ds_id.to_i) end def perform_action(template_json) diff --git a/src/sunstone/models/SunstoneServer.rb b/src/sunstone/models/SunstoneServer.rb index fba385ec96..2739d9b2b4 100644 --- a/src/sunstone/models/SunstoneServer.rb +++ b/src/sunstone/models/SunstoneServer.rb @@ -130,9 +130,22 @@ class SunstoneServer < CloudServer ############################################################################ def upload(template, file_path) image_hash = parse_json(template, 'image') + if OpenNebula.is_error?(image_hash) + return [500, image_hash.to_json] + end + image_hash['PATH'] = file_path - new_template = {:image => image_hash}.to_json + ds_id = parse_json(template, 'ds_id') + if OpenNebula.is_error?(ds_id) + return [500, ds_id.to_json] + end + + new_template = { + :image => image_hash, + :ds_id => ds_id, + }.to_json + image = ImageJSON.new(Image.build_xml, @client) rc = image.create(new_template) diff --git a/src/sunstone/public/js/plugins/dashboard-tab.js b/src/sunstone/public/js/plugins/dashboard-tab.js index 362c51e347..06b931244b 100644 --- a/src/sunstone/public/js/plugins/dashboard-tab.js +++ b/src/sunstone/public/js/plugins/dashboard-tab.js @@ -58,6 +58,10 @@ var dashboard_tab_content = <td class="key_td">' + tr("Hosts (total/active)") + '</td>\ <td class="value_td"><span id="total_hosts"></span><span id="active_hosts" class="green"></span></td>\ </tr>\ + <tr>\ + <td class="key_td">' + tr("Clusters") + '</td>\ + <td class="value_td"><span id="total_clusters"></span></td>\ + </tr>\ <tr>\ <td class="key_td">' + tr("Groups") + '</td>\ <td class="value_td"><span id="total_groups"></span></td>\ @@ -78,6 +82,10 @@ var dashboard_tab_content = <td class="key_td">' + tr("Virtual Networks (total/public)") + '</td>\ <td class="value_td"><span id="total_vnets"></span><span id="public_vnets"></span></td>\ </tr>\ + <tr>\ + <td class="key_td">' + tr("Datastores") + '</td>\ + <td class="value_td"><span id="total_datastores"></span></td>\ + </tr>\ <tr>\ <td class="key_td">' + tr("Images (total/public)") + '</td>\ <td class="value_td"><span id="total_images"></span><span id="public_images"></span></td>\ @@ -102,11 +110,13 @@ var dashboard_tab_content = <h3>' + tr("Quickstart") + '</h3>\ <form id="quickstart_form"><fieldset>\ <table style="width:100%;"><tr style="vertical-align:middle;"><td style="width:70%">\ -<label style="font-weight:bold;width:40px;height:10em;">' + tr("New")+': </label>\ +<label style="font-weight:bold;width:40px;height:12em;">' + tr("New")+': </label>\ <input type="radio" name="quickstart" value="Host.create_dialog">' + tr("Host") + '</input><br />\ + <input type="radio" name="quickstart" value="Cluster.create_dialog">' + tr("Cluster") + '</input><br />\ <input type="radio" name="quickstart" value="VM.create_dialog">' + tr("VM Instance") + '</input><br />\ <input type="radio" name="quickstart" value="Template.create_dialog">' + tr("VM Template") + '</input><br />\ - <input type="radio" name="quickstart" value="Network.create_dialog">' + tr("Virtual Network") + '</input><br />\ + <input type="radio" name="quickstart" value="Network.create_dialog">' + tr("Virtual Network") + '</iput><br />\ + <input type="radio" name="quickstart" value="Datastore.create_dialog">' + tr("Datastore") + '</input><br />\ <input type="radio" name="quickstart" value="Image.create_dialog">' + tr("Image") + '</input><br />\ <input type="radio" name="quickstart" value="User.create_dialog">' + tr("User") + '</input><br />\ <input type="radio" name="quickstart" value="Group.create_dialog">' + tr("Group") + '</input><br />\ @@ -316,5 +326,13 @@ function updateDashboard(what,json_info){ var total_acls=json_info.length; $('#total_acls',db).html(total_acls); break; + case "clusters": + var total_clusters=json_info.length; + $('#total_clusters',db).html(total_clusters); + break; + case "datastores": + var total_datastores=json_info.length; + $('#total_datastores',db).html(total_datastores); + break; } } diff --git a/src/sunstone/public/js/plugins/dashboard-users-tab.js b/src/sunstone/public/js/plugins/dashboard-users-tab.js index 4e602814be..f27ed855fb 100644 --- a/src/sunstone/public/js/plugins/dashboard-users-tab.js +++ b/src/sunstone/public/js/plugins/dashboard-users-tab.js @@ -69,6 +69,10 @@ var dashboard_tab_content = <td class="key_td">'+tr("Virtual Networks (total/public)")+'</td>\ <td class="value_td"><span id="total_vnets"></span><span id="public_vnets"></span></td>\ </tr>\ + <tr>\ + <td class="key_td">' + tr("Datastores") + '</td>\ + <td class="value_td"><span id="total_datastores"></span></td>\ + </tr>\ <tr>\ <td class="key_td">'+tr("Images (total/public)")+'</td>\ <td class="value_td"><span id="total_images"></span><span id="public_images"></span></td>\ @@ -85,7 +89,7 @@ var dashboard_tab_content = <h3>'+tr("Quickstart")+'</h3>\ <form id="quickstart_form"><fieldset>\ <table style="width:100%;"><tr style="vertical-align:middle;"><td style="width:70%">\ - <label style="font-weight:bold;width:40px;height:4em;">New:</label>\ + <label style="font-weight:bold;width:40px;height:6em;">New:</label>\ <input type="radio" name="quickstart" value="Template.create_dialog">'+tr("VM Template")+'</input><br />\ <input type="radio" name="quickstart" value="VM.create_dialog">'+tr("VM Instance")+'</input><br />\ <input type="radio" name="quickstart" value="Network.create_dialog">'+tr("Virtual Network")+'</input><br />\ @@ -296,5 +300,13 @@ function updateDashboard(what,json_info){ var total_acls=json_info.length; $('#total_acls',db).html(total_acls); break; + case "clusters": + var total_clusters=json_info.length; + $('#total_clusters',db).html(total_clusters); + break; + case "datastores": + var total_datastores=json_info.length; + $('#total_datastores',db).html(total_datastores); + break; } } \ No newline at end of file diff --git a/src/sunstone/public/js/plugins/datastores-tab.js b/src/sunstone/public/js/plugins/datastores-tab.js index 603fd6867e..88afb16aab 100644 --- a/src/sunstone/public/js/plugins/datastores-tab.js +++ b/src/sunstone/public/js/plugins/datastores-tab.js @@ -265,7 +265,8 @@ var datastore_buttons = { }, "Datastore.create_dialog" : { type: "create_dialog", - text: tr("+ New") + text: tr("+ New"), + condition: mustBeAdmin, }, "Datastore.update_dialog" : { type: "action", @@ -277,6 +278,7 @@ var datastore_buttons = { text: tr("Select cluster"), select: clusters_sel, tip: tr("Select the destination cluster:"), + condition: mustBeAdmin, }, "Datastore.chown" : { type: "confirm_with_select", @@ -354,22 +356,34 @@ function datastoreInfoListener(){ Sunstone.runAction("Datastore.showinfo",id); return false; }); -} +}; + +function updateDatastoreSelect(){ + datastores_select = makeSelectOptions(dataTable_datastores, + 1, + 4, + [], + [] + ); +}; function updateDatastoreElement(request, element_json){ var id = element_json.DATASTORE.ID; var element = datastoreElementArray(element_json); updateSingleElement(element,dataTable_datastores,'#datastore_'+id) + updateDatastoreSelect(); } function deleteDatastoreElement(request){ deleteElement(dataTable_datastores,'#datastore_'+request.request.data); + updateDatastoreSelect(); } function addDatastoreElement(request,element_json){ var id = element_json.DATASTORE.ID; var element = datastoreElementArray(element_json); addElement(element,dataTable_datastores); + updateDatastoreSelect(); } @@ -381,17 +395,28 @@ function updateDatastoresView(request, list){ }); updateView(list_array,dataTable_datastores); + updateDatastoreSelect(); updateDashboard("datastores",list); } function updateDatastoreInfo(request,ds){ var info = ds.DATASTORE; + var images_str = ""; + if (info.IMAGES.ID && + info.IMAGES.ID.constructor == Array){ + for (var i=0; i<info.IMAGES.ID.length;i++){ + images_str+=getImageName(info.IMAGES.ID[i])+', '; + }; + images_str=images_str.slice(0,-2); + } else if (info.IMAGES.ID){ + images_str=getImageName(info.IMAGES.ID); + }; var info_tab = { title : tr("Datastore information"), content: - '<table id="info_datastore_table" class="info_table">\ + '<table id="info_datastore_table" class="info_table" style="width:80%">\ <thead>\ <tr><th colspan="2">'+tr("Datastore information")+' - '+info.NAME+'</th></tr>\ </thead>\ @@ -428,6 +453,10 @@ function updateDatastoreInfo(request,ds){ <td class="key_td">'+tr("Base path")+'</td>\ <td class="value_td">'+info.BASE_PATH+'</td>\ </tr>\ + <tr>\ + <td class="key_td">'+tr("Images")+'</td>\ + <td class="value_td">'+images_str+'</td>\ + </tr>\ <tr><td class="key_td">'+tr("Permissions")+'</td><td></td></tr>\ <tr>\ <td class="key_td"> '+tr("Owner")+'</td>\ diff --git a/src/sunstone/public/js/plugins/images-tab.js b/src/sunstone/public/js/plugins/images-tab.js index ad8d818883..ca5dd57182 100644 --- a/src/sunstone/public/js/plugins/images-tab.js +++ b/src/sunstone/public/js/plugins/images-tab.js @@ -63,6 +63,12 @@ var create_image_tmpl = <textarea name="img_desc" id="img_desc" style="height:4em"></textarea>\ <div class="tip">'+tr("Human readable description of the image for other users.")+'</div>\ </div>\ + <div class="img_param">\ + <label for="img_type">'+tr("Datastore")+':</label>\ + <select id="img_datastore" name="img_datastore">\ + </select>\ + <div class="tip">'+tr("Select the datastore for this image")+'</div>\ + </div>\ </fieldset>\ <fieldset>\ <div class="img_param">\ @@ -850,7 +856,11 @@ function setupCreateImageDialog(){ }); if (exit) { return false; } - var ds_id = $('#img_ds_id',this).val(); + var ds_id = $('#img_datastore',this).val(); + if (!ds_id){ + notifyError(tr("Please select a datastore for this image")); + return false; + }; var img_json = {}; @@ -906,7 +916,6 @@ function setupCreateImageDialog(){ img_json[attr_name] = attr_value; }); - ds_id = 1; img_obj = { "image" : img_json, "ds_id" : ds_id}; @@ -932,6 +941,8 @@ function popUpCreateImageDialog(){ $('#file-uploader input',$create_image_dialog).removeAttr("style"); $('#file-uploader input',$create_image_dialog).attr('style','margin:0;width:256px!important'); + $('#img_datastore',$create_image_dialog).html(datastores_sel()); + $create_image_dialog.dialog('open'); } diff --git a/src/sunstone/public/js/plugins/vnets-tab.js b/src/sunstone/public/js/plugins/vnets-tab.js index b9b63a21b7..f1865b92dc 100644 --- a/src/sunstone/public/js/plugins/vnets-tab.js +++ b/src/sunstone/public/js/plugins/vnets-tab.js @@ -419,6 +419,7 @@ var vnet_buttons = { text: tr("Select cluster"), select: clusters_sel, tip: tr("Select the destination cluster:"), + condition: mustBeAdmin, }, "Network.chown" : { type: "confirm_with_select", diff --git a/src/sunstone/public/js/sunstone-util.js b/src/sunstone/public/js/sunstone-util.js index 02a060b5d3..4b16656250 100644 --- a/src/sunstone/public/js/sunstone-util.js +++ b/src/sunstone/public/js/sunstone-util.js @@ -403,19 +403,26 @@ function waitingNodes(dataTable){ function getUserName(uid){ if (typeof(dataTable_users) != "undefined"){ - return getName(uid,dataTable_users); + return getName(uid,dataTable_users,2); } return uid; } function getGroupName(gid){ if (typeof(dataTable_groups) != "undefined"){ - return getName(gid,dataTable_groups); + return getName(gid,dataTable_groups,2); } return gid; } -function getName(id,dataTable){ +function getImageName(id){ + if (typeof(dataTable_images) != "undefined"){ + return getName(id,dataTable_images,4); + } + return id; +}; + +function getName(id,dataTable,name_col){ var name = id; if (typeof(dataTable) == "undefined") { return name; @@ -424,7 +431,7 @@ function getName(id,dataTable){ $.each(nodes,function(){ if (id == this[1]) { - name = this[2]; + name = this[name_col]; return false; } }); @@ -755,6 +762,10 @@ function clusters_sel() { return clusters_select; } +function datastores_sel() { + return datastores_select; +} + function ownerUse(resource){