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">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'+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){