diff --git a/install.sh b/install.sh index b0801db3c6..48e5d7ef44 100755 --- a/install.sh +++ b/install.sh @@ -896,6 +896,7 @@ SUNSTONE_MODELS_JSON_FILES="src/sunstone/models/OpenNebulaJSON/HostJSON.rb \ src/sunstone/models/OpenNebulaJSON/UserJSON.rb \ src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb \ src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb \ + src/sunstone/models/OpenNebulaJSON/AclJSON.rb \ src/sunstone/models/OpenNebulaJSON/VirtualNetworkJSON.rb" SUNSTONE_TEMPLATE_FILES="src/sunstone/templates/login.html" @@ -917,6 +918,7 @@ SUNSTONE_PUBLIC_JS_PLUGINS_FILES="\ src/sunstone/public/js/plugins/templates-tab.js \ src/sunstone/public/js/plugins/users-tab.js \ src/sunstone/public/js/plugins/vms-tab.js \ + src/sunstone/public/js/plugins/acls-tab.js \ src/sunstone/public/js/plugins/vnets-tab.js" SUNSTONE_PUBLIC_CSS_FILES="src/sunstone/public/css/application.css \ diff --git a/src/ozones/Server/public/js/ozones-util.js b/src/ozones/Server/public/js/ozones-util.js index fabbc5d9b2..c6cae737f2 100644 --- a/src/ozones/Server/public/js/ozones-util.js +++ b/src/ozones/Server/public/js/ozones-util.js @@ -33,6 +33,16 @@ function updateVMsList(req,list,tag,zone_id,zone_name){ $.each(list,function(){ var vm = this.VM; var state = oZones.Helper.resource_state("vm",vm.STATE); + var hostname = "--"; + + if (state == "ACTIVE" || state == "SUSPENDED"){ + if (vm.HISTORY_RECORDS.HISTORY.constructor == Array){ + hostname = vm.HISTORY_RECORDS.HISTORY[vm.HISTORY_RECORDS.HISTORY.length-1].HOSTNAME; + } else { + hostname = vm.HISTORY_RECORDS.HISTORY.HOSTNAME; + }; + }; + if (state == "ACTIVE") { state = oZones.Helper.resource_state("vm_lcm",vm.LCM_STATE); } @@ -42,25 +52,25 @@ function updateVMsList(req,list,tag,zone_id,zone_name){ zone_id, zone_name, vm.ID, - vm.UID, - vm.GID, + vm.UNAME, + vm.GNAME, vm.NAME, state, vm.CPU, humanize_size(vm.MEMORY), - vm.HISTORY ? vm.HISTORY.HOSTNAME : "--", + hostname, pretty_time(vm.STIME) ]); } else { vms_array.push([ vm.ID, - vm.UID, - vm.GID, + vm.UNAME, + vm.GNAME, vm.NAME, state, vm.CPU, humanize_size(vm.MEMORY), - vm.HISTORY ? vm.HISTORY.HOSTNAME : "--", + vm.HISTORY_RECORDS ? vm.HISTORY_RECORDS.HISTORY.HOSTNAME : "--", pretty_time(vm.STIME) ]); }; @@ -88,8 +98,8 @@ function updateVNsList(req,list,tag,zone_id,zone_name){ zone_id, zone_name, network.ID, - network.UID, - network.GID, + network.UNAME, + network.GNAME, network.NAME, parseInt(network.TYPE) ? "FIXED" : "RANGED", network.BRIDGE, @@ -99,8 +109,8 @@ function updateVNsList(req,list,tag,zone_id,zone_name){ } else { vn_array.push([ network.ID, - network.UID, - network.GID, + network.UNAME, + network.GNAME, network.NAME, parseInt(network.TYPE) ? "FIXED" : "RANGED", network.BRIDGE, @@ -124,8 +134,8 @@ function updateTemplatesList(req,list,tag,zone_id,zone_name){ zone_id, zone_name, template.ID, - template.UID, - template.GID, + template.UNAME, + template.GNAME, template.NAME, pretty_time(template.REGTIME), parseInt(template.PUBLIC) ? "yes" : "no" @@ -133,8 +143,8 @@ function updateTemplatesList(req,list,tag,zone_id,zone_name){ } else { template_array.push([ template.ID, - template.UID, - template.GID, + template.UNAME, + template.GNAME, template.NAME, pretty_time(template.REGTIME), parseInt(template.PUBLIC) ? "yes" : "no" @@ -191,8 +201,8 @@ function updateImagesList(req,list,tag,zone_id,zone_name){ zone_id, zone_name, image.ID, - image.UID, - image.GID, + image.UNAME, + image.GNAME, image.NAME, oZones.Helper.image_type(image.TYPE), pretty_time(image.REGTIME), @@ -204,8 +214,8 @@ function updateImagesList(req,list,tag,zone_id,zone_name){ } else { image_array.push([ image.ID, - image.UID, - image.GID, + image.UNAME, + image.GNAME, image.NAME, oZones.Helper.image_type(image.TYPE), pretty_time(image.REGTIME), diff --git a/src/ozones/Server/public/js/ozones.js b/src/ozones/Server/public/js/ozones.js index b77601bca3..a825b391b0 100644 --- a/src/ozones/Server/public/js/ozones.js +++ b/src/ozones/Server/public/js/ozones.js @@ -21,7 +21,12 @@ var oZones = { var error = {}; if (resp.responseText) { - error = JSON.parse(resp.responseText); + try { + error = JSON.parse(resp.responseText); + } + catch (e) { + error.error = {message: "It appears there was a server exception. Please check server's log."}; + }; } else { diff --git a/src/ozones/Server/public/js/plugins/aggregated-tab.js b/src/ozones/Server/public/js/plugins/aggregated-tab.js index 3f7f83db4c..710e5fa53b 100644 --- a/src/ozones/Server/public/js/plugins/aggregated-tab.js +++ b/src/ozones/Server/public/js/plugins/aggregated-tab.js @@ -186,7 +186,6 @@ var agg_actions = { waitingNodes(dataTable_agg_hosts); Sunstone.runAction("ZoneHosts.list"); }, - callback: Empty, error: onError, notify: false }, @@ -207,7 +206,6 @@ var agg_actions = { waitingNodes(dataTable_agg_vms); Sunstone.runAction("ZoneVMs.list"); }, - callback: Empty, error: onError, notify: false }, @@ -228,7 +226,6 @@ var agg_actions = { waitingNodes(dataTable_agg_vns); Sunstone.runAction("ZoneVNs.list"); }, - callback: Empty, error: onError, notify: false }, @@ -249,7 +246,6 @@ var agg_actions = { waitingNodes(dataTable_agg_images); Sunstone.runAction("ZoneImages.list"); }, - callback: Empty, error: onError, notify: false }, @@ -270,7 +266,6 @@ var agg_actions = { waitingNodes(dataTable_agg_users); Sunstone.runAction("ZoneUsers.list"); }, - callback: Empty, error: onError, notify: false }, @@ -291,7 +286,6 @@ var agg_actions = { waitingNodes(dataTable_agg_templates); Sunstone.runAction("ZoneTemplates.list"); }, - callback: Empty, error: onError, notify: false }, diff --git a/src/ozones/Server/public/js/plugins/dashboard-tab.js b/src/ozones/Server/public/js/plugins/dashboard-tab.js index 20761d59b3..34553f45ab 100644 --- a/src/ozones/Server/public/js/plugins/dashboard-tab.js +++ b/src/ozones/Server/public/js/plugins/dashboard-tab.js @@ -177,8 +177,7 @@ var dashboard_tab_content = var dashboard_tab = { title: 'Dashboard', - content: dashboard_tab_content, - condition : True + content: dashboard_tab_content } Sunstone.addMainTab('dashboard_tab',dashboard_tab); diff --git a/src/ozones/Server/public/js/plugins/vdcs-tab.js b/src/ozones/Server/public/js/plugins/vdcs-tab.js index 9c113c1da7..c995495f43 100644 --- a/src/ozones/Server/public/js/plugins/vdcs-tab.js +++ b/src/ozones/Server/public/js/plugins/vdcs-tab.js @@ -94,7 +94,6 @@ var vdc_actions = { waitingNodes(dataTable_vdcs); Sunstone.runAction("Zone.list"); }, - callback: Empty, error: onError }, diff --git a/src/ozones/Server/public/js/plugins/zones-tab.js b/src/ozones/Server/public/js/plugins/zones-tab.js index 1006d523b8..920d024609 100644 --- a/src/ozones/Server/public/js/plugins/zones-tab.js +++ b/src/ozones/Server/public/js/plugins/zones-tab.js @@ -91,7 +91,6 @@ var zone_actions = { waitingNodes(dataTable_zones); Sunstone.runAction("Zone.list"); }, - callback: Empty, error: onError, notify: false }, diff --git a/src/sunstone/etc/sunstone-plugins.yaml b/src/sunstone/etc/sunstone-plugins.yaml index 3b4c997c4d..38228d404e 100644 --- a/src/sunstone/etc/sunstone-plugins.yaml +++ b/src/sunstone/etc/sunstone-plugins.yaml @@ -40,3 +40,8 @@ :user: :group: oneadmin: true +- plugins/acls-tab.js: + :ALL: false + :user: + :group: + oneadmin: true diff --git a/src/sunstone/models/OpenNebulaJSON.rb b/src/sunstone/models/OpenNebulaJSON.rb index 44685c68f9..0eb98bd37c 100644 --- a/src/sunstone/models/OpenNebulaJSON.rb +++ b/src/sunstone/models/OpenNebulaJSON.rb @@ -26,6 +26,7 @@ require 'OpenNebulaJSON/PoolJSON' require 'OpenNebulaJSON/UserJSON' require 'OpenNebulaJSON/VirtualMachineJSON' require 'OpenNebulaJSON/VirtualNetworkJSON' +require 'OpenNebulaJSON/AclJSON' module OpenNebula class Error diff --git a/src/sunstone/models/OpenNebulaJSON/AclJSON.rb b/src/sunstone/models/OpenNebulaJSON/AclJSON.rb new file mode 100644 index 0000000000..0db8a68ac1 --- /dev/null +++ b/src/sunstone/models/OpenNebulaJSON/AclJSON.rb @@ -0,0 +1,51 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# 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. # +#--------------------------------------------------------------------------- # + +require 'OpenNebulaJSON/JSONUtils' + +module OpenNebulaJSON + class AclJSON < OpenNebula::Acl + include JSONUtils + + def create(template_json) + acl_string = parse_json(template_json, 'acl') + acl_rule = Acl.parse_rule(acl_string) + if OpenNebula.is_error?(acl_rule) + return acl_rule + end + self.allocate(acl_rule[0],acl_rule[1],acl_rule[2]) + end + + def perform_action(template_json) + action_hash = parse_json(template_json, 'action') + if OpenNebula.is_error?(action_hash) + return action_hash + end + + error_msg = "#{action_hash['perform']} action not " << + " available for this resource" + OpenNebula::Error.new(error_msg) + + # rc = case action_hash['perform'] + # #no actions! + # else + # error_msg = "#{action_hash['perform']} action not " << + # " available for this resource" + # OpenNebula::Error.new(error_msg) + # end + end + end +end diff --git a/src/sunstone/models/OpenNebulaJSON/PoolJSON.rb b/src/sunstone/models/OpenNebulaJSON/PoolJSON.rb index 150956bdf6..a59db50c73 100644 --- a/src/sunstone/models/OpenNebulaJSON/PoolJSON.rb +++ b/src/sunstone/models/OpenNebulaJSON/PoolJSON.rb @@ -24,4 +24,5 @@ module OpenNebulaJSON class TemplatePoolJSON < OpenNebula::TemplatePool; include JSONUtils; end class GroupPoolJSON < OpenNebula::GroupPool; include JSONUtils; end class UserPoolJSON < OpenNebula::UserPool; include JSONUtils; end + class AclPoolJSON < OpenNebula::AclPool; include JSONUtils; end end diff --git a/src/sunstone/models/SunstoneServer.rb b/src/sunstone/models/SunstoneServer.rb index fc553b3559..18e98cc371 100644 --- a/src/sunstone/models/SunstoneServer.rb +++ b/src/sunstone/models/SunstoneServer.rb @@ -74,6 +74,7 @@ class SunstoneServer when "vm" then VirtualMachinePoolJSON.new(@client, user_flag) when "vnet" then VirtualNetworkPoolJSON.new(@client, user_flag) when "user" then UserPoolJSON.new(@client) + when "acl" then AclPoolJSON.new(@client) else error = Error.new("Error: #{kind} resource not supported") return [404, error.to_json] @@ -125,6 +126,7 @@ class SunstoneServer when "vm" then VirtualMachineJSON.new(VirtualMachine.build_xml,@client) when "vnet" then VirtualNetworkJSON.new(VirtualNetwork.build_xml, @client) when "user" then UserJSON.new(User.build_xml, @client) + when "acl" then AclJSON.new(Acl.build_xml, @client) else error = Error.new("Error: #{kind} resource not supported") return [404, error.to_json] @@ -249,15 +251,14 @@ class SunstoneServer end # The VM host and its VNC port - host = resource['HISTORY/HOSTNAME'] + host = resource['/VM/HISTORY_RECORDS/HISTORY[last()]/HOSTNAME'] vnc_port = resource['TEMPLATE/GRAPHICS/PORT'] # The noVNC proxy_port proxy_port = config[:vnc_proxy_base_port].to_i + vnc_port.to_i begin - novnc_cmd = "#{config[:novnc_path]}/utils/launch.sh" - pipe = IO.popen("#{novnc_cmd} --listen #{proxy_port} \ - --vnc #{host}:#{vnc_port}") + novnc_cmd = "#{config[:novnc_path]}/utils/wsproxy.py" + pipe = IO.popen("#{novnc_cmd} #{proxy_port} #{host}:#{vnc_port}") rescue Exception => e error = Error.new(e.message) return [500, error.to_json] @@ -344,6 +345,7 @@ class SunstoneServer when "vm" then VirtualMachineJSON.new_with_id(id, @client) when "vnet" then VirtualNetworkJSON.new_with_id(id, @client) when "user" then UserJSON.new_with_id(id, @client) + when "acl" then AclJSON.new_with_id(id, @client) else error = Error.new("Error: #{kind} resource not supported") return error diff --git a/src/sunstone/public/js/opennebula.js b/src/sunstone/public/js/opennebula.js index 769bffab40..276672778c 100644 --- a/src/sunstone/public/js/opennebula.js +++ b/src/sunstone/public/js/opennebula.js @@ -21,7 +21,12 @@ var OpenNebula = { var error = {}; if (resp.responseText) { - error = JSON.parse(resp.responseText); + try { + error = JSON.parse(resp.responseText); + } + catch (e) { + error.error = {message: "It appears there was a server exception. Please check server's log."}; + }; } else { @@ -2589,5 +2594,95 @@ var OpenNebula = { "chgrp" : function(params){ OpenNebula.Helper.chgrp(params,OpenNebula.Template.resource,"template"); } + }, + + "Acl" : { + "resource" : "ACL", + "create" : function(params){ + var callback = params.success; + var callback_error = params.error; + var data = params.data; + var resource = OpenNebula.Acl.resource; + + var request = OpenNebula.Helper.request(resource,"create",data); + + $.ajax({ + url: "acl", + type: "POST", + dataType: "json", + data: JSON.stringify(data), + success: function(response) + { + if (callback) + { + callback(request, response); + } + }, + error: function(response) + { + if (callback_error) + { + callback_error(request, OpenNebula.Error(response)); + } + } + }); + }, + "list" : function(params){ + var callback = params.success; + var callback_error = params.error; + var timeout = params.timeout || false; + + var resource = OpenNebula.Acl.resource; + var request = OpenNebula.Helper.request(resource,"list"); + + $.ajax({ + url: "acl", + type: "GET", + dataType: "json", + data: {timeout: timeout}, + success: function(response) + { + if (callback) + { + var acl_pool = OpenNebula.Helper.pool(resource,response); + callback(request, acl_pool); + } + }, + error: function(response) + { + if (callback_error) + { + callback_error(request, OpenNebula.Error(response)); + } + } + }); + }, + "delete" : function(params){ + var callback = params.success; + var callback_error = params.error; + var id = params.data.id; + var resource = OpenNebula.Acl.resource; + + var request = OpenNebula.Helper.request(resource,"delete", id); + + $.ajax({ + url: "acl/" + id, + type: "DELETE", + success: function() + { + if (callback) + { + callback(request); + } + }, + error: function(response) + { + if (callback_error) + { + callback_error(request, OpenNebula.Error(response)); + } + } + }); + } } } diff --git a/src/sunstone/public/js/plugins/acls-tab.js b/src/sunstone/public/js/plugins/acls-tab.js new file mode 100644 index 0000000000..d25e45dc49 --- /dev/null +++ b/src/sunstone/public/js/plugins/acls-tab.js @@ -0,0 +1,498 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* 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. */ +/* -------------------------------------------------------------------------- */ + +/*ACLs tab plugin*/ +var dataTable_acls; +var $create_acl_dialog; + +var acls_tab_content = +'
\ +
\ +
\ +\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
AllIDApplies toAffected resourcesResource ID / Owned byAllowed operations
\ +
'; + +var create_acl_tmpl = +'
\ +
\ +
\ + \ + \ +
\ + \ + Hosts
\ + Virtual Machines
\ + Virtual Networks
\ + Images
\ + Templates
\ + Users
\ + Groups
\ +
\ + \ + All
\ + Specific ID
\ + Owned by group
\ +
\ + \ + \ +
\ + \ + \ +
\ + \ + Create
\ + Delete
\ + Use
\ + Manage
\ + Get Information
\ + Get Pool of resources
\ + Get Pool of my/group\'s resources
\ + Change owner
\ + Deploy
\ +
\ + \ + \ +
\ +
\ +
\ +
\ + \ + \ +
\ +
\ +
'; + +var acl_actions = { + "Acl.create" : { + type: "create", + call: OpenNebula.Acl.create, + callback: function(){ + Sunstone.runAction("Acl.list"); + }, + error: onError, + notify: true + }, + + "Acl.create_dialog" : { + type: "custom", + call: popUpCreateAclDialog + }, + + "Acl.list" : { + type: "list", + call: OpenNebula.Acl.list, + callback: updateAclsView, + error: onError + }, + + "Acl.refresh" : { + type: "custom", + call: function () { + waitingNodes(dataTable_acls); + Sunstone.runAction("Acl.list"); + } + }, + + "Acl.autorefresh" : { + type: "custom", + call: function(){ + OpenNebula.Acl.list({ + timeout: true, + success: updateAclsView, + error: onError + }); + } + }, + + "Acl.delete" : { + type: "multiple", + call: OpenNebula.Acl.delete, + callback: deleteAclElement, + elements: aclElements, + error: onError, + notify: true + }, +} + +var acl_buttons = { + "Acl.refresh" : { + type: "image", + text: "Refresh list", + img: "images/Refresh-icon.png" + }, + "Acl.create_dialog" : { + type: "create_dialog", + text: "+ New" + }, + "Acl.delete" : { + type: "action", + text: "Delete" + } +} + +var acls_tab = { + title: "ACLs", + content: acls_tab_content, + buttons: acl_buttons +} + +Sunstone.addActions(acl_actions); +Sunstone.addMainTab('acls_tab',acls_tab); + +//Returns selected elements on the acl datatable +function aclElements(){ + return getSelectedNodes(dataTable_acls); +} + +//Receives a segment of an ACL and translates: +// * -> All +// @1 -> Group 1 (tries to translate "1" into group name) +// #1 -> User 1 (tries to translate "1" into username) +//Translation of usernames and groupnames depends on +//group and user plugins tables. +function parseUserAcl(user){ + var user_str=""; + if (user[0] == '*'){ + user_str = "All"; + } else { + if (user[0] == '#'){ + user_str="User "; + user_str+= getUserName(user.substring(1)); + } + else if (user[0] == '@'){ + user_str="Group "; + user_str+= getGroupName(user.substring(1)); + }; + }; + return user_str; +} + +//Similar to above, but #1 means resource with "ID 1" +function parseResourceAcl(user){ + var user_str=""; + if (user[0] == '*'){ + user_str = "All"; + } else { + if (user[0] == '#'){ + user_str="ID "; + user_str+= user.substring(1); + } + else if (user[0] == '@'){ + user_str="Group "; + user_str+= getGroupName(user.substring(1)); + }; + }; + return user_str; +} + +//Parses a full ACL string, and translates it into +//a legible array +//to be put in the datatable fields. +function parseAclString(string) { + var space_split = string.split(' '); + var user = space_split[0]; + var resources = space_split[1]; + var rights = space_split[2]; + + //User + var user_str=parseUserAcl(user); + + + //Resources + var resources_str=""; + var resources_array = resources.split('/'); + var belonging_to = parseResourceAcl(resources_array[1]); + resources_array = resources_array[0].split('+'); + for (var i=0; i', + acl.ID, + acl_array[0], + acl_array[1], + acl_array[2], + acl_array[3] + ] +} + + +// Callback to delete a single element from the dataTable +function deleteAclElement(request){ + deleteElement(dataTable_acls,'#acl_'+request.request.data); +} + +//update the datatable with new data +function updateAclsView(request,list){ + var list_array = []; + $.each(list,function(){ + list_array.push(aclElementArray(this)); + }); + updateView(list_array,dataTable_acls); + updateDashboard("acls",list); +} + +function setupCreateAclDialog(){ + dialogs_context.append('
'); + $create_acl_dialog = $('#create_acl_dialog',dialogs_context); + var dialog = $create_acl_dialog; + dialog.html(create_acl_tmpl); + var height = Math.floor($(window).height()*0.8); //set height to a percentage of the window + //Prepare jquery dialog + dialog.dialog({ + autoOpen: false, + modal:true, + width: 600, + height: height + }); + + $('#res_subgroup_all',dialog).attr("checked","checked"); + $('#res_id',dialog).attr("disabled","disabled"); + $('#belonging_to',dialog).attr("disabled","disabled"); + + $('button',dialog).button(); + + $('.res_subgroup',dialog).click(function(){ + var value = $(this).val(); + var context = $(this).parent(); + switch (value) { + case "*": + $('#res_id',context).attr("disabled","disabled"); + $('#belonging_to',context).attr("disabled","disabled"); + break; + case "res_id": + $('#res_id',context).removeAttr("disabled"); + $('#belonging_to').attr("disabled","disabled"); + break; + case "belonging_to": + $('#res_id',context).attr("disabled","disabled"); + $('#belonging_to',context).removeAttr("disabled"); + break; + }; + }); + + $('input#res_id',dialog).keyup(function(){ + $(this).trigger("change"); + }); + + //update the rule preview every time some field changes + $('input,select',dialog).change(function(){ + var context = $('#create_acl_form',$create_acl_dialog); + var user = $('#applies',context).val(); + + if ($('#applies :selected',context).hasClass("user")){ + user='#'+user; + } else if ($('#applies :selected',context).hasClass("group")){ + user = '@'+user; + }; + + var resources = ""; + $('.resource_cb:checked',context).each(function(){ + resources+=$(this).val()+'+'; + }); + if (resources.length) { resources = resources.substring(0,resources.length-1) }; + + var belonging=""; + var mode = $('.res_subgroup:checked',context).val(); + switch (mode) { + case "*": + belonging="*"; + break; + case "res_id": + belonging="#"+$('#res_id',context).val(); + break; + case "belonging_to": + belonging="@"+$('#belonging_to',context).val(); + break; + } + + + var rights = ""; + $('.right_cb:checked',context).each(function(){ + rights+=$(this).val()+'+'; + }); + if (rights.length) { rights = rights.substring(0,rights.length-1) }; + + var acl_string = user + ' ' + resources + '/' + belonging + ' ' + rights; + $('#acl_preview',context).val(acl_string); + + }); + + $('#create_acl_form',dialog).submit(function(){ + var user = $('#applies',this).val(); + if (!user.length) { + notifyError("Please specify to who this ACL applies"); + return false; + }; + + var resources = $('.resource_cb:checked',this).length; + if (!resources) { + notifyError("Please select at least one resource"); + return false; + } + + var mode = $('.res_subgroup:checked',this).val(); + switch (mode) { + case "res_id": + var l=$('#res_id',this).val().length; + if (!l){ + notifyError("Please provide a resource ID for the resource(s) in this rule"); + return false; + } + break; + case "belonging_to": + var l=$('#belonging_to',this).val().length; + if (!l){ + notifyError("Please select a group to which the selected resources belong to"); + return false; + } + break; + } + + var rights = $('.right_cb:checked',this).length; + if (!rights) { + notifyError("Please select at least one operation"); + return false; + } + + var acl_string = $('#acl_preview',this).val(); + + var acl_json = { "acl" : acl_string }; + Sunstone.runAction("Acl.create",acl_json); + $create_acl_dialog.dialog('close'); + return false; + }); +} + +// Before popping up the dialog, some prepartions are +// required: we have to put the right options in the +// selects. +function popUpCreateAclDialog(){ + var users = $(''); + $('.empty_value',users).remove(); + $('option',users).addClass("user"); + users.prepend(''); + + var groups = $(''); + $('.empty_value',groups).remove(); + $('option',groups).addClass("group"); + groups.prepend(''); + + var dialog = $create_acl_dialog; + $('#applies',dialog).html(''+ + users.html()+groups.html()); + $('#belonging_to',dialog).html(groups_select); + + $('#applies',dialog).trigger("change"); + dialog.dialog('open'); +} + +// Prepare the autorefresh of the list +function setAclAutorefresh(){ + setInterval(function(){ + var checked = $('input:checked',dataTable_acls.fnGetNodes()); + var filter = $("#datatable_acls_filter input",dataTable_acls.parents("#datatable_acls_wrapper")).attr("value"); + if (!checked.length && !filter.length){ + Sunstone.runAction("Acl.autorefresh"); + } + },INTERVAL+someTime()); +} + +$(document).ready(function(){ + //if we are not oneadmin, our tab will not even be in the DOM. + dataTable_acls = $("#datatable_acls",main_tabs_context).dataTable({ + "bJQueryUI": true, + "bSortClasses": false, + "sPaginationType": "full_numbers", + "bAutoWidth":false, + "aoColumnDefs": [ + { "bSortable": false, "aTargets": ["check"] }, + { "sWidth": "60px", "aTargets": [0] }, + { "sWidth": "35px", "aTargets": [1] } + ] + }); + dataTable_acls.fnClearTable(); + addElement([ + spinner, + '','','','',''],dataTable_acls); + + Sunstone.runAction("Acl.list"); + + setupCreateAclDialog(); + setAclAutorefresh(); + + initCheckAllBoxes(dataTable_acls); + tableCheckboxesListener(dataTable_acls); + //shortenedInfoFields('#datatable_acls'); + +}) diff --git a/src/sunstone/public/js/plugins/dashboard-tab.js b/src/sunstone/public/js/plugins/dashboard-tab.js index 2218cd3710..56b2b475e8 100644 --- a/src/sunstone/public/js/plugins/dashboard-tab.js +++ b/src/sunstone/public/js/plugins/dashboard-tab.js @@ -14,6 +14,7 @@ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ +/** HISTORY_LENGTH currently ignored on server, but it doesn't harm to have it**/ var HISTORY_LENGTH=40; var GRAPH_AUTOREFRESH_INTERVAL=60000; //60 secs @@ -81,6 +82,10 @@ var dashboard_tab_content = Users\ \ \ + \ + ACL Rules\ + \ + \ \ \ \ @@ -93,14 +98,15 @@ var dashboard_tab_content =

