1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-08 20:58:17 +03:00

Merge branch 'feature-4317'

This commit is contained in:
Ruben S. Montero 2016-02-26 15:43:17 +01:00
commit b47406c429
55 changed files with 3474 additions and 1154 deletions

View File

@ -55,7 +55,10 @@ public:
int resp_id; /**< Id of the object */
string resp_msg; /**< Additional response message */
RequestAttributes(){};
RequestAttributes()
{
resp_obj = PoolObjectSQL::NONE;
};
RequestAttributes(const RequestAttributes& ra)
{
@ -253,6 +256,15 @@ protected:
*/
void failure_response(ErrorCode ec, RequestAttributes& ra);
/**
* Builds an error response. A descriptive error message
* is constructed using att.resp_obj, att.resp_id and/or att.resp_msg and
* the ErrorCode
* @param ec error code for this call
* @param att the specific request attributes
*/
string failure_message(ErrorCode ec, RequestAttributes& att);
/* ---------------------------------------------------------------------- */
/* Authorization methods for requests */
/* ---------------------------------------------------------------------- */

View File

@ -33,12 +33,30 @@ protected:
const string& help)
:Request(method_name, "A:siiiiiiiiii", help){};
RequestManagerChmod(const string& method_name,
const string& params,
const string& help)
:Request(method_name, params, help){};
~RequestManagerChmod(){};
/* -------------------------------------------------------------------- */
virtual void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
static ErrorCode chmod( PoolSQL * pool,
int oid,
int owner_u,
int owner_m,
int owner_a,
int group_u,
int group_m,
int group_a,
int other_u,
int other_m,
int other_a,
RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */
@ -67,6 +85,7 @@ class TemplateChmod : public RequestManagerChmod
public:
TemplateChmod():
RequestManagerChmod("TemplateChmod",
"A:siiiiiiiiiib"
"Changes permission bits of a virtual machine template")
{
Nebula& nd = Nebula::instance();
@ -75,6 +94,9 @@ public:
};
~TemplateChmod(){};
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */
@ -113,6 +135,17 @@ public:
~ImageChmod(){};
static ErrorCode chmod( int oid,
int owner_u,
int owner_m,
int owner_a,
int group_u,
int group_m,
int group_a,
int other_u,
int other_m,
int other_a,
RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */

View File

@ -30,6 +30,18 @@ using namespace std;
class RequestManagerDelete: public Request
{
protected:
RequestManagerDelete(const string& method_name,
const string& params,
const string& help)
:Request(method_name, params, help)
{
auth_op = AuthRequest::MANAGE;
Nebula& nd = Nebula::instance();
clpool = nd.get_clpool();
aclm = nd.get_aclm();
};
RequestManagerDelete(const string& method_name,
const string& help)
:Request(method_name, "A:si", help)
@ -45,11 +57,14 @@ protected:
/* -------------------------------------------------------------------- */
void request_execute(xmlrpc_c::paramList const& _paramList,
void request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att);
bool delete_authorization(int oid,
RequestAttributes& att);
static ErrorCode delete_authorization(
PoolSQL* pool,
int oid,
AuthRequest::Operation auth_op,
RequestAttributes& att);
/* -------------------------------------------------------------------- */
@ -79,6 +94,7 @@ class TemplateDelete : public RequestManagerDelete
public:
TemplateDelete():
RequestManagerDelete("TemplateDelete",
"A:sib"
"Deletes a virtual machine template")
{
Nebula& nd = Nebula::instance();
@ -87,6 +103,9 @@ public:
};
~TemplateDelete(){};
void request_execute(
xmlrpc_c::paramList const& paramList, RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */
@ -137,7 +156,10 @@ public:
~ImageDelete(){};
int drop(int oid, PoolObjectSQL * object, string& error_msg);
void request_execute(
xmlrpc_c::paramList const& paramList, RequestAttributes& att);
static ErrorCode delete_img(int oid, RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */

View File

@ -70,6 +70,13 @@ public:
*(static_cast<VirtualMachineTemplate *>(obj_template)));
};
/**
* Returns all the DISK/IMAGE_IDs in the Template
* @return image IDs
*/
vector<int> get_img_ids();
// TODO: make const
// ------------------------------------------------------------------------
// Virtual Router
// ------------------------------------------------------------------------

View File

@ -878,6 +878,7 @@ VM_RESTRICTED_ATTR = "CPU_COST"
VM_RESTRICTED_ATTR = "MEMORY_COST"
VM_RESTRICTED_ATTR = "DISK_COST"
VM_RESTRICTED_ATTR = "PCI"
VM_RESTRICTED_ATTR = "USER_INPUTS"
#VM_RESTRICTED_ATTR = "RANK"
#VM_RESTRICTED_ATTR = "SCHED_RANK"

View File

@ -51,6 +51,13 @@ EOT
"information, such as the SIZE for each DISK"
}
RECURSIVE={
:name => "recursive",
:large => "--recursive",
:description => "Applies the action to the template plus any "+
"image defined in DISK/IMAGE_ID. Images defined by name are not affected"
}
def self.rname
"VMTEMPLATE"
end
@ -111,6 +118,9 @@ EOT
table
end
INT_EXP = /^-?\d+$/
FLOAT_EXP = /^-?\d+(\.\d+)?$/
def self.get_user_inputs(template)
user_inputs = template['VMTEMPLATE']['TEMPLATE']['USER_INPUTS']
@ -123,21 +133,39 @@ EOT
user_inputs.each do |key, val|
input_cfg = val.split('|')
if input_cfg.length != 3
STDERR.puts "Malformed user input. It should have 3 parts separated by '|':"
if input_cfg.length < 3
STDERR.puts "Malformed user input. It should have at least 3 parts separated by '|':"
STDERR.puts " #{key}: #{val}"
exit(-1)
end
optional, type, description = input_cfg
optional, type, description, params, initial = input_cfg
optional.strip!
type.strip!
description.strip!
print " * (#{key}) #{description}: "
if input_cfg.length > 3
if input_cfg.length != 5
STDERR.puts "Malformed user input. It should have 5 parts separated by '|':"
STDERR.puts " #{key}: #{val}"
exit(-1)
end
params.strip!
initial.strip!
end
puts " * (#{key}) #{description}"
header = " "
if initial != nil && initial != ""
header += "Press enter for default (#{initial}). "
end
case type
when 'text', 'text64'
print header
answer = STDIN.readline.chop
if answer == "<<EDITOR>>"
@ -147,13 +175,87 @@ EOT
if type == 'text64'
answer = Base64::encode64(answer).strip.delete("\n")
end
when 'password'
print header
answer = OpenNebulaHelper::OneHelper.get_password
when 'number', 'number-float'
if type == "number"
header += "Integer: "
exp = INT_EXP
else
header += "Float: "
exp = FLOAT_EXP
end
begin
print header
answer = STDIN.readline.chop
answer = initial if (answer == "")
end while (answer =~ exp) == nil
when 'range', 'range-float'
min,max = params.split('..')
if min.nil? || max.nil?
STDERR.puts "Malformed user input. Parameters should be 'min..max':"
STDERR.puts " #{key}: #{val}"
exit(-1)
end
if type == "range"
exp = INT_EXP
min = min.to_i
max = max.to_i
header += "Integer in the range [#{min}..#{max}]: "
else
exp = FLOAT_EXP
min = min.to_f
max = max.to_f
header += "Float in the range [#{min}..#{max}]: "
end
begin
print header
answer = STDIN.readline.chop
answer = initial if (answer == "")
end while ((answer =~ exp) == nil || answer.to_f < min || answer.to_f > max)
when 'list'
options = params.split(",")
options.each_with_index {|opt,i|
puts " #{i} #{opt}"
}
puts
header += "Please type the selection number: "
begin
print header
answer = STDIN.readline.chop
if (answer == "")
answer = initial
else
answer = options[answer.to_i]
end
end while (!options.include?(answer))
else
STDERR.puts "user input types can only be text or password:"
STDERR.puts "Wrong type for user input:"
STDERR.puts " #{key}: #{val}"
exit(-1)
end
answers << "#{key} = \""
answers << answer.gsub('"', "\\\"") << "\"\n"
end

View File

@ -163,9 +163,13 @@ cmd=CommandParser::CmdParser.new(ARGV) do
Deletes the given Template
EOT
command :delete, delete_desc, [:range, :templateid_list] do
command :delete, delete_desc, [:range, :templateid_list],
:options =>OneTemplateHelper::RECURSIVE do
recursive = (options[:recursive] == true)
helper.perform_actions(args[0],options,"deleted") do |t|
t.delete
t.delete(recursive)
end
end
@ -264,9 +268,13 @@ cmd=CommandParser::CmdParser.new(ARGV) do
Changes the Template permissions
EOT
command :chmod, chmod_desc, [:range, :templateid_list], :octet do
command :chmod, chmod_desc, [:range, :templateid_list], :octet,
:options =>OneTemplateHelper::RECURSIVE do
recursive = (options[:recursive] == true)
helper.perform_actions(args[0],options, "Permissions changed") do |t|
t.chmod_octet(args[1])
t.chmod_octet(args[1], recursive)
end
end

View File

@ -96,8 +96,15 @@ module OpenNebula
end
# Deletes the Template
def delete()
super(TEMPLATE_METHODS[:delete])
#
# @param recursive [true,false] optional, deletes the template plus
# any image defined in DISK/IMAGE_ID. Images defined by name are
# not affected
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def delete(recursive=false)
return call(TEMPLATE_METHODS[:delete], @pe_id, recursive)
end
# Creates a VM instance from a Template
@ -157,21 +164,40 @@ module OpenNebula
# Changes the Template permissions.
#
# @param octet [String] Permissions octed , e.g. 640
# @param recursive [true,false] optional, chmods the template plus
# any image defined in DISK/IMAGE_ID. Images defined by name are
# not affected
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def chmod_octet(octet)
super(TEMPLATE_METHODS[:chmod], octet)
def chmod_octet(octet, recursive=false)
owner_u = octet[0..0].to_i & 4 != 0 ? 1 : 0
owner_m = octet[0..0].to_i & 2 != 0 ? 1 : 0
owner_a = octet[0..0].to_i & 1 != 0 ? 1 : 0
group_u = octet[1..1].to_i & 4 != 0 ? 1 : 0
group_m = octet[1..1].to_i & 2 != 0 ? 1 : 0
group_a = octet[1..1].to_i & 1 != 0 ? 1 : 0
other_u = octet[2..2].to_i & 4 != 0 ? 1 : 0
other_m = octet[2..2].to_i & 2 != 0 ? 1 : 0
other_a = octet[2..2].to_i & 1 != 0 ? 1 : 0
chmod(owner_u, owner_m, owner_a, group_u, group_m, group_a, other_u,
other_m, other_a, recursive)
end
# Changes the Template permissions.
# Each [Integer] argument must be 1 to allow, 0 deny, -1 do not change
#
# @param recursive [true,false] optional, chmods the template plus
# any image defined in DISK/IMAGE_ID. Images defined by name are
# not affected
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def chmod(owner_u, owner_m, owner_a, group_u, group_m, group_a, other_u,
other_m, other_a)
super(TEMPLATE_METHODS[:chmod], owner_u, owner_m, owner_a, group_u,
group_m, group_a, other_u, other_m, other_a)
other_m, other_a, recursive=false)
return call(TEMPLATE_METHODS[:chmod], @pe_id, owner_u, owner_m, owner_a, group_u,
group_m, group_a, other_u, other_m, other_a, recursive)
end
# Clones this Template into a new one

View File

@ -585,7 +585,7 @@ void Request::failure_response(ErrorCode ec, const string& str_val,
/* -------------------------------------------------------------------------- */
void Request::failure_response(ErrorCode ec, RequestAttributes& att)
string Request::failure_message(ErrorCode ec, RequestAttributes& att)
{
std::ostringstream oss;
std::string obname;
@ -604,7 +604,7 @@ void Request::failure_response(ErrorCode ec, RequestAttributes& att)
switch(ec)
{
case SUCCESS:
return;
return "";
case AUTHORIZATION:
oss << "User [" << att.uid << "] ";
@ -652,7 +652,15 @@ void Request::failure_response(ErrorCode ec, RequestAttributes& att)
break;
}
failure_response(ec, oss.str(), att);
return oss.str();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Request::failure_response(ErrorCode ec, RequestAttributes& att)
{
failure_response(ec, failure_message(ec, att), att);
}
/* -------------------------------------------------------------------------- */

View File

@ -16,7 +16,6 @@
#include "RequestManagerChmod.h"
#include "NebulaLog.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
@ -39,6 +38,39 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList,
int other_m = xmlrpc_c::value_int(paramList.getInt(9));
int other_a = xmlrpc_c::value_int(paramList.getInt(10));
ErrorCode ec = chmod(pool, oid,
owner_u, owner_m, owner_a,
group_u, group_m, group_a,
other_u, other_m, other_a,
att);
if ( ec == SUCCESS )
{
success_response(oid, att);
}
else
{
failure_response(ec, att);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
Request::ErrorCode RequestManagerChmod::chmod(
PoolSQL * pool,
int oid,
int owner_u,
int owner_m,
int owner_a,
int group_u,
int group_m,
int group_a,
int other_u,
int other_m,
int other_a,
RequestAttributes& att)
{
PoolObjectSQL * object;
if ( att.uid != 0 && att.gid != 0)
@ -51,8 +83,7 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList,
if ( object == 0 )
{
att.resp_id = oid;
failure_response(NO_EXISTS, att);
return;
return NO_EXISTS;
}
object->get_permissions(perms);
@ -99,8 +130,7 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList,
if ( !enable_other )
{
att.resp_msg = "'other' permissions is disabled in oned.conf";
failure_response(AUTHORIZATION, att);
return;
return AUTHORIZATION;
}
}
@ -111,9 +141,7 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList,
if (UserPool::authorize(ar) == -1)
{
att.resp_msg = ar.message;
failure_response(AUTHORIZATION, att);
return;
return AUTHORIZATION;
}
}
@ -124,8 +152,7 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList,
if ( object == 0 )
{
att.resp_id = oid;
failure_response(NO_EXISTS, att);
return;
return NO_EXISTS;
}
int rc = object->set_permissions(owner_u, owner_m, owner_a, group_u,
@ -133,20 +160,114 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList,
if ( rc != 0 )
{
failure_response(INTERNAL, att);
object->unlock();
return;
return INTERNAL;
}
pool->update(object);
object->unlock();
success_response(oid, att);
return;
return SUCCESS;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void TemplateChmod::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
int oid = xmlrpc_c::value_int(paramList.getInt(1));
int owner_u = xmlrpc_c::value_int(paramList.getInt(2));
int owner_m = xmlrpc_c::value_int(paramList.getInt(3));
int owner_a = xmlrpc_c::value_int(paramList.getInt(4));
int group_u = xmlrpc_c::value_int(paramList.getInt(5));
int group_m = xmlrpc_c::value_int(paramList.getInt(6));
int group_a = xmlrpc_c::value_int(paramList.getInt(7));
int other_u = xmlrpc_c::value_int(paramList.getInt(8));
int other_m = xmlrpc_c::value_int(paramList.getInt(9));
int other_a = xmlrpc_c::value_int(paramList.getInt(10));
bool recursive = false;
if (paramList.size() > 11)
{
recursive = xmlrpc_c::value_boolean(paramList.getBoolean(11));
}
ErrorCode ec = chmod(pool, oid,
owner_u, owner_m, owner_a,
group_u, group_m, group_a,
other_u, other_m, other_a,
att);
if ( ec != SUCCESS )
{
failure_response(ec, att);
return;
}
if (recursive)
{
VMTemplate* tmpl = static_cast<VMTemplatePool*>(pool)->get(oid, true);
if ( tmpl == 0 )
{
att.resp_id = oid;
failure_response(NO_EXISTS, att);
return;
}
vector<int> img_ids = tmpl->get_img_ids();
tmpl->unlock();
ErrorCode ec;
for (vector<int>::iterator it = img_ids.begin(); it != img_ids.end(); it++)
{
ec = ImageChmod::chmod(*it,
owner_u, owner_m, owner_a,
group_u, group_m, group_a,
other_u, other_m, other_a,
att);
if (ec != SUCCESS)
{
NebulaLog::log("ReM", Log::ERROR, failure_message(ec, att));
}
// TODO rollback?
}
}
success_response(oid, att);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
Request::ErrorCode ImageChmod::chmod(
int oid,
int owner_u,
int owner_m,
int owner_a,
int group_u,
int group_m,
int group_a,
int other_u,
int other_m,
int other_a,
RequestAttributes& att)
{
return RequestManagerChmod::chmod(
Nebula::instance().get_ipool(),
oid,
owner_u, owner_m, owner_a,
group_u, group_m, group_a,
other_u, other_m, other_a,
att);
}

View File

@ -21,25 +21,26 @@ using namespace std;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool RequestManagerDelete::delete_authorization(
int oid,
RequestAttributes& att)
Request::ErrorCode RequestManagerDelete::delete_authorization(
PoolSQL* pool,
int oid,
AuthRequest::Operation auth_op,
RequestAttributes& att)
{
PoolObjectSQL * object;
PoolObjectAuth perms;
if ( att.uid == 0 )
{
return true;
return SUCCESS;
}
object = pool->get(oid,true);
object = pool->get(oid, true);
if ( object == 0 )
{
att.resp_id = oid;
failure_response(NO_EXISTS, att);
return false;
return NO_EXISTS;
}
object->get_permissions(perms);
@ -53,12 +54,10 @@ bool RequestManagerDelete::delete_authorization(
if (UserPool::authorize(ar) == -1)
{
att.resp_msg = ar.message;
failure_response(AUTHORIZATION, att);
return false;
return AUTHORIZATION;
}
return true;
return SUCCESS;
}
/* ------------------------------------------------------------------------- */
@ -70,9 +69,13 @@ void RequestManagerDelete::request_execute(xmlrpc_c::paramList const& paramList,
int oid = xmlrpc_c::value_int(paramList.getInt(1));
PoolObjectSQL * object;
string error_msg;
ErrorCode ec;
if ( delete_authorization(oid, att) == false )
ec = delete_authorization(pool, oid, auth_op, att);
if ( ec != SUCCESS )
{
failure_response(ec, att);
return;
}
@ -141,6 +144,81 @@ int RequestManagerDelete::drop(
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void TemplateDelete::request_execute(
xmlrpc_c::paramList const& paramList, RequestAttributes& att)
{
int oid = xmlrpc_c::value_int(paramList.getInt(1));
bool recursive = false;
VMTemplate * object;
string error_msg;
vector<int> img_ids;
ErrorCode ec;
if (paramList.size() > 2)
{
recursive = xmlrpc_c::value_boolean(paramList.getBoolean(2));
}
ec = delete_authorization(pool, oid, auth_op, att);
if ( ec != SUCCESS )
{
failure_response(ec, att);
return;
}
object = static_cast<VMTemplatePool*>(pool)->get(oid, true);
if ( object == 0 )
{
att.resp_id = oid;
failure_response(NO_EXISTS, att);
return;
}
int rc = pool->drop(object, error_msg);
if (recursive)
{
img_ids = object->get_img_ids();
}
object->unlock();
if ( rc != 0 )
{
att.resp_msg = "Cannot delete " + object_name(auth_object) + ". " + error_msg;
failure_response(ACTION, att);
return;
}
aclm->del_resource_rules(oid, auth_object);
if (recursive)
{
ErrorCode ec;
for (vector<int>::iterator it = img_ids.begin(); it != img_ids.end(); it++)
{
ec = ImageDelete::delete_img(*it, att);
if (ec != SUCCESS)
{
NebulaLog::log("ReM", Log::ERROR, failure_message(ec, att));
}
// TODO rollback?
}
}
success_response(oid, att);
return;
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
int HostDelete::drop(int oid, PoolObjectSQL * object, string& error_msg)
{
Nebula& nd = Nebula::instance();
@ -174,14 +252,66 @@ int HostDelete::drop(int oid, PoolObjectSQL * object, string& error_msg)
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
int ImageDelete::drop(int oid, PoolObjectSQL * object, string& error_msg)
void ImageDelete::request_execute(
xmlrpc_c::paramList const& paramList, RequestAttributes& att)
{
int oid = xmlrpc_c::value_int(paramList.getInt(1));
ErrorCode ec = delete_img(oid, att);
if ( ec == SUCCESS )
{
success_response(oid, att);
}
else
{
failure_response(ec, att);
}
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
Request::ErrorCode ImageDelete::delete_img(int oid, RequestAttributes& att)
{
Image * object;
string error_msg;
ErrorCode ec;
Nebula& nd = Nebula::instance();
ImageManager * imagem = nd.get_imagem();
AclManager * aclm = nd.get_aclm();
ImagePool * pool = nd.get_ipool();
object->unlock();
PoolObjectSQL::ObjectType auth_object = PoolObjectSQL::IMAGE;
return imagem->delete_image(oid, error_msg);
ec = delete_authorization(pool, oid, AuthRequest::MANAGE, att);
if ( ec != SUCCESS )
{
att.resp_obj = auth_object;
return ec;
}
object = pool->get(oid, false);
if ( object == 0 )
{
att.resp_id = oid;
return NO_EXISTS;
}
int rc = imagem->delete_image(oid, error_msg);
if ( rc != 0 )
{
att.resp_msg = "Cannot delete " + object_name(auth_object) + ". " + error_msg;
return ACTION;
}
aclm->del_resource_rules(oid, auth_object);
return SUCCESS;
}
/* ------------------------------------------------------------------------- */

View File

@ -136,50 +136,6 @@
#
:oneflow_server: http://localhost:2474/
################################################################################
# Default instance types for the cloud view
################################################################################
#
# These types are presented in the cloud view to customize VM Templates. Each
# type is defined by:
# name: the name of the type
# cpu: capacity allocated to the VM for scheduling purposes
# vcpu: number of cores
# memory: in MB for the VM
# description: to help the user pick one, it may include purpose or price.
:instance_types:
- :name: small-x1
:cpu: 1
:vcpu: 1
:memory: 128
:description: Very small instance for testing purposes
- :name: small-x2
:cpu: 2
:vcpu: 2
:memory: 512
:description: Small instance for testing multi-core applications
- :name: medium-x2
:cpu: 2
:vcpu: 2
:memory: 1024
:description: General purpose instance for low-load servers
- :name: medium-x4
:cpu: 4
:vcpu: 4
:memory: 2048
:description: General purpose instance for medium-load servers
- :name: large-x4
:cpu: 4
:vcpu: 4
:memory: 4096
:description: General purpose instance for servers
- :name: large-x8
:cpu: 8
:vcpu: 8
:memory: 8192
:description: General purpose instance for high-load servers
################################################################################
# Routes
################################################################################

View File

@ -75,7 +75,7 @@ tabs:
User.quotas_dialog: true
User.groups_dialog: true
User.chgrp: true
User.chauth: true
User.change_authentication: true
User.delete: true
groups-tab:
panel_tabs:
@ -96,6 +96,7 @@ tabs:
actions:
Group.refresh: true
Group.create_dialog: true
Group.update_dialog: true
Group.quotas_dialog: true
Group.delete: true
Group.edit_admins: true
@ -205,6 +206,7 @@ tabs:
VM.disk_snapshot_delete: true
VM.resched: true
VM.unresched: true
VM.saveas_template: true
templates-tab:
panel_tabs:
template_info_tab: true
@ -229,6 +231,9 @@ tabs:
Template.chmod: true
Template.clone_dialog: true
Template.delete: true
Template.delete_recursive: true
Template.share: true
Template.unshare: true
template_creation_tabs:
general: true
storage: true
@ -392,7 +397,9 @@ tabs:
panel_tabs:
actions:
NetworkTopology.refresh: true
NetworkTopology.toggleVMs: true
NetworkTopology.fit: true
NetworkTopology.collapseVMs: true
NetworkTopology.openVMs: true
vnets-tab:
panel_tabs:
vnet_info_tab: true
@ -417,6 +424,7 @@ tabs:
Network.create_dialog: true
Network.import_dialog: false
Network.update_dialog: true
Network.reserve_dialog: true
Network.addtocluster: true
Network.rename: true
Network.chown: true
@ -489,6 +497,8 @@ tabs:
Role.reboot_hard: true
Role.poweroff: true
Role.poweroff_hard: true
Role.undeploy: true
Role.undeploy_hard: true
Role.shutdown: true
Role.shutdown_hard: true
Role.delete: true
@ -540,12 +550,13 @@ tabs:
actions:
ServiceTemplate.refresh: true
ServiceTemplate.create_dialog: true
ServiceTemplate.update_dialog: true
ServiceTemplate.instantiate: true
ServiceTemplate.chown: true
ServiceTemplate.chgrp: true
ServiceTemplate.chmod: true
ServiceTemplate.rename: true
ServiceTemplate.clone: true
ServiceTemplate.clone_dialog: true
ServiceTemplate.delete: true
zones-tab:
panel_tabs:

View File

@ -16,6 +16,7 @@ enabled_tabs:
- clusters-tab
- hosts-tab
#- datastores-tab
- vnets-topology-tab
- vnets-tab
#- secgroups-tab
- vrouters-tab
@ -72,7 +73,7 @@ tabs:
User.quotas_dialog: true
User.groups_dialog: true
User.chgrp: true
User.chauth: true
User.change_authentication: true
User.delete: true
groups-tab:
panel_tabs:
@ -93,6 +94,7 @@ tabs:
actions:
Group.refresh: true
Group.create_dialog: true
Group.update_dialog: true
Group.quotas_dialog: true
Group.delete: true
Group.edit_admins: true
@ -202,6 +204,7 @@ tabs:
VM.disk_snapshot_delete: false
VM.resched: true
VM.unresched: true
VM.saveas_template: false
templates-tab:
panel_tabs:
template_info_tab: true
@ -226,6 +229,9 @@ tabs:
Template.chmod: true
Template.clone_dialog: true
Template.delete: true
Template.delete_recursive: false
Template.share: false
Template.unshare: false
template_creation_tabs:
general: true
storage: true
@ -384,12 +390,19 @@ tabs:
Datastore.delete: true
Datastore.enable: true
Datastore.disable: true
vnets-topology-tab:
panel_tabs:
actions:
NetworkTopology.refresh: true
NetworkTopology.fit: true
NetworkTopology.collapseVMs: true
NetworkTopology.openVMs: true
vnets-tab:
panel_tabs:
vnet_info_tab: true
vnet_ar_list_tab: true
vnet_leases_tab: true
vnet_sg_list_tab: true
vnet_sg_list_tab: false
vnet_vr_list_tab: true
table_columns:
- 0 # Checkbox
@ -408,6 +421,7 @@ tabs:
Network.create_dialog: true
Network.import_dialog: true
Network.update_dialog: true
Network.reserve_dialog: true
Network.addtocluster: true
Network.rename: true
Network.chown: true
@ -480,6 +494,8 @@ tabs:
Role.reboot_hard: true
Role.poweroff: true
Role.poweroff_hard: true
Role.undeploy: true
Role.undeploy_hard: true
Role.shutdown: true
Role.shutdown_hard: true
Role.delete: true
@ -531,12 +547,13 @@ tabs:
actions:
ServiceTemplate.refresh: true
ServiceTemplate.create_dialog: true
ServiceTemplate.update_dialog: true
ServiceTemplate.instantiate: true
ServiceTemplate.chown: true
ServiceTemplate.chgrp: true
ServiceTemplate.chmod: true
ServiceTemplate.rename: true
ServiceTemplate.clone: true
ServiceTemplate.clone_dialog: true
ServiceTemplate.delete: true
zones-tab:
panel_tabs:

View File

@ -1,39 +1,198 @@
small_logo: images/opennebula-sunstone-v4.14-small.png
provision_logo: images/one_small_logo.png
enabled_tabs:
- provision-tab
- dashboard-tab
- system-tab
- users-tab
- groups-tab
#- vdcs-tab
#- acls-tab
- vresources-tab
- vms-tab
- templates-tab
#- images-tab
#- files-tab
- infra-tab
#- clusters-tab
#- hosts-tab
#- datastores-tab
- vnets-topology-tab
- vnets-tab
- secgroups-tab
- vrouters-tab
#- zones-tab
- oneflow-dashboard-tab
- oneflow-services-tab
- oneflow-templates-tab
#- marketplaces-tab
#- marketplaceapps-tab
- settings-tab
#- support-tab
autorefresh: true
features:
showback: true
tabs:
provision-tab:
dashboard-tab:
panel_tabs:
vm_info_tab: false
vm_capacity_tab: false
vm_hotplugging_tab: false
vm_network_tab: false
actions:
Dashboard.refresh: false
Sunstone.toggle_top: false
widgets_three_per_row:
widgets_two_per_row:
- groupquotas
- quotas
widgets_one_per_row:
- vms
- users
widgets_one_footer:
system-tab:
panel_tabs:
actions:
users-tab:
panel_tabs:
user_info_tab: true
user_quotas_tab: true
user_groups_tab: true
user_accounting_tab: true
user_showback_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
#- 3 # Group
#- 4 # Auth driver
- 5 # VMs
- 6 # Memory
- 7 # CPU
#- 8 # Group ID
#- 9 # Hidden User Data
#- 10 # Labels
actions:
User.refresh: true
User.create_dialog: true
User.update_password: true
User.quotas_dialog: true
User.groups_dialog: false
User.chgrp: false
User.addgroup: false
User.delgroup: false
User.change_authentication: false
User.delete: true
groups-tab:
panel_tabs:
group_info_tab: true
group_users_tab: true
group_quotas_tab: true
group_accounting_tab: true
group_showback_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
- 3 # Users
- 4 # VMs
- 5 # Memory
- 6 # CPU
#- 7 # Labels
actions:
Group.refresh: true
Group.create_dialog: false
Group.update_dialog: false
Group.quotas_dialog: false
Group.delete: false
Group.edit_admins: false
vdcs-tab:
panel_tabs:
vdc_info_tab: true
vdc_groups_tab: true
vdc_resources_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
- 3 # Groups
- 4 # Clusters
- 5 # Hosts
- 6 # VNets
- 7 # Datastores
#- 8 # Labels
actions:
Vdc.refresh: true
Vdc.create_dialog: true
Vdc.update_dialog: true
Vdc.rename: true
Vdc.delete: true
acls-tab:
panel_tabs:
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Applies to
- 3 # Affected resources
- 4 # Resource ID / Owned by
- 5 # Allowed operations
- 6 # Zone
#- 7 # ACL String
actions:
Acl.refresh: true
Acl.create_dialog: true
Acl.delete: true
vresources-tab:
panel_tabs:
actions:
vms-tab:
panel_tabs:
vm_info_tab: true
vm_capacity_tab: true
vm_hotplugging_tab: true
vm_network_tab: true
vm_snapshot_tab: false
vm_placement_tab: false
vm_actions_tab: false
vm_template_tab: false
vm_log_tab: false
provision_tabs:
users: true
flows: true
templates: true
actions: &provisionactions
Template.chmod: true
Template.delete: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
#- 3 # Group
- 4 # Name
- 5 # Status
#- 6 # Used CPU
#- 7 # Used Memory
#- 8 # Host
- 9 # IPs
#- 10 # Start Time
- 11 # VNC
#- 12 # Hidden Template
#- 13 # Labels
actions:
VM.refresh: true
VM.create_dialog: true
VM.rename: true
VM.chown: true
VM.chgrp: false
VM.chmod: false
VM.deploy: false
VM.migrate: false
VM.migrate_live: false
VM.hold: true
VM.release: true
VM.suspend: false
VM.resume: true
VM.stop: false
VM.recover: false
VM.reboot: true
VM.reboot_hard: true
VM.poweroff: true
VM.poweroff_hard: true
VM.undeploy: false
VM.undeploy_hard: false
VM.undeploy: true
VM.undeploy_hard: true
VM.shutdown: true
VM.shutdown_hard: true
VM.delete: true
VM.delete_recreate: false
VM.resize: false
VM.attachdisk: false
VM.detachdisk: false
@ -46,28 +205,52 @@ tabs:
VM.disk_snapshot_create: false
VM.disk_snapshot_revert: false
VM.disk_snapshot_delete: false
dashboard:
quotas: false
vms: false
vdcquotas: true
vdcvms: true
users: true
create_vm:
capacity_select: true
network_select: true
disk_resize: true
settings-tab:
VM.resched: false
VM.unresched: false
VM.saveas_template: true
templates-tab:
panel_tabs:
user_info_tab: false
user_config_tab: true
user_quotas_tab: true
user_accounting_tab: true
user_showback_tab: true
template_info_tab: true
template_template_tab: false
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Registration time
#- 6 # Labels
actions:
User.quotas_dialog: false
vms-tab:
actions: *provisionactions
Template.refresh: true
Template.create_dialog: false
Template.import_dialog: false
Template.update_dialog: false
Template.instantiate_vms: true
Template.rename: true
Template.chown: true
Template.chgrp: false
Template.chmod: false
Template.clone_dialog: false
Template.delete: false
Template.delete_recursive: true
Template.share: true
Template.unshare: true
template_creation_tabs:
general: true
storage: true
network: true
os_booting: true
features: true
input_output: true
context: true
scheduling: true
hybrid: true
other: true
images-tab:
panel_tabs:
image_info_tab: true
image_vms_tab: true
image_snapshots_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
@ -82,16 +265,383 @@ tabs:
- 10 # Status
- 11 # #VMs
#- 12 # Target
vnets-tab:
#- 13 # Labels
actions:
Image.refresh: true
Image.create_dialog: true
Image.export_dialog: true
Image.rename: true
Image.chown: true
Image.chgrp: true
Image.chmod: true
Image.enable: true
Image.disable: true
Image.persistent: true
Image.nonpersistent: true
Image.clone_dialog: true
Image.delete: true
Image.snapshot_flatten: true
Image.snapshot_revert: true
Image.snapshot_delete: true
files-tab:
panel_tabs:
file_info_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Reservation
- 5 # Datastore
#- 6 # Size
- 7 # Type
#- 8 # Registration time
#- 9 # Persistent
- 10 # Status
#- 11 # #VMs
#- 12 # Target
#- 13 # Labels
actions:
File.refresh: true
File.create_dialog: true
File.rename: true
File.chown: true
File.chgrp: true
File.chmod: true
File.enable: true
File.disable: true
File.delete: true
infra-tab:
panel_tabs:
actions:
clusters-tab:
panel_tabs:
cluster_info_tab: true
cluster_host_tab: true
cluster_vnet_tab: true
cluster_datastore_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
- 3 # Hosts
- 4 # VNets
- 5 # Datastores
#- 6 # Labels
actions:
Cluster.refresh: true
Cluster.create_dialog: true
Cluster.update_dialog: true
Cluster.delete: true
Cluster.rename: true
hosts-tab:
panel_tabs:
host_info_tab: true
host_monitoring_tab: true
host_vms_tab: true
host_wilds_tab: true
host_esx_tab: true
host_pci_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
- 3 # Cluster
- 4 # RVMs
#- 5 # Real CPU
- 6 # Allocated CPU
#- 7 # Real MEM
- 8 # Allocated MEM
- 9 # Status
#- 10 # IM MAD
#- 11 # VM MAD
#- 12 # Last monitored on
#- 13 # Labels
actions:
Host.refresh: true
Host.create_dialog: true
Host.addtocluster: true
Host.rename: true
Host.enable: true
Host.disable: true
Host.delete: true
datastores-tab:
panel_tabs:
datastore_info_tab: true
datastore_image_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Capacity
- 6 # Cluster
#- 7 # Basepath
#- 8 # TM
#- 9 # DS
- 10 # Type
- 11 # Status
#- 12 # Labels
actions:
Datastore.refresh: true
Datastore.create_dialog: true
Datastore.addtocluster: true
Datastore.rename: true
Datastore.chown: true
Datastore.chgrp: true
Datastore.chmod: true
Datastore.delete: true
Datastore.enable: true
Datastore.disable: true
vnets-topology-tab:
panel_tabs:
actions:
NetworkTopology.refresh: true
NetworkTopology.fit: true
NetworkTopology.collapseVMs: true
NetworkTopology.openVMs: true
vnets-tab:
panel_tabs:
vnet_info_tab: false
vnet_ar_list_tab: false
vnet_leases_tab: true
vnet_sg_list_tab: true
vnet_vr_list_tab: false
table_columns:
- 0 # Checkbox
- 1 # ID
#- 2 # Owner
#- 3 # Group
- 4 # Name
#- 5 # Reservation
#- 6 # Cluster
#- 7 # Bridge
- 8 # Leases
#- 8 # Leases
#- 9 # VLAN ID
#- 10 # Labels
actions:
Network.refresh: true
Network.create_dialog: false
Network.import_dialog: false
Network.update_dialog: false
Network.reserve_dialog: false
Network.addtocluster: false
Network.rename: false
Network.chown: false
Network.chgrp: false
Network.chmod: false
Network.delete: false
Network.hold_lease: false
Network.release_lease: false
Network.add_ar: false
Network.remove_ar: false
Network.update_ar: false
secgroups-tab:
panel_tabs:
security_group_info_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
#- 2 # Owner
#- 3 # Group
- 4 # Name
#- 5 # Labels
actions:
SecurityGroup.refresh: true
SecurityGroup.create_dialog: false
SecurityGroup.update_dialog: false
SecurityGroup.rename: false
SecurityGroup.chown: false
SecurityGroup.chgrp: false
SecurityGroup.chmod: false
SecurityGroup.clone_dialog: false
SecurityGroup.delete: false
vrouters-tab:
panel_tabs:
virtual_router_info_tab: true
virtual_router_vms_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
#- 3 # Group
- 4 # Name
actions:
VirtualRouter.refresh: true
VirtualRouter.create_dialog: true
VirtualRouter.rename: true
VirtualRouter.chown: true
VirtualRouter.chgrp: false
VirtualRouter.chmod: false
VirtualRouter.delete: true
VirtualRouter.attachnic: false
VirtualRouter.detachnic: false
oneflow-dashboard-tab:
panel_tabs:
table_columns:
actions:
oneflow-services-tab:
panel_tabs:
service_info_tab: true
service_roles_tab: true
service_log_tab: true
panel_tabs_actions:
service_roles_tab:
Role.scale: true
Role.hold: true
Role.release: true
Role.suspend: false
Role.resume: true
Role.stop: false
Role.reboot: true
Role.reboot_hard: true
Role.poweroff: true
Role.poweroff_hard: true
Role.undeploy: true
Role.undeploy_hard: true
Role.shutdown: true
Role.shutdown_hard: true
Role.delete: true
Role.delete_recreate: false
RoleVM.hold: true
RoleVM.release: true
RoleVM.suspend: false
RoleVM.resume: true
RoleVM.stop: false
RoleVM.reboot: true
RoleVM.reboot_hard: true
RoleVM.poweroff: true
RoleVM.poweroff_hard: true
RoleVM.undeploy: true
RoleVM.undeploy_hard: true
RoleVM.shutdown: true
RoleVM.shutdown_hard: true
RoleVM.delete: true
RoleVM.delete_recreate: false
RoleVM.resched: false
RoleVM.unresched: false
RoleVM.recover: false
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
#- 3 # Group
- 4 # Name
- 5 # State
actions:
Service.refresh: true
Service.chown: true
Service.chgrp: false
Service.chmod: false
Service.rename: true
Service.shutdown: true
Service.recover: true
Service.delete: true
oneflow-templates-tab:
panel_tabs:
service_template_info_tab: true
service_template_roles_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
actions:
ServiceTemplate.refresh: true
ServiceTemplate.create_dialog: false
ServiceTemplate.update_dialog: false
ServiceTemplate.instantiate: true
ServiceTemplate.chown: false
ServiceTemplate.chgrp: false
ServiceTemplate.chmod: false
ServiceTemplate.rename: false
ServiceTemplate.clone_dialog: false
ServiceTemplate.delete: false
zones-tab:
panel_tabs:
zone_info_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
- 3 # Endpoint
#- 4 # Labels
actions:
Zone.refresh: true
Zone.create_dialog: true
Zone.rename: true
Zone.delete: true
support-tab:
panel_tabs:
support_info_tab: true
table_columns:
#- 0 # Checkbox
- 1 # ID
- 2 # Subject
- 3 # Created at
- 4 # Status
actions:
Support.refresh: true
Support.create_dialog: true
settings-tab:
panel_tabs:
user_info_tab: true
user_quotas_tab: true
group_quotas_tab: true
user_accounting_tab: true
user_showback_tab: true
actions:
User.quotas_dialog: false
marketplaces-tab:
panel_tabs:
marketplace_info_tab: true
marketplace_apps_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Capacity
- 6 # Apps
- 7 # Driver
#- 8 # Labels
actions:
MarketPlace.refresh: true
MarketPlace.create_dialog: true
MarketPlace.update_dialog: true
MarketPlace.rename: true
MarketPlace.chown: true
MarketPlace.chgrp: true
MarketPlace.chmod: true
MarketPlace.delete: true
marketplaceapps-tab:
panel_tabs:
marketplaceapp_info_tab: true
marketplaceapp_templates_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
#- 5 # Version
- 6 # Size
- 7 # State
#- 8 # Type
- 9 # Registration
- 10 # Marketplace
#- 11 # Labels
actions:
MarketPlaceApp.refresh: true
MarketPlaceApp.create_dialog: true
MarketPlaceApp.export_dialog: true
MarketPlaceApp.rename: true
MarketPlaceApp.chown: true
MarketPlaceApp.chgrp: true
MarketPlaceApp.chmod: true
MarketPlaceApp.enable: true
MarketPlaceApp.disable: true
MarketPlaceApp.delete: true

View File

@ -0,0 +1,97 @@
provision_logo: images/one_small_logo.png
enabled_tabs:
- provision-tab
- users-tab
- settings-tab
features:
showback: true
tabs:
provision-tab:
panel_tabs:
vm_info_tab: false
vm_capacity_tab: false
vm_hotplugging_tab: false
vm_network_tab: false
vm_snapshot_tab: false
vm_placement_tab: false
vm_actions_tab: false
vm_template_tab: false
vm_log_tab: false
provision_tabs:
users: true
flows: true
templates: true
actions: &provisionactions
Template.chmod: true
Template.delete: true
VM.rename: true
VM.resume: true
VM.reboot: true
VM.reboot_hard: true
VM.poweroff: true
VM.poweroff_hard: true
VM.undeploy: false
VM.undeploy_hard: false
VM.shutdown_hard: true
VM.delete: true
VM.resize: false
VM.attachdisk: false
VM.detachdisk: false
VM.disk_saveas: false
VM.attachnic: false
VM.detachnic: false
VM.snapshot_create: false
VM.snapshot_revert: false
VM.snapshot_delete: false
VM.disk_snapshot_create: false
VM.disk_snapshot_revert: false
VM.disk_snapshot_delete: false
dashboard:
quotas: false
vms: false
vdcquotas: true
vdcvms: true
users: true
create_vm:
capacity_select: true
network_select: true
disk_resize: true
settings-tab:
panel_tabs:
user_info_tab: false
user_config_tab: true
user_quotas_tab: true
user_accounting_tab: true
user_showback_tab: true
actions:
User.quotas_dialog: false
vms-tab:
actions: *provisionactions
images-tab:
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Datastore
#- 6 # Size
- 7 # Type
#- 8 # Registration time
#- 9 # Persistent
- 10 # Status
- 11 # #VMs
#- 12 # Target
vnets-tab:
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Reservation
- 6 # Cluster
#- 7 # Bridge
- 8 # Leases
#- 9 # VLAN ID

View File

@ -1,39 +1,198 @@
small_logo: images/opennebula-sunstone-v4.14-small.png
provision_logo: images/one_small_logo.png
enabled_tabs:
- provision-tab
- dashboard-tab
- system-tab
- users-tab
- groups-tab
#- vdcs-tab
#- acls-tab
- vresources-tab
- vms-tab
#- templates-tab
#- images-tab
#- files-tab
- infra-tab
#- clusters-tab
#- hosts-tab
#- datastores-tab
- vnets-topology-tab
- vnets-tab
#- secgroups-tab
- vrouters-tab
#- zones-tab
- oneflow-dashboard-tab
- oneflow-services-tab
- oneflow-templates-tab
#- marketplaces-tab
#- marketplaceapps-tab
- settings-tab
#- support-tab
autorefresh: true
features:
showback: true
tabs:
provision-tab:
dashboard-tab:
panel_tabs:
vm_info_tab: false
vm_capacity_tab: false
vm_hotplugging_tab: false
vm_network_tab: false
actions:
Dashboard.refresh: false
Sunstone.toggle_top: false
widgets_three_per_row:
widgets_two_per_row:
- groupquotas
- quotas
widgets_one_per_row:
- vms
- users
widgets_one_footer:
system-tab:
panel_tabs:
actions:
users-tab:
panel_tabs:
user_info_tab: true
user_quotas_tab: true
user_groups_tab: true
user_accounting_tab: true
user_showback_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
#- 3 # Group
#- 4 # Auth driver
- 5 # VMs
- 6 # Memory
- 7 # CPU
#- 8 # Group ID
#- 9 # Hidden User Data
#- 10 # Labels
actions:
User.refresh: true
User.create_dialog: true
User.update_password: true
User.quotas_dialog: true
User.groups_dialog: false
User.chgrp: false
User.addgroup: false
User.delgroup: false
User.change_authentication: false
User.delete: true
groups-tab:
panel_tabs:
group_info_tab: true
group_users_tab: true
group_quotas_tab: true
group_accounting_tab: true
group_showback_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
- 3 # Users
- 4 # VMs
- 5 # Memory
- 6 # CPU
#- 7 # Labels
actions:
Group.refresh: true
Group.create_dialog: false
Group.update_dialog: false
Group.quotas_dialog: false
Group.delete: false
Group.edit_admins: false
vdcs-tab:
panel_tabs:
vdc_info_tab: true
vdc_groups_tab: true
vdc_resources_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
- 3 # Groups
- 4 # Clusters
- 5 # Hosts
- 6 # VNets
- 7 # Datastores
#- 8 # Labels
actions:
Vdc.refresh: true
Vdc.create_dialog: true
Vdc.update_dialog: true
Vdc.rename: true
Vdc.delete: true
acls-tab:
panel_tabs:
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Applies to
- 3 # Affected resources
- 4 # Resource ID / Owned by
- 5 # Allowed operations
- 6 # Zone
#- 7 # ACL String
actions:
Acl.refresh: true
Acl.create_dialog: true
Acl.delete: true
vresources-tab:
panel_tabs:
actions:
vms-tab:
panel_tabs:
vm_info_tab: true
vm_capacity_tab: true
vm_hotplugging_tab: true
vm_network_tab: true
vm_snapshot_tab: false
vm_placement_tab: false
vm_actions_tab: false
vm_template_tab: false
vm_log_tab: false
provision_tabs:
users: true
flows: true
templates: false
actions: &provisionactions
Template.chmod: false
Template.delete: true
VM.rename: false
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
#- 3 # Group
- 4 # Name
- 5 # Status
#- 6 # Used CPU
#- 7 # Used Memory
#- 8 # Host
- 9 # IPs
#- 10 # Start Time
- 11 # VNC
#- 12 # Hidden Template
#- 13 # Labels
actions:
VM.refresh: true
VM.create_dialog: true
VM.rename: true
VM.chown: true
VM.chgrp: false
VM.chmod: false
VM.deploy: false
VM.migrate: false
VM.migrate_live: false
VM.hold: true
VM.release: true
VM.suspend: false
VM.resume: true
VM.stop: false
VM.recover: false
VM.reboot: true
VM.reboot_hard: true
VM.poweroff: true
VM.poweroff_hard: true
VM.undeploy: false
VM.undeploy_hard: false
VM.undeploy: true
VM.undeploy_hard: true
VM.shutdown: true
VM.shutdown_hard: true
VM.delete: true
VM.delete_recreate: false
VM.resize: false
VM.attachdisk: false
VM.detachdisk: false
@ -46,27 +205,52 @@ tabs:
VM.disk_snapshot_create: false
VM.disk_snapshot_revert: false
VM.disk_snapshot_delete: false
dashboard:
quotas: false
vms: false
vdcquotas: true
vdcvms: true
users: true
create_vm:
capacity_select: false
network_select: true
settings-tab:
VM.resched: false
VM.unresched: false
VM.saveas_template: false
templates-tab:
panel_tabs:
user_info_tab: false
user_config_tab: true
user_quotas_tab: true
user_accounting_tab: true
user_showback_tab: true
template_info_tab: true
template_template_tab: false
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Registration time
#- 6 # Labels
actions:
User.quotas_dialog: false
vms-tab:
actions: *provisionactions
Template.refresh: true
Template.create_dialog: false
Template.import_dialog: false
Template.update_dialog: false
Template.instantiate_vms: true
Template.rename: true
Template.chown: true
Template.chgrp: false
Template.chmod: false
Template.clone_dialog: false
Template.delete: false
Template.delete_recursive: true
Template.share: true
Template.unshare: true
template_creation_tabs:
general: true
storage: true
network: true
os_booting: true
features: true
input_output: true
context: true
scheduling: true
hybrid: true
other: true
images-tab:
panel_tabs:
image_info_tab: true
image_vms_tab: true
image_snapshots_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
@ -81,16 +265,383 @@ tabs:
- 10 # Status
- 11 # #VMs
#- 12 # Target
vnets-tab:
#- 13 # Labels
actions:
Image.refresh: true
Image.create_dialog: true
Image.export_dialog: true
Image.rename: true
Image.chown: true
Image.chgrp: true
Image.chmod: true
Image.enable: true
Image.disable: true
Image.persistent: true
Image.nonpersistent: true
Image.clone_dialog: true
Image.delete: true
Image.snapshot_flatten: true
Image.snapshot_revert: true
Image.snapshot_delete: true
files-tab:
panel_tabs:
file_info_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Reservation
- 5 # Datastore
#- 6 # Size
- 7 # Type
#- 8 # Registration time
#- 9 # Persistent
- 10 # Status
#- 11 # #VMs
#- 12 # Target
#- 13 # Labels
actions:
File.refresh: true
File.create_dialog: true
File.rename: true
File.chown: true
File.chgrp: true
File.chmod: true
File.enable: true
File.disable: true
File.delete: true
infra-tab:
panel_tabs:
actions:
clusters-tab:
panel_tabs:
cluster_info_tab: true
cluster_host_tab: true
cluster_vnet_tab: true
cluster_datastore_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
- 3 # Hosts
- 4 # VNets
- 5 # Datastores
#- 6 # Labels
actions:
Cluster.refresh: true
Cluster.create_dialog: true
Cluster.update_dialog: true
Cluster.delete: true
Cluster.rename: true
hosts-tab:
panel_tabs:
host_info_tab: true
host_monitoring_tab: true
host_vms_tab: true
host_wilds_tab: true
host_esx_tab: true
host_pci_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
- 3 # Cluster
- 4 # RVMs
#- 5 # Real CPU
- 6 # Allocated CPU
#- 7 # Real MEM
- 8 # Allocated MEM
- 9 # Status
#- 10 # IM MAD
#- 11 # VM MAD
#- 12 # Last monitored on
#- 13 # Labels
actions:
Host.refresh: true
Host.create_dialog: true
Host.addtocluster: true
Host.rename: true
Host.enable: true
Host.disable: true
Host.delete: true
datastores-tab:
panel_tabs:
datastore_info_tab: true
datastore_image_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Capacity
- 6 # Cluster
#- 7 # Basepath
#- 8 # TM
#- 9 # DS
- 10 # Type
- 11 # Status
#- 12 # Labels
actions:
Datastore.refresh: true
Datastore.create_dialog: true
Datastore.addtocluster: true
Datastore.rename: true
Datastore.chown: true
Datastore.chgrp: true
Datastore.chmod: true
Datastore.delete: true
Datastore.enable: true
Datastore.disable: true
vnets-topology-tab:
panel_tabs:
actions:
NetworkTopology.refresh: true
NetworkTopology.fit: true
NetworkTopology.collapseVMs: true
NetworkTopology.openVMs: true
vnets-tab:
panel_tabs:
vnet_info_tab: false
vnet_ar_list_tab: false
vnet_leases_tab: true
vnet_sg_list_tab: false
vnet_vr_list_tab: false
table_columns:
- 0 # Checkbox
- 1 # ID
#- 2 # Owner
#- 3 # Group
- 4 # Name
#- 5 # Reservation
#- 6 # Cluster
#- 7 # Bridge
- 8 # Leases
#- 8 # Leases
#- 9 # VLAN ID
#- 10 # Labels
actions:
Network.refresh: true
Network.create_dialog: false
Network.import_dialog: false
Network.update_dialog: false
Network.reserve_dialog: false
Network.addtocluster: false
Network.rename: false
Network.chown: false
Network.chgrp: false
Network.chmod: false
Network.delete: false
Network.hold_lease: false
Network.release_lease: false
Network.add_ar: false
Network.remove_ar: false
Network.update_ar: false
secgroups-tab:
panel_tabs:
security_group_info_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
#- 2 # Owner
#- 3 # Group
- 4 # Name
#- 5 # Labels
actions:
SecurityGroup.refresh: true
SecurityGroup.create_dialog: false
SecurityGroup.update_dialog: false
SecurityGroup.rename: false
SecurityGroup.chown: false
SecurityGroup.chgrp: false
SecurityGroup.chmod: false
SecurityGroup.clone_dialog: false
SecurityGroup.delete: false
vrouters-tab:
panel_tabs:
virtual_router_info_tab: true
virtual_router_vms_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
#- 3 # Group
- 4 # Name
actions:
VirtualRouter.refresh: true
VirtualRouter.create_dialog: true
VirtualRouter.rename: true
VirtualRouter.chown: true
VirtualRouter.chgrp: false
VirtualRouter.chmod: false
VirtualRouter.delete: true
VirtualRouter.attachnic: false
VirtualRouter.detachnic: false
oneflow-dashboard-tab:
panel_tabs:
table_columns:
actions:
oneflow-services-tab:
panel_tabs:
service_info_tab: true
service_roles_tab: true
service_log_tab: true
panel_tabs_actions:
service_roles_tab:
Role.scale: true
Role.hold: true
Role.release: true
Role.suspend: false
Role.resume: true
Role.stop: false
Role.reboot: true
Role.reboot_hard: true
Role.poweroff: true
Role.poweroff_hard: true
Role.undeploy: true
Role.undeploy_hard: true
Role.shutdown: true
Role.shutdown_hard: true
Role.delete: true
Role.delete_recreate: false
RoleVM.hold: true
RoleVM.release: true
RoleVM.suspend: false
RoleVM.resume: true
RoleVM.stop: false
RoleVM.reboot: true
RoleVM.reboot_hard: true
RoleVM.poweroff: true
RoleVM.poweroff_hard: true
RoleVM.undeploy: true
RoleVM.undeploy_hard: true
RoleVM.shutdown: true
RoleVM.shutdown_hard: true
RoleVM.delete: true
RoleVM.delete_recreate: false
RoleVM.resched: false
RoleVM.unresched: false
RoleVM.recover: false
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
#- 3 # Group
- 4 # Name
- 5 # State
actions:
Service.refresh: true
Service.chown: true
Service.chgrp: false
Service.chmod: false
Service.rename: true
Service.shutdown: true
Service.recover: true
Service.delete: true
oneflow-templates-tab:
panel_tabs:
service_template_info_tab: true
service_template_roles_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
actions:
ServiceTemplate.refresh: true
ServiceTemplate.create_dialog: false
ServiceTemplate.update_dialog: false
ServiceTemplate.instantiate: true
ServiceTemplate.chown: false
ServiceTemplate.chgrp: false
ServiceTemplate.chmod: false
ServiceTemplate.rename: false
ServiceTemplate.clone_dialog: false
ServiceTemplate.delete: false
zones-tab:
panel_tabs:
zone_info_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Name
- 3 # Endpoint
#- 4 # Labels
actions:
Zone.refresh: true
Zone.create_dialog: true
Zone.rename: true
Zone.delete: true
support-tab:
panel_tabs:
support_info_tab: true
table_columns:
#- 0 # Checkbox
- 1 # ID
- 2 # Subject
- 3 # Created at
- 4 # Status
actions:
Support.refresh: true
Support.create_dialog: true
settings-tab:
panel_tabs:
user_info_tab: true
user_quotas_tab: true
group_quotas_tab: true
user_accounting_tab: true
user_showback_tab: true
actions:
User.quotas_dialog: false
marketplaces-tab:
panel_tabs:
marketplace_info_tab: true
marketplace_apps_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Capacity
- 6 # Apps
- 7 # Driver
#- 8 # Labels
actions:
MarketPlace.refresh: true
MarketPlace.create_dialog: true
MarketPlace.update_dialog: true
MarketPlace.rename: true
MarketPlace.chown: true
MarketPlace.chgrp: true
MarketPlace.chmod: true
MarketPlace.delete: true
marketplaceapps-tab:
panel_tabs:
marketplaceapp_info_tab: true
marketplaceapp_templates_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
#- 5 # Version
- 6 # Size
- 7 # State
#- 8 # Type
- 9 # Registration
- 10 # Marketplace
#- 11 # Labels
actions:
MarketPlaceApp.refresh: true
MarketPlaceApp.create_dialog: true
MarketPlaceApp.export_dialog: true
MarketPlaceApp.rename: true
MarketPlaceApp.chown: true
MarketPlaceApp.chgrp: true
MarketPlaceApp.chmod: true
MarketPlaceApp.enable: true
MarketPlaceApp.disable: true
MarketPlaceApp.delete: true

View File

@ -0,0 +1,96 @@
provision_logo: images/one_small_logo.png
enabled_tabs:
- provision-tab
- users-tab
- settings-tab
features:
showback: true
tabs:
provision-tab:
panel_tabs:
vm_info_tab: false
vm_capacity_tab: false
vm_hotplugging_tab: false
vm_network_tab: false
vm_snapshot_tab: false
vm_placement_tab: false
vm_actions_tab: false
vm_template_tab: false
vm_log_tab: false
provision_tabs:
users: true
flows: true
templates: false
actions: &provisionactions
Template.chmod: false
Template.delete: true
VM.rename: false
VM.resume: true
VM.reboot: true
VM.reboot_hard: true
VM.poweroff: true
VM.poweroff_hard: true
VM.undeploy: false
VM.undeploy_hard: false
VM.shutdown_hard: true
VM.delete: true
VM.resize: false
VM.attachdisk: false
VM.detachdisk: false
VM.disk_saveas: false
VM.attachnic: false
VM.detachnic: false
VM.snapshot_create: false
VM.snapshot_revert: false
VM.snapshot_delete: false
VM.disk_snapshot_create: false
VM.disk_snapshot_revert: false
VM.disk_snapshot_delete: false
dashboard:
quotas: false
vms: false
vdcquotas: true
vdcvms: true
users: true
create_vm:
capacity_select: false
network_select: true
settings-tab:
panel_tabs:
user_info_tab: false
user_config_tab: true
user_quotas_tab: true
user_accounting_tab: true
user_showback_tab: true
actions:
User.quotas_dialog: false
vms-tab:
actions: *provisionactions
images-tab:
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Datastore
#- 6 # Size
- 7 # Type
#- 8 # Registration time
#- 9 # Persistent
- 10 # Status
- 11 # #VMs
#- 12 # Target
vnets-tab:
table_columns:
- 0 # Checkbox
- 1 # ID
- 2 # Owner
- 3 # Group
- 4 # Name
- 5 # Reservation
- 6 # Cluster
#- 7 # Bridge
- 8 # Leases
#- 9 # VLAN ID

View File

@ -16,6 +16,7 @@ enabled_tabs:
#- clusters-tab
#- hosts-tab
- datastores-tab
- vnets-topology-tab
- vnets-tab
- secgroups-tab
- vrouters-tab
@ -77,7 +78,7 @@ tabs:
User.chgrp: true
User.addgroup: true
User.delgroup: true
User.chauth: true
User.change_authentication: true
User.delete: true
groups-tab:
panel_tabs:
@ -98,6 +99,7 @@ tabs:
actions:
Group.refresh: true
Group.create_dialog: true
Group.update_dialog: true
Group.quotas_dialog: true
Group.delete: true
Group.edit_admins: true
@ -207,6 +209,7 @@ tabs:
VM.disk_snapshot_delete: true
VM.resched: false
VM.unresched: false
VM.saveas_template: true
templates-tab:
panel_tabs:
template_info_tab: true
@ -231,6 +234,9 @@ tabs:
Template.chmod: true
Template.clone_dialog: true
Template.delete: true
Template.delete_recursive: true
Template.share: true
Template.unshare: true
template_creation_tabs:
general: true
storage: true
@ -390,6 +396,13 @@ tabs:
Datastore.delete: false
Datastore.enable: false
Datastore.disable: false
vnets-topology-tab:
panel_tabs:
actions:
NetworkTopology.refresh: true
NetworkTopology.fit: true
NetworkTopology.collapseVMs: true
NetworkTopology.openVMs: true
vnets-tab:
panel_tabs:
vnet_info_tab: true
@ -414,6 +427,7 @@ tabs:
Network.create_dialog: false
Network.import_dialog: false
Network.update_dialog: true
Network.reserve_dialog: true
Network.addtocluster: false
Network.rename: true
Network.chown: false
@ -486,6 +500,8 @@ tabs:
Role.reboot_hard: true
Role.poweroff: true
Role.poweroff_hard: true
Role.undeploy: true
Role.undeploy_hard: true
Role.shutdown: true
Role.shutdown_hard: true
Role.delete: true
@ -537,12 +553,13 @@ tabs:
actions:
ServiceTemplate.refresh: true
ServiceTemplate.create_dialog: true
ServiceTemplate.update_dialog: true
ServiceTemplate.instantiate: true
ServiceTemplate.chown: false
ServiceTemplate.chgrp: false
ServiceTemplate.chmod: true
ServiceTemplate.rename: true
ServiceTemplate.clone: true
ServiceTemplate.clone_dialog: true
ServiceTemplate.delete: true
zones-tab:
panel_tabs:

View File

@ -50,10 +50,7 @@ module OpenNebulaJSON
when "instantiate" then self.instantiate(action_hash['params'])
when "clone" then self.clone(action_hash['params'])
when "rename" then self.rename(action_hash['params'])
when "delete_from_provision"
then self.delete_from_provision(action_hash['params'])
when "chmod_from_provision"
then self.chmod_from_provision(action_hash['params'])
when "delete_recursive" then self.delete_recursive(action_hash['params'])
else
error_msg = "#{action_hash['perform']} action not " <<
" available for this resource"
@ -82,8 +79,10 @@ module OpenNebulaJSON
end
def chmod_json(params=Hash.new)
recursive = (params['recursive'] == true)
if params['octet']
self.chmod_octet(params['octet'])
self.chmod_octet(params['octet'], recursive)
else
self.chmod((params['owner_u']||-1),
(params['owner_m']||-1),
@ -93,18 +92,13 @@ module OpenNebulaJSON
(params['group_a']||-1),
(params['other_u']||-1),
(params['other_m']||-1),
(params['other_a']||-1))
(params['other_a']||-1),
recursive)
end
end
def instantiate(params=Hash.new)
if params['template']
select_capacity = self['TEMPLATE/SUNSTONE/CAPACITY_SELECT']
if (select_capacity && select_capacity.upcase == "NO")
params['template'].delete("CPU")
params['template'].delete("MEMORY")
end
select_network = self['TEMPLATE/SUNSTONE/NETWORK_SELECT']
if (select_network && select_network.upcase == "NO")
params['template'].delete("NIC")
@ -131,36 +125,9 @@ module OpenNebulaJSON
super(params['name'])
end
def delete_from_provision(params=Hash.new)
# Delete associated images
self.each("TEMPLATE/DISK/IMAGE_ID"){|image_id|
img = OpenNebula::Image.new_with_id(image_id.text, @client)
rc = img.delete
if OpenNebula::is_error?(rc)
error_msg = "Some of the resources associated with " <<
"this template couldn't be deleted. Error: " << rc.message
return OpenNebula::Error.new(error_msg)
end
}
# Delete template
self.delete
end
def chmod_from_provision(params=Hash.new)
# Chmod associated images
self.each("TEMPLATE/DISK/IMAGE_ID"){|image_id|
img = OpenNebulaJSON::ImageJSON.new_with_id(image_id.text, @client)
rc = img.chmod_json(params)
if OpenNebula::is_error?(rc)
error_msg = "Some of the resources associated with " <<
"this template couldn't be published. Error: " << rc.message
return OpenNebula::Error.new(error_msg)
end
}
# Chmod template
self.chmod_json(params)
def delete_recursive(params=Hash.new)
recursive = (params['recursive'] == true)
self.delete(recursive)
end
end
end

View File

@ -60,12 +60,6 @@ module OpenNebulaJSON
def instantiate(params=Hash.new)
if params['template']
select_capacity = self['TEMPLATE/SUNSTONE_CAPACITY_SELECT']
if (select_capacity && select_capacity.upcase == "NO")
params['template'].delete("CPU")
params['template'].delete("MEMORY")
end
select_network = self['TEMPLATE/SUNSTONE_NETWORK_SELECT']
if (select_network && select_network.upcase == "NO")
params['template'].delete("NIC")

View File

@ -26,6 +26,7 @@ define(function(require) {
var OpenNebula = require('opennebula');
var Notifier = require('utils/notifier');
var Menu = require('utils/menu');
var Locale = require('utils/locale');
var _commonDialogs = [
require('utils/dialogs/confirm'),
@ -84,11 +85,39 @@ define(function(require) {
}
function _insertUserAndZoneSelector() {
var user_login_content = '<button href="#" data-dropdown="userSelectDropdown" class="button small radius secondary dropdown" id="logout">\
var user_login_content =
'<button href="#" data-dropdown="userSelectDropdown" class="button small radius secondary dropdown" id="logout">\
<i class="fa fa-user fa-lg fa-fw header-icon"></i> ' + config['display_name'] + '</button>\
<ul id="userSelectDropdown" data-dropdown-content class="f-dropdown">\
<li><a href="#" class="configuration"><i class="fa fa-cog"></i> Settings</a></li>\
<li><a href="#" class="logout"><i class="fa fa-power-off"></i> Sign Out</a></li>\
<ul id="userSelectDropdown" data-dropdown-content class="f-dropdown">';
if (config['available_views'].length > 1){
user_login_content +=
'<li><a href="#" class="quickconf_view_header"><i class="fa fa-fw fa-eye"></i> '+Locale.tr("Views")+'</a></li>';
$.each(config['available_views'], function(i, view) {
var faclass = "";
if (view == config['user_config']["default_view"]){
faclass = "fa fa-fw fa-check";
} else {
faclass = "fa fa-fw";
}
user_login_content +=
'<li><a href="#" class="quickconf_view" view="'+view+'"><i class="'+faclass+'"></i> '+view+'</a></li>';
});
user_login_content +=
'<li><hr/></li>';
}
if (Config.isTabEnabled(SETTINGS_TAB_ID)){
user_login_content +=
'<li><a href="#" class="configuration"><i class="fa fa-fw fa-cog"></i> '+Locale.tr("Settings")+'</a></li>';
}
user_login_content +=
'<li><a href="#" class="logout"><i class="fa fa-fw fa-power-off"></i> '+Locale.tr("Sign Out")+'</a></li>\
</ul>\
<button href="#" data-dropdown="drop2" class="button small radius secondary dropdown" id="zonelector">\
<i class="fa fa-home fa-lg fa-fw header-icon"></i> ' + config['zone_name'] + '</button>\
@ -96,9 +125,17 @@ define(function(require) {
$(".user-zone-info").html(user_login_content);
if (!Config.isTabEnabled(SETTINGS_TAB_ID)){
$(".user-zone-info a.configuration").parent('li').remove();
}
$(".user-zone-info a.quickconf_view_header").click(function() {
var context = $(this).closest('ul');
$(".quickconf_view", context).toggle();
return false;
});
$(".user-zone-info a.quickconf_view").click(function() {
var sunstone_setting = {DEFAULT_VIEW : $(this).attr("view")};
Sunstone.runAction("User.append_sunstone_setting_refresh", -1, sunstone_setting);
});
function zoneRefresh() {
// Populate Zones dropdown

View File

@ -25,10 +25,12 @@ define(function(require) {
OpenNebulaAction.create(params, RESOURCE);
},
"del" : function(params) {
OpenNebulaAction.del(params, RESOURCE);
var action_obj = params.data.extra_param;
OpenNebulaAction.del(params, RESOURCE, action_obj);
},
"delete_from_provision": function(params) {
OpenNebulaAction.simple_action(params, RESOURCE, "delete_from_provision");
"delete_recursive": function(params) {
var action_obj = {"recursive": true};
OpenNebulaAction.simple_action(params, RESOURCE, "delete_recursive", action_obj);
},
"list" : function(params) {
OpenNebulaAction.list(params, RESOURCE);
@ -46,10 +48,6 @@ define(function(require) {
var action_obj = params.data.extra_param;
OpenNebulaAction.simple_action(params, RESOURCE, "chmod", action_obj);
},
"chmod_from_provision": function(params) {
var action_obj = params.data.extra_param;
OpenNebulaAction.simple_action(params, RESOURCE, "chmod_from_provision", action_obj);
},
"append": function(params) {
var action_obj = {"template_raw" : params.data.extra_param, append : true};
OpenNebulaAction.simple_action(params, RESOURCE, "update", action_obj);

View File

@ -21,6 +21,9 @@ define(function(require) {
var Notifier = require('utils/notifier');
var OpenNebulaVM = require('opennebula/vm');
var Accounting = require('utils/accounting');
var OpenNebula = require('opennebula');
var QuotaWidgets = require('utils/quotas/quota-widgets');
var QuotaDefaults = require('utils/quotas/quota-defaults');
var TemplateDashboard = require('hbs!./dashboard-tab/html');
@ -36,6 +39,8 @@ define(function(require) {
var IMAGES_CREATE_FORM_PANEL_ID = require('tabs/images-tab/form-panels/create/formPanelId');
var VNETS_CREATE_FORM_PANEL_ID = require('tabs/vnets-tab/form-panels/create/formPanelId');
var TAB_ID = require('./dashboard-tab/tabId');
var _initialized = false;
var _activeWidgets = [];
var _widgets = {
@ -112,6 +117,104 @@ define(function(require) {
data: options
});
}
},
'groupquotas': {
'html': require('hbs!./provision-tab/dashboard/vdc-quotas'),
'onShow': function() {
OpenNebula.Group.show({
data : {
id: "-1"
},
success: function(request,group_json){
var group = group_json.GROUP;
QuotaWidgets.initEmptyQuotas(group);
if (!$.isEmptyObject(group.VM_QUOTA)){
var default_group_quotas = QuotaDefaults.default_quotas(group.DEFAULT_GROUP_QUOTAS);
var vms = QuotaWidgets.quotaInfo(
group.VM_QUOTA.VM.VMS_USED,
group.VM_QUOTA.VM.VMS,
default_group_quotas.VM_QUOTA.VM.VMS,
true);
$("#"+TAB_ID+" #provision_dashboard_vdc_rvms_percentage").html(vms["percentage"]);
$("#"+TAB_ID+" #provision_dashboard_vdc_rvms_str").html(vms["str"]);
$("#"+TAB_ID+" #provision_dashboard_vdc_rvms_meter").css("width", vms["percentage"]+"%");
var memory = QuotaWidgets.quotaMBInfo(
group.VM_QUOTA.VM.MEMORY_USED,
group.VM_QUOTA.VM.MEMORY,
default_group_quotas.VM_QUOTA.VM.MEMORY,
true);
$("#"+TAB_ID+" #provision_dashboard_vdc_memory_percentage").html(memory["percentage"]);
$("#"+TAB_ID+" #provision_dashboard_vdc_memory_str").html(memory["str"]);
$("#"+TAB_ID+" #provision_dashboard_vdc_memory_meter").css("width", memory["percentage"]+"%");
var cpu = QuotaWidgets.quotaFloatInfo(
group.VM_QUOTA.VM.CPU_USED,
group.VM_QUOTA.VM.CPU,
default_group_quotas.VM_QUOTA.VM.CPU,
true);
$("#"+TAB_ID+" #provision_dashboard_vdc_cpu_percentage").html(cpu["percentage"]);
$("#"+TAB_ID+" #provision_dashboard_vdc_cpu_str").html(cpu["str"]);
$("#"+TAB_ID+" #provision_dashboard_vdc_cpu_meter").css("width", cpu["percentage"]+"%");
}
}
});
}
},
'quotas': {
'html': require('hbs!./provision-tab/dashboard/quotas'),
'onShow': function() {
OpenNebula.User.show({
data : {
id: "-1"
},
success: function(request,user_json){
var user = user_json.USER;
QuotaWidgets.initEmptyQuotas(user);
if (!$.isEmptyObject(user.VM_QUOTA)){
var default_user_quotas = QuotaDefaults.default_quotas(user.DEFAULT_USER_QUOTAS);
var vms = QuotaWidgets.quotaInfo(
user.VM_QUOTA.VM.VMS_USED,
user.VM_QUOTA.VM.VMS,
default_user_quotas.VM_QUOTA.VM.VMS,
true);
$("#"+TAB_ID+" #provision_dashboard_rvms_percentage").html(vms["percentage"]);
$("#"+TAB_ID+" #provision_dashboard_rvms_str").html(vms["str"]);
$("#"+TAB_ID+" #provision_dashboard_rvms_meter").css("width", vms["percentage"]+"%");
var memory = QuotaWidgets.quotaMBInfo(
user.VM_QUOTA.VM.MEMORY_USED,
user.VM_QUOTA.VM.MEMORY,
default_user_quotas.VM_QUOTA.VM.MEMORY,
true);
$("#"+TAB_ID+" #provision_dashboard_memory_percentage").html(memory["percentage"]);
$("#"+TAB_ID+" #provision_dashboard_memory_str").html(memory["str"]);
$("#"+TAB_ID+" #provision_dashboard_memory_meter").css("width", memory["percentage"]+"%");
var cpu = QuotaWidgets.quotaFloatInfo(
user.VM_QUOTA.VM.CPU_USED,
user.VM_QUOTA.VM.CPU,
default_user_quotas.VM_QUOTA.VM.CPU,
true);
$("#"+TAB_ID+" #provision_dashboard_cpu_percentage").html(cpu["percentage"]);
$("#"+TAB_ID+" #provision_dashboard_cpu_str").html(cpu["str"]);
$("#"+TAB_ID+" #provision_dashboard_cpu_meter").css("width", cpu["percentage"]+"%");
}
}
});
}
}
}
@ -130,8 +233,6 @@ define(function(require) {
},
}
var TAB_ID = require('./dashboard-tab/tabId');
var Tab = {
tabId: TAB_ID,
resource: 'Dashboard',

View File

@ -185,6 +185,7 @@ define(function(require) {
if (this.action == "create") {
$("input#group_view_cloud").prop('checked', true).change();
$("input#group_admin_view_cloud").prop('checked', true).change();
$("input#group_admin_view_groupadmin").prop('checked', true).change();
_generateViewsSelect(context, "admin", "groupadmin");

View File

@ -104,8 +104,8 @@ define(function(require) {
$(".service_networks tbody").append(
'<tr>\
<td>\
<input class="service_network_name" type="text" pattern="[\\w]+"/>\
<small class="error">'+Locale.tr("Only word characters are allowed")+'</small>\
<input class="service_network_name" type="text" pattern="^\\w+$"/>\
<small class="error">'+Locale.tr("Can only contain alphanumeric and underscore characters")+'</small>\
</td>\
<td>\
<textarea class="service_network_description"/>\
@ -201,14 +201,6 @@ define(function(require) {
$(document).foundation('tab', 'reflow');
context.foundation({
abide : {
patterns: {
word_chars: /^\w+$/
}
}
});
// Add first role
$("#tf_btn_roles", context).trigger("click");

View File

@ -19,7 +19,7 @@
<label for="name">{{tr "Role Name"}}
<span class="tip">{{tr "Name of the role"}}</span>
</label>
<input type="text" id="role_name" name="name" required pattern="word_chars"/>
<input type="text" id="role_name" name="name" required pattern="^\w+$"/>
<small class="error">{{tr "Can only contain alphanumeric and underscore characters"}}</small>
</div>
<div class="service_template_param service_role medium-2 columns end">

View File

@ -35,6 +35,9 @@ define(function(require) {
var NicsSection = require('utils/nics-section');
var TemplateUtils = require('utils/template-utils');
var LabelsUtils = require('utils/labels/utils');
var WizardFields = require('utils/wizard-fields');
var UserInputs = require('utils/user-inputs');
var CapacityInputs = require('tabs/templates-tab/form-panels/create/wizard-tabs/general/capacity-inputs');
var ProvisionQuotaWidget = require('./provision-tab/users/quota-widget');
@ -103,7 +106,6 @@ define(function(require) {
$("#flow_name", context).val('');
//$(".provision_selected_networks").html("");
$(".provision-pricing-table", context).removeClass("selected");
//$('a[href="#provision_system_templates_selector"]', context).click();
},
error: Notifier.onError
},
@ -119,7 +121,9 @@ define(function(require) {
$(".provision_selected_networks").html("");
$(".provision-pricing-table", context).removeClass("selected");
$(".alert-box-error", context).hide();
$('a[href="#provision_system_templates_selector"]', context).click();
$('#provision_vm_instantiate_templates_owner_filter').val('all').change();
$('#provision_vm_instantiate_template_search').val('').trigger('input');
},
error: Notifier.onError
}
@ -127,83 +131,6 @@ define(function(require) {
$(document).foundation();
function generate_custom_attrs(context, custom_attrs) {
context.off();
var text_attrs = [];
$.each(custom_attrs, function(key, value){
var parts = value.split("|");
// 0 mandatory; 1 type; 2 desc;
var attrs = {
"name": key,
"mandatory": parts[0],
"type": parts[1],
"description": parts[2],
}
switch (parts[1]) {
case "text":
case "text64":
case "password":
text_attrs.push(attrs)
break;
}
});
if (text_attrs.length > 0) {
context.html(
'<br>'+
'<div class="row">'+
'<div class="large-12 large-centered columns">'+
'<h3 class="subheader text-right">'+
'<span class="left">'+
'<i class="fa fa-th fa-gears"></i>&emsp;'+
Locale.tr("Custom Attributes")+
'</span>'+
'</h3>'+
'<br>'+
'</div>'+
'</div>'+
'<br>'+
'<div class="provision_custom_attributes">'+
'</div>'+
'<br>'+
'<br>'+
'<br>');
$.each(text_attrs, function(index, custom_attr){
var input;
switch (custom_attr.type) {
case "text":
input = '<textarea type="text" rows="1" attr_name="'+custom_attr.name+'" class="provision_custom_attribute provision-input" style="height: 40px !important; font-size: 16px; padding: 0.5rem !important;"/>';
break;
case "text64":
input = '<textarea type="text" rows="1" text64="true" attr_name="'+custom_attr.name+'" class="provision_custom_attribute provision-input" style="height: 40px !important; font-size: 16px; padding: 0.5rem !important;"/>';
break;
case "password":
input = '<input type="password" attr_name="'+custom_attr.name+'" class="provision_custom_attribute provision-input" style="height: 40px !important; font-size: 16px; padding: 0.5rem !important;"/>';
break;
}
$(".provision_custom_attributes", context).append(
'<br>'+
'<div class="row">'+
'<div class="large-10 large-centered columns">'+
'<label style="font-size: 16px">' +
'<i class="fa fa-asterisk" style="color:#0099c3"/> '+
TemplateUtils.htmlDecode(custom_attr.description) +
input +
'</label>'+
'</div>'+
'</div>');
});
} else {
context.html("");
}
}
function generate_cardinality_selector(context, role_template, template_json) {
context.off();
var min_vms = (role_template.min_vms||1);
@ -339,15 +266,18 @@ define(function(require) {
}
}
var provision_instance_type_accordion_id = 0;
var provision_capacity_accordion_id = 0;
function generate_provision_capacity_accordion(context, element) {
var capacity = element.TEMPLATE;
function generate_provision_instance_type_accordion(context, capacity) {
context.off();
var memory_value;
var memory_unit;
if (capacity.MEMORY > 1000){
memory_value = Math.floor(capacity.MEMORY/1024);
if (capacity.MEMORY >= 1024){
memory_value = (capacity.MEMORY/1024).toFixed(2);
memory_unit = "GB";
} else {
memory_value = (capacity.MEMORY ? capacity.MEMORY : '-');
@ -379,38 +309,17 @@ define(function(require) {
'<br>'+
'</div>'+
'</div>'+
(Config.provision.create_vm.isEnabled("capacity_select") &&
!((capacity.SUNSTONE) && (capacity.SUNSTONE.CAPACITY_SELECT == "NO")) ?
(Config.provision.create_vm.isEnabled("capacity_select") ?
'<div class="row">'+
'<div class="large-12 large-centered columns">'+
'<dl class="accordion" data-accordion="provision_accordion_'+provision_instance_type_accordion_id+'">'+
'<dl class="accordion" data-accordion="provision_accordion_'+provision_capacity_accordion_id+'">'+
'<dd class="accordion-navigation">'+
'<a href="#provision_instance_type_dd_'+provision_instance_type_accordion_id+'" class="button large-12 medium radius" style="color: #555;">'+
'<a href="#provision_capacity_dd_'+provision_capacity_accordion_id+'" class="button large-12 medium radius" style="color: #555;">'+
Locale.tr("Change Capacity")+
'</a>'+
'<div id="provision_instance_type_dd_'+provision_instance_type_accordion_id+'" class="content">'+
'<div class="row">'+
'<div class="large-12 large-centered columns">'+
'<h3 class="subheader text-right">'+
'<input type="search" class="provision-search-input right" placeholder="Search"/>'+
'</h3>'+
'<br>'+
'</div>'+
'</div>'+
'<div class="row">'+
'<div class="large-12 large-centered columns">'+
'<table class="provision_instance_types_table">'+
'<thead class="hidden">'+
'<tr>'+
'<th>'+Locale.tr("Name")+'</th>'+
'</tr>'+
'</thead>'+
'<tbody class="hidden">'+
'</tbody>'+
'</table>'+
'<br>'+
'</div>'+
'</div>'+
'<div id="provision_capacity_dd_'+provision_capacity_accordion_id+'" class="content">'+
'<br>'+
CapacityInputs.html() +
'</div>'+
'</dd>'+
'</dl>'+
@ -418,6 +327,31 @@ define(function(require) {
'</div>' : '' ) +
'<br>');
if (Config.provision.create_vm.isEnabled("capacity_select")) {
provision_capacity_accordion_id += 1;
CapacityInputs.setup(context);
CapacityInputs.fill(context, element);
CapacityInputs.setCallback(context, function(values){
$(".cpu_value", context).html(values.CPU);
var memory_value;
var memory_unit;
if (values.MEMORY >= 1024){
memory_value = (values.MEMORY/1024).toFixed(2);
memory_unit = "GB";
} else {
memory_value = values.MEMORY;
memory_unit = "MB";
}
$(".memory_value", context).html(memory_value);
$(".memory_unit", context).html(memory_unit);
});
}
var cost = 0;
var cpuCost = capacity.CPU_COST;
@ -431,135 +365,31 @@ define(function(require) {
memoryCost = Config.onedConf.DEFAULT_COST.MEMORY_COST;
}
var _redoCost = function(values){
var cost = 0;
if (values.CPU != undefined){
cost += cpuCost * values.CPU;
}
if (values.MEMORY != undefined){
cost += memoryCost * values.MEMORY;
}
$(".cost_value", context).html(cost.toFixed(2));
};
if ((cpuCost != 0 || memoryCost != 0) && Config.isFeatureEnabled("showback")) {
$(".provision_create_template_cost_div").show();
if (capacity.CPU) {
cost += capacity.CPU * cpuCost;
$(".cost_value").data("CPU_COST", cpuCost);
}
_redoCost(capacity);
if (capacity.MEMORY) {
cost += capacity.MEMORY * memoryCost;
$(".cost_value").data("MEMORY_COST", memoryCost);
if (Config.provision.create_vm.isEnabled("capacity_select")){
CapacityInputs.setCallback(context, _redoCost);
}
$(".cost_value").html(cost.toFixed(2));
} else {
$(".provision_create_template_cost_div").hide();
}
if (Config.provision.create_vm.isEnabled("capacity_select") &&
!((capacity.SUNSTONE) && (capacity.SUNSTONE.CAPACITY_SELECT == "NO"))) {
provision_instance_type_accordion_id += 1;
var provision_instance_types_datatable = $('.provision_instance_types_table', context).dataTable({
"iDisplayLength": 6,
"sDom" : '<"H">t<"F"lp>',
"bSort" : false,
"aLengthMenu": [[6, 12, 36, 72], [6, 12, 36, 72]],
"aoColumnDefs": [
{ "bVisible": false, "aTargets": ["all"]}
],
"aoColumns": [
{ "mDataProp": "name" }
],
"fnPreDrawCallback": function (oSettings) {
// create a thumbs container if it doesn't exist. put it in the dataTables_scrollbody div
if (this.$('tr', {"filter": "applied"} ).length == 0) {
this.html('<div class="text-center">'+
'<span class="fa-stack fa-5x" style="color: #dfdfdf">'+
'<i class="fa fa-cloud fa-stack-2x"></i>'+
'<i class="fa fa-info-circle fa-stack-1x fa-inverse"></i>'+
'</span>'+
'<br>'+
'<br>'+
'<span style="font-size: 18px; color: #999">'+
Locale.tr("There are no instance_types available. Please contact your cloud administrator")+
'</span>'+
'</div>');
} else {
$(".provision_instance_types_table", context).html(
'<ul class="provision_instance_types_ul large-block-grid-3 medium-block-grid-3 small-block-grid-1 text-center">'+
'</ul>');
}
return true;
},
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
var data = aData;
var li = $('<li>'+
'<ul class="provision-pricing-table hoverable only-one" cpu="'+data.cpu+'" memory="'+data.memory+'">'+
'<li class="provision-title" title="'+data.name+'">'+
data.name+
'</li>'+
'<li class="provision-bullet-item">'+
'<span style="font-size: 40px">'+
'<i class="fa fa-fw fa-laptop"/>&emsp;'+
'<span style="vertical-align: middle; font-size:14px">'+
'x'+data.cpu+' - '+
((data.memory > 1000) ?
(Math.floor(data.memory/1024)+'GB') :
(data.memory+'MB'))+
'</span>'+
'</span>'+
'</li>'+
'<li class="provision-description">'+
(data.description || '')+
'</li>'+
'</ul>'+
'</li>').appendTo($(".provision_instance_types_ul", context));
$(".provision-pricing-table", li).data("opennebula", data)
return nRow;
}
});
$('.provision-search-input', context).on('input',function(){
provision_instance_types_datatable.fnFilter( $(this).val() );
})
context.on("click", ".provision-pricing-table.only-one" , function(){
$(".cpu_value", context).html($(this).attr("cpu"));
var memory_value;
var memory_unit;
if ($(this).attr("memory") > 1000){
memory_value = Math.floor($(this).attr("memory")/1024);
memory_unit = "GB";
} else {
memory_value = $(this).attr("memory");
memory_unit = "MB";
}
$(".memory_value", context).html(memory_value);
$(".memory_unit", context).html(memory_unit);
if (Config.isFeatureEnabled("showback")) {
var cost = 0;
if ($(".cost_value").data("CPU_COST")) {
cost += $(this).attr("cpu") * $(".cost_value").data("CPU_COST")
}
if ($(".cost_value").data("MEMORY_COST")) {
cost += $(this).attr("memory") * $(".cost_value").data("MEMORY_COST")
}
$(".cost_value").html(cost.toFixed(2));
}
$('.accordion a', context).first().trigger("click");
})
$(document).foundation();
update_provision_instance_types_datatable(provision_instance_types_datatable);
}
}
function show_provision_dashboard() {
@ -902,18 +732,10 @@ define(function(require) {
function show_provision_create_vm() {
OpenNebula.Action.clear_cache("VMTEMPLATE");
ProvisionTemplatesList.updateDatatable(provision_system_templates_datatable);
provision_system_templates_datatable.fnFilter("^-$", 2, true, false)
ProvisionTemplatesList.updateDatatable(provision_vdc_templates_datatable);
provision_vdc_templates_datatable.fnFilter("^(?!\-$)", 2, true, false);
provision_vdc_templates_datatable.fnFilter("^1$", 3, true, false);
if (Config.isProvisionTabEnabled("provision-tab", "templates")) {
ProvisionTemplatesList.updateDatatable(provision_saved_templates_datatable);
provision_saved_templates_datatable.fnFilter("^(?!\-$)", 2, true, false);
provision_saved_templates_datatable.fnFilter("^0$", 3, true, false);
}
ProvisionTemplatesList.updateDatatable(provision_vm_instantiate_templates_datatable);
$('#provision_vm_instantiate_templates_owner_filter').val('all').change();
$('#provision_vm_instantiate_template_search').val('').trigger('input');
$(".provision_accordion_template .selected_template").hide();
$(".provision_accordion_template .select_template").show();
@ -964,25 +786,6 @@ define(function(require) {
Sunstone.runAction('Provision.Group.show', "-1");
}
function update_provision_instance_types_datatable(datatable) {
datatable.fnClearTable(true);
if (!config['instance_types'] || config['instance_types'].length == 0) {
datatable.html('<div class="text-center">'+
'<span class="fa-stack fa-5x" style="color: #dfdfdf">'+
'<i class="fa fa-cloud fa-stack-2x"></i>'+
'<i class="fa fa-info-circle fa-stack-1x fa-inverse"></i>'+
'</span>'+
'<br>'+
'<br>'+
'<span style="font-size: 18px; color: #999">'+
Locale.tr("There are no instance types available")+
'</span>'+
'</div>');
} else {
datatable.fnAddData(config['instance_types']);
}
}
function update_provision_flow_templates_datatable(datatable, timeout) {
datatable.html('<div class="text-center">'+
'<span class="fa-stack fa-5x" style="color: #dfdfdf">'+
@ -1160,6 +963,16 @@ define(function(require) {
'</span>';
}
var owner;
if (data.UID == config.user_id){
owner = Locale.tr("mine");
} else if (data.GID == config.user_gid){
owner = Locale.tr("group");
} else {
owner = Locale.tr("system");
}
var li = $('<li>'+
'<ul class="provision-pricing-table hoverable only-one" opennebula_id="'+data.ID+'">'+
'<li class="provision-title" title="'+data.NAME+'">'+
@ -1171,6 +984,12 @@ define(function(require) {
'<li class="provision-description">'+
(data.TEMPLATE.DESCRIPTION || '...')+
'</li>'+
'<li class="text-right provision-bullet-item">'+
'<span class="left" style="color: #999;">'+
'<i class="fa fa-fw fa-lg fa-user"/>&emsp;'+
owner+
'</span>'+
'</li>'+
'</ul>'+
'</li>').appendTo($("#"+tableID+'_ul'));
@ -1199,7 +1018,8 @@ define(function(require) {
return true;
}
provision_system_templates_datatable = $('#provision_system_templates_table').dataTable({
provision_vm_instantiate_templates_datatable = $('#provision_vm_instantiate_templates_table').dataTable({
"iDisplayLength": 6,
"sDom" : '<"H">t<"F"lp>',
"aLengthMenu": [[6, 12, 36, 72], [6, 12, 36, 72]],
@ -1209,100 +1029,62 @@ define(function(require) {
"aoColumns": [
{ "mDataProp": "VMTEMPLATE.ID" },
{ "mDataProp": "VMTEMPLATE.NAME" },
{ "mDataProp": "VMTEMPLATE.TEMPLATE.SAVED_TEMPLATE_ID", "sDefaultContent" : "-" },
{ "mDataProp": "VMTEMPLATE.PERMISSIONS.GROUP_U" },
{ "mDataProp": function ( data, type, val ) {
var owner;
if (data.VMTEMPLATE.UID == config.user_id){
owner = "mine";
} else if (data.VMTEMPLATE.GID == config.user_gid){
owner = "group";
} else {
owner = "system";
}
if (type === 'filter') {
// In order to make "mine" search work
if(owner == "mine"){
return Locale.tr("mine");
} else if(owner == "group"){
return Locale.tr("group");
} else if(owner == "system"){
return Locale.tr("system");
}
}
return owner;
}
},
{ "mDataProp": "VMTEMPLATE.TEMPLATE.LABELS", "sDefaultContent" : "-" }
],
"fnPreDrawCallback": function (oSettings) {
initializeTemplateCards(this, "provision_system_templates")
initializeTemplateCards(this, "provision_vm_instantiate_templates");
},
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
appendTemplateCard(aData, "provision_system_templates");
appendTemplateCard(aData, "provision_vm_instantiate_templates");
return nRow;
},
"fnDrawCallback": function(oSettings) {
}
});
provision_vdc_templates_datatable = $('#provision_vdc_templates_table').dataTable({
"iDisplayLength": 6,
"sDom" : '<"H">t<"F"lp>',
"aLengthMenu": [[6, 12, 36, 72], [6, 12, 36, 72]],
"aoColumnDefs": [
{ "bVisible": false, "aTargets": ["all"]}
],
"aoColumns": [
{ "mDataProp": "VMTEMPLATE.ID" },
{ "mDataProp": "VMTEMPLATE.NAME" },
{ "mDataProp": "VMTEMPLATE.TEMPLATE.SAVED_TEMPLATE_ID", "sDefaultContent" : "-" },
{ "mDataProp": "VMTEMPLATE.PERMISSIONS.GROUP_U" },
{ "mDataProp": "VMTEMPLATE.TEMPLATE.LABELS", "sDefaultContent" : "-" }
],
"fnPreDrawCallback": function (oSettings) {
initializeTemplateCards(this, "provision_vdc_templates")
},
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
appendTemplateCard(aData, "provision_vdc_templates");
return nRow;
}
$('#provision_vm_instantiate_template_search').on('input',function(){
provision_vm_instantiate_templates_datatable.fnFilter( $(this).val() );
});
provision_saved_templates_datatable = $('#provision_saved_templates_table').dataTable({
"iDisplayLength": 6,
"sDom" : '<"H">t<"F"lp>',
"aLengthMenu": [[6, 12, 36, 72], [6, 12, 36, 72]],
"aoColumnDefs": [
{ "bVisible": false, "aTargets": ["all"]}
],
"aoColumns": [
{ "mDataProp": "VMTEMPLATE.ID" },
{ "mDataProp": "VMTEMPLATE.NAME" },
{ "mDataProp": "VMTEMPLATE.TEMPLATE.SAVED_TEMPLATE_ID", "sDefaultContent" : "-" },
{ "mDataProp": "VMTEMPLATE.PERMISSIONS.GROUP_U" },
{ "mDataProp": "VMTEMPLATE.TEMPLATE.LABELS", "sDefaultContent" : "-" }
],
"fnPreDrawCallback": function (oSettings) {
initializeTemplateCards(this, "provision_saved_templates")
},
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
appendTemplateCard(aData, "provision_saved_templates");
return nRow;
$('#provision_vm_instantiate_templates_owner_filter').on('change', function(){
switch($(this).val()){
case "all":
provision_vm_instantiate_templates_datatable.fnFilter('', 2);
break;
default:
provision_vm_instantiate_templates_datatable.fnFilter("^" + $(this).val() + "$", 2, true, false);
break;
}
});
$('#provision_create_system_template_search').on('input',function(){
provision_system_templates_datatable.fnFilter( $(this).val() );
})
$('#provision_create_vdc_template_search').on('input',function(){
provision_vdc_templates_datatable.fnFilter( $(this).val() );
})
$('#provision_create_saved_template_search').on('input',function(){
provision_saved_templates_datatable.fnFilter( $(this).val() );
})
$('[href="#provision_system_templates_selector"]').on('click', function() {
ProvisionTemplatesList.updateDatatable(provision_system_templates_datatable);
})
$('[href="#provision_saved_templates_selector"]').on('click', function() {
ProvisionTemplatesList.updateDatatable(provision_saved_templates_datatable);
})
$('[href="#provision_vdc_templates_selector"]').on('click', function() {
ProvisionTemplatesList.updateDatatable(provision_vdc_templates_datatable);
})
$("#provision_create_template_refresh_button").click(function(){
OpenNebula.Action.clear_cache("VMTEMPLATE");
ProvisionTemplatesList.updateDatatable(provision_system_templates_datatable);
ProvisionTemplatesList.updateDatatable(provision_saved_templates_datatable);
ProvisionTemplatesList.updateDatatable(provision_vdc_templates_datatable);
ProvisionTemplatesList.updateDatatable(provision_vm_instantiate_templates_datatable);
});
tab.on("click", "#provision_create_vm .provision_select_template .provision-pricing-table.only-one" , function(){
@ -1330,9 +1112,17 @@ define(function(require) {
$(".provision_accordion_template a").first().trigger("click");
generate_provision_instance_type_accordion(
generate_provision_capacity_accordion(
$(".provision_capacity_selector", create_vm_context),
template_json.VMTEMPLATE.TEMPLATE);
template_json.VMTEMPLATE);
provisionInvalidCapacity = function(input){
if(!$(input).closest(".accordion-navigation").hasClass("active")){
$("a", $(input).closest(".accordion-navigation")).click();
}
};
$(".provision_capacity_selector input[required]", create_vm_context).attr("oninvalid", "provisionInvalidCapacity(this)");
var disksContext = $(".provision_disk_selector", create_vm_context);
if (Config.provision.create_vm.isEnabled("disk_resize")) {
@ -1348,9 +1138,11 @@ define(function(require) {
}
if (template_json.VMTEMPLATE.TEMPLATE.USER_INPUTS) {
generate_custom_attrs(
$(".provision_custom_attributes_selector", create_vm_context),
template_json.VMTEMPLATE.TEMPLATE.USER_INPUTS);
UserInputs.vmTemplateInsert(
$(".provision_custom_attributes_selector", create_vm_context),
template_json,
{text_header: '<i class="fa fa-gears fa-lg"></i>&emsp;'+Locale.tr("Custom Attributes")});
} else {
$(".provision_custom_attributes_selector", create_vm_context).html("");
}
@ -1369,7 +1161,7 @@ define(function(require) {
$("#provision_create_vm").submit(function(){
var context = $(this);
var template_id = $(".tabs-content .content.active .selected", context).attr("opennebula_id");
var template_id = $(".provision_select_template .selected", context).attr("opennebula_id");
if (!template_id) {
$(".alert-box-error", context).fadeIn().html(Locale.tr("You must select at least a template configuration"));
return false;
@ -1378,7 +1170,6 @@ define(function(require) {
var vm_name = $("#vm_name", context).val();
var nics = NicsSection.retrieve(context);
var disks = DisksResize.retrieve($(".provision_disk_selector", context));
var instance_type = $(".provision_instance_types_ul .selected", context);
var extra_info = {
'vm_name' : vm_name,
@ -1394,37 +1185,12 @@ define(function(require) {
extra_info.template.DISK = disks;
}
if (instance_type.length > 0) {
var instance_typa_data = $.extend({}, instance_type.data("opennebula"));
delete instance_typa_data.name;
delete instance_typa_data.description;
$.extend(extra_info.template, instance_typa_data)
if (Config.provision.create_vm.isEnabled("capacity_select")){
capacityContext = $(".provision_capacity_selector", context);
$.extend(extra_info.template, CapacityInputs.retrieveChanges(capacityContext));
}
var missing_attr = false;
var user_inputs_values = {};
if ($(".provision_custom_attributes", $(this))) {
$(".provision_custom_attribute", $(".provision_custom_attributes", $(this))).each(function(){
if (!$(this).val()) {
$(this).parent("label").css("color", "red");
missing_attr = true;
} else {
$(this).parent("label").css("color", "#777");
if ($(this).attr('text64') == "true"){
user_inputs_values[$(this).attr("attr_name")] = btoa($(this).val());
} else {
user_inputs_values[$(this).attr("attr_name")] = $(this).val();
}
}
})
}
if (missing_attr) {
$(".alert-box-error", $(this)).fadeIn().html(Locale.tr("You have not specified all the Custom Atrributes for this VM"));
return false;
}
var user_inputs_values = WizardFields.retrieve($(".provision_custom_attributes_selector", $(this)));
if (!$.isEmptyObject(user_inputs_values)) {
$.extend(extra_info.template, user_inputs_values)
@ -1596,11 +1362,6 @@ define(function(require) {
});
}
//if (text_attrs.length > 0) {
// generate_custom_attrs(
// $(".provision_custom_attributes_selector", context),
// text_attrs);
//}
} else {
$(".provision_network_selector", context).html("")
$(".provision_custom_attributes_selector", context).html("")
@ -1649,9 +1410,11 @@ define(function(require) {
template_json);
if (template_json.VMTEMPLATE.TEMPLATE.USER_INPUTS) {
generate_custom_attrs(
$(".provision_custom_attributes_selector", role_context),
template_json.VMTEMPLATE.TEMPLATE.USER_INPUTS);
UserInputs.vmTemplateInsert(
$(".provision_custom_attributes_selector", role_context),
template_json,
{text_header: '<i class="fa fa-gears fa-lg"></i>&emsp;'+Locale.tr("Custom Attributes")});
} else {
$(".provision_custom_attributes_selector", role_context).html("");
}
@ -1705,21 +1468,9 @@ define(function(require) {
}
var roles = [];
var missing_attr = false;
$(".provision_create_flow_role", context).each(function(){
var user_inputs_values = {};
if ($(".provision_custom_attributes", $(this))) {
$(".provision_custom_attribute", $(".provision_custom_attributes", $(this))).each(function(){
if (!$(this).val()) {
$(this).parent("label").css("color", "red");
missing_attr = true;
} else {
$(this).parent("label").css("color", "#777");
user_inputs_values[$(this).attr("attr_name")] = $(this).val();
}
})
}
var user_inputs_values = WizardFields.retrieve($(".provision_custom_attributes_selector", $(this)));
var role_template = $(this).data("opennebula");
@ -1746,11 +1497,6 @@ define(function(require) {
extra_info["merge_template"]["name"] = flow_name;
}
if (missing_attr) {
$(".alert-box-error", $(this)).fadeIn().html(Locale.tr("You have not specified all the Custom Atrributes for this Service"));
return false;
}
Sunstone.runAction("Provision.Flow.instantiate", template_id, extra_info);
return false;
})

View File

@ -41,10 +41,9 @@
<table class="provision_templates_table">
<thead class="hidden">
<tr>
<th>{{tr "ID"}}</th>
<th>{{tr "Name"}}</th>
<th>{{tr "Saved"}}</th>
<th>{{tr "User ID"}}</th>
<th>ID</th>
<th>Name</th>
<th>User ID</th>
</tr>
</thead>
<tbody class="hidden"></tbody>

View File

@ -50,7 +50,7 @@ define(function(require) {
function html(opts_arg){
opts = $.extend({
title: Locale.tr("Saved Templates"),
title: Locale.tr("Templates"),
refresh: true,
create: true,
active: true,
@ -120,7 +120,6 @@ define(function(require) {
"aoColumns": [
{ "mDataProp": "VMTEMPLATE.ID" },
{ "mDataProp": "VMTEMPLATE.NAME" },
{ "mDataProp": "VMTEMPLATE.TEMPLATE.SAVED_TEMPLATE_ID", "sDefaultContent" : "-" },
{ "mDataProp": "VMTEMPLATE.UID" }
],
"fnPreDrawCallback": function (oSettings) {
@ -134,7 +133,7 @@ define(function(require) {
'<br>'+
'<br>'+
'<span style="font-size: 18px; color: #999">'+
Locale.tr("There are no saved templates available")+
Locale.tr("There are no templates available")+
'<br>'+
Locale.tr("Create a template by saving a running Virtual Machine")+
'</span>'+
@ -163,18 +162,30 @@ define(function(require) {
actions_html += '<a class="provision_confirm_delete_template_button" title="'+ Locale.tr("Delete")+'" style="color:#555" href="#"><i class="fa fa-fw fa-lg fa-trash-o right only-on-hover"/></a>';
}
var cpu_txt = "";
var mem_txt = "";
if(data.TEMPLATE.CPU){
cpu_txt = 'x'+data.TEMPLATE.CPU;
}
if(data.TEMPLATE.MEMORY){
if (data.TEMPLATE.MEMORY > 1000){
mem_txt = Math.floor(data.TEMPLATE.MEMORY/1024)+'GB';
} else {
mem_txt = data.TEMPLATE.MEMORY+'MB';
}
}
$(".provision_templates_ul", context).append('<li>'+
'<ul class="provision-pricing-table" opennebula_id="'+data.ID+'" saved_to_image_id="'+data.TEMPLATE.SAVED_TO_IMAGE_ID+'" datatable_index="'+iDisplayIndexFull+'">'+
'<ul class="provision-pricing-table" opennebula_id="'+data.ID+'" datatable_index="'+iDisplayIndexFull+'">'+
'<li class="provision-title text-left" title="'+data.NAME+'">'+
data.NAME +
'</li>'+
'<li class="provision-bullet-item text-left" >'+
'<i class="fa fa-fw fa-lg fa-laptop"/> '+
'x'+data.TEMPLATE.CPU+' - '+
((data.TEMPLATE.MEMORY > 1000) ?
(Math.floor(data.TEMPLATE.MEMORY/1024)+'GB') :
(data.TEMPLATE.MEMORY+'MB'))+
' - '+
cpu_txt+' - '+
mem_txt+' - '+
get_provision_disk_image(data) +
'</li>'+
'<li class="provision-description text-left" style="padding-top:0px; padding-bottom: 5px">'+
@ -199,8 +210,6 @@ define(function(require) {
}
});
provision_templates_datatable.fnFilter("^(?!\-$)", 2, true, false);
$('.provision_list_templates_search', context).on('input',function(){
provision_templates_datatable.fnFilter( $(this).val() );
})
@ -218,9 +227,9 @@ define(function(require) {
$(".provision_list_templates_filter", context).on("change", ".resource_list_select", function(){
if ($(this).val() != "-2"){
provision_templates_datatable.fnFilter("^" + $(this).val() + "$", 3, true, false);
provision_templates_datatable.fnFilter("^" + $(this).val() + "$", 2, true, false);
} else {
provision_templates_datatable.fnFilter("", 3);
provision_templates_datatable.fnFilter("", 2);
}
})
@ -269,7 +278,7 @@ define(function(require) {
var template_id = $(this).attr("template_id");
OpenNebula.Template.delete_from_provision({
OpenNebula.Template.delete_recursive({
timeout: true,
data : {
id : template_id
@ -317,11 +326,14 @@ define(function(require) {
var template_id = $(this).attr("template_id");
OpenNebula.Template.chmod_from_provision({
OpenNebula.Template.chmod({
timeout: true,
data : {
id : template_id,
extra_param: {'group_u': 1}
extra_param: {
'group_u': 1,
'recursive' : true
}
},
success: function (){
$(".provision_templates_list_refresh_button", context).trigger("click");
@ -359,11 +371,14 @@ define(function(require) {
var template_id = $(this).attr("template_id");
OpenNebula.Template.chmod_from_provision({
OpenNebula.Template.chmod({
timeout: true,
data : {
id : template_id,
extra_param: {'group_u': 0}
extra_param: {
'group_u': 0,
'recursive' : true
}
},
success: function (){
$(".provision_templates_list_refresh_button", context).trigger("click");

View File

@ -17,12 +17,14 @@
<div class="row">
<div class="large-10 large-centered columns">
<h2 class="subheader">{{tr "Create Virtual Machine"}}</h2>
<br></div>
<br>
</div>
</div>
<div class="row">
<div class="large-8 large-centered columns">
<input type="text" id="vm_name" class="provision-input" placeholder="{{tr "Virtual Machine Name"}}" style="height: 40px !important; font-size: 16px; padding: 0.5rem !important;"/>
<br></div>
<br>
</div>
</div>
<div class="row">
<div class="large-10 large-centered columns">
@ -37,87 +39,36 @@
</span>
</a>
<div id="provision_dd_template" class="active content">
<div class="row">
<div class="medium-8 columns">
<button href="#" data-options="align:right" data-dropdown="provisionVMInstantiateLabelsDropdown" class="right small secondary button dropdown radius">
<i class="fa fa-tags"/> {{tr "Labels"}}
</button>
<ul id="provisionVMInstantiateLabelsDropdown" class="labels-dropdown f-dropdown" data-dropdown-content></ul>
<input type="search" class="right provision-search-input" placeholder="Search" id="provision_vm_instantiate_template_search"/>
</div>
<div class="medium-4 columns">
<select id="provision_vm_instantiate_templates_owner_filter">
<option value="all" selected="selected">{{tr "ALL"}}</option>
<option value="mine">{{tr "mine"}}</option>
<option value="group">{{tr "group"}}</option>
<option value="system">{{tr "system"}}</option>
</select>
</div>
</div>
<div class="row provision_select_template">
<div class="large-12 large-centered columns">
<dl class="tabs text-center" data-tab style="width: 100%">
<dd class="active" style="width: 33%;">
<a href="#provision_system_templates_selector">{{tr "System"}}</a>
</dd>
<dd style="width: 33%;">
<a href="#provision_vdc_templates_selector">{{tr "Group"}}</a>
</dd>
<dd style="width: 34%;">
<a href="#provision_saved_templates_selector">{{tr "Saved"}}</a>
</dd>
</dl>
<div class="tabs-content">
<div class="content active" id="provision_system_templates_selector">
<div class="row">
<div class="large-12 columns">
<button href="#" data-options="align:right" data-dropdown="provisionSystemLabelsDropdown" class="right small secondary button dropdown radius">
<i class="fa fa-tags"/> {{tr "Labels"}}</button>
<ul id="provisionSystemLabelsDropdown" class="labels-dropdown f-dropdown" data-dropdown-content></ul>
<input type="search" class="right provision-search-input" placeholder="Search" id="provision_create_system_template_search"/>
</div>
</div>
<table id="provision_system_templates_table">
<thead class="hidden">
<tr>
<th>{{tr "ID"}}</th>
<th>{{tr "Name"}}</th>
<th>{{tr "Saved"}}</th>
<th>{{tr "Shared"}}</th>
<th>{{tr "Labels"}}</th>
</tr>
</thead>
<tbody class="hidden"></tbody>
</table>
</div>
<div class="content" id="provision_vdc_templates_selector">
<div class="row">
<div class="large-12 columns">
<button href="#" data-options="align:right" data-dropdown="provisionSystemLabelsDropdown" class="right small secondary button dropdown radius">
<i class="fa fa-tags"/> {{tr "Labels"}}</button>
<ul id="provisionVdcLabelsDropdown" class="labels-dropdown f-dropdown" data-dropdown-content></ul>
<input type="search" class="right provision-search-input" placeholder="Search" id="provision_create_vdc_template_search"/>
</div>
</div>
<table id="provision_vdc_templates_table">
<thead class="hidden">
<tr>
<th>{{tr "ID"}}</th>
<th>{{tr "Name"}}</th>
<th>{{tr "Saved"}}</th>
<th>{{tr "Shared"}}</th>
<th>{{tr "Labels"}}</th>
</tr>
</thead>
<tbody class="hidden"></tbody>
</table>
</div>
<div class="content" id="provision_saved_templates_selector">
<div class="row">
<div class="large-12 columns">
<button href="#" data-options="align:right" data-dropdown="provisionSystemLabelsDropdown" class="right small secondary button dropdown radius">
<i class="fa fa-tags"/> {{tr "Labels"}}</button>
<ul id="provisionSavedLabelsDropdown" class="labels-dropdown f-dropdown" data-dropdown-content></ul>
<input type="search" class="right provision-search-input" placeholder="Search" id="provision_create_saved_template_search"/>
</div>
</div>
<table id="provision_saved_templates_table">
<thead class="hidden">
<tr>
<th>{{tr "ID"}}</th>
<th>{{tr "Name"}}</th>
<th>{{tr "Saved"}}</th>
<th>{{tr "Shared"}}</th>
<th>{{tr "Labels"}}</th>
</tr>
</thead>
<tbody class="hidden"></tbody>
</table>
</div>
</div>
<div class="small-12 columns">
<table id="provision_vm_instantiate_templates_table">
<thead class="hidden">
<tr>
<th>ID</th>
<th>Name</th>
<th>OWNER</th>
<th>Labels</th>
</tr>
</thead>
<tbody class="hidden"></tbody>
</table>
</div>
</div>
</div>
@ -147,4 +98,5 @@
</div>
</div>
<br>
<br></form>
<br>
</form>

View File

@ -127,26 +127,16 @@ define(function(require) {
});
$("#provision_change_view_form").submit(function() {
var sunstone_template = {};
if (that.element.TEMPLATE.SUNSTONE) {
$.extend(sunstone_template, that.element.TEMPLATE.SUNSTONE);
}
var sunstone_setting = {DEFAULT_VIEW : $('#provision_user_views_select', this).val()};
Sunstone.runAction("User.append_sunstone_setting_refresh", that.element.ID, sunstone_setting);
sunstone_template.DEFAULT_VIEW = $('#provision_user_views_select', this).val();
var template_str = TemplateUtils.templateToString({'SUNSTONE': sunstone_template});
Sunstone.runAction("User.append_template_refresh", that.element.ID, template_str);
return false;
});
$("#provision_change_language_form").submit(function() {
var sunstone_template = {};
if (that.element.TEMPLATE.SUNSTONE) {
$.extend(sunstone_template, that.element.TEMPLATE.SUNSTONE);
}
var sunstone_setting = {LANG : $('#provision_new_language', this).val()};
Sunstone.runAction("User.append_sunstone_setting_refresh", that.element.ID, sunstone_setting);
sunstone_template.LANG = $('#provision_new_language', this).val();
var template_str = TemplateUtils.templateToString({'SUNSTONE': sunstone_template});
Sunstone.runAction("User.append_template_refresh", that.element.ID, template_str);
return false;
});

View File

@ -38,9 +38,67 @@ define(function(require) {
"Template.show" : _commonActions.show(),
"Template.refresh" : _commonActions.refresh(),
"Template.delete" : _commonActions.del(),
"Template.delete_recursive":
{
type: "multiple",
call: OpenNebulaResource.delete_recursive,
callback : function(request, response) {
var elementId = request.request.data[0][0].toString();
Sunstone.getDataTable(TAB_ID).deleteElement(elementId);
},
elements: function() {
return Sunstone.getDataTable(TAB_ID).elements();
},
error: Notifier.onError,
notify: true
},
"Template.chown": _commonActions.multipleAction('chown'),
"Template.chgrp": _commonActions.multipleAction('chgrp'),
"Template.chmod": _commonActions.singleAction('chmod'),
"Template.share":
{
type: "multiple",
call: function(params){
var permissions = {
'group_u' : 1,
'recursive' : true
};
Sunstone.runAction(RESOURCE+".chmod", params.data.id, permissions);
},
callback : function(request, response) {
Sunstone.runAction(RESOURCE+".show", req.request.data[0][0]);
},
elements: function() {
return Sunstone.getDataTable(TAB_ID).elements();
},
error: Notifier.onError,
notify: false
},
"Template.unshare":
{
type: "multiple",
call: function(params){
var permissions = {
'group_u' : 0,
'recursive' : true
};
Sunstone.runAction(RESOURCE+".chmod", params.data.id, permissions);
},
callback : function(request, response) {
Sunstone.runAction(RESOURCE+".show", req.request.data[0][0]);
},
elements: function() {
return Sunstone.getDataTable(TAB_ID).elements();
},
error: Notifier.onError,
notify: false
},
"Template.rename": _commonActions.singleAction('rename'),
"Template.create" : _commonActions.create(CREATE_DIALOG_ID),
"Template.create_dialog" : _commonActions.showCreate(CREATE_DIALOG_ID),

View File

@ -63,11 +63,30 @@ define(function(require) {
layout: "main",
text: Locale.tr("Clone")
},
"Template.share" : {
type: "confirm",
layout: "main",
text: Locale.tr("Share"),
tip: Locale.tr("The template, along with any image defined in DISK/IMAGE_ID, will be shared with the group's users. Images defined by name are not affected. Permission changed: GROUP USE"),
},
"Template.unshare" : {
type: "confirm",
layout: "main",
text: Locale.tr("Unshare"),
tip: Locale.tr("The template, along with any image defined in DISK/IMAGE_ID, will be unshared with the group's users. Images defined by name are not affected. Permission changed: GROUP USE"),
},
"Template.delete" : {
type: "confirm",
layout: "del"
text: Locale.tr("Delete"),
layout: "vmsdelete_buttons"
},
"Template.delete_recursive" : {
type: "confirm",
text: Locale.tr('Delete <span class="label secondary radius">recursive</span>'),
tip: Locale.tr("The template will be deleted, along with any image defined in DISK/IMAGE_ID. Images defined by name are not affected"),
layout: "vmsdelete_buttons"
}
}
};
return Buttons;
})

View File

@ -27,6 +27,7 @@ define(function(require) {
var CustomTagsTable = require('utils/custom-tags-table');
var FilesTable = require('tabs/files-tab/datatable')
var OpenNebulaHost = require('opennebula/host');
var UserInputs = require('utils/user-inputs');
/*
TEMPLATES
@ -78,6 +79,7 @@ define(function(require) {
function _html() {
return TemplateHTML({
'userInputsHTML': UserInputs.html(),
'customTagsTableHTML': CustomTagsTable.html(),
'contextFilesTableHTML': this.contextFilesTable.dataTableHTML
});
@ -145,6 +147,7 @@ define(function(require) {
opt.attr('selected', 'selected');
});
UserInputs.setup(context);
CustomTagsTable.setup(context);
var selectOptions = {
@ -160,34 +163,6 @@ define(function(require) {
that.contextFilesTable.initialize(selectOptions);
that.contextFilesTable.refreshResourceTableSelect();
context.on("click", ".add_service_custom_attr", function() {
$(".service_custom_attrs tbody").append(
'<tr>' +
'<td>' +
'<input class="user_input_name" type="text" pattern="[\\w]+"/>' +
'<small class="error">' + Locale.tr("Only word characters are allowed") + '</small>' +
'</td>' +
'<td>' +
'<select class="user_input_type" >' +
'<option value="text">' + Locale.tr("text") + '</option>' +
'<option value="text64">' + Locale.tr("text (base64)") + '</option>' +
'<option value="password">' + Locale.tr("password") + '</option>' +
'</select>' +
'</td>' +
'<td>' +
'<textarea class="user_input_description"/>' +
'</td>' +
'<td>' +
'<a href="#"><i class="fa fa-times-circle remove-tab"></i></a>' +
'</td>' +
'</tr>');
})
context.on("click", ".service_custom_attrs i.remove-tab", function() {
var tr = $(this).closest('tr');
tr.remove();
});
}
function _fillCustomizations(context, customizations) {
@ -238,15 +213,11 @@ define(function(require) {
contextJSON["TOKEN"] = "YES";
}
var userInputsJSON = {};
$(".service_custom_attrs tbody tr", context).each(function() {
if ($(".user_input_name", $(this)).val()) {
var attr_name = $(".user_input_name", $(this)).val();
var attr_type = $(".user_input_type", $(this)).val();
var attr_desc = $(".user_input_description", $(this)).val();
userInputsJSON[attr_name] = "M|" + attr_type + "|" + attr_desc;
contextJSON[attr_name] = "$" + attr_name.toUpperCase();
}
var userInputsJSON = UserInputs.retrieve(context);
$.each(userInputsJSON, function(key,value){
var name = key.toUpperCase();
contextJSON[name] = "$" + name;
});
var start_script = $("#START_SCRIPT", context).val();
@ -296,19 +267,13 @@ define(function(require) {
$("#network_context", context).removeAttr('checked');
if (userInputsJSON) {
$.each(userInputsJSON, function(key, value) {
$(".add_service_custom_attr", context).trigger("click");
UserInputs.fill(context, templateJSON);
var context = $(".service_custom_attrs tbody tr", context).last();
var parts = value.split("|");
$(".user_input_name", context).val(key);
$(".user_input_type", context).val(parts[1]);
$(".user_input_description", context).val(TemplateUtils.escapeDoubleQuotes(TemplateUtils.htmlDecode(parts[2])));
if (contextJSON) {
if (contextJSON) {
$.each(userInputsJSON, function(key, value){
delete contextJSON[key];
}
});
});
}
delete templateJSON['USER_INPUTS'];
}

View File

@ -102,34 +102,13 @@
</div>
<div class="row">
<div class="large-12 columns">
<table class="service_custom_attrs policies_table dataTable">
<thead>
<tr>
<th colspan="4" style="font-size: 16px !important"> <i class="fa fa-lg fa-fw fa-cogs off-color"/>{{tr "User Inputs"}}
{{{tip (tr "These attributes must be provided by the user when a new VM is intantatiated using each template. They will be included in the VM context")}}}
</th>
</tr>
</thead>
<thead>
<tr>
<th style="width:30%">{{tr "Name"}}</th>
<th style="width:20%">{{tr "Type"}}</th>
<th style="width:50%">{{tr "Description"}}</th>
<th style="width:3%"></th>
</tr>
</thead>
<tbody></tbody>
<tfoot>
<tr>
<td colspan="4">
<a href="#" class="add_service_custom_attr button small small-12 secondary radius">
<i class="fa fa-plus"></i>
{{tr "Add another attribute"}}
</a>
</td>
</tr>
</tfoot>
</table>
<i class="fa fa-lg fa-fw fa-cogs off-color"/>{{tr "User Inputs"}}
{{{tip (tr "These attributes must be provided by the user when a new VM is intantatiated using each template. They will be included in the VM context")}}}
</div>
</div>
<div class="row">
<div class="large-12 columns">
{{{userInputsHTML}}}
</div>
</div>
</div>

View File

@ -21,7 +21,7 @@ define(function(require) {
var Locale = require('utils/locale');
var Tips = require('utils/tips');
var CapacityInputs = require('./general/capacity-inputs');
var CapacityCreate = require('./general/capacity-create');
var WizardFields = require('utils/wizard-fields');
var Config = require('sunstone-config');
@ -62,7 +62,7 @@ define(function(require) {
function _html() {
return TemplateHTML({
'capacityInputsHTML': CapacityInputs.html(),
'capacityCreateHTML': CapacityCreate.html(),
'logos': Config.vmLogos
});
}
@ -103,7 +103,7 @@ define(function(require) {
// There is another listener in context.js setup
});
CapacityInputs.setup(context);
CapacityCreate.setup($("div.capacityCreate", context));
}
function _retrieve(context) {
@ -119,9 +119,6 @@ define(function(require) {
}
var sunstone_template = {};
if ($('#sunstone_capacity_select:checked', context).length > 0) {
sunstone_template["CAPACITY_SELECT"] = "NO"
}
if ($('#sunstone_network_select:checked', context).length > 0) {
sunstone_template["NETWORK_SELECT"] = "NO"
@ -131,19 +128,14 @@ define(function(require) {
templateJSON['SUNSTONE'] = sunstone_template;
}
$.extend(templateJSON, CapacityCreate.retrieve($("div.capacityCreate", context)));
return templateJSON;
}
function _fill(context, templateJSON) {
var sunstone_template = templateJSON.SUNSTONE;
if (sunstone_template) {
if (sunstone_template["CAPACITY_SELECT"] &&
sunstone_template["CAPACITY_SELECT"].toUpperCase() == "NO") {
$("#sunstone_capacity_select", context).attr("checked", "checked");
}
delete sunstone_template["CAPACITY_SELECT"];
if (sunstone_template["NETWORK_SELECT"] &&
sunstone_template["NETWORK_SELECT"].toUpperCase() == "NO") {
$("#sunstone_network_select", context).attr("checked", "checked");
@ -182,6 +174,8 @@ define(function(require) {
delete templateJSON["HYPERVISOR"];
}
CapacityCreate.fill($("div.capacityCreate", context), templateJSON);
WizardFields.fill(context, templateJSON);
}
});

View File

@ -0,0 +1,246 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems */
/* */
/* 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. */
/* -------------------------------------------------------------------------- */
define(function(require) {
/*
DEPENDENCIES
*/
require('foundation.slider');
var Locale = require('utils/locale');
var Tips = require('utils/tips');
var WizardFields = require('utils/wizard-fields');
var UserInputs = require('utils/user-inputs');
/*
TEMPLATES
*/
var TemplateHTML = require('hbs!./capacity-create/html');
/*
CONSTRUCTOR
*/
return {
'html': _html,
'setup': _setup,
'fill': _fill,
'retrieve': _retrieve
};
/*
FUNCTION DEFINITIONS
*/
function _html() {
return TemplateHTML();
}
function _setup(context) {
// MB to GB
context.on("input", "div.memory_input input", function(){
if (this.value && this.value >= 0) {
$("div.memory_gb_input input", context).val( this.value / 1024 );
} else {
$("div.memory_gb_input input", context).val("");
}
});
// MB to GB, range input
context.on("input", "div.memory_modify_opt.range input.mb_unit", function(){
var val = this.value.split("..").map(function(e){
if(isNaN(e) || e == ""){
return "";
}
return e / 1024;
}).join("..");
$("div.memory_modify_opt.range input.gb_unit", context).val(val);
});
// MB to GB, list input
context.on("input", "div.memory_modify_opt.list input.mb_unit", function(){
var val = this.value.split(",").map(function(e){
if(isNaN(e) || e == ""){
return "";
}
return e / 1024;
}).join(",");
$("div.memory_modify_opt.list input.gb_unit", context).val(val);
});
// GB to MB
context.on("input", "div.memory_gb_input input", function(){
if (this.value && this.value >= 0) {
$("div.memory_input input", context).val( Math.floor(this.value * 1024) );
} else {
$("div.memory_input input", context).val("");
}
});
// GB to MB, range input
context.on("input", "div.memory_modify_opt.range input.gb_unit", function(){
var val = this.value.split("..").map(function(e){
if(isNaN(e) || e == ""){
return "";
}
return Math.floor(e * 1024);
}).join("..");
$("div.memory_modify_opt.range input.mb_unit", context).val(val);
});
// GB to MB, list input
context.on("input", "div.memory_modify_opt.list input.gb_unit", function(){
var val = this.value.split(",").map(function(e){
if(isNaN(e) || e == ""){
return "";
}
return Math.floor(e * 1024);
}).join(",");
$("div.memory_modify_opt.list input.mb_unit", context).val(val);
});
// Unit select
$("#memory_unit", context).on('change', function() {
var memory_unit_val = $('#memory_unit :selected', context).val();
if (memory_unit_val == 'GB') {
$(".mb_unit", context).hide();
$(".gb_unit", context).show();
} else {
$(".mb_unit", context).show();
$(".gb_unit", context).hide();
}
$(".memory_modify_unit", context).text(memory_unit_val);
});
$("#memory_unit", context).change();
// Select for memory, cpu, vcpu modification on instantiate
$.each(["memory","cpu","vcpu"], function(i,classname){
$("."+classname+"_modify_type", context).on("change", function(){
$("."+classname+"_modify_opt", context).hide();
$("."+classname+"_modify_opt."+this.value, context).show();
$("#memory_unit", context).change();
});
$("."+classname+"_modify_type", context).change();
});
}
/**
* Fills the capacity inputs
* @param {Object} context JQuery selector
* @param {Object} template VM or VMTemplate object
*/
function _fill(context, element) {
var fields = $('[wizard_field]', context);
fields.each(function() {
var field_name = $(this).attr('wizard_field');
$(this).data("original_value", element[field_name]);
});
WizardFields.fill(context, element);
// Update memory_gb with the value set in memory
$("div.memory_input input", context).trigger("input");
if ($("div.memory_input input", context).val() && $("div.memory_input input", context).val() < 1024){
$("#memory_unit", context).val("MB").change();
} else {
$("#memory_unit", context).val("GB").change();
}
var userInputsJSON = element['USER_INPUTS'];
$("[class$=_modify_type]", context).val("fixed").change();
if (userInputsJSON) {
$.each(["memory","cpu","vcpu"], function(i,classname){
var name = classname.toUpperCase();
if (userInputsJSON[name] != undefined){
var attr = UserInputs.unmarshall(userInputsJSON[name]);
$("."+classname+"_modify_type", context).val(attr.type).change();
$("input."+classname+"_modify_opt."+attr.type, context).val(attr.params).trigger("input");
delete userInputsJSON[name];
}
});
}
}
/**
* Retrieves the input values
* @param {Object} context JQuery selector
* @return {Object} If the input is not empty, returns:
* - CPU
* - MEMORY
* - VCPU
* - USER_INPUTS for cpu, memory, vcpu
*/
function _retrieve(context) {
var templateJSON = WizardFields.retrieve(context);
var userInputsJSON = {};
$.each(["memory","cpu","vcpu"], function(i,classname){
var attr = {};
attr.type = $("."+classname+"_modify_type", context).val();
if (attr.type == "fixed"){
// No user input, continue
return true;
}
attr.name = classname.toUpperCase();
attr.mandatory = true;
attr.description = "";
attr.initial = $('input[wizard_field="'+attr.name+'"]', context).val();
if (attr.type == "range" ||
attr.type == "range-float" ||
attr.type == "list"){
attr.params = $("input."+classname+"_modify_opt."+attr.type, context).val();
}
userInputsJSON[attr.name] = UserInputs.marshall(attr);
});
if (!$.isEmptyObject(userInputsJSON)) {
templateJSON['USER_INPUTS'] = userInputsJSON;
}
return templateJSON;
}
});

View File

@ -0,0 +1,148 @@
{{! -------------------------------------------------------------------------- }}
{{! Copyright 2002-2015, OpenNebula Project, OpenNebula Systems }}
{{! }}
{{! 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. }}
{{! -------------------------------------------------------------------------- }}
<div class="row">
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label class="" for="MEMORY">
{{tr "Memory"}}
{{{tip (tr "Amount of RAM required for the VM, in Megabytes.")}}}
</label>
</div>
<div class="small-8 columns">
<div class="mb_unit memory_input">
<input type="number" min="0" step="256" wizard_field="MEMORY" id="MEMORY"/>
</div>
<div class="gb_unit memory_gb_input">
<input type="number" min="0" step="0.25" name="memory_gb"/>
</div>
</div>
<div class="small-4 columns">
<select id="memory_unit" name="MEMORY_UNIT">
<option value="MB">{{tr "MB"}}</option>
<option value="GB" selected>{{tr "GB"}}</option>
</select>
</div>
</div>
</div>
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label>
{{tr "Memory modification"}}
{{{tip (tr "Allow users to modify this template's memory on instantiate")}}}
</label>
</div>
<div class="small-4 columns">
<select class="memory_modify_type" >
<option value="fixed">{{tr "fixed"}}</option>
<option selected value="number">{{tr "number"}}</option>
<option value="range">{{tr "range"}}</option>
<option value="list">{{tr "list"}}</option>
</select>
</div>
<div class="small-6 columns">
<div class="memory_modify_opt range">
<input type=text class="mb_unit memory_modify_opt range" placeholder="512..4096"/>
<input type=text class="gb_unit" placeholder="0.5..4"/>
</div>
<div class="memory_modify_opt list">
<input type=text class="mb_unit memory_modify_opt list" placeholder="1024,4096,8192"/>
<input type=text class="gb_unit" placeholder="1,4,8"/>
</div>
</div>
<div class="small-2 columns">
<span class="memory_modify_opt range list memory_modify_unit">
</span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label class="" for="CPU">
{{tr "CPU"}}
{{{tip (tr "Percentage of CPU divided by 100 required for the Virtual Machine. Half a processor is written 0.5.")}}}
</label>
<div class="cpu_input">
<input type="number" step="0.01" min="0" wizard_field="CPU" id="CPU"/>
</div>
</div>
</div>
</div>
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label>
{{tr "CPU modification"}}
{{{tip (tr "Allow users to modify this template's CPU on instantiate")}}}
</label>
</div>
<div class="small-4 columns">
<select class="cpu_modify_type" >
<option value="fixed">{{tr "fixed"}}</option>
<option selected value="number-float">{{tr "number"}}</option>
<option value="range">{{tr "range"}}</option>
<option value="list">{{tr "list"}}</option>
</select>
</div>
<div class="small-8 columns">
<input type=text class="cpu_modify_opt range" placeholder="0.5..8"/>
<input type=text class="cpu_modify_opt list" placeholder="0.5,1,4,16"/>
</div>
</div>
</div>
</div>
<div class="row">
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label class="" for="VCPU">
{{tr "VCPU"}}
{{{tip (tr "Number of virtual cpus. This value is optional, the default hypervisor behavior is used, usually one virtual CPU.")}}}
</label>
<div class="vcpu_input">
<input type="number" step="1" min="0" wizard_field="VCPU" id="VCPU"/>
</div>
</div>
</div>
</div>
<div class="medium-6 small-12 columns">
<div class="row">
<div class="small-12 columns">
<label>
{{tr "VCPU modification"}}
{{{tip (tr "Allow users to modify this template's VCPU on instantiate")}}}
</label>
</div>
<div class="small-4 columns">
<select class="vcpu_modify_type" >
<option value="fixed">{{tr "fixed"}}</option>
<option selected value="number">{{tr "number"}}</option>
<option value="range">{{tr "range"}}</option>
<option value="list">{{tr "list"}}</option>
</select>
</div>
<div class="small-8 columns">
<input type=text class="vcpu_modify_opt range" placeholder="1..8"/>
<input type=text class="vcpu_modify_opt list" placeholder="4,8,16"/>
</div>
</div>
</div>
</div>

View File

@ -23,6 +23,7 @@ define(function(require) {
var Locale = require('utils/locale');
var Tips = require('utils/tips');
var WizardFields = require('utils/wizard-fields');
var UserInputs = require('utils/user-inputs');
/*
TEMPLATES
@ -40,7 +41,7 @@ define(function(require) {
'setCallback': _setCallback,
'fill': _fill,
'retrieve': _retrieve,
'retrieveResize': _retrieveResize
'retrieveChanges': _retrieveChanges
};
/*
@ -52,139 +53,42 @@ define(function(require) {
}
function _setup(context) {
// Define the cpu slider
var cpu_input = $("#CPU", context);
var cpu_slider = $("#cpu_slider", context)
// MB to GB
$("div.memory_input", context).on("input", "input, select", function(){
var val = "";
context.foundation('slider', 'reflow');
//cpu_slider.attr('data-options', 'start: 0; end: 1600; step: 50;');
cpu_slider.on('change.fndtn.slider', function(){
if ($(this).attr('data-slider') >= 0) {
cpu_input.val($(this).attr('data-slider') / 100);
}
});
cpu_input.on('change', function() {
if (this.value && this.value >= 0) {
cpu_slider.foundation('slider', 'set_value', this.value * 100);
} else {
cpu_slider.foundation('slider', 'set_value', -1);
val = this.value / 1024;
}
$("input, select", $("div.memory_gb_input", context)).val(val);
});
cpu_slider.foundation('slider', 'set_value', 100);
// GB to MB
$("div.memory_gb_input", context).on("input", "input, select", function(){
var val = "";
// Define the memory slider
var final_memory_input = $("#MEMORY", context);
var memory_input = $("#MEMORY_TMP", context);
var memory_unit = $("#memory_unit", context);
var current_memory_unit = memory_unit.val();
var update_final_memory_input = function() {
if (current_memory_unit == 'MB') {
final_memory_input.val(Math.floor(memory_input.val()));
} else {
final_memory_input.val(Math.floor(memory_input.val() * 1024));
}
}
memory_input.on('change', function() {
if (this.value && this.value >= 0) {
$("#memory_slider", context).foundation('slider', 'set_value', this.value * 100);
update_final_memory_input();
} else {
$("#memory_slider", context).foundation('slider', 'set_value', -1);
final_memory_input.val("");
val = Math.floor(this.value * 1024);
}
$("input, select", $("div.memory_input", context)).val(val);
});
final_memory_input.on('change', function() {
if (this.value && this.value >= 0) {
$("#memory_slider", context).foundation('slider', 'set_value', this.value * 100);
memory_input.val(Math.floor(this.value));
} else {
$("#memory_slider", context).foundation('slider', 'set_value', -1);
memory_input.val("");
}
});
$("#memory_slider", context).on('change.fndtn.slider', function() {
if ($(this).attr('data-slider') >= 0) {
memory_input.val($(this).attr('data-slider') / 100);
update_final_memory_input();
}
});
memory_unit.on('change', function() {
// Unit select
$("#memory_unit", context).on('change', function() {
var memory_unit_val = $('#memory_unit :selected', context).val();
if (current_memory_unit != memory_unit_val) {
current_memory_unit = memory_unit_val
var new_val;
if (memory_unit_val == 'GB') {
$("#memory_slider", context).detach();
$(".memory_slider_container", context).html(
'<div id="memory_slider" class="range-slider radius" data-slider data-options="start: 0; end: 1600; step: 50;">'+
'<span class="range-slider-handle"></span>'+
'<span class="range-slider-active-segment"></span>'+
'<input type="hidden">'+
'</div>');
new_val = memory_input.val() / 1024;
} else if (memory_unit_val == 'MB') {
$("#memory_slider", context).detach();
$(".memory_slider_container", context).html(
'<div id="memory_slider" class="range-slider radius" data-slider data-options="start: 0; end: 409600; step: 12800;">'+
'<span class="range-slider-handle"></span>'+
'<span class="range-slider-active-segment"></span>'+
'<input type="hidden">'+
'</div>');
new_val = Math.floor(memory_input.val() * 1024);
}
$("#memory_slider", context).foundation('slider', 'reflow');
memory_input.val(new_val);
$("#memory_slider", context).foundation('slider', 'set_value', new_val * 100);
$("#memory_slider", context).on('change.fndtn.slider', function() {
if ($(this).attr('data-slider') >= 0) {
memory_input.val($(this).attr('data-slider') / 100);
update_final_memory_input();
}
});
update_final_memory_input();
}
});
// init::start is ignored for some reason
$("#memory_slider", context).foundation('slider', 'set_value', 51200);
// Define the vcpu slider
var vcpu_input = $("#VCPU", context);
var vcpu_slider = $("#vcpu_slider", context)
//vcpu_slider.attr('data-options', 'start: 0; end: 1600; step: 50;');
vcpu_slider.on('change.fndtn.slider', function(){
if ($(this).attr('data-slider') > 0) {
vcpu_input.val($(this).attr('data-slider') / 100);
}
});
vcpu_input.on('change', function() {
if (this.value && this.value > 0) {
vcpu_slider.foundation('slider', 'set_value', this.value * 100);
if (memory_unit_val == 'GB') {
$("div.memory_input", context).hide();
$("div.memory_gb_input", context).show();
} else {
vcpu_slider.foundation('slider', 'set_value', -1);
$("div.memory_input", context).show();
$("div.memory_gb_input", context).hide();
}
});
vcpu_slider.foundation('slider', 'set_value', 0);
$("#memory_unit", context).change();
}
/**
@ -200,7 +104,84 @@ define(function(require) {
$(this).data("original_value", element.TEMPLATE[field_name]);
});
var userInputs;
if (element.USER_TEMPLATE != undefined){
userInputs = element.USER_TEMPLATE.USER_INPUTS;
} else {
userInputs = element.TEMPLATE.USER_INPUTS;
}
if (userInputs != undefined){
if (userInputs.CPU != undefined){
var attr = UserInputs.parse("CPU", userInputs.CPU);
if (element.TEMPLATE.CPU != undefined){
attr.initial = element.TEMPLATE.CPU;
}
var input = UserInputs.attributeInput(attr);
$("div.cpu_input", context).html(input);
}
if (userInputs.VCPU != undefined){
var attr = UserInputs.parse("VCPU", userInputs.VCPU);
if (element.TEMPLATE.VCPU != undefined){
attr.initial = element.TEMPLATE.VCPU;
}
var input = UserInputs.attributeInput(attr);
$("div.vcpu_input", context).html(input);
}
if (userInputs.MEMORY != undefined){
// Normal input for MB
var attr = UserInputs.parse("MEMORY", userInputs.MEMORY);
var input = UserInputs.attributeInput(attr);
$("div.memory_input", context).html(input);
// Modified input for GB
var attr_gb = UserInputs.parse("MEMORY", userInputs.MEMORY);
attr_gb.initial = attr_gb.initial / 1024;
if (attr_gb.type == "range"){
attr_gb.type = "range-float";
attr_gb.min = (attr_gb.min / 1024);
attr_gb.max = (attr_gb.max / 1024);
attr_gb.step = "any";
} else if (attr_gb.type == "list"){
attr_gb.options = attr_gb.options.map(function(e){
return e / 1024;
});
} else if (attr_gb.type == "number"){
attr_gb.type = "number-float";
attr_gb.step = "any";
}
input = UserInputs.attributeInput(attr_gb);
$("div.memory_gb_input", context).html(input);
$("input, select", $("div.memory_gb_input", context)).removeAttr("wizard_field");
}
}
WizardFields.fill(context, element.TEMPLATE);
// Update memory_gb with the value set in memory
$("input, select", $("div.memory_input", context)).trigger("input");
if ($("input, select", $("div.memory_input", context)).val() >= 1024){
$("#memory_unit", context).val("GB").change();
} else {
$("#memory_unit", context).val("MB").change();
}
}
/**
@ -209,9 +190,11 @@ define(function(require) {
* @param {Function} callback will be called as callback( retrieve(context) )
*/
function _setCallback(context, callback) {
context.on("change.fndtn.slider", function(){
context.on("input", function(){
callback( _retrieve(context) );
});
callback( _retrieve(context) );
}
/**
@ -235,7 +218,7 @@ define(function(require) {
* - MEMORY
* - VCPU
*/
function _retrieveResize(context) {
function _retrieveChanges(context) {
var templateJSON = WizardFields.retrieve(context);
var fields = $('[wizard_field]', context);

View File

@ -16,70 +16,45 @@
<div class="row">
<div class="large-12 columns">
<div class="">
<input type="hidden" wizard_field="MEMORY" id="MEMORY" name="memory" />
<label class="" for="MEMORY">
{{tr "Memory"}}
{{{tip (tr "Amount of RAM required for the VM, in Megabytes.")}}}
</label>
</div>
<div class="small-10 columns">
<div class="memory_input">
<input type="number" min="0" step="256" wizard_field="MEMORY" id="MEMORY" disabled/>
</div>
<div class="large-12 columns">
<label class="" for="MEMORY">
{{tr "Memory"}}
{{{tip (tr "Amount of RAM required for the VM, in Megabytes.")}}}
</label>
<div class="memory_gb_input">
<input type="number" min="0" step="0.25" name="memory_gb" disabled/>
</div>
<div class="medium-8 columns memory_slider_container">
<div id="memory_slider" class="range-slider radius" data-slider data-options="start: 0; end: 409600; step: 12800;">
<span class="range-slider-handle"></span>
<span class="range-slider-active-segment"></span>
<input type="hidden">
</div>
</div>
<div class="medium-2 small-6 columns">
<input type="text" id="MEMORY_TMP" name="memory_tmp" size="4" />
</div>
<div class="medium-2 small-6 columns">
<select id="memory_unit" name="MEMORY_UNIT">
<option value="MB">{{tr "MB"}}</option>
<option value="GB">{{tr "GB"}}</option>
</select>
</div>
<div class="small-2 columns">
<select id="memory_unit" name="MEMORY_UNIT">
<option value="MB">{{tr "MB"}}</option>
<option value="GB" selected>{{tr "GB"}}</option>
</select>
</div>
</div>
<div class="row">
<div class="small-12 columns">
<label class="" for="CPU">
{{tr "CPU"}}
{{{tip (tr "Percentage of CPU divided by 100 required for the Virtual Machine. Half a processor is written 0.5.")}}}
</label>
<div class="cpu_input">
<input type="number" step="0.01" min="0" wizard_field="CPU" id="CPU" disabled/>
</div>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<div class="large-12 columns">
<label class="" for="CPU">
{{tr "CPU"}}
{{{tip (tr "Percentage of CPU divided by 100 required for the Virtual Machine. Half a processor is written 0.5.")}}}
</label>
</div>
<div class="large-10 medium-10 columns">
<div id="cpu_slider" class="range-slider radius" data-slider data-options="start: 0; end: 1600; step: 50;">
<span class="range-slider-handle"></span>
<span class="range-slider-active-segment"></span>
<input type="hidden">
</div>
</div>
<div class="large-2 medium-2 columns">
<input type="text" wizard_field="CPU" id="CPU" name="cpu"/>
<div class="small-12 columns">
<label class="" for="VCPU">
{{tr "VCPU"}}
{{{tip (tr "Number of virtual cpus. This value is optional, the default hypervisor behavior is used, usually one virtual CPU.")}}}
</label>
<div class="vcpu_input">
<input type="number" step="1" min="0" wizard_field="VCPU" id="VCPU" disabled/>
</div>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<div class="large-12 columns">
<label class="" for="VCPU">
{{tr "VCPU"}}
{{{tip (tr "Number of virtual cpus. This value is optional, the default hypervisor behavior is used, usually one virtual CPU.")}}}
</label>
</div>
<div class="large-10 medium-10 columns">
<div id="vcpu_slider" class="range-slider radius" data-slider data-options="start: 100; end: 1600; step: 100;">
<span class="range-slider-handle"></span>
<span class="range-slider-active-segment"></span>
<input type="hidden">
</div>
</div>
<div class="large-2 medium-2 columns">
<input type="text" wizard_field="VCPU" id="VCPU" name="vcpu"/>
</div>
</div>
</div>
</div>

View File

@ -81,11 +81,13 @@
</div>
</div>
<div class="row">
<div class="large-7 columns">
{{{capacityInputsHTML}}}
<div class="capacityCreate large-12 columns">
{{{capacityCreateHTML}}}
</div>
<div class="large-5 columns">
{{#isFeatureEnabled "showback"}}
</div>
{{#isFeatureEnabled "showback"}}
<div class="row">
<div class="medium-6 columns">
<fieldset>
<legend>{{tr "Cost"}}</legend>
<div class="medium-6 columns">
@ -110,18 +112,9 @@
<input type="text" wizard_field="DISK_COST" id="DISK_COST" name="name"/>
</div>
</fieldset>
{{/isFeatureEnabled}}
</div>
</div>
<div class="row">
<div class="large-6 columns">
<input type="checkbox" id="sunstone_capacity_select" name="name"/>
<label for="sunstone_capacity_select">
{{tr "Do not allow to change capacity"}}
{{{tip (tr "Users using the cloud view will not be able to select a new capacity for this template")}}}
</label>
</div>
</div>
{{/isFeatureEnabled}}
<div class="row">
<div class="large-6 columns">
<input type="checkbox" id="sunstone_network_select" name="name"/>

View File

@ -125,7 +125,7 @@ define(function(require) {
}
capacityContext = $(".capacityContext" + template_id, context);
$.extend(tmp_json, CapacityInputs.retrieveResize(capacityContext));
$.extend(tmp_json, CapacityInputs.retrieveChanges(capacityContext));
extra_info['template'] = tmp_json;
@ -209,31 +209,23 @@ define(function(require) {
}
if ((cpuCost != 0 || memoryCost != 0) && Config.isFeatureEnabled("showback")) {
var cost = 0;
var cpu = template_json.VMTEMPLATE.TEMPLATE.CPU;
var memory = template_json.VMTEMPLATE.TEMPLATE.MEMORY;
if (cpu != undefined && memory != undefined) {
cost = cpuCost * cpu + memoryCost * memory;
}
$(".cost_value", capacityContext).html(cost.toFixed(2));
$(".capacity_cost_div", capacityContext).show();
CapacityInputs.setCallback(capacityContext, function(values){
var cost = cpuCost * values.CPU + memoryCost * values.MEMORY;
var cost = 0;
if (values.CPU != undefined){
cost += cpuCost * values.CPU;
}
if (values.MEMORY != undefined){
cost += memoryCost * values.MEMORY;
}
$(".cost_value", capacityContext).html(cost.toFixed(2));
});
}
if (template_json.VMTEMPLATE.TEMPLATE.SUNSTONE &&
template_json.VMTEMPLATE.TEMPLATE.SUNSTONE.CAPACITY_SELECT &&
template_json.VMTEMPLATE.TEMPLATE.SUNSTONE.CAPACITY_SELECT.toUpperCase() == "NO"){
capacityContext.hide();
}
idsDone += 1;
if (idsLength == idsDone){
Sunstone.enableFormPanelSubmit(TAB_ID);

View File

@ -21,6 +21,7 @@ define(function(require) {
var DataTable = require('./datatable');
var OpenNebulaResource = require('opennebula/user');
var CommonActions = require('utils/common-actions');
var TemplateUtils = require('utils/template-utils');
var TAB_ID = require('./tabId');
var CREATE_DIALOG_ID = require('./form-panels/create/formPanelId');
@ -163,6 +164,28 @@ define(function(require) {
error: Notifier.onError
},
"User.append_sunstone_setting_refresh" : {
type: "single",
call: function(params){
OpenNebulaResource.show({
data : {
id: params.data.id
},
success: function(request, response) {
var sunstone_template = {};
if (response[XML_ROOT].TEMPLATE.SUNSTONE) {
$.extend(sunstone_template, response[XML_ROOT].TEMPLATE.SUNSTONE);
}
$.extend(sunstone_template, params.data.extra_param)
var template_str = TemplateUtils.templateToString({'SUNSTONE': sunstone_template});
Sunstone.runAction("User.append_template_refresh", params.data.id, template_str);
},
error: Notifier.onError
});
}
},
"User.fetch_quotas" : {
type: "single",
call: OpenNebulaResource.show,

View File

@ -170,14 +170,8 @@ define(function(require) {
context.off("change", "#table_order_select")
context.on("change", "#table_order_select", function() {
var sunstone_template = {};
if (that.element.TEMPLATE.SUNSTONE) {
$.extend(sunstone_template, that.element.TEMPLATE.SUNSTONE);
}
sunstone_template.TABLE_ORDER = $(this).val();
var template_str = TemplateUtils.templateToString({'SUNSTONE': sunstone_template});
Sunstone.runAction("User.append_template_refresh", that.element.ID, template_str);
var sunstone_setting = {TABLE_ORDER : $(this).val()};
Sunstone.runAction("User.append_sunstone_setting_refresh", that.element.ID, sunstone_setting);
});
// Change language
@ -194,14 +188,8 @@ define(function(require) {
context.off("change", "#language_select")
context.on("change", "#language_select", function() {
var sunstone_template = {};
if (that.element.TEMPLATE.SUNSTONE) {
$.extend(sunstone_template, that.element.TEMPLATE.SUNSTONE);
}
sunstone_template.LANG = $(this).val();
var template_str = TemplateUtils.templateToString({'SUNSTONE': sunstone_template});
Sunstone.runAction("User.append_template_refresh", that.element.ID, template_str);
var sunstone_setting = {LANG : $(this).val()};
Sunstone.runAction("User.append_sunstone_setting_refresh", that.element.ID, sunstone_setting);
});
// Change view
@ -223,14 +211,8 @@ define(function(require) {
context.off("change", "#view_select")
context.on("change", "#view_select", function() {
var sunstone_template = {};
if (that.element.TEMPLATE.SUNSTONE) {
$.extend(sunstone_template, that.element.TEMPLATE.SUNSTONE);
}
sunstone_template.DEFAULT_VIEW = $(this).val();
var template_str = TemplateUtils.templateToString({'SUNSTONE': sunstone_template});
Sunstone.runAction("User.append_template_refresh", that.element.ID, template_str);
var sunstone_setting = {DEFAULT_VIEW : $(this).val()};
Sunstone.runAction("User.append_sunstone_setting_refresh", that.element.ID, sunstone_setting);
});
return false;

View File

@ -72,7 +72,7 @@ define(function(require) {
Tips.setup(context);
$('#' + DIALOG_ID + 'Form', context).submit(function() {
var templateJSON = CapacityInputs.retrieveResize(context);
var templateJSON = CapacityInputs.retrieveChanges(context);
var enforce = $("#enforce", this).is(":checked");

View File

@ -97,7 +97,8 @@ define(function(require) {
type: "multiple",
call : that.openNebulaResource.del,
callback : function(request, response) {
Sunstone.getDataTable(that.tabId).deleteElement(request, response);
var elementId = request.request.data.toString();
Sunstone.getDataTable(that.tabId).deleteElement(elementId);
},
elements: function() {
return Sunstone.getDataTable(that.tabId).elements();

View File

@ -268,9 +268,9 @@ define(function(require) {
this.dataTable.fnAddData(element);
}
//deletes an element with id 'tag' from a dataTable
function _deleteElement(req) {
var tag = '#' + this.resource.toLowerCase() + '_' + req.request.data;
//deletes an element with id 'elementId' from a dataTable
function _deleteElement(elementId) {
var tag = '#' + this.resource.toLowerCase() + '_' + elementId;
var tr = $(tag, this.dataTable).parents('tr')[0];
this.dataTable.fnDeleteRow(tr);
this.recountCheckboxes();

View File

@ -19,13 +19,118 @@ define(function(require) {
var TemplateUtils = require('utils/template-utils');
var VNetsTable = require('tabs/vnets-tab/datatable');
var TemplateHTML = require('hbs!./user-inputs/table');
var RowTemplateHTML = require('hbs!./user-inputs/row');
//==============================================================================
// VM & Service user inputs
//==============================================================================
return {
// User inputs edition
'html': _html,
'setup': _setup,
'fill': _fill,
'retrieve': _retrieve,
// Instantiate
'vmTemplateInsert': _generateVMTemplateUserInputs,
'serviceTemplateInsert': _generateServiceTemplateUserInputs
'serviceTemplateInsert': _generateServiceTemplateUserInputs,
// Utils
'marshall': _marshall,
'unmarshall': _unmarshall,
'parse': _parse,
'generateInputElement': _generateInputElement,
'attributeInput': _attributeInput
};
function _html(){
return TemplateHTML();
}
function _setup(context){
context.on("click", ".add_user_input_attr", function() {
$(".user_input_attrs tbody", context).append(RowTemplateHTML());
$("select.user_input_type", context).change();
});
context.on("change", "select.user_input_type", function() {
var row = $(this).closest("tr");
$(".user_input_type_right", row).hide();
$(".user_input_type_right."+this.value, row).show();
});
context.on("click", ".user_input_attrs i.remove-tab", function() {
$(this).closest('tr').remove();
});
}
function _retrieve(context){
var userInputsJSON = {};
$(".user_input_attrs tbody tr", context).each(function() {
if ($(".user_input_name", $(this)).val()) {
var attr = {};
attr.name = $(".user_input_name", $(this)).val();
attr.mandatory = true;
attr.type = $(".user_input_type", $(this)).val();
attr.description = $(".user_input_description", $(this)).val();
switch(attr.type){
case "number":
case "number-float":
attr.initial = $("."+attr.type+" input.user_input_initial", $(this)).val();
break;
case "range":
case "range-float":
case "list":
attr.params = $("."+attr.type+" input.user_input_params", $(this)).val();
attr.initial = $("."+attr.type+" input.user_input_initial", $(this)).val();
break;
}
userInputsJSON[attr.name] = _marshall(attr);
}
});
return userInputsJSON;
}
function _fill(context, templateJSON){
var userInputsJSON = templateJSON['USER_INPUTS'];
if (userInputsJSON) {
$.each(userInputsJSON, function(key, value) {
$(".add_user_input_attr", context).trigger("click");
var trcontext = $(".user_input_attrs tbody tr", context).last();
$(".user_input_name", trcontext).val(key);
var attr = _unmarshall(value);
$(".user_input_type", trcontext).val(attr.type).change();
$(".user_input_description", trcontext).val(attr.description);
switch(attr.type){
case "number":
case "number-float":
$("."+attr.type+" input.user_input_initial", trcontext).val(attr.initial);
break;
case "range":
case "range-float":
case "list":
$("."+attr.type+" input.user_input_params", trcontext).val(attr.params);
$("."+attr.type+" input.user_input_initial", trcontext).val(attr.initial);
break;
}
});
}
}
// It will replace the div's html with a row for each USER_INPUTS
@ -33,8 +138,14 @@ define(function(require) {
// opts.network_header: header text for the network inputs
// returns true if at least one input was inserted
function _generateVMTemplateUserInputs(div, template_json, opts) {
return _generateInstantiateUserInputs(
div, template_json.VMTEMPLATE.TEMPLATE.USER_INPUTS, opts);
// Delete the special user inputs for the capacity
var inputs = $.extend({}, template_json.VMTEMPLATE.TEMPLATE.USER_INPUTS);
delete inputs["CPU"];
delete inputs["MEMORY"];
delete inputs["VCPU"];
return _generateInstantiateUserInputs(div, inputs, opts);
}
// It will replace the div's html with a row for each USER_INPUTS
@ -70,27 +181,15 @@ define(function(require) {
}
var network_attrs = [];
var text_attrs = [];
var input_attrs = [];
$.each(user_inputs, function(key, value) {
var parts = value.split("|");
// 0 mandatory; 1 type; 2 desc;
var attrs = {
"name": key,
"mandatory": parts[0],
"type": parts[1],
"description": parts[2],
}
var attrs = _parse(key, value);
switch (parts[1]) {
case "vnet_id":
network_attrs.push(attrs)
break;
case "text":
case "text64":
case "password":
text_attrs.push(attrs)
break;
if (attrs.type == "vnet_id"){
network_attrs.push(attrs);
} else {
input_attrs.push(attrs);
}
});
@ -137,7 +236,7 @@ define(function(require) {
});
}
if (text_attrs.length > 0) {
if (input_attrs.length > 0) {
if (opts.text_header.length > 0) {
div.append(
'<br>' +
@ -152,33 +251,229 @@ define(function(require) {
div.append('<div class="instantiate_user_inputs"/>');
$.each(text_attrs, function(index, custom_attr) {
var input;
switch (custom_attr.type) {
case "text":
input = '<textarea type="text" rows="1" wizard_field="' + custom_attr.name + '" required/>';
break;
case "text64":
input = '<textarea type="text" rows="1" wizard_field_64="true" wizard_field="' + custom_attr.name + '" required/>';
break;
case "password":
input = '<input type="password" wizard_field="' + custom_attr.name + '" required/>';
break;
}
$.each(input_attrs, function(index, custom_attr) {
$(".instantiate_user_inputs", div).append(
'<div class="row">' +
'<div class="large-12 large-centered columns">' +
'<label>' +
TemplateUtils.htmlDecode(custom_attr.description) +
input +
_attributeInput(custom_attr) +
'</label>' +
'</div>' +
'</div>');
});
}
return (network_attrs.length > 0 || text_attrs.length > 0);
return (network_attrs.length > 0 || input_attrs.length > 0);
}
})
/**
* Transforms a user input object to a string
* @param {object} attr user input object, e.g.
* { "name":
* "mandatory": true/false
* "type":
* "description":
* ["params":] "2..8" / "2,4,8"
* ["initial":] "3"
* }
* @return {string} String in the form "M|range|Description here|2..8|4"
*/
function _marshall(attr) {
var st = "";
st += (attr.mandatory ? "M" : "O") + "|" +
(attr.type != undefined ? attr.type : "text") + "|" +
(attr.description != undefined ? attr.description : "");
switch (attr.type) {
case "number":
case "number-float":
st += ("| |" + (attr.initial != undefined ? attr.initial : "") );
break;
case "range":
case "range-float":
case "list":
st += ("|" + (attr.params != undefined ? attr.params : "") +
"|" + (attr.initial != undefined ? attr.initial : "") );
break;
}
return st;
}
/**
* Transforms a user input string to an object
* @param {string} value String in the form "M|range|Description here|2..8|4"
* @return {object} user input object, e.g.
* { "mandatory": true/false
* "type":
* "description":
* ["params":] "2..8" / "2,4,8"
* ["initial":] "3"
* }
*/
function _unmarshall(value) {
var parts = value.split("|");
var attr = {
"mandatory": (parts[0] == "M"),
"type": parts[1],
"description": parts[2],
};
if (parts[3] != undefined){
attr.params = parts[3];
}
if (parts[4] != undefined){
attr.initial = parts[4];
}
return attr;
}
/**
* Returns a structure with the user input parameters
* @param {string} name Template Attribute name, e.g. USER_PASSWORD
* @param {string} value Template Attribute value,
* e.g. "M|range|Description here|2..8|4"
* @return {object} { "name":
"mandatory":
"type":
"description":
["params":] "2..8" / "2,4,8"
["initial":]
["min":]
["max":]
["step":]
["options":]
}
*/
function _parse(name, value) {
var attr = _unmarshall(value);
attr.name = name;
// TODO: error management (params undefined)
switch (attr.type) {
case "number":
attr.step = "1";
break;
case "number-float":
attr.step = "any";
break;
case "range":
var params = attr.params.split(".."); // "2..8"
attr.min = parseInt( params[0] );
attr.max = parseInt( params[1] );
attr.step = "1";
break;
case "range-float":
var params = attr.params.split(".."); // "2.4..8.75"
attr.min = parseFloat( params[0] );
attr.max = parseFloat( params[1] );
attr.step = "any";
break;
case "list":
attr.options = attr.params.split(","); // "2,4,16"
break;
}
return attr;
}
/**
* Returns an html <input> for the given user input attribute
* @param {object} attr structure as returned by parse
* @return {string} string containing an html <input> element
*/
function _attributeInput(attr) {
var input;
switch (attr.type) {
case "text":
input = '<textarea type="text" rows="1" wizard_field="' + attr.name + '" required/>';
break;
case "text64":
input = '<textarea type="text" rows="1" wizard_field_64="true" wizard_field="' + attr.name + '" required/>';
break;
case "password":
input = '<input type="password" wizard_field="' + attr.name + '" required/>';
break;
case "number":
case "number-float":
input = '<input type="number" step="'+attr.step+'" value="'+attr.initial+'" wizard_field="' + attr.name + '" required/>';
break;
case "range":
case "range-float":
input =
'<div class="row uinput-slider-container">'+
'<div class="small-8 columns">'+
'<input type="range" class="uinput-slider" style="width:100%"'+
'min="'+attr.min+'" max="'+attr.max+'" step="'+attr.step+'" '+
'value="'+attr.initial+'"/>'+
'</div>'+
'<div class="small-4 columns">'+
'<input type="number" class="uinput-slider-val" '+
'min="'+attr.min+'" max="'+attr.max+'" step="'+attr.step+'" '+
'value="'+attr.initial+'" wizard_field="' + attr.name + '" required/>'+
'</div>'+
'</div>';
$(document).off("input", "input.uinput-slider-val");
$(document).on("input", "input.uinput-slider-val", function(){
$("input[type=range]", $(this).closest('.uinput-slider-container')).val( this.value );
});
$(document).off("input", "input.uinput-slider");
$(document).on("input", "input.uinput-slider", function(){
$("input[type=number]", $(this).closest('.uinput-slider-container')).val( this.value );
});
break;
case "list":
input = '<select wizard_field="' + attr.name + '" required>';
$.each(attr.options, function(){
var selected = (attr.initial == this);
input += '<option value="'+this+'" '+
(selected? 'selected' : '')+'>'+
this+
'</option>';
});
input += '</select>';
break;
}
return input;
}
/**
* Returns an html <input> for the given USER_INPUT attribute
* @param {string} name Template Attribute name, e.g. USER_PASSWORD
* @param {string} value Template Attribute value,
* e.g. "M|range|Description here|2..8|4"
* @return {string} string containing an html <input> element
*/
function _generateInputElement(name, value) {
var attrs = _parse(name, value);
return _attributeInput(attrs);
}
});

View File

@ -0,0 +1,52 @@
<tr>
<td>
<label>{{tr "Name"}}
<input class="user_input_name" type="text" pattern="[^\w+$]+"/>
<small class="error">{{tr "Can only contain alphanumeric and underscore characters"}}</small>
</label>
</td>
<td>
<label>{{tr "Type"}}
<select class="user_input_type" >
<option value="text"> {{tr "text"}} </option>
<option value="text64"> {{tr "text (base64)"}} </option>
<option value="password"> {{tr "password"}} </option>
<option value="number"> {{tr "number"}} </option>
<option value="number-float"> {{tr "number (float)"}} </option>
<option value="range"> {{tr "range"}} </option>
<option value="range-float"> {{tr "range (float)"}} </option>
<option value="list"> {{tr "list"}} </option>
</select>
</label>
</td>
<td>
<label>{{tr "Description"}}
<textarea class="user_input_description"/>
</label>
<div class="user_input_type_right number number-float">
<label class="user_input_opt">{{tr "Default value"}}
<input type=text class="user_input_initial" placeholder="42"/>
</label>
</div>
<div class="user_input_type_right range range-float">
<label class="user_input_opt">{{tr "Options"}}
<input type=text class="user_input_params" placeholder="2..16"/>
</label>
<label class="user_input_opt">{{tr "Default value"}}
<input type=text class="user_input_initial" placeholder="8"/>
</label>
</div>
<div class="user_input_type_right list">
<label class="user_input_opt">{{tr "Options"}}
<input type=text class="user_input_params" placeholder="optA,optB,optC"/>
</label>
<label class="user_input_opt">{{tr "Default value"}}
<input type=text class="user_input_initial" placeholder="optB"/>
</label>
</div>
</td>
<td>
</br>
<a href="#"><i class="fa fa-times-circle remove-tab"></i></a>
</td>
</tr>

View File

@ -0,0 +1,22 @@
<table class="user_input_attrs policies_table dataTable">
<thead>
<tr>
<th style="width:30%"></th>
<th style="width:20%"></th>
<th style="width:50%"></th>
<th style="width:3%"></th>
</tr>
</thead>
<tbody style="vertical-align:top">
</tbody>
<tfoot>
<tr>
<td colspan="4">
<a href="#" class="add_user_input_attr button small small-12 secondary radius">
<i class="fa fa-plus"></i>
{{tr "Add another attribute"}}
</a>
</td>
</tr>
</tfoot>
</table>

View File

@ -1476,4 +1476,14 @@ div.vis-network-tooltip {
background: #bfbfbf;
}
}
}
// For abide validation
.error input {
border-bottom-color: $alert-color !important;
}
.error textarea {
border-bottom-color: $alert-color !important;
}

View File

@ -295,10 +295,6 @@ helpers do
session.clear
return [204, ""]
end
def cloud_view_instance_types
$conf[:instance_types] || []
end
end
before do

View File

@ -41,7 +41,6 @@
'user_gid' : '<%= session[:user_gid] %>',
'display_name' : '<%= session[:display_name] %>',
'zone_name' : '<%= session[:zone_name] %>',
'instance_types' : JSON.parse('<%= cloud_view_instance_types().to_json %>'),
'page_length' : '<%= session[:page_length] %>',
'vm_logos' : <%= logos_conf.to_json %>,
'oned_conf' : <%= oned_conf.to_json %>

View File

@ -257,3 +257,34 @@ bool VMTemplate::is_vrouter()
return vr;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
vector<int> VMTemplate::get_img_ids()
{
vector<int> img_ids;
// TODO: xpaths(vector<int>..) is not working
//xpaths(img_ids,"/VMTEMPLATE/TEMPLATE/DISK/IMAGE_ID");
vector<string> img_ids_st;
vector<string>::iterator it;
xpaths(img_ids_st,"/VMTEMPLATE/TEMPLATE/DISK/IMAGE_ID");
for (it = img_ids_st.begin(); it != img_ids_st.end(); it++)
{
istringstream iss(*it);
int val;
iss >> dec >> val;
if (!iss.fail())
{
img_ids.push_back( val );
}
}
return img_ids;
}