Quickstart

\
\
\ - \ + \ Host
\ - Group
\ - VM Template
\ VM Instance
\ + VM Template
\ Virtual Network
\ Image
\ User
\ + Group
\ + Acl
\
\ \ \ @@ -138,26 +144,27 @@ var dashboard_tab_content = var dashboard_tab = { title: 'Dashboard', - content: dashboard_tab_content, - condition : True + content: dashboard_tab_content } Sunstone.addMainTab('dashboard_tab',dashboard_tab); function plot_global_graph(data,info){ + var context = $('#historical_table',main_tabs_context); var id = info.title; var monitoring = data.monitoring; var serie; var series = []; var width = ($(window).width()-129)*48/100; var mon_count = 0; + var labels_array = info.monitor_resources.split(','); - $('#'+id).html('
'); + $('#'+id,context).html('
'); - for (var label in monitoring) { + for (var i=0; i
'); + $('#'+id,context).html('
'); - for (var label in monitoring) { + for (var i=0; i\ @@ -93,9 +92,7 @@ var group_actions = { waitingNodes(dataTable_groups); Sunstone.runAction("Group.list"); }, - callback: function(){}, - error: onError, - notify: false + error: onError }, "Group.delete" : { @@ -103,7 +100,7 @@ var group_actions = { call : OpenNebula.Group.delete, callback : deleteGroupElement, error : onError, - elements: function() { return getSelectedNodes(dataTable_groups); }, + elements: groupElements, notify:true }, @@ -122,13 +119,11 @@ var group_buttons = { "Group.refresh" : { type: "image", text: "Refresh list", - img: "images/Refresh-icon.png", - condition: True + img: "images/Refresh-icon.png" }, "Group.create_dialog" : { type: "create_dialog", - text: "+ New Group", - condition : True + text: "+ New Group" }, // "Group.chown" : { // type: "confirm_with_select", @@ -140,21 +135,23 @@ var group_buttons = { "Group.delete" : { type: "action", - text: "Delete", - condition : True + text: "Delete" } }; var groups_tab = { title: 'Groups', content: groups_tab_content, - buttons: group_buttons, - condition: True + buttons: group_buttons } Sunstone.addActions(group_actions); Sunstone.addMainTab('groups_tab',groups_tab); +function groupElements(){ + return getSelectedNodes(dataTable_groups); +} + function groupElementArray(group_json){ var group = group_json.GROUP; @@ -176,19 +173,24 @@ function groupElementArray(group_json){ users_str ]; } -function groupInfoListener(){ - $('#tbodygroups tr').live("click",function(e){ - //do nothing if we are clicking a checkbox! - if ($(e.target).is('input')) {return true;} - var aData = dataTable_groups.fnGetData(this); - var id = $(aData[0]).val(); - Sunstone.runAction("Group.showinfo",id); - return false; - }); -} +// function groupInfoListener(){ +// $('#groups_tab #tbodygroups tr',main_tabs_context).live("click",function(e){ +// //do nothing if we are clicking a checkbox! +// if ($(e.target).is('input')) {return true;} +// var aData = dataTable_groups.fnGetData(this); +// var id = $(aData[0]).val(); +// Sunstone.runAction("Group.showinfo",id); +// return false; +// }); +// } function updateGroupSelect(){ - groups_select = makeSelectOptions(dataTable_groups,1,2,-1,"",-1); + groups_select = makeSelectOptions(dataTable_groups, + 1,//id_col + 2,//name_col + [],//status_cols + []//bad_status_cols + ); } function updateGroupElement(request, group_json){ @@ -199,7 +201,7 @@ function updateGroupElement(request, group_json){ } function deleteGroupElement(request){ - deleteElement(dataTable_groups,'#group_'+req.request.data); + deleteElement(dataTable_groups,'#group_'+request.request.data); updateGroupSelect(); } @@ -226,27 +228,30 @@ function updateGroupsView(request, group_list){ //Prepares the dialog to create function setupCreateGroupDialog(){ - $('div#dialogs').append('
'); - $('#create_group_dialog').html(create_group_tmpl); - $('#create_group_dialog').dialog({ + dialogs_context.append('
'); + $create_group_dialog = $('#create_group_dialog',dialogs_context); + var dialog = $create_group_dialog; + + dialog.html(create_group_tmpl); + dialog.dialog({ autoOpen: false, modal: true, width: 400 }); - $('#create_group_dialog button').button(); + $('button',dialog).button(); - $('#create_group_form').submit(function(){ + $('#create_group_form',dialog).submit(function(){ var name=$('#name',this).val(); var group_json = { "group" : { "name" : name }}; Sunstone.runAction("Group.create",group_json); - $('#create_group_dialog').dialog('close'); + $create_group_dialog.dialog('close'); return false; }); } function popUpCreateGroupDialog(){ - $('#create_group_dialog').dialog('open'); + $create_group_dialog.dialog('open'); return false; } @@ -254,7 +259,7 @@ function popUpCreateGroupDialog(){ function setGroupAutorefresh(){ setInterval(function(){ var checked = $('input:checked',dataTable_groups.fnGetNodes()); - var filter = $("#datatable_groups_filter input").attr("value"); + var filter = $("#datatable_groups_filter input",dataTable_groups.parents("#datatable_groups_wrapper")).attr("value"); if (!checked.length && !filter.length){ Sunstone.runAction("Group.autorefresh"); } @@ -262,7 +267,7 @@ function setGroupAutorefresh(){ } $(document).ready(function(){ - dataTable_groups = $("#datatable_groups").dataTable({ + dataTable_groups = $("#datatable_groups",main_tabs_context).dataTable({ "bJQueryUI": true, "bSortClasses": false, "sPaginationType": "full_numbers", diff --git a/src/sunstone/public/js/plugins/hosts-tab.js b/src/sunstone/public/js/plugins/hosts-tab.js index 333388c144..655fe75d07 100644 --- a/src/sunstone/public/js/plugins/hosts-tab.js +++ b/src/sunstone/public/js/plugins/hosts-tab.js @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ /*Host tab plugin*/ - +/* HOST_HISTORY_LENGTH is ignored by server */ var HOST_HISTORY_LENGTH = 40; var host_graphs = [ { @@ -98,8 +98,8 @@ var create_host_tmpl =
'; var hosts_select=""; -var host_list_json = {}; var dataTable_hosts; +var $create_host_dialog; //Setup actions var host_actions = { @@ -121,8 +121,7 @@ var host_actions = { type: "list", call: OpenNebula.Host.list, callback: updateHostsView, - error: onError, - notify: false + error: onError }, "Host.show" : { @@ -145,9 +144,7 @@ var host_actions = { waitingNodes(dataTable_hosts); Sunstone.runAction("Host.list"); }, - callback: function(){}, - error: onError, - notify:false + error: onError }, "Host.autorefresh" : { @@ -163,7 +160,7 @@ var host_actions = { callback : function (req) { Sunstone.runAction("Host.show",req.request.data[0]); }, - elements: function() { return getSelectedNodes(dataTable_hosts); }, + elements: hostElements, error : onError, notify: true }, @@ -174,7 +171,7 @@ var host_actions = { callback : function (req) { Sunstone.runAction("Host.show",req.request.data[0]); }, - elements: function() { return getSelectedNodes(dataTable_hosts); }, + elements: hostElements, error : onError, notify:true }, @@ -183,7 +180,7 @@ var host_actions = { type: "multiple", call : OpenNebula.Host.delete, callback : deleteHostElement, - elements: function() { return getSelectedNodes(dataTable_hosts); }, + elements: hostElements, error : onError, notify:true }, @@ -215,8 +212,7 @@ var host_actions = { callback: function (request,response) { $('#template_update_dialog #template_update_textarea').val(response.template); }, - error: onError, - notify: false + error: onError }, "Host.update_dialog" : { @@ -232,8 +228,7 @@ var host_actions = { callback: function() { notifyMessage("Template updated correctly"); }, - error: onError, - notify: false + error: onError } }; @@ -241,34 +236,28 @@ var host_buttons = { "Host.refresh" : { type: "image", text: "Refresh list", - img: "images/Refresh-icon.png", - condition: True + img: "images/Refresh-icon.png" }, "Host.create_dialog" : { type: "create_dialog", - text: "+ New", - condition :True + text: "+ New" }, "Host.update_dialog" : { type: "action", text: "Update a template", - condition: True, alwaysActive: true }, "Host.enable" : { type: "action", - text: "Enable", - condition : True + text: "Enable" }, "Host.disable" : { type: "action", - text: "Disable", - condition : True + text: "Disable" }, "Host.delete" : { type: "action", - text: "Delete host", - condition : True + text: "Delete host" } }; @@ -292,8 +281,7 @@ var host_info_panel = { var hosts_tab = { title: 'Hosts', content: hosts_tab_content, - buttons: host_buttons, - condition: True + buttons: host_buttons } Sunstone.addActions(host_actions); @@ -301,6 +289,10 @@ Sunstone.addMainTab('hosts_tab',hosts_tab); Sunstone.addInfoPanel("host_info_panel",host_info_panel); +function hostElements(){ + return getSelectedNodes(dataTable_hosts); +} + //Creates an array to be added to the dataTable from the JSON of a host. function hostElementArray(host_json){ @@ -357,8 +349,7 @@ function hostElementArray(host_json){ //Listen to clicks on the tds of the tables and shows the info dialogs. function hostInfoListener(){ - $('#tbodyhosts tr').live("click",function(e){ - + $('#tbodyhosts tr',dataTable_hosts).live("click",function(e){ //do nothing if we are clicking a checkbox! if ($(e.target).is('input')) {return true;} popDialogLoading(); @@ -371,7 +362,12 @@ function hostInfoListener(){ //updates the host select by refreshing the options in it function updateHostSelect(){ - hosts_select = makeSelectOptions(dataTable_hosts,1,2,7,"DISABLED",-1); + hosts_select = makeSelectOptions(dataTable_hosts, + 1,//id_col + 2,//name_col + [6,6],//status_cols + ["ERROR","OFF"]//bad_st + ); } //callback for an action affecting a host element @@ -398,7 +394,6 @@ function addHostElement(request,host_json){ //callback to update the list of hosts. function updateHostsView (request,host_list){ - host_list_json = host_list; var host_list_array = []; $.each(host_list,function(){ @@ -409,7 +404,7 @@ function updateHostsView (request,host_list){ updateView(host_list_array,dataTable_hosts); updateHostSelect(); //dependency with the dashboard plugin - updateDashboard("hosts",host_list_json); + updateDashboard("hosts",host_list); } //Updates the host info panel tab's content and pops it up @@ -511,18 +506,21 @@ function updateHostInfo(request,host){ //Prepares the host creation dialog function setupCreateHostDialog(){ - $('div#dialogs').append('
'); - $('div#create_host_dialog').html(create_host_tmpl); - $('#create_host_dialog').dialog({ + dialogs_context.append('
'); + $create_host_dialog = $('div#create_host_dialog'); + var dialog = $create_host_dialog; + + dialog.html(create_host_tmpl); + dialog.dialog({ autoOpen: false, modal: true, width: 500 }); - $('#create_host_dialog button').button(); + $('button',dialog).button(); //Handle the form submission - $('#create_host_form').submit(function(){ + $('#create_host_form',dialog).submit(function(){ if (!($('#name',this).val().length)){ notifyError("Host name missing!"); return false; @@ -539,14 +537,14 @@ function setupCreateHostDialog(){ //Create the OpenNebula.Host. //If it's successfull we refresh the list. Sunstone.runAction("Host.create",host_json); - $('#create_host_dialog').dialog('close'); + $create_host_dialog.dialog('close'); return false; }); } //Open creation dialogs function popUpCreateHostDialog(){ - $('#create_host_dialog').dialog('open'); + $create_host_dialog.dialog('open'); return false; } @@ -554,7 +552,7 @@ function popUpCreateHostDialog(){ function setHostAutorefresh() { setInterval(function(){ var checked = $('input:checked',dataTable_hosts.fnGetNodes()); - var filter = $("#datatable_hosts_filter input").attr("value"); + var filter = $("#datatable_hosts_filter input",dataTable_hosts.parents('#datatable_hosts_wrapper')).attr("value"); if (!checked.length && !filter.length){ Sunstone.runAction("Host.autorefresh"); } @@ -570,6 +568,9 @@ function hostMonitorError(req,error_json){ $('#host_monitoring_tab '+id).html('
'+message+'
'); } +function hosts_sel() { + return hosts_select; +} //This is executed after the sunstone.js ready() is run. //Here we can basicly init the host datatable, preload it @@ -577,7 +578,7 @@ function hostMonitorError(req,error_json){ $(document).ready(function(){ //prepare host datatable - dataTable_hosts = $("#datatable_hosts").dataTable({ + dataTable_hosts = $("#datatable_hosts",main_tabs_context).dataTable({ "bJQueryUI": true, "bSortClasses": false, "bAutoWidth":false, diff --git a/src/sunstone/public/js/plugins/images-tab.js b/src/sunstone/public/js/plugins/images-tab.js index e0a675456a..b1ed59e5cb 100644 --- a/src/sunstone/public/js/plugins/images-tab.js +++ b/src/sunstone/public/js/plugins/images-tab.js @@ -156,8 +156,8 @@ var create_image_tmpl =
'; var images_select = ""; -var image_list_json = {}; var dataTable_images; +var $create_image_dialog; var image_actions = { @@ -216,8 +216,7 @@ var image_actions = { callback: function (request,response) { $('#template_update_dialog #template_update_textarea').val(response.template); }, - error: onError, - notify: false + error: onError }, "Image.update_dialog" : { @@ -233,8 +232,7 @@ var image_actions = { callback: function() { notifyMessage("Template updated correctly"); }, - error: onError, - notify: false + error: onError }, "Image.enable" : { @@ -243,7 +241,7 @@ var image_actions = { callback: function (req) { Sunstone.runAction("Image.show",req.request.data[0]); }, - elements: function() { return getSelectedNodes(dataTable_images); }, + elements: imageElements, error: onError, notify: true }, @@ -254,7 +252,7 @@ var image_actions = { callback: function (req) { Sunstone.runAction("Image.show",req.request.data[0]); }, - elements: function() { return getSelectedNodes(dataTable_images); }, + elements: imageElements, error: onError, notify: true }, @@ -265,7 +263,7 @@ var image_actions = { callback: function (req) { Sunstone.runAction("Image.show",req.request.data[0]); }, - elements: function() { return getSelectedNodes(dataTable_images); }, + elements: imageElements, error: onError, notify: true }, @@ -276,7 +274,7 @@ var image_actions = { callback: function (req) { Sunstone.runAction("Image.show",req.request.data[0]); }, - elements: function() { return getSelectedNodes(dataTable_images); }, + elements: imageElements, error: onError, notify: true }, @@ -287,7 +285,7 @@ var image_actions = { callback: function (req) { Sunstone.runAction("Image.show",req.request.data[0]); }, - elements: function() { return getSelectedNodes(dataTable_images); }, + elements: imageElements, error: onError, notify: true }, @@ -298,7 +296,7 @@ var image_actions = { callback: function (req) { Sunstone.runAction("Image.show",req.request.data[0]); }, - elements: function() { return getSelectedNodes(dataTable_images); }, + elements: imageElements, error: onError, notify: true }, @@ -307,7 +305,7 @@ var image_actions = { type: "multiple", call: OpenNebula.Image.delete, callback: deleteImageElement, - elements: function() { return getSelectedNodes(dataTable_images); }, + elements: imageElements, error: onError, notify: true }, @@ -318,7 +316,7 @@ var image_actions = { callback: function (req) { Sunstone.runAction("Image.show",req.request.data[0]); }, - elements: function() { return getSelectedNodes(dataTable_images); }, + elements: imageElements, error: onError, notify: true }, @@ -329,7 +327,7 @@ var image_actions = { callback: function (req) { Sunstone.runAction("Image.show",req.request.data[0]); }, - elements: function() { return getSelectedNodes(dataTable_images); }, + elements: imageElements, error: onError, notify: true } @@ -340,74 +338,63 @@ var image_buttons = { "Image.refresh" : { type: "image", text: "Refresh list", - img: "images/Refresh-icon.png", - condition: True + img: "images/Refresh-icon.png" }, "Image.create_dialog" : { type: "create_dialog", - text: "+ New", - condition: True + text: "+ New" }, "Image.update_dialog" : { type: "action", text: "Update a template", - condition: True, alwaysActive: true }, "Image.chown" : { type: "confirm_with_select", text: "Change owner", - select: function() {return users_select;}, + select: users_sel, tip: "Select the new owner:", - condition: function() { return gid == 0; } + condition: mustBeAdmin }, "Image.chgrp" : { type: "confirm_with_select", text: "Change group", - select: function() {return groups_select;}, + select: groups_sel, tip: "Select the new group:", - condition: function() { return gid == 0; } + condition: mustBeAdmin }, "action_list" : { type: "select", - condition: True, actions: { "Image.enable" : { type: "action", - text: "Enable", - condition: True + text: "Enable" }, "Image.disable" : { type: "action", - text: "Disable", - condition: True + text: "Disable" }, "Image.publish" : { type: "action", - text: "Publish", - condition: True + text: "Publish" }, "Image.unpublish" : { type: "action", - text: "Unpublish", - condition: True + text: "Unpublish" }, "Image.persistent" : { type: "action", - text: "Make persistent", - condition: True + text: "Make persistent" }, "Image.nonpersistent" : { type: "action", - text: "Make non persistent", - condition: True + text: "Make non persistent" } } }, "Image.delete" : { type: "action", - text: "Delete", - condition: True + text: "Delete" } } @@ -427,14 +414,18 @@ var image_info_panel = { var images_tab = { title: "Images", content: images_tab_content, - buttons: image_buttons, - condition: True + buttons: image_buttons } Sunstone.addActions(image_actions); Sunstone.addMainTab('images_tab',images_tab); Sunstone.addInfoPanel('image_info_panel',image_info_panel); + +function imageElements() { + return getSelectedNodes(dataTable_images); +} + // Returns an array containing the values of the image_json and ready // to be inserted in the dataTable function imageElementArray(image_json){ @@ -456,8 +447,7 @@ function imageElementArray(image_json){ // Set up the listener on the table TDs to show the info panel function imageInfoListener(){ - - $('#tbodyimages tr').live("click",function(e){ + $('#tbodyimages tr',dataTable_images).live("click",function(e){ if ($(e.target).is('input')) {return true;} popDialogLoading(); var aData = dataTable_images.fnGetData(this); @@ -470,11 +460,16 @@ function imageInfoListener(){ //Updates the select input field with an option for each image function updateImageSelect(){ images_select = - makeSelectOptions(dataTable_images,1,4,9,"DISABLED",2); + makeSelectOptions(dataTable_images, + 1, + 4, + [9,9,9], + ["DISABLED","LOCKED","ERROR"] + ); //update static selectors: //in the VM section - $('div.vm_section#disks select#IMAGE_ID').html(images_select); + $('div.vm_section#disks select#IMAGE_ID', $create_template_dialog).html(images_select); } // Callback to update an element in the dataTable @@ -500,16 +495,15 @@ function addImageElement(request, image_json){ // Callback to refresh the list of images function updateImagesView(request, images_list){ - image_list_json = images_list; var image_list_array = []; - $.each(image_list_json,function(){ + + $.each(images_list,function(){ image_list_array.push(imageElementArray(this)); }); updateView(image_list_array,dataTable_images); updateImageSelect(); - updateDashboard("images",image_list_json); - + updateDashboard("images",images_list); } // Callback to update the information panel tabs and pop it up @@ -582,85 +576,82 @@ function updateImageInfo(request,img){ // Prepare the image creation dialog function setupCreateImageDialog(){ - $('div#dialogs').append('
'); - - //Insert HTML in place - $('#create_image_dialog').html(create_image_tmpl); + dialogs_context.append('
'); + $create_image_dialog = $('#create_image_dialog',dialogs_context); + var dialog = $create_image_dialog; + dialog.html(create_image_tmpl); var height = Math.floor($(window).height()*0.8); //set height to a percentage of the window //Prepare jquery dialog - $('#create_image_dialog').dialog({ + dialog.dialog({ autoOpen: false, modal:true, width: 520, height: height }); - $('#img_tabs').tabs(); - $('#create_image_dialog button').button(); - $('#img_type option').first().attr("selected","selected"); - $('#datablock_img').attr("disabled","disabled"); + $('#img_tabs',dialog).tabs(); + $('button',dialog).button(); + $('#img_type option',dialog).first().attr("selected","selected"); + $('#datablock_img',dialog).attr("disabled","disabled"); - //Chrome workaround - $('select#img_type').change(function(){ - $(this).trigger("click"); - }); - - $('select#img_type').click(function(){ + $('select#img_type',dialog).change(function(){ var value = $(this).val(); + var context = $create_image_dialog; switch (value){ case "DATABLOCK": - $('#datablock_img').removeAttr("disabled"); + $('#datablock_img',context).removeAttr("disabled"); break; default: - $('#datablock_img').attr("disabled","disabled"); - $('#path_img').attr("checked","checked"); - $('#img_source,#img_fstype,#img_size').parent().hide(); - $('#img_path').parent().show(); + $('#datablock_img',context).attr("disabled","disabled"); + $('#path_img',context).attr("checked","checked"); + $('#img_source,#img_fstype,#img_size',context).parent().hide(); + $('#img_path',context).parent().show(); } }); - $('#img_source,#img_fstype,#img_size').parent().hide(); - $('#path_img').attr("checked","checked"); - $('#img_path').parent().addClass("img_man"); + $('#img_source,#img_fstype,#img_size',dialog).parent().hide(); + $('#path_img',dialog).attr("checked","checked"); + $('#img_path',dialog).parent().addClass("img_man"); - $('#img_public').click(function(){ - $('#img_persistent').removeAttr("checked"); + $('#img_public',dialog).click(function(){ + $('#img_persistent',$create_image_dialog).removeAttr("checked"); }); - $('#img_persistent').click(function(){ - $('#img_public').removeAttr("checked"); + $('#img_persistent',dialog).click(function(){ + $('#img_public',$create_image_dialog).removeAttr("checked"); }); $('#src_path_select input').click(function(){ + var context = $create_image_dialog; var value = $(this).val(); switch (value){ case "path": - $('#img_source,#img_fstype,#img_size').parent().hide(); - $('#img_source,#img_fstype,#img_size').parent().removeClass("img_man"); - $('#img_path').parent().show(); - $('#img_path').parent().addClass("img_man"); + $('#img_source,#img_fstype,#img_size',context).parent().hide(); + $('#img_source,#img_fstype,#img_size',context).parent().removeClass("img_man"); + $('#img_path',context).parent().show(); + $('#img_path',context).parent().addClass("img_man"); break; case "source": - $('#img_path,#img_fstype,#img_size').parent().hide(); - $('#img_path,#img_fstype,#img_size').parent().removeClass("img_man"); - $('#img_source').parent().show(); - $('#img_source').parent().addClass("img_man"); + $('#img_path,#img_fstype,#img_size',context).parent().hide(); + $('#img_path,#img_fstype,#img_size',context).parent().removeClass("img_man"); + $('#img_source',context).parent().show(); + $('#img_source',context).parent().addClass("img_man"); break; case "datablock": - $('#img_source,#img_path').parent().hide(); - $('#img_source,#img_path').parent().removeClass("img_man"); - $('#img_fstype,#img_size').parent().show(); - $('#img_fstype,#img_size').parent().addClass("img_man"); + $('#img_source,#img_path',context).parent().hide(); + $('#img_source,#img_path',context).parent().removeClass("img_man"); + $('#img_fstype,#img_size',context).parent().show(); + $('#img_fstype,#img_size',context).parent().addClass("img_man"); break; } }); - $('#create_image_form_easy').submit(function(){ + $('#create_image_form_easy',dialog).submit(function(){ var exit = false; $('.img_man',this).each(function(){ if (!$('input',this).val().length){ @@ -672,41 +663,41 @@ function setupCreateImageDialog(){ if (exit) { return false; } var img_json = {}; - var name = $('#img_name').val(); + var name = $('#img_name',this).val(); img_json["NAME"] = name; - var desc = $('#img_desc').val(); + var desc = $('#img_desc',this).val(); if (desc.length){ img_json["DESCRIPTION"] = desc; } - var type = $('#img_type').val(); + var type = $('#img_type',this).val(); img_json["TYPE"]= type; - img_json["PUBLIC"] = $('#img_public:checked').length ? "YES" : "NO"; + img_json["PUBLIC"] = $('#img_public:checked',this).length ? "YES" : "NO"; - img_json["PERSISTENT"] = $('#img_persistent:checked').length ? "YES" : "NO"; + img_json["PERSISTENT"] = $('#img_persistent:checked',this).length ? "YES" : "NO"; - var dev_prefix = $('#img_dev_prefix').val(); + var dev_prefix = $('#img_dev_prefix',this).val(); if (dev_prefix.length){ img_json["DEV_PREFIX"] = dev_prefix; } - var bus = $('#img_bus').val(); + var bus = $('#img_bus',this).val(); img_json["BUS"] = bus; - switch ($('#src_path_select input:checked').val()){ + switch ($('#src_path_select input:checked',this).val()){ case "path": - path = $('#img_path').val(); + path = $('#img_path',this).val(); img_json["PATH"] = path; break; case "source": - source = $('#img_source').val(); + source = $('#img_source',this).val(); img_json["SOURCE"] = source; break; case "datablock": - size = $('#img_size').val(); - fstype = $('#img_fstype').val(); + size = $('#img_size',this).val(); + fstype = $('#img_fstype',this).val(); img_json["SIZE"] = size; img_json["FSTYPE"] = fstype; break; @@ -714,28 +705,28 @@ function setupCreateImageDialog(){ var obj = { "image" : img_json }; Sunstone.runAction("Image.register", obj); - $('#create_image_dialog').dialog('close'); + $create_image_dialog.dialog('close'); return false; }); - $('#create_image_form_manual').submit(function(){ + $('#create_image_form_manual',dialog).submit(function(){ var template=$('#template',this).val(); Sunstone.runAction("Image.register",template); - $('#create_image_dialog').dialog('close'); + $create_image_dialog.dialog('close'); return false; }); - } function popUpCreateImageDialog(){ - $('#create_image_dialog').dialog('open'); + $create_image_dialog.dialog('open'); } // Set the autorefresh interval for the datatable function setImageAutorefresh() { setInterval(function(){ var checked = $('input:checked',dataTable_images.fnGetNodes()); - var filter = $("#datatable_images_filter input").attr("value"); + var filter = $("#datatable_images_filter input", + dataTable_images.parents("#datatable_images_wrapper")).attr("value"); if (!checked.length && !filter.length){ Sunstone.runAction("Image.autorefresh"); } @@ -745,7 +736,7 @@ function setImageAutorefresh() { //The DOM is ready at this point $(document).ready(function(){ - dataTable_images = $("#datatable_images").dataTable({ + dataTable_images = $("#datatable_images",main_tabs_context).dataTable({ "bJQueryUI": true, "bSortClasses": false, "bAutoWidth":false, @@ -765,7 +756,7 @@ $(document).ready(function(){ Sunstone.runAction("Image.list"); setupCreateImageDialog(); - setupTips($('#create_image_dialog')); + setupTips($create_image_dialog); setImageAutorefresh(); initCheckAllBoxes(dataTable_images); diff --git a/src/sunstone/public/js/plugins/templates-tab.js b/src/sunstone/public/js/plugins/templates-tab.js index 2dfe909977..cd89b8856b 100644 --- a/src/sunstone/public/js/plugins/templates-tab.js +++ b/src/sunstone/public/js/plugins/templates-tab.js @@ -118,7 +118,7 @@ var create_template_tmpl = '
\ \
Path to the OS kernel to boot the image
\
\ -
\ +
\ \ \
Path to the initrd image
\ @@ -290,7 +290,7 @@ var create_template_tmpl = '
\ \
\
\ -
\ +
\ \ \ @@ -326,14 +326,61 @@ var create_template_tmpl = '
\ \
Hardware that will emulate this network interface. With Xen this is the type attribute of the vif.
\
\ +
\ + \ + \ +
\ +
\ +
\ + \ + \ +
Permits access to the VM only through the specified ports in the TCP protocol
\ +
\ +
\ + \ + \ +
Disallow access to the VM through the specified ports in the TCP protocol
\ +
\ +
\ + \ + \ +
\ +
\ +
\ + \ + \ +
Permits access to the VM only through the specified ports in the UDP protocol
\ +
\ +
\ + \ + \ +
Disallow access to the VM through the specified ports in the UDP protocol
\ +
\ +
\ + \ + \ +
ICMP policy
\ +
\ +
\
\ \ - \ -
\ - \ - \ -
\ + \ +
\ + \ + \ +
\
\ \ \ @@ -534,8 +581,8 @@ var create_template_tmpl = '
\
'; var templates_select = ""; -var template_list_json = {}; var dataTable_templates; +var $create_template_dialog; var template_actions = { @@ -601,8 +648,7 @@ var template_actions = { callback: function() { notifyMessage("Template updated correctly"); }, - error: onError, - notify: false + error: onError }, "Template.fetch_template" : { @@ -611,45 +657,39 @@ var template_actions = { callback: function (request,response) { $('#template_update_dialog #template_update_textarea').val(response.template); }, - error: onError, - notify: false + error: onError }, "Template.publish" : { type: "multiple", call: OpenNebula.Template.publish, - callback: function (req) { - Sunstone.runAction("Template.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_templates); }, + callback: templateShow, + elements: templateElements, error: onError, notify: true }, "Template.unpublish" : { - type: "multiple", - call: OpenNebula.Template.unpublish, - callback: function (req) { - Sunstone.runAction("Template.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_templates); }, - error: onError, - notify: true + type: "multiple", + call: OpenNebula.Template.unpublish, + callback: templateShow, + elements: templateElements, + error: onError, + notify: true }, "Template.delete" : { - type: "multiple", - call: OpenNebula.Template.delete, - callback: deleteTemplateElement, - elements: function() { return getSelectedNodes(dataTable_templates); }, - error: onError, - notify: true + type: "multiple", + call: OpenNebula.Template.delete, + callback: deleteTemplateElement, + elements: templateElements, + error: onError, + notify: true }, "Template.instantiate" : { type: "single", call: OpenNebula.Template.instantiate, - callback: function(){}, error: onError, notify: true }, @@ -662,89 +702,75 @@ var template_actions = { Sunstone.runAction("Template.instantiate",this,""); }); Sunstone.runAction("VM.refresh"); - }, - notify: false + } }, "Template.chown" : { type: "multiple", call: OpenNebula.Template.chown, - callback: function (req) { - Sunstone.runAction("Template.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_templates); }, + callback: templateShow, + elements: templateElements, error:onError, notify: true }, "Template.chgrp" : { type: "multiple", call: OpenNebula.Template.chgrp, - callback: function (req) { - Sunstone.runAction("Template.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_templates); }, + callback: templateShow, + elements: templateElements, error:onError, notify: true } } - var template_buttons = { "Template.refresh" : { type: "image", text: "Refresh list", - img: "images/Refresh-icon.png", - condition: True + img: "images/Refresh-icon.png" }, "Template.create_dialog" : { type: "create_dialog", - text: "+ New", - condition: True + text: "+ New" }, "Template.update_dialog" : { type: "action", text: "Update a template", - condition: True, alwaysActive: true }, "Template.instantiate_vms" : { type: "action", - text: "Instantiate", - condition: True + text: "Instantiate" }, "Template.chown" : { type: "confirm_with_select", text: "Change owner", - select: function() {return users_select;}, + select: users_sel, tip: "Select the new owner:", - condition: function(){return gid==0;} + condition: mustBeAdmin }, "Template.chgrp" : { type: "confirm_with_select", text: "Change group", - select: function() {return groups_select;}, + select: groups_sel, tip: "Select the new group:", - condition: function(){return gid==0;} + condition: mustBeAdmin }, "action_list" : { type: "select", - condition: True, actions: { "Template.publish" : { type: "action", - text: "Publish", - condition: True + text: "Publish" }, "Template.unpublish" : { type: "action", - text: "Unpublish", - condition: True + text: "Unpublish" }, } }, "Template.delete" : { type: "action", - text: "Delete", - condition: True + text: "Delete" } } @@ -758,14 +784,23 @@ var template_info_panel = { var templates_tab = { title: "Templates", content: templates_tab_content, - buttons: template_buttons, - condition: True + buttons: template_buttons } Sunstone.addActions(template_actions); Sunstone.addMainTab('templates_tab',templates_tab); Sunstone.addInfoPanel('template_info_panel',template_info_panel); +//Returns selected elements in the template table +function templateElements(){ + return getSelectedNodes(dataTable_templates); +} + +//Runs a show action on the template with from a prev request +function templateShow(req){ + Sunstone.runAction("Template.show",req.request.data[0]); +} + // Returns an array containing the values of the template_json and ready // to be inserted in the dataTable function templateElementArray(template_json){ @@ -783,8 +818,7 @@ function templateElementArray(template_json){ // Set up the listener on the table TDs to show the info panel function templateInfoListener(){ - - $('#tbodytemplates tr').live("click",function(e){ + $('#tbodytemplates tr',dataTable_templates).live("click",function(e){ if ($(e.target).is('input')) {return true;} popDialogLoading(); var aData = dataTable_templates.fnGetData(this); @@ -797,11 +831,15 @@ function templateInfoListener(){ //Updates the select input field with an option for each template function updateTemplateSelect(){ templates_select = - makeSelectOptions(dataTable_templates,1,4,7,"no",2); + makeSelectOptions(dataTable_templates, + 1,//id_col + 4,//name_col + [7],//published_col + ["no"]//bad status col + ); //update static selectors: - $('#create_vm_dialog #template_id').html(templates_select); - $('#speed_virt').html(templates_select); + $('#template_id', $create_vm_dialog).html(templates_select); } // Callback to update an element in the dataTable @@ -827,15 +865,15 @@ function addTemplateElement(request, template_json){ // Callback to refresh the list of templates function updateTemplatesView(request, templates_list){ - template_list_json = templates_list; var template_list_array = []; - $.each(template_list_json,function(){ + + $.each(templates_list,function(){ template_list_array.push(templateElementArray(this)); }); updateView(template_list_array,dataTable_templates); updateTemplateSelect(); - updateDashboard("templates",template_list_json); + updateDashboard("templates",templates_list); } @@ -888,7 +926,6 @@ function updateTemplateInfo(request,template){ Sunstone.updateInfoPanelTab("template_info_panel","template_template_tab",template_tab); Sunstone.popUpInfoPanel("template_info_panel"); - } // Prepare the template creation dialog @@ -903,30 +940,30 @@ function setupCreateTemplateDialog(){ // ui.index // zero-based index of the selected (clicked) tab //disable all items - $(items).attr("disabled","disabled"); + $(items,dialog).attr("disabled","disabled"); //hide all mandatory icons - $('.vm_param .man_icon').css("display","none"); + $('.vm_param .man_icon',dialog).css("display","none"); //empty selects - $('div#os_boot_opts select#BOOT').empty(); - $('div#disks select#TYPE').empty(); - $('div#disks select#BUS').empty(); + $('select#BOOT',section_os_boot).empty(); + $('select#TYPE',section_disks).empty(); + $('select#BUS',section_disks).empty(); //hide options about boot method $('div#kernel_bootloader',section_os_boot).show(); - $('.kernel, .bootloader', $('div#os_boot_opts')).hide(); - $('div#os_boot_opts select#BOOT').parent().hide(); + $('.kernel, .bootloader', section_os_boot).hide(); + $('select#BOOT',section_os_boot).parent().hide(); //unselect boot method - $('select#boot_method option').removeAttr("selected"); + $('select#boot_method option',section_os_boot).removeAttr("selected"); //hide non common sections $(section_inputs).hide(); $(section_graphics).hide(); //Repopulate images select - $('div.vm_section#disks select#IMAGE_ID').html(images_select); + $('select#IMAGE_ID',section_disks).html(images_select); //Repopulate network select - $('div.vm_section#networks select#NETWORK_ID').html(vnetworks_select); + $('select#NETWORK_ID',section_networks).html(vnetworks_select); switch(ui.index){ @@ -973,8 +1010,8 @@ function setupCreateTemplateDialog(){ var enable_kvm = function(){ man_class="kvm"; opt_class="kvm_opt"; - $(kvm_items).removeAttr("disabled"); - $('.kvm .man_icon').css("display","inline-block"); + $(kvm_items,dialog).removeAttr("disabled"); + $('.kvm .man_icon',dialog).css("display","inline-block"); //KVM particularities: // * Add custom disk types @@ -993,7 +1030,7 @@ function setupCreateTemplateDialog(){ \ '; - $('div#disks select#TYPE').html(type_opts); + $('select#TYPE',section_disks).html(type_opts); var boot_opts = '\ @@ -1001,16 +1038,16 @@ function setupCreateTemplateDialog(){ \ '; - $('div#os_boot_opts select#BOOT').html(boot_opts); - $('div#os_boot_opts select#BOOT').parent().show(); - $('select#boot_method option#no_boot').html("Driver default"); + $('select#BOOT',section_os_boot).html(boot_opts); + $('select#BOOT',section_os_boot).parent().show(); + $('select#boot_method option#no_boot',section_os_boot).html("Driver default"); var bus_opts = '\ \ '; - $('div#disks select#BUS').html(bus_opts); + $('select#BUS',section_disks).html(bus_opts); $('input#TYPE', section_raw).val("kvm"); @@ -1022,8 +1059,8 @@ function setupCreateTemplateDialog(){ var enable_xen = function(){ man_class="xen"; opt_class="xen_opt"; - $(xen_items).removeAttr("disabled"); - $('.xen .man_icon').css("display","inline-block"); + $(xen_items,dialog).removeAttr("disabled"); + $('.xen .man_icon',dialog).css("display","inline-block"); // XEN particularities: // * Add custom disk types @@ -1040,15 +1077,15 @@ function setupCreateTemplateDialog(){ \ '; - $('div#disks select#TYPE').html(type_opts); + $('select#TYPE',section_disks).html(type_opts); - $('select#boot_method option#no_boot').html("Please choose"); + $('select#boot_method option#no_boot',section_os_boot).html("Please choose"); var bus_opts = '\ '; - $('div#disks select#BUS').html(bus_opts); + $('select#BUS',section_disks).html(bus_opts); $('input#TYPE', section_raw).val("xen"); $(section_graphics).show(); @@ -1058,8 +1095,8 @@ function setupCreateTemplateDialog(){ var enable_vmware = function() { man_class="vmware"; opt_class="vmware_opt"; - $(vmware_items).removeAttr("disabled"); - $('.vmware .man_icon').css("display","inline-block"); + $(vmware_items,dialog).removeAttr("disabled"); + $('.vmware .man_icon',dialog).css("display","inline-block"); //VMWARE particularities // * Add custom disk types @@ -1072,7 +1109,7 @@ function setupCreateTemplateDialog(){ \ '; - $('div#disks select#TYPE').html(type_opts); + $('select#TYPE',section_disks).html(type_opts); $('div#kernel_bootloader',section_os_boot).hide(); @@ -1080,10 +1117,9 @@ function setupCreateTemplateDialog(){ '\ '; - $('div#disks select#BUS').html(bus_opts); - + $('select#BUS',section_disks).html(bus_opts); $('input#TYPE', section_raw).val("vmware"); - } + }; //This function checks that all mandatory items within a section //have some value. Returns true if so, false if not. @@ -1096,14 +1132,14 @@ function setupCreateTemplateDialog(){ //we fail it the item is enabled and has no value $.each(man_items,function(){ - if ($(this).parents(".vm_param").attr("disabled") || - !($(this).val().length)) { + var item = $(this); + if (item.parents(".vm_param").attr("disabled") || + !(item.val().length)) { r = false; return false; }; }); return r; - }; //Adds an option element to a multiple select box. Before doing so, @@ -1127,12 +1163,13 @@ function setupCreateTemplateDialog(){ //With each enabled field we form a JSON object var id = null; $.each(fields,function(){ - if (!($(this).parents(".vm_param").attr("disabled")) && - $(this).val().length){ + var field = $(this); + if (!(field.parents(".vm_param").attr("disabled")) && + field.val().length){ //Pick up parent's ID if we do not have one - id = $(this).attr('id').length ? $(this).attr('id') : $(this).parent().attr('id'); - value[id] = $(this).val(); - } + id = field.attr('id').length ? field.attr('id') : field.parent().attr('id'); + value[id] = field.val(); + }; }); var value_string = JSON.stringify(value); var option= @@ -1145,7 +1182,7 @@ function setupCreateTemplateDialog(){ //Removes selected elements from a multiple select box var box_remove_element = function(section_tag,box_tag){ - var context = $(section_tag); + var context = $(section_tag,dialog); $('select'+box_tag+' :selected',context).remove(); return false; }; @@ -1160,22 +1197,25 @@ function setupCreateTemplateDialog(){ var fields = $.merge(inputs,selects); fields.each(function(){ - if (!($(this).parents(".vm_param").attr("disabled"))){ //if ! disabled - if ($(this).val().length){ //if has a length - template_json[$(this).attr('id')]=$(this).val(); - } - } + var field=$(this); + if (!(field.parents(".vm_param").attr("disabled"))){ //if ! disabled + if (field.val().length){ //if has a length + template_json[field.attr('id')]=field.val(); + }; + }; }); - } + }; - // Given an array (usually empty), a section (context) and a tag for - // a multiple select in that section, it adds the contents of the - // box as objects in the array. - // TODO: Make it return a new array? - var addBoxJSON = function(array,context,box_tag){ + // Given a section (context) and a tag for + // a multiple select in that section, it adds the + // JSON values to an array parsed as objects. + // Returns the array + var addBoxJSON = function(context,box_tag){ + var array = []; $('select'+box_tag+' option',context).each(function(){ array.push( JSON.parse($(this).val()) ); }); + return array; } //Given an object, removes those elements which are empty @@ -1212,7 +1252,7 @@ function setupCreateTemplateDialog(){ //Toggles the icon when a section is folded/unfolded var iconToggle = function(){ - $('.icon_right').toggle( + $('.icon_right',dialog).toggle( function(e){ $('span',e.currentTarget).removeClass("ui-icon-plusthick"); $('span',e.currentTarget).addClass("ui-icon-minusthick"); @@ -1246,13 +1286,8 @@ function setupCreateTemplateDialog(){ return false; }); - //Chrome workaround - $('#boot_method').change(function(){ - $(this).trigger("click"); - }); - //Depending on the boot method we enable/disable some options - $('#boot_method',section_os_boot).click(function(){ + $('#boot_method',section_os_boot).change(function(){ select = $(this).val(); switch (select) { @@ -1331,14 +1366,9 @@ function setupCreateTemplateDialog(){ //hide_disabled(section_disks); }); - //Chrome workaround - $('select#TYPE',section_disks).change(function(){ - $(this).trigger('click'); - }); - //Depending on the type of disk we need to show/hide //different options and make then mandatory or not - $('select#TYPE',section_disks).click(function(){ + $('select#TYPE',section_disks).change(function(){ var select = $(this).val(); switch (select) { //size,format,target @@ -1428,8 +1458,8 @@ function setupCreateTemplateDialog(){ //hide_disabled(section_disks); }); - //Our filter for the disks section fields is the mandatory - //filter for this section + //Our filter for the disks section fields is the standard + //mandatory filter applied for this section var diskFilter = function(){ return mandatory_filter(section_disks); }; @@ -1448,6 +1478,7 @@ function setupCreateTemplateDialog(){ var networks_setup = function(){ $('.vm_param',section_networks).hide(); + $('.firewall_select',section_networks).hide(); $('fieldset',section_networks).hide(); $('#add_networks',section_networks).click(function(){ @@ -1459,6 +1490,12 @@ function setupCreateTemplateDialog(){ //some fields $('#network_vs_niccfg input',section_networks).click(function(){ + //firewall + $('.firewall',section_networks).hide(); + $('.firewall',section_networks).attr("disabled","disabled"); + $('.firewall_select',section_networks).show(); + $('.firewall_select select option',section_networks).removeAttr("selected"); + select = $('#network_vs_niccfg :checked',section_networks).val(); switch (select) { case "network": @@ -1477,6 +1514,50 @@ function setupCreateTemplateDialog(){ //hide_disabled(section_networks); }); + $('#black_white_tcp',section_networks).change(function(){ + switch ($(this).val()) { + case "whitelist": + $('#BLACK_PORTS_TCP',section_networks).parent().attr("disabled","disabled"); + $('#BLACK_PORTS_TCP',section_networks).parent().hide(); + $('#WHITE_PORTS_TCP',section_networks).parent().removeAttr("disabled"); + $('#WHITE_PORTS_TCP',section_networks).parent().show(); + break; + case "blacklist": + $('#WHITE_PORTS_TCP',section_networks).parent().attr("disabled","disabled"); + $('#WHITE_PORTS_TCP',section_networks).parent().hide(); + $('#BLACK_PORTS_TCP',section_networks).parent().removeAttr("disabled"); + $('#BLACK_PORTS_TCP',section_networks).parent().show(); + break; + default: + $('#WHITE_PORTS_TCP',section_networks).parent().attr("disabled","disabled"); + $('#WHITE_PORTS_TCP',section_networks).parent().hide(); + $('#BLACK_PORTS_TCP',section_networks).parent().attr("disabled","disabled"); + $('#BLACK_PORTS_TCP',section_networks).parent().hide(); + }; + }); + + $('#black_white_udp',section_networks).change(function(){ + switch ($(this).val()) { + case "whitelist": + $('#BLACK_PORTS_UDP',section_networks).parent().attr("disabled","disabled"); + $('#BLACK_PORTS_UDP',section_networks).parent().hide(); + $('#WHITE_PORTS_UDP',section_networks).parent().removeAttr("disabled"); + $('#WHITE_PORTS_UDP',section_networks).parent().show(); + break; + case "blacklist": + $('#WHITE_PORTS_UDP',section_networks).parent().attr("disabled","disabled"); + $('#WHITE_PORTS_UDP',section_networks).parent().hide(); + $('#BLACK_PORTS_UDP',section_networks).parent().removeAttr("disabled"); + $('#BLACK_PORTS_UDP',section_networks).parent().show(); + break; + default: + $('#WHITE_PORTS_UDP',section_networks).parent().attr("disabled","disabled"); + $('#WHITE_PORTS_UDP',section_networks).parent().hide(); + $('#BLACK_PORTS_UDP',section_networks).parent().attr("disabled","disabled"); + $('#BLACK_PORTS_UDP',section_networks).parent().hide(); + }; + }); + //The filter to add a new network checks that we have selected a //network, or that the ip or mac are set //TODO: Improve this check @@ -1506,7 +1587,7 @@ function setupCreateTemplateDialog(){ $('#add_input_button',section_inputs).click(function(){ //no filter - box_add_element(section_inputs,'#inputs_box',True); + box_add_element(section_inputs,'#inputs_box',function(){return true}); return false; }); $('#remove_input_button',section_inputs).click(function(){ @@ -1556,11 +1637,10 @@ function setupCreateTemplateDialog(){ $('#PORT',section_graphics).parent().hide(); $('#PASSWD',section_graphics).parent().hide(); $('#KEYMAP',section_graphics).parent().hide(); - } }); - } + }; //Set up the context section - TODO: Apply improvements here... var context_setup = function(){ @@ -1589,8 +1669,6 @@ function setupCreateTemplateDialog(){ box_remove_element(section_context,'#context_box'); return false; }); - - }; // Set up the placement section @@ -1648,17 +1726,21 @@ filled in"); //***CREATE VM DIALOG MAIN BODY*** - $('div#dialogs').append('
'); + dialogs_context.append('
'); + $create_template_dialog = $('#create_template_dialog',dialogs_context) + var dialog = $create_template_dialog; + //Insert HTML in place - $('#create_template_dialog').html(create_template_tmpl); + dialog.html(create_template_tmpl); + //Enable tabs - $('#template_create_tabs').tabs({ + $('#template_create_tabs',dialog).tabs({ select:vmTabChange }); //Prepare jquery dialog var height = Math.floor($(window).height()*0.8); //set height to a percentage of the window - $('#create_template_dialog').dialog({ + dialog.dialog({ autoOpen: false, modal: true, width: 600, @@ -1666,26 +1748,26 @@ filled in"); }); // Enhace buttons - $('#create_template_dialog button').button(); + $('button',dialog).button(); // Re-Setup tips - setupTips($('#create_template_dialog')); + setupTips(dialog); //Enable different icon for folded/unfolded categories iconToggle(); //toogle +/- buttons //Sections, used to stay within their scope - var section_capacity = $('#capacity'); - var section_os_boot = $('#os_boot_opts'); - var section_features = $('#features'); - var section_disks = $('#disks'); - var section_networks = $('#networks'); - var section_inputs = $('#inputs'); - var section_graphics = $('#graphics'); - var section_context = $('#context'); - var section_placement = $('#placement'); - var section_raw = $('#raw'); - var section_custom_var = $('#custom_var'); + var section_capacity = $('div#capacity',dialog); + var section_os_boot = $('div#os_boot_opts',dialog); + var section_features = $('div#features',dialog); + var section_disks = $('div#disks',dialog); + var section_networks = $('div#networks',dialog); + var section_inputs = $('div#inputs',dialog); + var section_graphics = $('div#graphics',dialog); + var section_context = $('div#context',dialog); + var section_placement = $('div#placement',dialog); + var section_raw = $('div#raw',dialog); + var section_custom_var = $('div#custom_var',dialog); //Different selector for items of kvm and xen (mandatory and optional) var items = '.vm_param input,.vm_param select'; @@ -1707,14 +1789,15 @@ filled in"); vmTabChange(0,{index : 0}); //enable kvm //Fold/unfold all sections button - $('#fold_unfold_vm_params').toggle( + $('#fold_unfold_vm_params',dialog).toggle( function(){ - $('.vm_section fieldset').show(); + $('.vm_section fieldset',$create_template_dialog).show(); return false; }, function(){ - $('.vm_section fieldset').hide(); - $('.vm_section fieldset').first().show(); //Show capacity opts + $('.vm_section fieldset',$create_template_dialog).hide(); + //Show capacity opts + $('.vm_section fieldset',$create_template_dialog).first().show(); return false; }); @@ -1732,7 +1815,7 @@ filled in"); custom_variables_setup(); //Process form - $('button#create_template_form_easy').click(function(){ + $('button#create_template_form_easy',dialog).click(function(){ //validate form var vm_json = {}; @@ -1771,18 +1854,15 @@ filled in"); //process disks -> fetch from box scope = section_disks; - vm_json["DISK"] = []; - addBoxJSON(vm_json["DISK"],scope,'#disks_box'); + vm_json["DISK"] = addBoxJSON(scope,'#disks_box'); //process nics -> fetch from box scope = section_networks; - vm_json["NIC"] = []; - addBoxJSON(vm_json["NIC"],scope,'#nics_box'); + vm_json["NIC"] = addBoxJSON(scope,'#nics_box'); //process inputs -> fetch from box scope = section_inputs; - vm_json["INPUT"] = []; - addBoxJSON(vm_json["INPUT"],scope,'#inputs_box'); + vm_json["INPUT"] = addBoxJSON(scope,'#inputs_box'); //process graphics -> fetch fields with value scope = section_graphics; @@ -1830,41 +1910,42 @@ filled in"); Sunstone.runAction("Template.create",vm_json); - $('#create_template_dialog').dialog('close'); + $create_template_dialog.dialog('close'); return false; }); //Handle manual forms - $('button#create_template_form_manual').click(function(){ - var template = $('#textarea_vm_template').val(); + $('button#create_template_form_manual',$create_template_dialog).click(function(){ + var template = $('textarea#textarea_vm_template',$create_template_dialog).val(); //wrap it in the "vm" object template = {"vmtemplate": {"template_raw": template}}; Sunstone.runAction("Template.create",template); - $('#create_template_dialog').dialog('close'); + $create_template_dialog.dialog('close'); return false; }); //Reset form - empty boxes - $('button#reset_vm_form').click(function(){ + $('button#reset_vm_form',dialog).click(function(){ $('select#disks_box option',section_disks).remove(); $('select#nics_box option',section_networks).remove(); $('select#inputs_box option',section_inputs).remove(); + $('select#custom_var_box option',section_custom_var).remove(); return true; }); - } function popUpCreateTemplateDialog(){ - $('#create_template_dialog').dialog('open'); + $create_template_dialog.dialog('open'); } // Set the autorefresh interval for the datatable function setTemplateAutorefresh() { setInterval(function(){ var checked = $('input:checked',dataTable_templates.fnGetNodes()); - var filter = $("#datatable_templates_filter input").attr("value"); + var filter = $("#datatable_templates_filter input", + dataTable_templates.parents('#datatable_templates_wrapper')).attr("value"); if (!checked.length && !filter.length){ Sunstone.runAction("Template.autorefresh"); } @@ -1874,7 +1955,7 @@ function setTemplateAutorefresh() { //The DOM is ready at this point $(document).ready(function(){ - dataTable_templates = $("#datatable_templates").dataTable({ + dataTable_templates = $("#datatable_templates",main_tabs_context).dataTable({ "bJQueryUI": true, "bSortClasses": false, "bAutoWidth":false, diff --git a/src/sunstone/public/js/plugins/users-tab.js b/src/sunstone/public/js/plugins/users-tab.js index d36105e279..0c48249ef8 100644 --- a/src/sunstone/public/js/plugins/users-tab.js +++ b/src/sunstone/public/js/plugins/users-tab.js @@ -15,9 +15,9 @@ /* -------------------------------------------------------------------------- */ /*Users tab plugin*/ -var user_list_json = {}; var dataTable_users; var users_select=""; +var $create_user_dialog; var users_tab_content = '
\ @@ -92,9 +92,7 @@ var user_actions = { success: updateUsersView, error: onError }); - }, - condition: True, - notify: false + } }, "User.chgrp" : { @@ -103,7 +101,7 @@ var user_actions = { callback : function(req){ Sunstone.runAction("User.show",req.request.data[0]); }, - elements : function() {return getSelectedNodes(dataTable_users);}, + elements : userElements, error: onError, notify: true }, @@ -141,7 +139,7 @@ var user_actions = { type: "multiple", call: OpenNebula.User.delete, callback: deleteUserElement, - elements: function() { return getSelectedNodes(dataTable_users); }, + elements: userElements, error: onError, notify: true }, @@ -151,20 +149,17 @@ var user_buttons = { "User.refresh" : { type: "image", text: "Refresh list", - img: "images/Refresh-icon.png", - condition: True + img: "images/Refresh-icon.png" }, "User.create_dialog" : { type: "create_dialog", - text: "+ New", - condition: True + text: "+ New" }, "User.chgrp" : { type: "confirm_with_select", text: "Change group", - select: function(){ return groups_select; }, - tip: "This will change the main group of the selected users. Select the new group:", - condition: True + select: groups_sel, + tip: "This will change the main group of the selected users. Select the new group:" }, // "User.addgroup" : { // type: "confirm_with_select", @@ -182,21 +177,23 @@ var user_buttons = { // }, "User.delete" : { type: "action", - text: "Delete", - condition: True + text: "Delete" } } var users_tab = { title: "Users", content: users_tab_content, - buttons: user_buttons, - condition: True + buttons: user_buttons } Sunstone.addActions(user_actions); Sunstone.addMainTab('users_tab',users_tab); +function userElements(){ + return getSelectedNodes(dataTable_users); +} + // Returns an array with the values from the user_json ready to be // added to the dataTable function userElementArray(user_json){ @@ -212,7 +209,12 @@ function userElementArray(user_json){ function updateUserSelect(){ - users_select = makeSelectOptions(dataTable_users,1,2,-1,"",-1); + users_select = makeSelectOptions(dataTable_users, + 1,//id_col + 2,//name_col + [],//status_cols + []//bad status values + ); } // Callback to refresh a single element from the dataTable @@ -237,32 +239,33 @@ function addUserElement(request,user_json){ // Callback to update the list of users function updateUsersView(request,users_list){ - user_list_json = users_list; var user_list_array = []; - $.each(user_list_json,function(){ + $.each(users_list,function(){ user_list_array.push(userElementArray(this)); }); updateView(user_list_array,dataTable_users); - updateDashboard("users",user_list_json); + updateDashboard("users",users_list); updateUserSelect(); } // Prepare the user creation dialog function setupCreateUserDialog(){ - $('div#dialogs').append('
'); - $('#create_user_dialog').html(create_user_tmpl); + dialogs_context.append('
'); + $create_user_dialog = $('#create_user_dialog',dialogs_context); + var dialog = $create_user_dialog; + dialog.html(create_user_tmpl); //Prepare jquery dialog - $('#create_user_dialog').dialog({ + dialog.dialog({ autoOpen: false, modal:true, width: 400 }); - $('#create_user_dialog button').button(); + $('button',dialog).button(); - $('#create_user_form').submit(function(){ + $('#create_user_form',dialog).submit(function(){ var user_name=$('#username',this).val(); var user_password=$('#pass',this).val(); if (!user_name.length || !user_password.length){ @@ -275,20 +278,21 @@ function setupCreateUserDialog(){ "password" : user_password } }; Sunstone.runAction("User.create",user_json); - $('#create_user_dialog').dialog('close'); + $create_user_dialog.dialog('close'); return false; }); } function popUpCreateUserDialog(){ - $('#create_user_dialog').dialog('open'); + $create_user_dialog.dialog('open'); } // Prepare the autorefresh of the list function setUserAutorefresh(){ setInterval(function(){ var checked = $('input:checked',dataTable_users.fnGetNodes()); - var filter = $("#datatable_users_filter input").attr("value"); + var filter = $("#datatable_users_filter input", + dataTable_users.parents("#datatable_users_wrapper")).attr("value"); if (!checked.length && !filter.length){ Sunstone.runAction("User.autorefresh"); } @@ -297,7 +301,7 @@ function setUserAutorefresh(){ $(document).ready(function(){ //if we are not oneadmin, our tab will not even be in the DOM. - dataTable_users = $("#datatable_users").dataTable({ + dataTable_users = $("#datatable_users",main_tabs_context).dataTable({ "bJQueryUI": true, "bSortClasses": false, "sPaginationType": "full_numbers", @@ -320,6 +324,6 @@ $(document).ready(function(){ initCheckAllBoxes(dataTable_users); tableCheckboxesListener(dataTable_users); - shortenedInfoFields('#datatable_users'); + //shortenedInfoFields('#datatable_users'); }) diff --git a/src/sunstone/public/js/plugins/vms-tab.js b/src/sunstone/public/js/plugins/vms-tab.js index 76592e1fff..ba33ae67a1 100644 --- a/src/sunstone/public/js/plugins/vms-tab.js +++ b/src/sunstone/public/js/plugins/vms-tab.js @@ -77,9 +77,11 @@ var create_vm_tmpl ='\
\ \
\ - \ - \ + \ +
\ + \ + \
\ \
\ @@ -92,6 +94,9 @@ var create_vm_tmpl ='\ var vmachine_list_json = {}; var dataTable_vMachines; +var $create_vm_dialog; +var $saveas_vm_dialog; +var $vnc_dialog; var rfb; var vm_actions = { @@ -149,10 +154,8 @@ var vm_actions = { "VM.deploy" : { type: "multiple", call: OpenNebula.VM.deploy, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, @@ -160,9 +163,7 @@ var vm_actions = { "VM.migrate" : { type: "multiple", call: OpenNebula.VM.migrate, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, + callback: vmShow, elements: function() { return getSelectedNodes(dataTable_vMachines); }, error: onError, notify: true @@ -171,10 +172,8 @@ var vm_actions = { "VM.livemigrate" : { type: "multiple", call: OpenNebula.VM.livemigrate, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, @@ -182,10 +181,8 @@ var vm_actions = { "VM.hold" : { type: "multiple", call: OpenNebula.VM.hold, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, @@ -193,10 +190,8 @@ var vm_actions = { "VM.release" : { type: "multiple", call: OpenNebula.VM.release, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, @@ -204,10 +199,8 @@ var vm_actions = { "VM.suspend" : { type: "multiple", call: OpenNebula.VM.suspend, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, @@ -215,10 +208,8 @@ var vm_actions = { "VM.resume" : { type: "multiple", call: OpenNebula.VM.resume, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, @@ -226,10 +217,8 @@ var vm_actions = { "VM.stop" : { type: "multiple", call: OpenNebula.VM.stop, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, @@ -237,10 +226,8 @@ var vm_actions = { "VM.restart" : { type: "multiple", call: OpenNebula.VM.restart, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, @@ -248,10 +235,8 @@ var vm_actions = { "VM.resubmit" : { type: "multiple", call: OpenNebula.VM.resubmit, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, @@ -259,10 +244,9 @@ var vm_actions = { "VM.saveasmultiple" : { type: "custom", call: function(){ - var elems = vm_actions["VM.saveasmultiple"].elements(); + var elems = vmElements(); popUpSaveasDialog(elems); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); } + } }, "VM.saveas" : { @@ -270,10 +254,7 @@ var vm_actions = { call: function(obj) { OpenNebula.VM.saveas( {data:obj, - success: function (req) { - Sunstone.runAction("VM.show", - req.request.data[0][0]); - }, + success: vmShow, error: onError }); } }, @@ -282,17 +263,14 @@ var vm_actions = { type: "single", call: OpenNebula.VM.show, callback: saveasDisksCallback, - error: onError, - notify: false + error: onError }, "VM.shutdown" : { type: "multiple", call: OpenNebula.VM.shutdown, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, @@ -300,10 +278,8 @@ var vm_actions = { "VM.cancel" : { type: "multiple", call: OpenNebula.VM.cancel, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, @@ -312,7 +288,7 @@ var vm_actions = { type: "multiple", call: OpenNebula.VM.delete, callback: deleteVMachineElement, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + elements: vmElements, error: onError, notify: true }, @@ -352,7 +328,6 @@ var vm_actions = { "VM.stopvnc" : { type: "single", call: OpenNebula.VM.stopvnc, - callback: null, error: onError, notify: true }, @@ -379,20 +354,16 @@ var vm_actions = { "VM.chown" : { type: "multiple", call: OpenNebula.VM.chown, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true }, "VM.chgrp" : { type: "multiple", call: OpenNebula.VM.chgrp, - callback: function (req) { - Sunstone.runAction("VM.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vMachines); }, + callback: vmShow, + elements: vmElements, error: onError, notify: true } @@ -404,39 +375,35 @@ var vm_buttons = { "VM.refresh" : { type: "image", text: "Refresh list", - img: "images/Refresh-icon.png", - condition: True + img: "images/Refresh-icon.png" }, "VM.create_dialog" : { type: "action", text: "+ New", - condition: True, - alwaysActive: true, - + alwaysActive: true }, "VM.chown" : { type: "confirm_with_select", text: "Change owner", - select: function() {return users_select;}, + select: users_sel, tip: "Select the new owner:", - condition: function() { return gid == 0; } + condition: mustBeAdmin }, "VM.chgrp" : { type: "confirm_with_select", text: "Change group", - select: function() {return groups_select;}, + select: groups_sel, tip: "Select the new group:", - condition: function() { return gid == 0; } + condition: mustBeAdmin }, "VM.shutdown" : { type: "confirm", text: "Shutdown", - tip: "This will initiate the shutdown process in the selected VMs", - condition: True + tip: "This will initiate the shutdown process in the selected VMs" }, "action_list" : { @@ -446,95 +413,75 @@ var vm_buttons = { type: "confirm_with_select", text: "Deploy", tip: "This will deploy the selected VMs on the chosen host", - select: function(){ - if (hosts_select){return hosts_select} - else {return ""} - }, - condition: function() { return gid == 0; } + select: hosts_sel, + condition: mustBeAdmin }, "VM.migrate" : { type: "confirm_with_select", text: "Migrate", tip: "This will migrate the selected VMs to the chosen host", - select: function(){ - if (hosts_select){return hosts_select} - else {return ""} - }, - condition: function() { return gid == 0; } + select: hosts_sel, + condition: mustBeAdmin }, "VM.livemigrate" : { type: "confirm_with_select", text: "Live migrate", tip: "This will live-migrate the selected VMs to the chosen host", - select: function(){ - if (hosts_select){return hosts_select} - else {return ""} - }, - condition: function() { return gid == 0; } + select: hosts_sel, + condition: mustBeAdmin }, "VM.hold" : { type: "confirm", text: "Hold", - tip: "This will hold selected pending VMs from being deployed", - condition: True + tip: "This will hold selected pending VMs from being deployed" }, "VM.release" : { type: "confirm", text: "Release", - tip: "This will release held machines", - condition: True + tip: "This will release held machines" }, "VM.suspend" : { type: "confirm", text: "Suspend", - tip: "This will suspend selected machines", - condition: True + tip: "This will suspend selected machines" }, "VM.resume" : { type: "confirm", text: "Resume", - tip: "This will resume selected stopped or suspended VMs", - condition: True + tip: "This will resume selected stopped or suspended VMs" }, "VM.stop" : { type: "confirm", text: "Stop", - tip: "This will stop selected VMs", - condition: True + tip: "This will stop selected VMs" }, "VM.restart" : { type: "confirm", text: "Restart", - tip: "This will redeploy selected VMs (in UNKNOWN or BOOT state)", - condition: True + tip: "This will redeploy selected VMs (in UNKNOWN or BOOT state)" }, "VM.resubmit" : { type: "confirm", text: "Resubmit", - tip: "This will resubmits VMs to PENDING state", - condition: True + tip: "This will resubmits VMs to PENDING state" }, "VM.saveasmultiple" : { type: "action", - text: "Save as", - condition: True + text: "Save as" }, "VM.cancel" : { type: "confirm", text: "Cancel", - tip: "This will cancel selected VMs", - condition: True + tip: "This will cancel selected VMs" } - }, - condition: True + } }, "VM.delete" : { type: "confirm", text: "Delete", - tip: "This will delete the selected VMs from the database", - condition: True + tip: "This will delete the selected VMs from the database" } } @@ -556,8 +503,7 @@ var vm_info_panel = { var vms_tab = { title: "Virtual Machines", content: vms_tab_content, - buttons: vm_buttons, - condition: True + buttons: vm_buttons } Sunstone.addActions(vm_actions); @@ -565,6 +511,14 @@ Sunstone.addMainTab('vms_tab',vms_tab); Sunstone.addInfoPanel('vm_info_panel',vm_info_panel); +function vmElements() { + return getSelectedNodes(dataTable_vMachines); +} + +function vmShow(req) { + Sunstone.runAction("VM.show",req.request.data[0]); +} + // Returns a human readable running time for a VM function str_start_time(vm){ return pretty_time(vm.STIME); @@ -575,9 +529,19 @@ function str_start_time(vm){ function vMachineElementArray(vm_json){ var vm = vm_json.VM; var state = OpenNebula.Helper.resource_state("vm",vm.STATE); + var hostname = "--"; + + if (state == "ACTIVE" || state == "SUSPENDED"){ + if (vm.HISTORY_RECORDS.HISTORY.constructor == Array){ + hostname = vm.HISTORY_RECORDS.HISTORY[vm.HISTORY_RECORDS.HISTORY.length-1].HOSTNAME; + } else { + hostname = vm.HISTORY_RECORDS.HISTORY.HOSTNAME; + }; + }; + if (state == "ACTIVE") { state = OpenNebula.Helper.resource_state("vm_lcm",vm.LCM_STATE); - } + }; return [ '', @@ -588,7 +552,7 @@ function vMachineElementArray(vm_json){ state, vm.CPU, humanize_size(vm.MEMORY), - vm.HISTORY ? vm.HISTORY.HOSTNAME : "--", + hostname, str_start_time(vm), vncIcon(vm) ]; @@ -598,7 +562,7 @@ function vMachineElementArray(vm_json){ //Creates a listener for the TDs of the VM table function vMachineInfoListener(){ - $('#tbodyvmachines tr').live("click", function(e){ + $('#tbodyvmachines tr',dataTable_vMachines).live("click", function(e){ if ($(e.target).is('input') || $(e.target).is('a img')) {return true;} popDialogLoading(); var aData = dataTable_vMachines.fnGetData(this); @@ -616,8 +580,8 @@ function updateVMachineElement(request, vm_json){ } // Callback to delete a single element from the list -function deleteVMachineElement(req){ - deleteElement(dataTable_vMachines,'#vm_'+req.request.data); +function deleteVMachineElement(request){ + deleteElement(dataTable_vMachines,'#vm_'+request.request.data); } // Callback to add an element to the list @@ -630,7 +594,6 @@ function addVMachineElement(request,vm_json){ // Callback to refresh the list of Virtual Machines function updateVMachinesView(request, vmachine_list){ - vmachine_list_json = vmachine_list; var vmachine_list_array = []; $.each(vmachine_list,function(){ @@ -638,13 +601,23 @@ function updateVMachinesView(request, vmachine_list){ }); updateView(vmachine_list_array,dataTable_vMachines); - updateDashboard("vms",vmachine_list_json); + updateDashboard("vms",vmachine_list); } // Refreshes the information panel for a VM function updateVMInfo(request,vm){ var vm_info = vm.VM; + var vm_state = OpenNebula.Helper.resource_state("vm",vm_info.STATE); + var hostname = "--" + if (vm_state == "ACTIVE" || vm_state == "SUSPENDED") { + if (vm_info.HISTORY_RECORDS.HISTORY.constructor == Array){ + hostname = vm_info.HISTORY_RECORDS.HISTORY[vm_info.HISTORY_RECORDS.HISTORY.length-1].HOSTNAME + } else { + hostname = vm_info.HISTORY_RECORDS.HISTORY.HOSTNAME; + }; + }; + var info_tab = { title : "VM information", content: @@ -671,12 +644,16 @@ function updateVMInfo(request,vm){ \ \ State\ - '+OpenNebula.Helper.resource_state("vm",vm_info.STATE)+'\ + '+vm_state+'\ \ \ LCM State\ '+OpenNebula.Helper.resource_state("vm_lcm",vm_info.LCM_STATE)+'\ \ + \ + Hostname\ + '+ hostname +'\ + \ \ Start time\ '+pretty_time(vm_info.STIME)+'\ @@ -751,46 +728,68 @@ function updateVMInfo(request,vm){ // which is a lot. function setupCreateVMDialog(){ - $('div#dialogs').append('
'); + dialogs_context.append('
'); //Insert HTML in place - $('#create_vm_dialog').html(create_vm_tmpl); + $create_vm_dialog = $('#create_vm_dialog') + var dialog = $create_vm_dialog; + dialog.html(create_vm_tmpl); //Prepare jquery dialog - $('#create_vm_dialog').dialog({ + dialog.dialog({ autoOpen: false, modal: true, width: 400 }); - $('#create_vm_dialog button').button(); + $('button',dialog).button(); - $('#create_vm_dialog #create_vm_proceed').click(function(){ - var vm_name = $('#create_vm_form #vm_name').val(); - var template_id = $('#create_vm_form #template_id').val(); + $('#create_vm_form',dialog).submit(function(){ + var vm_name = $('#vm_name',this).val(); + var template_id = $('#template_id',this).val(); + var n_times = $('#vm_n_times',this).val(); + var n_times_int=1; - Sunstone.runAction("VM.create",template_id,vm_name); - $('#create_vm_dialog').dialog('close'); + if (!template_id.length){ + notifyError("You have not selected a template"); + return false; + } + + if (n_times.length){ + n_times_int=parseInt(n_times,10); + } + + if (n_times_int>1){ + if (!vm_name.length){ + vm_name = $('#template_id option:selected',this).text(); + } + for (var i=0; i< n_times_int; i++){ + Sunstone.runAction("Template.instantiate",template_id,vm_name+"_"+i); + }; + } else { + Sunstone.runAction("Template.instantiate",template_id,vm_name); + }; + + Sunstone.runAction("VM.list"); + $create_vm_dialog.dialog('close'); return false; }); - - $('#create_vm_dialog #create_vm_cancel').click(function(){ - - }); } // Open creation dialog function popUpCreateVMDialog(){ - $('#create_vm_dialog').dialog('open'); + $create_vm_dialog.dialog('open'); } //Prepares a dialog to saveas a VM function setupSaveasDialog(){ //Append to DOM - $('div#dialogs').append('
'); + dialogs_context.append('
'); + $saveas_vm_dialog = $('#saveas_vm_dialog',dialogs_context); + var dialog = $saveas_vm_dialog; //Put HTML in place - $('#saveas_vm_dialog').html('\ - \ + dialog.html('\ + \
\
\
\ @@ -800,7 +799,7 @@ function setupSaveasDialog(){
\
'); - $('#saveas_vm_dialog').dialog({ + dialog.dialog({ autoOpen:false, width:600, modal:true, @@ -808,8 +807,8 @@ function setupSaveasDialog(){ resizable:true, }); - $('#saveas_vm_dialog #vm_saveas_proceed').click(function(){ - var elems = $('#saveas_vm_dialog #saveas_tabs div.saveas_tab'); + $('#saveas_vm_form',dialog).submit(function(){ + var elems = $('#saveas_tabs div.saveas_tab',this); var args = []; $.each(elems,function(){ var id = $('#vm_id',this).text(); @@ -836,25 +835,26 @@ function setupSaveasDialog(){ notifySubmit("VM.saveas",args); } - $('#saveas_vm_dialog').dialog('close'); + $saveas_vm_dialog.dialog('close'); return false; }); - $('#saveas_vm_dialog #vm_saveas_cancel').click(function(){ - $('#saveas_vm_dialog').dialog('close'); + $('#vm_saveas_cancel',dialog).click(function(){ + $saveas_vm_dialog.dialog('close'); return false; }); } function popUpSaveasDialog(elems){ - $('#saveas_vm_dialog #saveas_tabs').tabs('destroy'); - $('#saveas_vm_dialog #saveas_tabs').empty(); - $('#saveas_vm_dialog #saveas_tabs').html(''); + var dialog = $saveas_vm_dialog; + $('#saveas_tabs',dialog).tabs('destroy'); + $('#saveas_tabs',dialog).empty(); + $('#saveas_tabs',dialog).html(''); $.each(elems,function(){ var li = '
  • VM '+this+'
  • ' - $('#saveas_vm_dialog #saveas_tabs ul').append(li); + $('#saveas_tabs ul',dialog).append(li); var tab = '
    \
    Saveas for VM with ID '+this+'
    \
    \ @@ -884,12 +884,12 @@ function popUpSaveasDialog(elems){ -->\
    \
    '; - $('#saveas_vm_dialog #saveas_tabs').append(tab); + $('#saveas_tabs',dialog).append(tab); Sunstone.runAction("VM.saveas_disks",this); }); - $('#saveas_vm_dialog #saveas_tabs').tabs(); - $('#saveas_vm_dialog button').button(); - $('#saveas_vm_dialog').dialog('open'); + $('#saveas_tabs',dialog).tabs(); + $('button',dialog).button(); + dialog.dialog('open'); } function saveasDisksCallback(req,response){ @@ -917,7 +917,7 @@ function saveasDisksCallback(req,response){ select+= gen_option(disks.DISK_ID,disks.IMAGE,disks.SOURCE); } //introduce options in the right tab - $('#saveas_tabs #saveas_tab_'+id+' #vm_disk_id').html(select); + $('#saveas_tabs #saveas_tab_'+id+' #vm_disk_id',$saveas_vm_dialog).html(select); } @@ -925,10 +925,11 @@ function saveasDisksCallback(req,response){ function setVMAutorefresh(){ setInterval(function(){ var checked = $('input:checked',dataTable_vMachines.fnGetNodes()); - var filter = $("#datatable_vmachines_filter input").attr("value"); + var filter = $("#datatable_vmachines_filter input", + dataTable_vMachines.parents('#datatable_vmachines_wrapper')).attr("value"); if (!checked.length && !filter.length){ Sunstone.runAction("VM.autorefresh"); - } + }; },INTERVAL+someTime()); } @@ -970,9 +971,11 @@ function updateVNCState(rfb, state, oldstate, msg) { function setupVNC(){ //Append to DOM - $('div#dialogs').append('
    '); + dialogs_context.append('
    '); + $vnc_dialog = $('#vnc_dialog',dialogs_context); + var dialog = $vnc_dialog; - $('#vnc_dialog').html('\ + dialog.html('\
    \ \ \ @@ -987,12 +990,7 @@ function setupVNC(){ \ '); - $('#sendCtrlAltDelButton').click(function(){ - rfb.sendCtrlAltDel(); - return false; - }); - - $('#vnc_dialog').dialog({ + dialog.dialog({ autoOpen:false, width:700, modal:true, @@ -1000,22 +998,26 @@ function setupVNC(){ resizable:true, }); - $( "#vnc_dialog" ).bind( "dialogclose", function(event, ui) { - var id = $("#vnc_dialog").attr("vm_id"); + $('#sendCtrlAltDelButton',dialog).click(function(){ + rfb.sendCtrlAltDel(); + return false; + }); + + dialog.bind( "dialogclose", function(event, ui) { + var id = $vnc_dialog.attr("vm_id"); rfb.disconnect(); Sunstone.runAction("VM.stopvnc",id); }); - $('.vnc').live("click",function(){ + $('.vnc',main_tabs_context).live("click",function(){ //Which VM is it? var id = $(this).attr("vm_id"); //Set attribute to dialog - $('#vnc_dialog').attr("vm_id",id); + $vnc_dialog.attr("vm_id",id); //Request proxy server start Sunstone.runAction("VM.startvnc",id); return false; }); - } function vncCallback(request,response){ @@ -1035,7 +1037,7 @@ function vncCallback(request,response){ setTimeout(function(){ rfb.connect(vnc_host, vnc_port, vnc_pw); - $('#vnc_dialog').dialog('open'); + $vnc_dialog.dialog('open'); },4000); } @@ -1052,7 +1054,6 @@ function vncIcon(vm){ gr_icon = 'VNC Disabled'; } return gr_icon; - } function vmMonitorError(req,error_json){ @@ -1067,7 +1068,7 @@ function vmMonitorError(req,error_json){ // At this point the DOM is ready and the sunstone.js ready() has been run. $(document).ready(function(){ - dataTable_vMachines = $("#datatable_vmachines").dataTable({ + dataTable_vMachines = $("#datatable_vmachines",main_tabs_context).dataTable({ "bJQueryUI": true, "bSortClasses": false, "sPaginationType": "full_numbers", diff --git a/src/sunstone/public/js/plugins/vnets-tab.js b/src/sunstone/public/js/plugins/vnets-tab.js index 09c88afc80..7d6f6de516 100644 --- a/src/sunstone/public/js/plugins/vnets-tab.js +++ b/src/sunstone/public/js/plugins/vnets-tab.js @@ -122,8 +122,8 @@ var create_vn_tmpl = '; var vnetworks_select=""; -var network_list_json = {}; var dataTable_vNetworks; +var $create_vn_dialog; //Setup actions @@ -181,10 +181,8 @@ var vnet_actions = { "Network.publish" : { type: "multiple", call: OpenNebula.Network.publish, - callback: function (req) { - Sunstone.runAction("Network.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vNetworks); }, + callback: vnShow, + elements: vnElements, error: onError, notify: true }, @@ -192,10 +190,8 @@ var vnet_actions = { "Network.unpublish" : { type: "multiple", call: OpenNebula.Network.unpublish, - callback: function (req) { - Sunstone.runAction("Network.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vNetworks); }, + callback: vnShow, + elements: vnElements, error: onError, notify: true }, @@ -204,7 +200,7 @@ var vnet_actions = { type: "multiple", call: OpenNebula.Network.delete, callback: deleteVNetworkElement, - elements: function() { return getSelectedNodes(dataTable_vNetworks); }, + elements: vnElements, error: onError, notify: true }, @@ -212,10 +208,8 @@ var vnet_actions = { "Network.chown" : { type: "multiple", call: OpenNebula.Network.chown, - callback: function (req) { - Sunstone.runAction("Network.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vNetworks); }, + callback: vnShow, + elements: vnElements, error:onError, notify: true }, @@ -223,10 +217,8 @@ var vnet_actions = { "Network.chgrp" : { type: "multiple", call: OpenNebula.Network.chgrp, - callback: function (req) { - Sunstone.runAction("Network.show",req.request.data[0]); - }, - elements: function() { return getSelectedNodes(dataTable_vNetworks); }, + callback: vnShow, + elements: vnElements, error:onError, notify: true } @@ -237,48 +229,43 @@ var vnet_buttons = { "Network.refresh" : { type: "image", text: "Refresh list", - img: "images/Refresh-icon.png", - condition: True + img: "images/Refresh-icon.png" }, "Network.create_dialog" : { type: "create_dialog", - text: "+ New", - condition: True + text: "+ New" }, "Network.publish" : { type: "action", - text: "Publish", - condition: True + text: "Publish" }, "Network.unpublish" : { type: "action", - text: "Unpublish", - condition: True + text: "Unpublish" }, "Network.chown" : { type: "confirm_with_select", text: "Change owner", - select: function() {return users_select;}, + select: users_sel, tip: "Select the new owner:", - condition: function() { return gid == 0; } + condition: mustBeAdmin }, "Network.chgrp" : { type: "confirm_with_select", text: "Change group", - select: function() {return groups_select;}, + select: groups_sel, tip: "Select the new group:", - condition: function() { return gid == 0; } + condition: mustBeAdmin, }, "Network.delete" : { type: "action", - text: "Delete", - condition: True + text: "Delete" } } @@ -296,14 +283,22 @@ var vnet_info_panel = { var vnets_tab = { title: "Virtual Networks", content: vnets_tab_content, - buttons: vnet_buttons, - condition: True + buttons: vnet_buttons } Sunstone.addActions(vnet_actions); Sunstone.addMainTab('vnets_tab',vnets_tab); Sunstone.addInfoPanel('vnet_info_panel',vnet_info_panel); + +function vnElements(){ + return getSelectedNodes(dataTable_vNetworks); +} + +function vnShow(req){ + Sunstone.runAction("Network.show",req.request.data[0]); +} + //returns an array with the VNET information fetched from the JSON object function vNetworkElementArray(vn_json){ var network = vn_json.VNET; @@ -331,7 +326,7 @@ function vNetworkElementArray(vn_json){ //Adds a listener to show the extended info when clicking on a row function vNetworkInfoListener(){ - $('#tbodyvnetworks tr').live("click", function(e){ + $('#tbodyvnetworks tr',dataTable_vNetworks).live("click", function(e){ if ($(e.target).is('input')) {return true;} popDialogLoading(); var aData = dataTable_vNetworks.fnGetData(this); @@ -344,11 +339,16 @@ function vNetworkInfoListener(){ //updates the vnet select different options function updateNetworkSelect(){ vnetworks_select= - makeSelectOptions(dataTable_vNetworks,1,4,7,"no",2); + makeSelectOptions(dataTable_vNetworks, + 1, + 4, + [], + [] + ); //update static selectors: //in the VM creation dialog - $('div.vm_section#networks select#NETWORK_ID').html(vnetworks_select); + $('div.vm_section#networks select#NETWORK_ID',$create_template_dialog).html(vnetworks_select); } //Callback to update a vnet element after an action on it @@ -374,7 +374,6 @@ function addVNetworkElement(request,vn_json){ //updates the list of virtual networks function updateVNetworksView(request, network_list){ - network_list_json = network_list; var network_list_array = []; $.each(network_list,function(){ @@ -384,7 +383,7 @@ function updateVNetworksView(request, network_list){ updateView(network_list_array,dataTable_vNetworks); updateNetworkSelect(); //dependency with dashboard - updateDashboard("vnets",network_list_json); + updateDashboard("vnets",network_list); } @@ -449,11 +448,13 @@ function updateVNetworkInfo(request,vn){ //Prepares the vnet creation dialog function setupCreateVNetDialog() { - $('div#dialogs').append('
    '); - $('#create_vn_dialog').html(create_vn_tmpl); + dialogs_context.append('
    '); + $create_vn_dialog = $('#create_vn_dialog',dialogs_context) + var dialog = $create_vn_dialog; + dialog.html(create_vn_tmpl); //Prepare the jquery-ui dialog. Set style options here. - $('#create_vn_dialog').dialog({ + dialog.dialog({ autoOpen: false, modal: true, width: 475, @@ -461,22 +462,22 @@ function setupCreateVNetDialog() { }); //Make the tabs look nice for the creation mode - $('#vn_tabs').tabs(); - $('div#ranged').hide(); - $('#fixed_check').click(function(){ - $('div#fixed').show(); - $('div#ranged').hide(); + $('#vn_tabs',dialog).tabs(); + $('div#ranged',dialog).hide(); + $('#fixed_check',dialog).click(function(){ + $('div#fixed',$create_vn_dialog).show(); + $('div#ranged',$create_vn_dialog).hide(); }); - $('#ranged_check').click(function(){ - $('div#fixed').hide(); - $('div#ranged').show(); + $('#ranged_check',dialog).click(function(){ + $('div#fixed',$create_vn_dialog).hide(); + $('div#ranged',$create_vn_dialog).show(); }); - $('#create_vn_dialog button').button(); + $('button',dialog).button(); //When we hit the add lease button... - $('#add_lease').click(function(){ - var create_form = $('#create_vn_form_easy'); //this is our scope + $('#add_lease',dialog).click(function(){ + var create_form = $('#create_vn_form_easy',$create_vn_dialog); //this is our scope //Fetch the interesting values var lease_ip = $('#leaseip',create_form).val(); @@ -500,17 +501,17 @@ function setupCreateVNetDialog() { }; //We append the HTML into the select box. - $('select#leases').append(lease); + $('select#leases',$create_vn_dialog).append(lease); return false; }); - $('#remove_lease').click(function(){ - $('select#leases :selected').remove(); + $('#remove_lease', dialog).click(function(){ + $('select#leases :selected',$create_vn_dialog).remove(); return false; }); //Handle submission of the easy mode - $('#create_vn_form_easy').submit(function(){ + $('#create_vn_form_easy',dialog).submit(function(){ //Fetch values var name = $('#name',this).val(); if (!name.length){ @@ -563,27 +564,28 @@ function setupCreateVNetDialog() { //Create the VNetwork. Sunstone.runAction("Network.create",network_json); - $('#create_vn_dialog').dialog('close'); + $create_vn_dialog.dialog('close'); return false; }); - $('#create_vn_form_manual').submit(function(){ + $('#create_vn_form_manual',dialog).submit(function(){ var template=$('#template',this).val(); var vnet_json = {vnet: {vnet_raw: template}}; Sunstone.runAction("Network.create",vnet_json); - $('#create_vn_dialog').dialog('close'); + $create_vn_dialog.dialog('close'); return false; }); } function popUpCreateVnetDialog() { - $('#create_vn_dialog').dialog('open'); + $create_vn_dialog.dialog('open'); } function setVNetAutorefresh() { setInterval(function(){ var checked = $('input:checked',dataTable_vNetworks.fnGetNodes()); - var filter = $("#datatable_vnetworks_filter input").attr("value"); + var filter = $("#datatable_vnetworks_filter input", + dataTable_vNetworks.parents("#datatable_vnetworks_wrapper")).attr("value"); if (!checked.length && !filter.length){ Sunstone.runAction("Network.autorefresh"); } @@ -594,7 +596,7 @@ function setVNetAutorefresh() { //has been executed at this point. $(document).ready(function(){ - dataTable_vNetworks = $("#datatable_vnetworks").dataTable({ + dataTable_vNetworks = $("#datatable_vnetworks",main_tabs_context).dataTable({ "bJQueryUI": true, "bSortClasses": false, "bAutoWidth":false, diff --git a/src/sunstone/public/js/sunstone-util.js b/src/sunstone/public/js/sunstone-util.js index dadc422efb..94bbdccd67 100644 --- a/src/sunstone/public/js/sunstone-util.js +++ b/src/sunstone/public/js/sunstone-util.js @@ -82,98 +82,94 @@ function humanize_size(value) { } //Wrapper to add an element to a dataTable -function addElement(element,data_table){ - data_table.fnAddData(element); +function addElement(element,dataTable){ + dataTable.fnAddData(element); } //deletes an element with id 'tag' from a dataTable -function deleteElement(data_table,tag){ - var tr = $(tag).parents('tr')[0]; - data_table.fnDeleteRow(tr); - $('input',data_table).trigger("change"); +function deleteElement(dataTable,tag){ + var tr = $(tag,dataTable).parents('tr')[0]; + dataTable.fnDeleteRow(tr); + recountCheckboxes(dataTable); } -//Listens to the checkboxes of the datatable. This function is used -//by standard sunstone plugins to enable/disable certain action buttons -//according to the number of elements checked in the dataTables. -//It also checks the "check-all" box when all elements are checked -function tableCheckboxesListener(dataTable){ - - //Initialization - disable all buttons - var context = dataTable.parents('form'); +//Handle the activation of action buttons and the check_all box +//when elements in a datatable are modified. +function recountCheckboxes(dataTable){ + var table = $('tbody',dataTable); + var context = table.parents('form'); + var nodes = $('tr',table); //visible nodes + var total_length = nodes.length; + var checked_length = $('input:checked',nodes).length; var last_action_b = $('.last_action_button',context); - $('.top_button, .list_button',context).button("disable"); - if (last_action_b.length && last_action_b.val().length){ + + if (checked_length) { //at least 1 element checked + //enable action buttons + $('.top_button, .list_button',context).button("enable"); + //check if the last_action_button should be enabled + if (last_action_b.length && last_action_b.val().length){ + last_action_b.button("enable"); + }; + //enable checkall box + if (total_length == checked_length){ + $('.check_all',dataTable).attr("checked","checked"); + }; + } else { //no elements cheked + //disable action buttons, uncheck checkAll + $('.check_all',dataTable).removeAttr("checked"); + $('.top_button, .list_button',context).button("disable"); last_action_b.button("disable"); }; + + //any case the create dialog buttons should always be enabled. + $('.create_dialog_button',context).button("enable"); + $('.alwaysActive',context).button("enable"); +} + +//Init action buttons and checkboxes listeners +function tableCheckboxesListener(dataTable){ + //Initialization - disable all buttons + var context = dataTable.parents('form'); + + $('.last_action_button',context).button("disable"); + $('.top_button, .list_button',context).button("disable"); + //These are always enabled $('.create_dialog_button',context).button("enable"); $('.alwaysActive',context).button("enable"); //listen to changes in the visible inputs $('tbody input',dataTable).live("change",function(){ - var table = $(this).parents('tbody'); - var context = table.parents('form'); - var nodes = $('tr',table); - var total_length = nodes.length; - var checked_length = $('input:checked',nodes).length; - - var last_action_b = $('.last_action_button',context); - - - //if all elements are checked we check the check-all box - if (total_length == checked_length && total_length != 0){ - $('.check_all',dataTable).attr("checked","checked"); - } else { - $('.check_all',dataTable).removeAttr("checked"); - } - - //if some element is checked, we enable buttons, otherwise - //we disable them. - if (checked_length){ - $('.top_button, .list_button',context).button("enable"); - //check if the last_action_button should be enabled - if (last_action_b.length && last_action_b.val().length){ - last_action_b.button("enable"); - }; - } else { - $('.top_button, .list_button',context).button("disable"); - last_action_b.button("disable"); - } - - //any case the create dialog buttons should always be enabled. - $('.create_dialog_button',context).button("enable"); - $('.alwaysActive',context).button("enable"); + var datatable = $(this).parents('table'); + recountCheckboxes(dataTable); }); - } // Updates a data_table, with a 2D array containing the new values // Does a partial redraw, so the filter and pagination are kept -function updateView(item_list,data_table){ - if (data_table!=null) { - data_table.fnClearTable(); - data_table.fnAddData(item_list); - data_table.fnDraw(false); +function updateView(item_list,dataTable){ + if (dataTable) { + dataTable.fnClearTable(); + dataTable.fnAddData(item_list); + dataTable.fnDraw(false); }; } //replaces an element with id 'tag' in a dataTable with a new one -function updateSingleElement(element,data_table,tag){ - var nodes = data_table.fnGetNodes(); +function updateSingleElement(element,dataTable,tag){ + var nodes = dataTable.fnGetNodes(); var tr = $(tag,nodes).parents('tr')[0]; - var position = data_table.fnGetPosition(tr); - data_table.fnUpdate(element,position,0,false); - $('input',data_table).trigger("change"); - + var position = dataTable.fnGetPosition(tr); + dataTable.fnUpdate(element,position,0,false); + recountCheckboxes(dataTable); } // Returns an string in the form key=value key=value ... // Does not explore objects in depth. function stringJSON(json){ - var str = "" + var str = ""; for (field in json) { str+= field + '=' + json[field] + ' '; - } + }; return str; } @@ -187,9 +183,10 @@ function notifySubmit(action, args, extra_param){ msg += action_text; } else { msg += action_text + ": " + args; - } - if (extra_param != null) + }; + if (extra_param) { msg += " >> " + extra_param; + }; $.jGrowl(msg, {theme: "jGrowl-notify-submit"}); } @@ -197,19 +194,19 @@ function notifySubmit(action, args, extra_param){ //Notification on error function notifyError(msg){ msg = "

    Error

    " + msg; - $.jGrowl(msg, {theme: "jGrowl-notify-error", sticky: true }); } +//Standard notification function notifyMessage(msg){ msg = "

    Info

    " + msg; - $.jGrowl(msg, {theme: "jGrowl-notify-submit"}); } -// Returns an HTML string with the json keys and values in the form -// key: value
    -// It recursively explores objects +// Returns an HTML string with the json keys and values +// Attempts to css format output, giving different values to +// margins etc. according to depth level etc. +// See exapmle of use in plugins. function prettyPrintJSON(template_json,padding,weight, border_bottom,padding_top_bottom){ var str = "" if (!template_json){ return "Not defined";} @@ -287,26 +284,18 @@ function prettyPrintRowJSON(field,value,padding,weight, border_bottom,padding_to //Add a listener to the check-all box of a datatable, enabling it to //check and uncheck all the checkboxes of its elements. function initCheckAllBoxes(datatable){ - //not showing nice in that position - //$('.check_all').button({ icons: {primary : "ui-icon-check" }, - // text : true}); //small css hack $('.check_all',datatable).css({"border":"2px"}); - $('.check_all',datatable).click(function(){ - if ($(this).attr("checked")) { - $('tbody input:checkbox', - $(this).parents("table")).each(function(){ - $(this).attr("checked","checked"); - }); - - } else { - $('tbody input:checkbox', - $(this).parents("table")).each(function(){ - $(this).removeAttr("checked"); - }); - } - $('tbody input:checkbox',$(this).parents("table")).trigger("change"); + $('.check_all',datatable).change(function(){ + var table = $(this).parents('table'); + var checked = $(this).attr("checked"); + if (checked) { //check all + $('tbody input:checkbox',table).attr("checked","checked"); + } else { //uncheck all + $('tbody input:checkbox',table).removeAttr("checked"); + }; + recountCheckboxes(table); }); } @@ -321,44 +310,51 @@ function onError(request,error_json) { var m; var message = error_json.error.message; + if ( typeof onError.disabled == 'undefined' ) { + onError.disabled=false; + }; + //redirect to login if unauthenticated if (error_json.error.http_status=="401") { window.location.href = "login"; + onError.disabled=false; + return false; }; + if (!message){ - notifyError("Cannot contact server: is Sunstone server running and reachable?"); + if (!onError.disabled){ + notifyError("Cannot contact server: is it running and reachable?"); + onError.disabled=true; + } return false; - } + }; + + if (message.match(/^Network is unreachable .+$/)){ + if (!onError.disabled){ + notifyError("Network is unreachable: is OpenNebula running?"); + onError.disabled=true; + }; + return false; + } else { + onError.disabled=false; + }; + //Parse known errors: - var action_error = /^\[(\w+)\] Error trying to (\w+) (\w+) \[(\w+)\].*Reason: (.*)\.$/; - var action_error_noid = /^\[(\w+)\] Error trying to (\w+) (\w+) (.*)\.$/; - var get_error = /^\[(\w+)\] Error getting (\w+) \[(\w+)\]\.$/; - var auth_error = /^\[(\w+)\] User \[.\] not authorized to perform (\w+) on (\w+) \[?(\w+)\]?\.?$/; + var get_error = /^\[(\w+)\] Error getting ([\w ]+) \[(\d+)\]\.$/; + var auth_error = /^\[(\w+)\] User \[(\d+)\] not authorized to perform action on ([\w ]+).$/; - if (m = message.match(action_error)) { + if (m = message.match(get_error)) { method = m[1]; - action = m[2]; - object = m[3]; - id = m[4]; - reason = m[5]; - } else if (m = message.match(action_error_noid)) { - method = m[1]; - action = m[2]; - object = m[3]; - reason = m[4]; - } else if (m = message.match(get_error)) { - method = m[1]; - action = "SHOW"; + action = "Show"; object = m[2]; id = m[3]; } else if (m = message.match(auth_error)) { method = m[1]; - action = m[2]; - object = m[3]; - id = m[4]; - } + object = m[3]; + reason = "Unauthorized"; + }; if (m) { var rows; @@ -373,7 +369,7 @@ function onError(request,error_json) { message += ""; } message = "
    Loading
    "+key+""+value+"
    " + message + "
    "; - } + }; notifyError(message); return true; @@ -385,8 +381,8 @@ function waitingNodes(dataTable){ var nodes = dataTable.fnGetData(); for (var i=0;i'); - $(this).append(''); + obj.html(''); + obj.append(''); - $(this).append(''); + obj.append(''); //add the text to .tipspan - $('span.tipspan',this).html(tip); + $('span.tipspan',obj).html(tip); //make sure it is not floating in the wrong place - $(this).parent().append('
    '); + obj.parent().append('
    '); //hide the text - $('span.tipspan',this).hide(); + $('span.tipspan',obj).hide(); //When the mouse is hovering on the icon we fadein/out //the tip text - $('span.info_icon',this).hover(function(e){ + $('span.info_icon',obj).hover(function(e){ + var icon = $(this); var top, left; top = e.pageY - 15;// - $(this).parents('#create_vm_dialog').offset().top - 15; left = e.pageX + 15;// - $(this).parents('#create_vm_dialog').offset().left; - $(this).next().css( + icon.next().css( {"top":top+"px", "left":left+"px"}); - $(this).next().fadeIn(); + icon.next().fadeIn(); },function(){ $(this).next().fadeOut(); }); @@ -459,41 +457,45 @@ function setupTips(context){ //returns an array of ids of selected elements in a dataTable function getSelectedNodes(dataTable){ var selected_nodes = []; - if (dataTable != null){ + if (dataTable){ //Which rows of the datatable are checked? - var nodes = $('input:checked',$('tbody',dataTable)); + var nodes = $('tbody input:checked',dataTable); $.each(nodes,function(){ selected_nodes.push($(this).val()); }); - } + }; return selected_nodes; } //returns a HTML string with a select input code generated from -//a dataTable +//a dataTable. Allows filtering elements. function makeSelectOptions(dataTable, id_col,name_col, - status_col, - status_bad, - user_col){ + status_cols, + bad_status_values){ var nodes = dataTable.fnGetData(); - var select = ""; + var select = ''; var array; - $.each(nodes,function(){ - var id = this[id_col]; - var name = this[name_col]; - var status; - if (status_col >= 0) { - status = this[status_col]; - } - var user = user_col > 0 ? this[user_col] : false; - var isMine = user ? (username == user) || (uid == user) : true; - - - if (status_col < 0 || (status != status_bad) || isMine ){ + for (var j=0; j'+name+''; - } - }); + }; + }; return select; } @@ -503,13 +505,18 @@ function escapeDoubleQuotes(string){ return string.replace(/"/g,'\\"'); } +//Generate the div elements in which the monitoring graphs +//will be contained. They have some elements which ids are +//determined by the graphs configuration, so when the time +//of plotting comes, we can put the data in the right place. function generateMonitoringDivs(graphs, id_prefix){ var str = ""; - //40% of the width of the screen minus + //42% of the width of the screen minus //129px (left menu size) var width = ($(window).width()-129)*42/100; var id_suffix=""; var label=""; + var id=""; $.each(graphs,function(){ label = this.monitor_resources; @@ -528,25 +535,35 @@ function generateMonitoringDivs(graphs, id_prefix){ return str; } +//Draws data for plotting. It will find the correct +//div for doing it in the context with an id +//formed by a prefix (i.e. "hosts") and a suffix +//determined by the graph configuration: "info". function plot_graph(data,context,id_prefix,info){ var labels = info.monitor_resources; var humanize = info.humanize_figures ? humanize_size : function(val){ return val }; var id_suffix = labels.replace(/,/g,'_'); + var labels_array = labels.split(','); var monitoring = data.monitoring var series = []; var serie; var mon_count = 0; - for (var label in monitoring) { + //make sure series are painted in the order of the + //labels array. + for (var i=0; i
    '); + dialogs_context.append('
    '); + var dialog = $('#template_update_dialog',dialogs_context); //Put HTML in place - $('#template_update_dialog').html( + dialog.html( '
    \

    Update the template here:

    \
    \ @@ -609,7 +630,8 @@ function setupTemplateUpdateDialog(){
    \
    '); - $('#template_update_dialog').dialog({ + //Convert into jQuery + dialog.dialog({ autoOpen:false, width:700, modal:true, @@ -617,33 +639,40 @@ function setupTemplateUpdateDialog(){ resizable:false, }); - $('#template_update_dialog button').button(); + $('button',dialog).button(); - $('#template_update_dialog #template_update_select').live("change",function(){ + $('#template_update_select',dialog).change(function(){ var id = $(this).val(); + var dialog = $('#template_update_dialog'); if (id.length){ - var resource = $('#template_update_dialog #template_update_button').val(); - $('#template_update_dialog #template_update_textarea').val("Loading..."); + var resource = $('#template_update_button',dialog).val(); + $('#template_update_textarea',dialog).val("Loading..."); Sunstone.runAction(resource+".fetch_template",id); } else { - $('#template_update_dialog #template_update_textarea').val(""); - } + $('#template_update_textarea',dialog).val(""); + }; }); - $('#template_update_dialog #template_update_button').click(function(){ - var new_template = $('#template_update_dialog #template_update_textarea').val(); - var id = $('#template_update_dialog #template_update_select').val(); + $('#template_update_button',dialog).click(function(){ + var dialog = $('#template_update_dialog'); + var new_template = $('#template_update_textarea',dialog).val(); + var id = $('#template_update_select',dialog).val(); var resource = $(this).val(); Sunstone.runAction(resource+".update",id,new_template); - $('#template_update_dialog').dialog('close'); + dialog.dialog('close'); return false; }); } +//Pops up a dialog to update a template. +//If 1 element is selected, then this the only one shown. +//If no elements are selected, then all elements are included in the select box. +//If several elements are selected, only those are included in the select box. function popUpTemplateUpdateDialog(elem_str,select_items,sel_elems){ - $('#template_update_dialog #template_update_button').val(elem_str); - $('#template_update_dialog #template_update_select').html(select_items); - $('#template_update_dialog #template_update_textarea').val(""); + var dialog = $('#template_update_dialog'); + $('#template_update_button',dialog).val(elem_str); + $('#template_update_select',dialog).html(select_items); + $('#template_update_textarea',dialog).val(""); if (sel_elems.length >= 1){ //several items in the list are selected //grep them @@ -653,24 +682,29 @@ function popUpTemplateUpdateDialog(elem_str,select_items,sel_elems){ new_select+=''; }; }); - $('#template_update_dialog #template_update_select').html(new_select); + $('#template_update_select',dialog).html(new_select); if (sel_elems.length == 1) { - $('#template_update_dialog #template_update_select option').attr("selected","selected"); - $('#template_update_dialog #template_update_select').trigger("change"); + $('#template_update_select option',dialog).attr("selected","selected"); + $('#template_update_select',dialog).trigger("change"); } }; - $('#template_update_dialog').dialog('open'); + dialog.dialog('open'); return false; } -//functions that used as true and false conditions for testing mainly -function True(){ - return true; -} -function False(){ - return false; +function mustBeAdmin(){ + return gid == 0; } -function Empty(){ -}; +function users_sel(){ + return users_select; +} + +function groups_sel(){ + return groups_select; +} + +function hosts_sel(){ + return hosts_select; +} diff --git a/src/sunstone/public/js/sunstone.js b/src/sunstone/public/js/sunstone.js index c642261d6f..cbc3d4553e 100644 --- a/src/sunstone/public/js/sunstone.js +++ b/src/sunstone/public/js/sunstone.js @@ -17,8 +17,14 @@ var cookie = {}; var username = ''; var uid = ''; +var gid = ''; var spinner = 'retrieving'; +var main_tabs_context; +var dialogs_context; +var plots_context; +var info_panels_context; + //Sunstone configuration is formed by predifined "actions", main tabs //and "info_panels". Each tab has "content" and "buttons". Each @@ -67,7 +73,7 @@ var Sunstone = { "updateMainTabContent" : function(tab_id,content_arg,refresh){ SunstoneCfg["tabs"][tab_id]["content"]=content_arg; if (refresh){ //if not present it won't be updated - $('div#'+tab_id).html(content_arg); + $('div#'+tab_id, main_tabs_context).html(content_arg); } }, @@ -75,7 +81,7 @@ var Sunstone = { "updateMainTabButtons" : function(tab_id,buttons_arg,refresh){ SunstoneCfg["tabs"][tab_id]["buttons"]=buttons_arg; if (refresh){ - $('div#'+tab_id+' .action_blocks').empty(); + $('div#'+tab_id+' .action_blocks', main_tabs_context).empty(); insertButtonsInTab(tab_id); } }, @@ -84,7 +90,7 @@ var Sunstone = { "removeMainTab" : function(tab_id,refresh) { delete SunstoneCfg["tabs"][tab_id]; if (refresh) { - $('div#'+tab_id).remove(); + $('div#'+tab_id, main_tabs_context).remove(); $('ul#navigation li#li_'+tab_id).remove(); } }, @@ -138,7 +144,7 @@ var Sunstone = { SunstoneCfg["info_panels"][panel_name][panel_tab_id] = panel_tab_obj; if (refresh){ var tab_content = panel_tab_obj.content; - $('div#'+panel_name+' div#'+panel_tab_id).html(tab_content); + $('div#'+panel_name+' div#'+panel_tab_id,info_panel_context).html(tab_content); } }, @@ -278,6 +284,13 @@ var Sunstone = { //Plugins have done their pre-ready jobs when we execute this. That means //all startup configuration is in place regarding tabs, info panels etc. $(document).ready(function(){ + + //Contexts - make everything more efficient + main_tabs_context = $('div.inner-center'); + dialogs_context = $('div#dialogs'); + plots_context = $('div#plots'); + info_panels_context = $('div#info_panels'); + readCookie(); setLogin(); @@ -299,7 +312,6 @@ $(document).ready(function(){ //An action buttons runs a predefined action. If it has type //"multiple" it runs that action on the elements of a datatable. $('.action_button').live("click",function(){ - var error = 0; var table = null; var value = $(this).attr("value"); @@ -329,14 +341,14 @@ $(document).ready(function(){ //Listen .confirm_buttons. These buttons show a confirmation dialog //before running the action. - $('.confirm_button').live("click",function(){ + $('.confirm_button',main_tabs_context).live("click",function(){ popUpConfirmDialog(this); return false; }); //Listen .confirm_buttons. These buttons show a confirmation dialog //with a select box before running the action. - $('.confirm_with_select_button').live("click",function(){ + $('.confirm_with_select_button',main_tabs_context).live("click",function(){ popUpConfirmWithSelectDialog(this); return false; }); @@ -351,7 +363,7 @@ $(document).ready(function(){ //Close select lists when clicking somewhere else. $('*:not(.action_list,.list_button)').click(function(){ - $('.action_list:visible').hide(); + $('.action_blocks .action_list:visible',main_tabs_context).hide(); }); //Start with the dashboard (supposing we have one). @@ -380,8 +392,8 @@ function setLogin(){ uid = cookie["one-user_id"]; gid = cookie["one-user_gid"]; - $("#user").html(username); - $("#logout").click(function(){ + $("div#header span#user").html(username); + $("div#header a#logout").click(function(){ //todo, this is ugly var f_logout = typeof(OpenNebula)!="undefined"? OpenNebula.Auth.logout : oZones.Auth.logout; @@ -420,10 +432,12 @@ function insertTab(tab_name){ //skip this tab if we do not meet the condition if (condition && !condition()) {return;} - $("div.inner-center").append('
    '); - $('div#'+tab_name).html(tab_info.content); - $('ul#navigation').append('
  • '+tab_info.title+'
  • '); + main_tabs_context.append('
    '); + + $('div#'+tab_name,main_tabs_context).html(tab_info.content); + + $('div#menu ul#navigation').append('
  • '+tab_info.title+'
  • '); } function hideSubTabs(){ @@ -431,7 +445,7 @@ function hideSubTabs(){ var tab_info = SunstoneCfg["tabs"][tab]; var tabClass = tab_info["tabClass"]; if (tabClass=="subTab"){ - $('#li_'+tab).hide(); + $('div#menu ul#navigation #li_'+tab).hide(); }; }; } @@ -440,7 +454,7 @@ function hideSubTabs(){ //Inserts the buttons of all tabs. function insertButtons(){ - for (tab in SunstoneCfg["tabs"]){ + for (tab in SunstoneCfg["tabs"]){ insertButtonsInTab(tab) } } @@ -455,7 +469,9 @@ function insertButtonsInTab(tab_name){ //Check if we have included an appropiate space our tab to //insert them (an .action_blocks div) - if ($('div#'+tab_name+' div.action_blocks').length){ + var action_block = $('div#'+tab_name+' div.action_blocks',main_tabs_context) + + if (action_block.length){ //for every button defined for this tab... for (button_name in buttons){ @@ -501,10 +517,10 @@ function insertButtonsInTab(tab_name){ button_code = $(button_code).addClass("alwaysActive"); } - $('div#'+tab_name+' .action_blocks').append(button_code); + action_block.append(button_code); }//for each button in tab - $('.top_button').button(); + $('.top_button',action_block).button(); }//if tab exists } @@ -514,7 +530,7 @@ function insertButtonsInTab(tab_name){ function initListButtons(){ //for each multi_action select - $('.multi_action_slct').each(function(){ + $('.multi_action_slct',main_tabs_context).each(function(){ //prepare replacement buttons var buttonset = $('
    Previous action').button(); @@ -551,7 +567,7 @@ function initListButtons(){ //below the listeners for events on these buttons and list //enable run the last action button - $('.action_list li a').click(function(){ + $('.action_list li a',main_tabs_context).click(function(){ //enable run last action button var prev_action_button = $('.last_action_button',$(this).parents('.action_blocks')); prev_action_button.val($(this).val()); @@ -565,28 +581,26 @@ function initListButtons(){ //return false; }); - //Show the list of actions in place - $('.list_button').click(function(){ - $('.action_list',$(this).parents('.action_blocks')).css({ - "left": $(this).prev().position().left, - "top": $(this).prev().position().top+13, - "width": $(this).parent().outerWidth()-11 - }); - $('.action_list',$(this).parents('.action_blocks')).toggle("blind",100); - return false; + //Show the list of actions in place + $('.list_button',main_tabs_context).click(function(){ + $('.action_list',$(this).parents('.action_blocks')).css({ + "left": $(this).prev().position().left, + "top": $(this).prev().position().top+13, + "width": $(this).parent().outerWidth()-11 }); + //100ms animation time + $('.action_list',$(this).parents('.action_blocks')).toggle("blind",100); + return false; + }); } //Prepares the standard confirm dialogs function setupConfirmDialogs(){ - - //add div to the main body if it isn't present. - if (!($('div#confirm_dialog').length)){ - $('div#dialogs').append('
    '); - }; + dialogs_context.append('
    '); + var dialog = $('div#confirm_dialog',dialogs_context); //add the HTML with the standard question and buttons. - $('div#confirm_dialog').html( + dialog.html( '
    \
    You have to confirm this action.
    \
    \ @@ -599,7 +613,7 @@ function setupConfirmDialogs(){
    '); //prepare the jquery dialog - $('div#confirm_dialog').dialog({ + dialog.dialog({ resizable:false, modal:true, width:300, @@ -608,14 +622,12 @@ function setupConfirmDialogs(){ }); //enhace the button look - $('div#confirm_dialog button').button(); + $('button',dialog).button(); - //same for the confirm with select dialog. - if (!($('div#confirm_with_select_dialog').length)){ - $('div#dialogs').append('
    '); - }; + dialogs_context.append('
    '); + dialog = $('div#confirm_with_select_dialog',dialogs_context); - $('div#confirm_with_select_dialog').html( + dialog.html( '
    \
    You need to select something.
    \