1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-25 23:21:29 +03:00

Merge branch 'feature-1712'

Conflicts:
	src/scheduler/src/pool/HostXML.cc
This commit is contained in:
Ruben S. Montero 2013-10-04 15:00:44 +02:00
commit 5899820844
43 changed files with 2402 additions and 1100 deletions

View File

@ -30,17 +30,6 @@ using namespace std;
class Cluster : public PoolObjectSQL
{
public:
/**
* Returns the SYSTEM_DS attribute
*
* @return the SYSTEM_DS attribute
*/
int get_ds_id()
{
return system_ds;
}
/**
* Returns the DATASTORE_LOCATION for the hosts of the cluster. If not
* defined that in oned.conf is returned.
@ -107,6 +96,20 @@ public:
*/
int del_datastore(int id, string& error_msg);
/**
* Returns a copy of the datastore IDs set
*/
set<int> get_datastores()
{
return datastores.get_collection_copy();
};
/**
* Returns a system DS for the cluster when none is set at the API level
* @return the ID of the System
*/
static int get_default_sysetm_ds(const set<int>& ds_collection);
/**
* Adds this vnet ID to the set.
* @param id to be added to the cluster
@ -212,11 +215,6 @@ private:
ObjectCollection datastores;
ObjectCollection vnets;
/**
* System datastore id
*/
int system_ds;
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************

View File

@ -139,6 +139,28 @@ public:
*/
static int xpath_value(string& value, const char *xml, const char *xpath);
/**
* Search the Object for a given attribute in a set of object specific
* routes.
* @param name of the attribute
* @param value of the attribute
*
* @return -1 if the element was not found
*/
virtual int search(const char *name, string& value);
/**
* Search the Object for a given attribute in a set of object specific
* routes. integer version
*/
virtual int search(const char *name, int& value);
/**
* Search the Object for a given attribute in a set of object specific
* routes. float version
*/
virtual int search(const char *name, float& value);
/**
* Get xml nodes by Xpath
* @param xpath_expr the Xpath for the elements
@ -247,6 +269,17 @@ public:
return os;
};
protected:
/**
* Array of paths to look for attributes in search methods
*/
const char **paths;
/**
* Number of elements in paths array
*/
int num_paths;
private:
/**
* XML representation of the Object
@ -262,6 +295,14 @@ private:
* Parse a XML documents and initializes XPath contexts
*/
void xml_parse(const string &xml_doc);
/**
* Search the Object for a given attribute in a set of object specific
* routes.
* @param name of the attribute
* @results vector of attributes that matches the query
*/
void search(const char* name, vector<string>& results);
};
#endif /*OBJECT_XML_H_*/

View File

@ -56,15 +56,27 @@ protected:
PoolObjectAuth * ds_perm,
AuthRequest::Operation op);
int get_host_information(int hid,
int get_host_information(
int hid,
string& name,
string& vmm,
string& vnm,
string& tm,
int& cluster_id,
string& ds_location,
PoolObjectAuth& host_perms,
RequestAttributes& att);
int get_ds_information(
int ds_id,
int& ds_cluster_id,
string& tm_mad,
RequestAttributes& att);
int get_default_ds_information(
int cluster_id,
int& ds_id,
RequestAttributes& att,
PoolObjectAuth& host_perms);
string& tm_mad,
RequestAttributes& att);
bool check_host(int hid,
int cpu,
@ -112,7 +124,7 @@ public:
VirtualMachineDeploy():
RequestManagerVirtualMachine("VirtualMachineDeploy",
"Deploys a virtual machine",
"A:siib")
"A:siibi")
{
auth_op = AuthRequest::ADMIN;
};

View File

@ -102,7 +102,6 @@ class OneClusterHelper < OpenNebulaHelper::OneHelper
CLIHelper.print_header(str_h1 % "CLUSTER #{cluster['ID']} INFORMATION")
puts str % ["ID", cluster.id.to_s]
puts str % ["NAME", cluster.name]
puts str % ["SYSTEM DS", cluster['SYSTEM_DS']]
puts
CLIHelper.print_header(str_h1 % "CLUSTER TEMPLATE", false)

View File

@ -547,6 +547,10 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
VirtualMachine.get_reason d["REASON"]
end
column :DS, "System Datastore", :size=>4 do |d|
d["DS_ID"]
end
column :START, "Time when the state changed", :size=>15 do |d|
OpenNebulaHelper.time_to_str(d['STIME'])
end
@ -569,7 +573,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
OpenNebulaHelper.short_period_to_str(dtime)
end
default :SEQ, :HOST, :ACTION, :REASON, :START, :TIME, :PROLOG
default :SEQ, :HOST, :ACTION, :DS, :START, :TIME, :PROLOG
end
vm_hash=vm.to_hash

View File

@ -111,6 +111,10 @@ cmd=CommandParser::CmdParser.new(ARGV) do
OpenNebulaHelper.rname_to_id(arg, "USER")
end
set :format, :datastoreid, OpenNebulaHelper.rname_to_id_desc("DATASTORE") do |arg|
OpenNebulaHelper.rname_to_id(arg, "DATASTORE")
end
set :format, :vmid, OneVMHelper.to_id_desc do |arg|
helper.to_id(arg)
end
@ -413,17 +417,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: PENDING
EOT
command :deploy, deploy_desc, [:range,:vmid_list], :hostid,
command :deploy, deploy_desc, [:range,:vmid_list], :hostid, [:datastoreid,nil],
:options=>[ENFORCE] do
host_id = args[1]
verbose = "deploying in host #{host_id}"
enforce = options[:enforce].nil? ? false : options[:enforce]
ds_id = args[2].nil? ? -1 : args[2]
helper.perform_actions(args[0],options,verbose) do |vm|
if !options[:enforce].nil?
vm.deploy(host_id, options[:enforce])
else
vm.deploy(host_id)
end
vm.deploy(host_id, enforce, ds_id)
end
end

View File

@ -34,9 +34,9 @@ const char * Cluster::db_bootstrap = "CREATE TABLE IF NOT EXISTS cluster_pool ("
"gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, "
"UNIQUE(name))";
/* ************************************************************************ */
/* ************************************************************************** */
/* Cluster :: Constructor/Destructor */
/* ************************************************************************ */
/* ************************************************************************** */
Cluster::Cluster(
int id,
@ -45,8 +45,7 @@ Cluster::Cluster(
PoolObjectSQL(id,CLUSTER,name,-1,-1,"","",table),
hosts("HOSTS"),
datastores("DATASTORES"),
vnets("VNETS"),
system_ds(DatastorePool::SYSTEM_DS_ID)
vnets("VNETS")
{
if (cl_template != 0)
{
@ -58,8 +57,8 @@ Cluster::Cluster(
}
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Cluster::check_drop(string& error_msg)
{
@ -97,8 +96,8 @@ error_common:
return -1;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& Cluster::get_ds_location(string &ds_location)
{
@ -114,8 +113,8 @@ string& Cluster::get_ds_location(string &ds_location)
return ds_location;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Cluster::add_datastore(int id, Datastore::DatastoreType ds_type, string& error_msg)
{
@ -130,36 +129,18 @@ int Cluster::add_datastore(int id, Datastore::DatastoreType ds_type, string& err
return -1;
}
if ( ds_type == Datastore::SYSTEM_DS )
{
if ( system_ds != DatastorePool::SYSTEM_DS_ID )
{
ostringstream oss;
oss << "Cluster " << oid << " already contains the System Datastore "
<< system_ds << ".";
error_msg = oss.str();
return -1;
}
}
int rc = datastores.add_collection_id(id);
if ( rc < 0 )
{
error_msg = "Datastore ID is already in the cluster set.";
}
else if ( ds_type == Datastore::SYSTEM_DS )
{
system_ds = id;
}
return rc;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Cluster::del_datastore(int id, string& error_msg)
{
@ -169,17 +150,45 @@ int Cluster::del_datastore(int id, string& error_msg)
{
error_msg = "Datastore ID is not part of the cluster set.";
}
else if ( system_ds == id )
{
system_ds = DatastorePool::SYSTEM_DS_ID;
}
return rc;
}
/* ************************************************************************ */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Cluster::get_default_sysetm_ds(const set<int>& ds_set)
{
Nebula& nd = Nebula::instance();
DatastorePool* dspool = nd.get_dspool();
Datastore* ds;
for (set<int>::const_iterator it = ds_set.begin(); it != ds_set.end(); it++)
{
ds = dspool->get(*it, true);
if (ds == 0)
{
continue;
}
if (ds->get_type() == Datastore::SYSTEM_DS)
{
ds->unlock();
return *it;
}
ds->unlock();
}
return -1;
}
/* ************************************************************************** */
/* Cluster :: Database Access Functions */
/* ************************************************************************ */
/* ************************************************************************** */
int Cluster::insert_replace(SqlDB *db, bool replace, string& error_str)
{
@ -266,8 +275,8 @@ error_common:
return -1;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& Cluster::to_xml(string& xml) const
{
@ -281,8 +290,6 @@ string& Cluster::to_xml(string& xml) const
"<CLUSTER>" <<
"<ID>" << oid << "</ID>" <<
"<NAME>" << name << "</NAME>" <<
"<SYSTEM_DS>" << system_ds << "</SYSTEM_DS>" <<
hosts.to_xml(host_collection_xml) <<
datastores.to_xml(ds_collection_xml) <<
vnets.to_xml(vnet_collection_xml) <<
@ -294,8 +301,8 @@ string& Cluster::to_xml(string& xml) const
return xml;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Cluster::from_xml(const string& xml)
{
@ -308,7 +315,6 @@ int Cluster::from_xml(const string& xml)
// Get class base attributes
rc += xpath(oid, "/CLUSTER/ID", -1);
rc += xpath(name, "/CLUSTER/NAME", "not_found");
rc += xpath(system_ds, "/CLUSTER/SYSTEM_DS", -1);
// Set oneadmin as the owner
set_user(0,"");
@ -384,6 +390,6 @@ int Cluster::from_xml(const string& xml)
return 0;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -491,11 +491,13 @@ public class VirtualMachine extends PoolElement{
* @param enforce If it is set to true, the host capacity
* will be checked, and the deployment will fail if the host is
* overcommited. Defaults to false
* @param dsId The System Datastore where to deploy the VM. To use the
* default, set it to -1
* @return If an error occurs the error message contains the reason.
*/
public OneResponse deploy(int hostId, boolean enforce)
public OneResponse deploy(int hostId, boolean enforce, int dsId)
{
return client.call(DEPLOY, id, hostId, enforce);
return client.call(DEPLOY, id, hostId, enforce, dsId);
}
/**
@ -507,7 +509,7 @@ public class VirtualMachine extends PoolElement{
*/
public OneResponse deploy(int hostId)
{
return deploy(hostId, false);
return deploy(hostId, false, -1);
}
/**

View File

@ -216,11 +216,13 @@ module OpenNebula
# @param enforce [true|false] If it is set to true, the host capacity
# will be checked, and the deployment will fail if the host is
# overcommited. Defaults to false
# @param ds_id [Integer] The System Datastore where to deploy the VM. To
# use the default, set it to -1
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def deploy(host_id, enforce=false)
return call(VM_METHODS[:deploy], @pe_id, host_id.to_i, enforce)
def deploy(host_id, enforce=false, ds_id=-1)
return call(VM_METHODS[:deploy], @pe_id, host_id.to_i, enforce, ds_id)
end
# Shutdowns an already deployed VM

View File

@ -96,49 +96,26 @@ bool RequestManagerVirtualMachine::vm_authorization(
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int RequestManagerVirtualMachine::get_host_information(int hid,
string& name,
string& vmm,
string& vnm,
string& tm,
string& ds_location,
int RequestManagerVirtualMachine::get_default_ds_information(
int cluster_id,
int& ds_id,
RequestAttributes& att,
PoolObjectAuth& host_perms)
string& tm_mad,
RequestAttributes& att)
{
Nebula& nd = Nebula::instance();
HostPool * hpool = nd.get_hpool();
Host * host;
ClusterPool* clpool = nd.get_clpool();
Cluster* cluster;
Datastore * ds;
int cluster_id;
ds_id = -1;
host = hpool->get(hid,true);
if ( host == 0 )
if (cluster_id == ClusterPool::NONE_CLUSTER_ID)
{
failure_response(NO_EXISTS,
get_error(object_name(PoolObjectSQL::HOST),hid),
att);
return -1;
ds_id = DatastorePool::SYSTEM_DS_ID;
}
name = host->get_name();
vmm = host->get_vmm_mad();
vnm = host->get_vnm_mad();
host->get_permissions(host_perms);
cluster_id = host->get_cluster_id();
host->unlock();
if ( cluster_id != -1 )
else
{
cluster = nd.get_clpool()->get(cluster_id, true);
cluster = clpool->get(cluster_id, true);
if (cluster == 0)
{
@ -149,20 +126,43 @@ int RequestManagerVirtualMachine::get_host_information(int hid,
return -1;
}
ds_id = cluster->get_ds_id();
cluster->get_ds_location(ds_location);
set<int> ds_ids = cluster->get_datastores();
cluster->unlock();
}
else
ds_id = Cluster::get_default_sysetm_ds(ds_ids);
if (ds_id == -1)
{
ds_id = DatastorePool::SYSTEM_DS_ID;
ostringstream oss;
nd.get_configuration_attribute("DATASTORE_LOCATION", ds_location);
oss << object_name(PoolObjectSQL::CLUSTER)
<< " [" << cluster_id << "] does not have any "
<< object_name(PoolObjectSQL::DATASTORE) << " of type "
<< Datastore::type_to_str(Datastore::SYSTEM_DS) << ".";
failure_response(ACTION, request_error(oss.str(),""), att);
return -1;
}
}
ds = nd.get_dspool()->get(ds_id, true);
return get_ds_information(ds_id, cluster_id, tm_mad, att);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int RequestManagerVirtualMachine::get_ds_information(int ds_id,
int& ds_cluster_id,
string& tm_mad,
RequestAttributes& att)
{
Nebula& nd = Nebula::instance();
Datastore * ds = nd.get_dspool()->get(ds_id, true);
ds_cluster_id = -1;
if ( ds == 0 )
{
@ -177,23 +177,87 @@ int RequestManagerVirtualMachine::get_host_information(int hid,
{
ostringstream oss;
oss << "Trying to use " << object_name(PoolObjectSQL::DATASTORE)
<< " [" << ds_id << "] to deploy the VM, but it is not of type"
<< " system datastore.";
failure_response(INTERNAL, request_error(oss.str(),""), att);
ds->unlock();
oss << object_name(PoolObjectSQL::CLUSTER)
<< " [" << cluster_id << "] has its SYSTEM_DS set to "
<< object_name(PoolObjectSQL::DATASTORE)
<< " [" << ds_id << "], but it is not a system one.";
return -1;
}
failure_response(INTERNAL,
request_error(oss.str(),""),
ds_cluster_id = ds->get_cluster_id();
tm_mad = ds->get_tm_mad();
ds->unlock();
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int RequestManagerVirtualMachine::get_host_information(
int hid,
string& name,
string& vmm,
string& vnm,
int& cluster_id,
string& ds_location,
PoolObjectAuth& host_perms,
RequestAttributes& att)
{
Nebula& nd = Nebula::instance();
HostPool * hpool = nd.get_hpool();
Host * host = hpool->get(hid,true);
if ( host == 0 )
{
failure_response(NO_EXISTS,
get_error(object_name(PoolObjectSQL::HOST),hid),
att);
return -1;
}
tm = ds->get_tm_mad();
name = host->get_name();
vmm = host->get_vmm_mad();
vnm = host->get_vnm_mad();
ds->unlock();
cluster_id = host->get_cluster_id();
host->get_permissions(host_perms);
host->unlock();
if ( cluster_id != -1 )
{
Cluster * cluster = nd.get_clpool()->get(cluster_id, true);
if ( cluster == 0 )
{
failure_response(NO_EXISTS,
get_error(object_name(PoolObjectSQL::CLUSTER),cluster_id),
att);
return -1;
}
cluster->get_ds_location(ds_location);
cluster->unlock();
}
else //Default System DS
{
nd.get_configuration_attribute("DATASTORE_LOCATION", ds_location);
}
return 0;
}
@ -451,39 +515,87 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
DispatchManager * dm = nd.get_dm();
VirtualMachine * vm;
PoolObjectAuth host_perms;
string hostname;
string vmm_mad;
string vnm_mad;
string tm_mad;
int cluster_id;
string ds_location;
int ds_id;
PoolObjectAuth host_perms;
string tm_mad;
bool auth = false;
// ------------------------------------------------------------------------
// Get request parameters and information about the target host
// ------------------------------------------------------------------------
int id = xmlrpc_c::value_int(paramList.getInt(1));
int hid = xmlrpc_c::value_int(paramList.getInt(2));
bool enforce = false;
bool auth = false;
int ds_id = -1;
if ( paramList.size() > 3 )
{
enforce = xmlrpc_c::value_boolean(paramList.getBoolean(3));
}
if ( paramList.size() > 4 )
{
ds_id = xmlrpc_c::value_int(paramList.getInt(4));
}
if (get_host_information(hid,
hostname,
vmm_mad,
vnm_mad,
tm_mad,
cluster_id,
ds_location,
ds_id,
att,
host_perms) != 0)
host_perms,
att) != 0)
{
return;
}
// ------------------------------------------------------------------------
// Get information about the system DS to use (tm_mad)
// ------------------------------------------------------------------------
if ( ds_id == -1 ) //Use default system DS for cluster
{
if (get_default_ds_information(cluster_id, ds_id, tm_mad, att) != 0)
{
return;
}
}
else //Get information from user selected system DS
{
int ds_cluster_id;
if (get_ds_information(ds_id, ds_cluster_id, tm_mad, att) != 0)
{
return;
}
if (ds_cluster_id != cluster_id)
{
ostringstream oss;
oss << object_name(PoolObjectSQL::DATASTORE)
<< " [" << ds_id << "] and " << object_name(PoolObjectSQL::HOST)
<< " [" << hid <<"] are not in the same cluster.";
failure_response(ACTION, request_error(oss.str(),""), att);
return;
}
}
// ------------------------------------------------------------------------
// Authorize request
// ------------------------------------------------------------------------
auth = vm_authorization(id, 0, 0, att, &host_perms, 0, auth_op);
if (auth == false)
@ -491,6 +603,12 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
return;
}
// ------------------------------------------------------------------------
// Check request consistency:
// - VM States are right
// - Host capacity if required
// ------------------------------------------------------------------------
if ((vm = get_vm(id, att)) == 0)
{
return;
@ -528,6 +646,10 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
}
}
// ------------------------------------------------------------------------
// Add a new history record and deploy the VM
// ------------------------------------------------------------------------
if (add_history(vm,
hid,
hostname,
@ -559,19 +681,24 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
DispatchManager * dm = nd.get_dm();
VirtualMachine * vm;
PoolObjectAuth host_perms;
string hostname;
string vmm_mad;
string vnm_mad;
string tm_mad;
int cluster_id;
string ds_location;
int ds_id;
PoolObjectAuth host_perms;
PoolObjectAuth aux_perms;
int current_ds_id;
string aux_st;
int current_hid;
int c_hid;
int c_cluster_id;
int c_ds_id;
string c_tm_mad;
bool auth = false;
// ------------------------------------------------------------------------
// Get request parameters and information about the target host
// ------------------------------------------------------------------------
int id = xmlrpc_c::value_int(paramList.getInt(1));
int hid = xmlrpc_c::value_int(paramList.getInt(2));
@ -583,21 +710,22 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
enforce = xmlrpc_c::value_boolean(paramList.getBoolean(4));
}
bool auth = false;
if (get_host_information(hid,
hostname,
vmm_mad,
vnm_mad,
tm_mad,
cluster_id,
ds_location,
ds_id,
att,
host_perms) != 0)
host_perms,
att) != 0)
{
return;
}
// ------------------------------------------------------------------------
// Authorize request
// ------------------------------------------------------------------------
auth = vm_authorization(id, 0, 0, att, &host_perms, 0, auth_op);
if (auth == false)
@ -605,6 +733,14 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
return;
}
// ------------------------------------------------------------------------
// Check request consistency:
// - VM States are right and there is at least a history record
// - New host is not the current one
// - Host capacity if required
// - New host and current one are in the same cluster
// ------------------------------------------------------------------------
if ((vm = get_vm(id, att)) == 0)
{
return;
@ -622,14 +758,16 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
return;
}
current_hid = vm->get_hid();
// Check we are not migrating to the same host
if (current_hid == hid)
c_hid = vm->get_hid();
if (c_hid == hid)
{
ostringstream oss;
oss << "VM is already running on "
<< object_name(PoolObjectSQL::HOST) << " [" << current_hid << "]";
<< object_name(PoolObjectSQL::HOST) << " [" << c_hid << "]";
failure_response(ACTION,
request_error(oss.str(),""),
@ -639,6 +777,14 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
return;
}
// Get System DS information from current History record
istringstream iss(vm->get_ds_id());
iss >> c_ds_id;
c_tm_mad = vm->get_tm_mad();
if (enforce)
{
int cpu, mem, disk;
@ -659,28 +805,29 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
vm->unlock();
}
if (get_host_information(current_hid,
aux_st,
aux_st,
aux_st,
aux_st,
aux_st,
current_ds_id,
att,
aux_perms) != 0)
// Check we are in the same cluster
Host * host = nd.get_hpool()->get(c_hid, true);
if (host == 0)
{
return;
failure_response(NO_EXISTS,
get_error(object_name(PoolObjectSQL::HOST), c_hid),
att);
}
if ( current_ds_id != ds_id )
c_cluster_id = host->get_cluster_id();
host->unlock();
if ( c_cluster_id != cluster_id )
{
ostringstream oss;
oss << "Cannot migrate to a different cluster with different system "
<< "datastore. Current " << object_name(PoolObjectSQL::HOST)
<< " [" << current_hid << "] uses system datastore [" << current_ds_id
<< "], new " << object_name(PoolObjectSQL::HOST) << " [" << hid
<< "] uses system datastore [" << ds_id << "]";
oss << "Cannot migrate to a different cluster. VM running in a host"
<< " in " << object_name(PoolObjectSQL::CLUSTER) << " ["
<< c_cluster_id << "] , and new host is in "
<< object_name(PoolObjectSQL::CLUSTER) << " [" << cluster_id << "]";
failure_response(ACTION,
request_error(oss.str(),""),
@ -689,6 +836,10 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
return;
}
// ------------------------------------------------------------------------
// Add a new history record and migrate the VM
// ------------------------------------------------------------------------
if ( (vm = get_vm(id, att)) == 0 )
{
return;
@ -699,9 +850,9 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
hostname,
vmm_mad,
vnm_mad,
tm_mad,
c_tm_mad,
ds_location,
ds_id,
c_ds_id,
att) != 0)
{
vm->unlock();

View File

@ -35,6 +35,17 @@
# - rank: Custom arithmetic exprission to rank suitable hosts based in their
# attributes
#
# DEFAULT_DS_SCHED: Definition of the default storage scheduling algorithm
# - policy:
# 0 = Packing. Tries to optimize storage usage by selecting the DS with
# less free space
# 1 = Striping. Tries to optimize I/O by distributing the VMs across
# datastores.
# 2 = Custom.
# - rank: Custom arithmetic exprission to rank suitable datastores based on
# their attributes
#
#
# LOG: Configuration for the logging system
# - system: defines the logging system:
# file to log in the sched.log file
@ -58,6 +69,10 @@ DEFAULT_SCHED = [
policy = 1
]
DEFAULT_DS_SCHED = [
policy = 1
]
#DEFAULT_SCHED = [
# policy = 3,
# rank = "- (RUNNING_VMS * 50 + FREE_CPU)"

View File

@ -27,8 +27,9 @@ class ClusterPoolXML : public PoolXML
{
public:
ClusterPoolXML(Client* client):PoolXML(client)
{};
ClusterPoolXML(Client* client):PoolXML(client){};
~ClusterPoolXML(){};
/**
* Gets an object from the pool
@ -41,6 +42,11 @@ public:
return static_cast<ClusterXML *>(PoolXML::get(oid));
};
/**
* Identifier for the "none" cluster
*/
static const int NONE_CLUSTER_ID;
protected:
int get_suitable_nodes(vector<xmlNodePtr>& content)

View File

@ -0,0 +1,57 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs */
/* */
/* 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. */
/* -------------------------------------------------------------------------- */
#ifndef DATASTORE_POOL_XML_H_
#define DATASTORE_POOL_XML_H_
#include "PoolXML.h"
#include "DatastoreXML.h"
using namespace std;
class DatastorePoolXML : public PoolXML
{
public:
DatastorePoolXML(Client* client):PoolXML(client){};
~DatastorePoolXML(){};
/**
* Gets an object from the pool
* @param oid the object unique identifier
*
* @return a pointer to the object, 0 in case of failure
*/
DatastoreXML * get(int oid) const
{
return static_cast<DatastoreXML *>(PoolXML::get(oid));
};
protected:
int get_suitable_nodes(vector<xmlNodePtr>& content)
{
return get_nodes("/DATASTORE_POOL/DATASTORE[TYPE=1]", content);
};
void add_object(xmlNodePtr node);
int load_info(xmlrpc_c::value &result);
};
#endif /* DATASTORE_POOL_XML_H_ */

View File

@ -0,0 +1,84 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs */
/* */
/* 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. */
/* -------------------------------------------------------------------------- */
#ifndef DATASTORE_XML_H_
#define DATASTORE_XML_H_
#include "ObjectXML.h"
using namespace std;
class DatastoreXML : public ObjectXML
{
public:
DatastoreXML(const string &xml_doc):ObjectXML(xml_doc)
{
init_attributes();
};
DatastoreXML(const xmlNodePtr node):ObjectXML(node)
{
init_attributes();
};
/**
* Tests whether a new VM can be hosted by the datasotre
* @param vm_disk_mb capacity needed by the VM
* @return true if the datastore can host the VM
*/
bool test_capacity(unsigned int vm_disk_mb) const
{
return true;
//TODO Perform test.
//return (vm_disk_mb < free_mb);
};
/**
* Adds a new VM to the datastore
* @param vm_disk_mb capacity needed by the VM
* @return 0 on success
*/
void add_capacity(unsigned int vm_disk_mb)
{
free_mb += vm_disk_mb;
};
int get_oid() const
{
return oid;
};
int get_cid() const
{
return cluster_id;
};
private:
int oid;
int cluster_id;
unsigned int free_mb; /**< Free disk for VMs (in Mb). */
static const char *ds_paths[]; /**< paths for search function */
static int ds_num_paths; /**< number of paths*/
void init_attributes();
};
#endif /* DATASTORE_XML_H_ */

View File

@ -33,6 +33,8 @@ public:
HostXML::set_hypervisor_mem(mem);
};
~HostPoolXML(){};
int set_up();
/**

View File

@ -76,6 +76,32 @@ public:
running_vms++;
};
/**
* Deletes a VM to the given host by updating the cpu,mem and disk
* counters
* @param cpu needed by the VM (percentage)
* @param mem needed by the VM (in KB)
* @param disk needed by the VM
* @return 0 on success
*/
void del_capacity(int cpu, int mem, int disk)
{
cpu_usage -= cpu;
mem_usage -= mem;
disk_usage -= disk;
running_vms--;
};
/**
* Search the Object for a given attribute in a set of object specific
* routes. Overwrite ObjectXML function to deal with pseudo-attributes
* - CURRENT_VMS. value is the VM ID to search in the set of VMS
* running VMs in the host. If the VM_ID is found value is not modified
* otherwise is set to -1
*/
int search(const char *name, int& value);
/**
* Sets the memory fraction reserved for the hypervisor. This function
* should be called before using the host pool.
@ -102,6 +128,10 @@ private:
static float hypervisor_mem; /**< Fraction of memory for the VMs */
static const char *host_paths[]; /**< paths for search function */
static int host_num_paths; /**< number of paths*/
void init_attributes();
};

View File

@ -22,74 +22,150 @@
using namespace std;
class RankPolicy : public SchedulerHostPolicy
class RankPolicy : public SchedulerPolicy
{
public:
RankPolicy(
VirtualMachinePoolXML * vmpool,
HostPoolXML * hpool,
const string& dr,
float w = 1.0)
:SchedulerHostPolicy(vmpool,hpool,w), default_rank(dr){};
RankPolicy(PoolXML * _pool, const string& dr, float w = 1.0):
SchedulerPolicy(w), default_rank(dr), pool(_pool) {};
~RankPolicy(){};
virtual ~RankPolicy(){};
private:
protected:
/**
* Gets the rank to apply.
*/
virtual const string& get_rank(ObjectXML *obj) = 0;
/**
* Default rank for resources
*/
string default_rank;
void policy(
VirtualMachineXML * vm)
/**
* Pool of matched resources
*/
PoolXML * pool;
private:
/**
* Implements the Match-Making policy by computing the rank of each resource
* @param obj The Schedulable object
* @param priority for each resource.
*/
void policy(ObjectXML * obj, vector<float>& priority)
{
string srank;
int rank;
ObjectXML * resource;
char * errmsg = 0;
char * errmsg;
int rc;
int rc, rank = 0;
vector<int> hids;
unsigned int i;
const vector<Resource *> resources = get_match_resources(obj);
HostXML * host;
string srank = get_rank(obj);
vm->get_matching_hosts(hids);
srank = vm->get_rank();
priority.clear();
if (srank.empty())
{
srank = default_rank;
priority.resize(resources.size(),0);
return;
}
for (i=0;i<hids.size();i++)
for (unsigned int i=0; i<resources.size(); rank=0, i++)
{
rank = 0;
resource = pool->get(resources[i]->oid);
if (srank != "")
if ( resource != 0 )
{
host = hpool->get(hids[i]);
if ( host != 0 )
{
rc = host->eval_arith(srank, rank, &errmsg);
rc = resource->eval_arith(srank, rank, &errmsg);
if (rc != 0)
{
ostringstream oss;
oss << "Computing host rank, expression: " << srank
<< ", error: " << errmsg;
NebulaLog::log("RANK",Log::ERROR,oss);
oss << "Computing rank, expression: " << srank;
if (errmsg != 0)
{
oss << ", error: " << errmsg;
errmsg = 0;
free(errmsg);
}
NebulaLog::log("RANK",Log::ERROR,oss);
}
}
priority.push_back(rank);
}
};
};
class RankHostPolicy : public RankPolicy
{
public:
RankHostPolicy(HostPoolXML * pool, const string& dr, float w = 1.0):
RankPolicy(pool, dr, w){};
~RankHostPolicy(){};
private:
const vector<Resource *> get_match_resources(ObjectXML *obj)
{
VirtualMachineXML * vm = dynamic_cast<VirtualMachineXML *>(obj);
return vm->get_match_hosts();
};
const string& get_rank(ObjectXML *obj)
{
VirtualMachineXML * vm = dynamic_cast<VirtualMachineXML *>(obj);
if (vm->get_rank().empty())
{
return default_rank;
}
return vm->get_rank();
};
};
class RankDatastorePolicy : public RankPolicy
{
public:
RankDatastorePolicy(DatastorePoolXML * pool, const string& dr,float w=1.0):
RankPolicy(pool, dr, w){};
~RankDatastorePolicy(){};
private:
const vector<Resource *> get_match_resources(ObjectXML *obj)
{
VirtualMachineXML * vm = dynamic_cast<VirtualMachineXML *>(obj);
return vm->get_match_datastores();
};
const string& get_rank(ObjectXML *obj)
{
VirtualMachineXML * vm = dynamic_cast<VirtualMachineXML *>(obj);
if (vm->get_ds_rank().empty())
{
return default_rank;
}
return vm->get_ds_rank();
};
};
#endif /*RANK_POLICY_H_*/

View File

@ -0,0 +1,114 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs */
/* */
/* 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. */
/* -------------------------------------------------------------------------- */
#ifndef RESOURCE_H_
#define RESOURCE_H_
#include <map>
class PoolXML;
/**
* This class represents a target resource to schedule a "schedulable"
* resource.
*/
class Resource
{
public:
Resource(int _oid):oid(_oid), priority(0){};
virtual ~Resource(){};
static bool cmp (const Resource * a, const Resource * b)
{
return a->priority < b->priority;
};
bool operator<(const Resource& b) const
{
return priority < b.priority;
};
int oid;
float priority;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/**
* Abstract class that models an object that can be scheduled over a resource
*/
class ResourceMatch
{
public:
ResourceMatch(){};
virtual ~ResourceMatch()
{
clear();
};
/**
* Adds a matching resource to the object
* @param oid of the resource
*/
virtual void add_resource(int oid)
{
Resource * r = new Resource(oid);
resources.push_back(r);
}
/**
* Sort the matched resources in the vector
*/
void sort_resources()
{
sort(resources.begin(), resources.end(), Resource::cmp);
}
/**
* Return a reference to the resources of the object
* @return vector of resources.
*/
const vector<Resource *>& get_resources() const
{
return resources;
};
/**
* Clear the resources by freeing memory and reducing the effective size
* to 0.
*/
void clear()
{
vector<Resource *>::iterator jt;
for (jt=resources.begin(); jt!=resources.end(); jt++)
{
delete *jt;
}
resources.clear();
}
private:
vector<Resource *> resources;
};
#endif /*RESOURCE_H_*/

View File

@ -20,6 +20,7 @@
#include "Log.h"
#include "HostPoolXML.h"
#include "ClusterPoolXML.h"
#include "DatastorePoolXML.h"
#include "VirtualMachinePoolXML.h"
#include "SchedulerPolicy.h"
#include "ActionManager.h"
@ -85,6 +86,11 @@ protected:
delete vmapool;
}
if ( dspool != 0)
{
delete dspool;
}
if ( acls != 0)
{
delete acls;
@ -105,6 +111,7 @@ protected:
VirtualMachinePoolXML * vmpool;
VirtualMachineActionsPoolXML* vmapool;
DatastorePoolXML * dspool;
AclXML * acls;
@ -112,11 +119,16 @@ protected:
// Scheduler Policies
// ---------------------------------------------------------------
void add_host_policy(SchedulerHostPolicy *policy)
void add_host_policy(SchedulerPolicy *policy)
{
host_policies.push_back(policy);
}
void add_ds_policy(SchedulerPolicy *policy)
{
ds_policies.push_back(policy);
}
// ---------------------------------------------------------------
// Scheduler main methods
// ---------------------------------------------------------------
@ -126,12 +138,10 @@ protected:
* the capacity of the host is checked. If there is enough room to host the
* VM a share vector is added to the VM.
*/
virtual void match();
virtual void match_schedule();
virtual void dispatch();
virtual int schedule();
/**
* Retrieves the pools
*
@ -141,7 +151,6 @@ protected:
*/
virtual int set_up_pools();
virtual int do_scheduled_actions();
private:
@ -155,7 +164,8 @@ private:
// Scheduling Policies
// ---------------------------------------------------------------
vector<SchedulerHostPolicy *> host_policies;
vector<SchedulerPolicy *> host_policies;
vector<SchedulerPolicy *> ds_policies;
// ---------------------------------------------------------------
// Configuration attributes

View File

@ -17,66 +17,84 @@
#ifndef SCHEDULER_POLICY_H_
#define SCHEDULER_POLICY_H_
#include "HostPoolXML.h"
#include "VirtualMachinePoolXML.h"
#include "ObjectXML.h"
#include <cmath>
#include <algorithm>
using namespace std;
class SchedulerHostPolicy
/**
* Abstract class that represents a Scheduling policy
*/
class SchedulerPolicy
{
public:
SchedulerPolicy(float w=1.0):sw(w){};
SchedulerHostPolicy(
VirtualMachinePoolXML * _vmpool,
HostPoolXML * _hpool,
float w=1.0):
vmpool(_vmpool),hpool(_hpool),sw(w){};
virtual ~SchedulerPolicy(){};
virtual ~SchedulerHostPolicy(){};
const vector<float>& get(
VirtualMachineXML * vm)
/**
* Main interface for the class schedule the objects applying the policy.
* It returns a reference to a vector of priorities for each "schedulable"
* object.
* @param obj, pointer to the object to schedule
*
*/
const void schedule(ObjectXML * obj)
{
priority.clear();
vector<float> priority;
const vector<Resource *> resources = get_match_resources(obj);
policy(vm);
if(!priority.empty())
if (resources.empty())
{
sw.max = fabs(*max_element(
priority.begin(),
priority.end(),
SchedulerHostPolicy::abs_cmp));
transform(
priority.begin(),
priority.end(),
priority.begin(),
sw);
return;
}
return priority;
//1. Compute priorities
policy(obj, priority);
//2. Scale priorities
sw.max =fabs(*max_element(priority.begin(), priority.end(), abs_cmp));
transform(priority.begin(), priority.end(), priority.begin(), sw);
//3. Aggregate to other policies
for (unsigned int i=0; i< resources.size(); i++)
{
resources[i]->priority += priority[i];
}
};
protected:
vector<float> priority;
/**
* Get the vector of matched resources for the Object being schedule
* @param obj pointer to the object
* @return a reference to the vector
*/
virtual const vector<Resource *> get_match_resources(ObjectXML *obj) = 0;
virtual void policy(VirtualMachineXML * vm) = 0;
VirtualMachinePoolXML * vmpool;
HostPoolXML * hpool;
/**
* Implements the actual schedule by computing the priority of each
* matching resource.
*/
virtual void policy(ObjectXML * obj, vector<float>& priority) = 0;
private:
/**
* ABS compare to sort priorities
*/
static bool abs_cmp(float fl1, float fl2)
{
return fabs(fl1)<fabs(fl2);
};
//--------------------------------------------------------------------------
/**
* Private class to scale priorities on resources. Each resource has a
* priority assgined by a policy, in order to sort and combine policies
* priorities are scaled to 1.0 and weighted.
*/
class ScaleWeight
{
public:
@ -96,17 +114,10 @@ private:
}
};
private:
friend class SchedulerHostPolicy;
float weight;
float max;
} sw;
};
//--------------------------------------------------------------------------
ScaleWeight sw;
};
/* -------------------------------------------------------------------------- */
#endif /*SCHEDULER_POLICY_H_*/

View File

@ -32,6 +32,8 @@ public:
string get_policy() const;
string get_ds_policy() const;
private:
/**
* Name for the configuration file, oned.conf

View File

@ -60,7 +60,7 @@ public:
* @param hid the id of the target host
* @param resched the machine is going to be rescheduled
*/
int dispatch(int vid, int hid, bool resched) const;
int dispatch(int vid, int hid, int dsid, bool resched) const;
/**
* Update the VM template

View File

@ -22,6 +22,8 @@
#include "ObjectXML.h"
#include "HostPoolXML.h"
#include "Resource.h"
#include "VirtualMachineTemplate.h"
using namespace std;
@ -30,19 +32,27 @@ class VirtualMachineXML : public ObjectXML
{
public:
VirtualMachineXML(const string &xml_doc):
ObjectXML(xml_doc)
VirtualMachineXML(const string &xml_doc): ObjectXML(xml_doc)
{
init_attributes();
};
VirtualMachineXML(const xmlNodePtr node):
ObjectXML(node)
VirtualMachineXML(const xmlNodePtr node): ObjectXML(node)
{
init_attributes();
}
~VirtualMachineXML();
~VirtualMachineXML()
{
if (vm_template != 0)
{
delete vm_template;
}
}
//--------------------------------------------------------------------------
// Get Methods for VirtualMachineXML class
//--------------------------------------------------------------------------
int get_oid() const
{
@ -64,48 +74,115 @@ public:
return hid;
};
int get_dsid() const
{
return dsid;
};
bool is_resched() const
{
return (resched == 1);
}
/**
* Adds a new host to the list of suitable hosts to start this VM
* @param hid of the selected host
*/
void add_host(int hid);
/**
* Gets the matching hosts ids
* @param mh vector with the hids of the matching hosts
*/
void get_matching_hosts(vector<int>& mh);
/**
* Sets the priorities for each matching host
*/
void set_priorities(vector<float>& total);
/**
*
*/
int get_host(int& hid,
HostPoolXML * hpool,
map<int,int>& host_vms,
int max_vms);
void get_requirements (int& cpu, int& memory, int& disk);
const string& get_rank()
{
return rank;
};
const string& get_ds_rank()
{
return ds_rank;
};
const string& get_requirements()
{
return requirements;
};
const string& get_ds_requirements()
{
return ds_requirements;
}
void get_requirements (int& cpu, int& memory, int& disk);
//--------------------------------------------------------------------------
// Matched Resources Interface
//--------------------------------------------------------------------------
/**
* Adds a matching host if it is not equal to the actual one
* @param oid of the host
*/
void add_match_host(int oid)
{
if (( resched == 1 && hid != oid ) || ( resched == 0 ))
{
match_hosts.add_resource(oid);
}
};
/**
* Adds a matching datastore
* @param oid of the datastore
*/
void add_match_datastore(int oid)
{
match_datastores.add_resource(oid);
}
/**
* Returns a vector of matched hosts
*/
const vector<Resource *> get_match_hosts()
{
return match_hosts.get_resources();
}
/**
* Returns a vector of matched datastores
*/
const vector<Resource *> get_match_datastores()
{
return match_datastores.get_resources();
}
/**
* Sort the matched hosts for the VM
*/
void sort_match_hosts()
{
match_hosts.sort_resources();
}
/**
* Sort the matched datastores for the VM
*/
void sort_match_datastores()
{
match_datastores.sort_resources();
}
/**
* Removes the matched hosts
*/
void clear_match_hosts()
{
match_hosts.clear();
}
/**
* Removes the matched datastores
*/
void clear_match_datastores()
{
match_datastores.clear();
}
//--------------------------------------------------------------------------
// Action Interface
//--------------------------------------------------------------------------
/**
* Get the user template of the VM
* @return the template as a XML string
@ -158,28 +235,7 @@ public:
/**
* Function to write a Virtual Machine in an output stream
*/
friend ostream& operator<<(ostream& os, VirtualMachineXML& vm)
{
if (vm.hosts.empty())
{
return os;
}
vector<VirtualMachineXML::Host *>::reverse_iterator i;
vector<int>::iterator j;
os << "\t PRI\tHID VM: " << vm.oid << endl
<< "\t-----------------------" << endl;
for (i=vm.hosts.rbegin();i!=vm.hosts.rend();i++)
{
os << "\t" << (*i)->priority << "\t" << (*i)->hid << endl;
}
os << endl;
return os;
};
friend ostream& operator<<(ostream& os, VirtualMachineXML& vm);
/**
* Adds a message to the VM's USER_TEMPLATE/SCHED_MESSAGE attribute
@ -194,41 +250,18 @@ protected:
*/
void init_attributes();
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
struct Host
{
int hid;
float priority;
ResourceMatch match_hosts;
Host(int _hid):
hid(_hid),
priority(0){};
ResourceMatch match_datastores;
~Host(){};
bool operator<(const Host& b) const { //Sort by priority
return priority < b.priority;
}
};
static bool host_cmp (const Host * a, const Host * b )
{
return (*a < *b );
};
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// ----------------------- VIRTUAL MACHINE ATTRIBUTES --------------------
/**
*
*/
/* ----------------------- VIRTUAL MACHINE ATTRIBUTES ------------------- */
int oid;
int uid;
int gid;
int hid;
int dsid;
int resched;
@ -238,15 +271,10 @@ protected:
string rank;
string requirements;
/**
* Matching hosts
*/
vector<VirtualMachineXML::Host *> hosts;
string ds_requirements;
string ds_rank;
/**
* The VM user template
*/
VirtualMachineTemplate * vm_template;
VirtualMachineTemplate * vm_template; /**< The VM user template */
};
#endif /* VM_XML_H_ */

View File

@ -16,6 +16,8 @@
#include "ClusterPoolXML.h"
const int ClusterPoolXML::NONE_CLUSTER_ID = -1;
void ClusterPoolXML::add_object(xmlNodePtr node)
{
if ( node == 0 || node->children == 0 )

View File

@ -0,0 +1,64 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs */
/* */
/* 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. */
/* -------------------------------------------------------------------------- */
#include "DatastorePoolXML.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void DatastorePoolXML::add_object(xmlNodePtr node)
{
if ( node == 0 || node->children == 0 )
{
NebulaLog::log("DATASTORE",Log::ERROR,
"XML Node does not represent a valid Host");
return;
}
DatastoreXML* ds = new DatastoreXML(node);
objects.insert(pair<int,ObjectXML*>(ds->get_oid(), ds));
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int DatastorePoolXML::load_info(xmlrpc_c::value &result)
{
try
{
client->call( client->get_endpoint(), // serverUrl
"one.datastorepool.info", // methodName
"s", // arguments format
&result, // resultP
client->get_oneauth().c_str() // argument
);
return 0;
}
catch (exception const& e)
{
ostringstream oss;
oss << "Exception raised: " << e.what();
NebulaLog::log("DATASTORE", Log::ERROR, oss);
return -1;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,47 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs */
/* */
/* 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. */
/* -------------------------------------------------------------------------- */
#include <sstream>
#include "DatastoreXML.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int DatastoreXML::ds_num_paths = 2;
const char * DatastoreXML::ds_paths[] = {
"/DATASTORE/TEMPLATE/",
"/DATASTORE/"
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void DatastoreXML::init_attributes()
{
oid = atoi(((*this)["/DATASTORE/ID"] )[0].c_str() );
cluster_id = atoi(((*this)["/DATASTORE/CLUSTER_ID"] )[0].c_str() );
free_mb = static_cast<unsigned int>(
atol(((*this)["/DATASTORE/FREE_MB"])[0].c_str()));
ObjectXML::paths = ds_paths;
ObjectXML::num_paths = ds_num_paths;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -15,11 +15,23 @@
/* -------------------------------------------------------------------------- */
#include <math.h>
#include <sstream>
#include "HostXML.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
float HostXML::hypervisor_mem;
int HostXML::host_num_paths = 4;
const char *HostXML::host_paths[] = {
"/HOST/TEMPLATE/",
"/HOST/HOST_SHARE/",
"/HOST/",
"/HOST/CLUSTER_TEMPLATE/"};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -40,8 +52,50 @@ void HostXML::init_attributes()
//Reserve memory for the hypervisor
max_mem = static_cast<int>(hypervisor_mem * static_cast<float>(max_mem));
//Init search xpath routes
ObjectXML::paths = host_paths;
ObjectXML::num_paths = host_num_paths;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int HostXML::search(const char *name, int& value)
{
string s_name(name);
if (s_name == "CURRENT_VMS")
{
vector<string>::iterator it;
istringstream iss;
int id;
vector<string> results = (*this)["/HOST/VMS/ID"];
for (it=results.begin(); it!=results.end(); it++)
{
iss.clear();
iss.str(*it);
iss >> id;
if (!iss.fail() && id == value)
{
return 0; //VMID found in VMS value is VMID
}
}
value = -1; //VMID not found in VMS value is -1
return 0;
}
else
{
return ObjectXML::search(name, value);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -26,7 +26,9 @@ source_files=[
'HostXML.cc',
'VirtualMachinePoolXML.cc',
'VirtualMachineXML.cc',
'ClusterPoolXML.cc']
'ClusterPoolXML.cc',
'DatastorePoolXML.cc',
'DatastoreXML.cc']
# Build library
sched_env.StaticLibrary(lib_name, source_files)

View File

@ -96,22 +96,21 @@ int VirtualMachinePoolXML::load_info(xmlrpc_c::value &result)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachinePoolXML::dispatch(int vid, int hid, bool resched) const
int VirtualMachinePoolXML::dispatch(int vid, int hid, int dsid, bool resched) const
{
ostringstream oss;
xmlrpc_c::value deploy_result;
if (resched == true)
{
oss << "Rescheduling ";
oss << "Rescheduling " << "VM " << vid << " to host " << hid;
}
else
{
oss << "Dispatching ";
oss << "Dispatching " << "VM " << vid << " to host " << hid
<< " and datastore " << dsid;
}
oss << "virtual machine " << vid << " to host " << hid;
NebulaLog::log("VM",Log::INFO,oss);
try
@ -132,12 +131,13 @@ int VirtualMachinePoolXML::dispatch(int vid, int hid, bool resched) const
{
client->call(client->get_endpoint(), // serverUrl
"one.vm.deploy", // methodName
"siib", // arguments format
"siibi", // arguments format
&deploy_result, // resultP
client->get_oneauth().c_str(), // argument 0 (AUTH)
vid, // argument 1 (VM)
hid, // argument 2 (HOST)
false); // argument 3 (ENFORCE)
false, // argument 3 (ENFORCE)
dsid); // argument 5 (SYSTEM SD)
}
}
catch (exception const& e)

View File

@ -24,6 +24,8 @@ void VirtualMachineXML::init_attributes()
vector<string> result;
vector<xmlNodePtr> nodes;
string automatic_requirements;
oid = atoi(((*this)["/VM/ID"] )[0].c_str());
uid = atoi(((*this)["/VM/UID"])[0].c_str());
gid = atoi(((*this)["/VM/GID"])[0].c_str());
@ -52,6 +54,8 @@ void VirtualMachineXML::init_attributes()
cpu = 0;
}
// ------------------------ RANK & DS_RANK ---------------------------------
result = ((*this)["/VM/USER_TEMPLATE/SCHED_RANK"]);
if (result.size() > 0)
@ -67,28 +71,33 @@ void VirtualMachineXML::init_attributes()
{
rank = result[0];
}
else
}
result = ((*this)["/VM/USER_TEMPLATE/SCHED_DS_RANK"]);
if (result.size() > 0)
{
rank = "";
}
ds_rank = result[0];
}
// ------------------- REQUIREMENTS & DS_REQUIREMENTS ----------------------
result = ((*this)["/VM/TEMPLATE/AUTOMATIC_REQUIREMENTS"]);
if (result.size() > 0)
{
requirements = result[0];
automatic_requirements = result[0];
}
result = ((*this)["/VM/USER_TEMPLATE/SCHED_REQUIREMENTS"]);
if (result.size() > 0)
{
if ( !requirements.empty() )
if ( !automatic_requirements.empty() )
{
ostringstream oss;
oss << requirements << " & ( " << result[0] << " )";
oss << automatic_requirements << " & ( " << result[0] << " )";
requirements = oss.str();
}
@ -97,6 +106,34 @@ void VirtualMachineXML::init_attributes()
requirements = result[0];
}
}
else if ( !automatic_requirements.empty() )
{
requirements = automatic_requirements;
}
result = ((*this)["/VM/USER_TEMPLATE/SCHED_DS_REQUIREMENTS"]);
if (result.size() > 0)
{
if ( !automatic_requirements.empty() )
{
ostringstream oss;
oss << automatic_requirements << " & ( " << result[0] << " )";
ds_requirements = oss.str();
}
else
{
ds_requirements = result[0];
}
}
else if ( !automatic_requirements.empty() )
{
ds_requirements = automatic_requirements;
}
// ---------------- HISTORY HID, DSID, RESCHED & TEMPLATE ------------------
result = ((*this)["/VM/HISTORY_RECORDS/HISTORY/HID"]);
@ -109,6 +146,17 @@ void VirtualMachineXML::init_attributes()
hid = -1;
}
result = ((*this)["/VM/HISTORY_RECORDS/HISTORY/DS_ID"]);
if (result.size() > 0)
{
dsid = atoi(result[0].c_str());
}
else
{
dsid = -1;
}
result = ((*this)["/VM/RESCHED"]);
if (result.size() > 0)
@ -137,120 +185,43 @@ void VirtualMachineXML::init_attributes()
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VirtualMachineXML::~VirtualMachineXML()
ostream& operator<<(ostream& os, VirtualMachineXML& vm)
{
vector<VirtualMachineXML::Host *>::iterator jt;
const vector<Resource *> resources = vm.match_hosts.get_resources();
for (jt=hosts.begin();jt!=hosts.end();jt++)
vector<Resource *>::const_reverse_iterator i;
if (resources.empty())
{
delete *jt;
return os;
}
hosts.clear();
os << "Virtual Machine: " << vm.oid << endl << endl;
if (vm_template != 0)
os << "\tPRI\tID - HOSTS"<< endl
<< "\t------------------------" << endl;
for (i = resources.rbegin(); i != resources.rend() ; i++)
{
delete vm_template;
}
os << "\t" << (*i)->priority << "\t" << (*i)->oid << endl;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
os << endl;
void VirtualMachineXML::add_host(int host_id)
os << "\tPRI\tID - DATASTORES"<< endl
<< "\t------------------------" << endl;
const vector<Resource *> ds_resources = vm.match_datastores.get_resources();
for (i = ds_resources.rbegin(); i != ds_resources.rend() ; i++)
{
if (( resched == 1 && host_id != hid ) || ( resched == 0 ))
{
VirtualMachineXML::Host * ss;
ss = new VirtualMachineXML::Host(host_id);
hosts.push_back(ss);
}
os << "\t" << (*i)->priority << "\t" << (*i)->oid << endl;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
os << endl;
void VirtualMachineXML::get_matching_hosts(vector<int>& mh)
{
vector<VirtualMachineXML::Host *>::iterator i;
for(i=hosts.begin();i!=hosts.end();i++)
{
mh.push_back((*i)->hid);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineXML::set_priorities(vector<float>& total)
{
if ( hosts.size() != total.size() )
{
NebulaLog::log("VM",Log::ERROR,"Wrong size for priority vector");
return;
}
for (unsigned int i=0; i<hosts.size(); i++)
{
hosts[i]->priority = total[i];
}
//Sort the shares using the priority
sort(hosts.begin(),hosts.end(),VirtualMachineXML::host_cmp);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachineXML::get_host(int& hid,
HostPoolXML * hpool,
map<int,int>& host_vms,
int max_vms)
{
vector<VirtualMachineXML::Host *>::reverse_iterator i;
vector<int>::iterator j;
HostXML * host;
int cpu;
int mem;
int dsk;
pair<map<int,int>::iterator,bool> rc;
get_requirements(cpu,mem,dsk);
for (i=hosts.rbegin();i!=hosts.rend();i++)
{
host = hpool->get( (*i)->hid );
if ( host == 0 )
{
continue;
}
if (host->test_capacity(cpu,mem,dsk)==true)
{
rc = host_vms.insert(make_pair((*i)->hid,0));
if ( rc.first->second < max_vms )
{
host->add_capacity(cpu,mem,dsk);
hid = (*i)->hid;
rc.first->second++;
return 0;
}
}
}
hid = -1;
return -1;
}
return os;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -14,11 +14,9 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include <stdexcept>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
@ -216,6 +214,7 @@ void Scheduler::start()
machines_limit,
(live_rescheds == 1));
vmapool= new VirtualMachineActionsPoolXML(client, machines_limit);
dspool = new DatastorePoolXML(client);
acls = new AclXML(client);
@ -314,6 +313,17 @@ int Scheduler::set_up_pools()
return rc;
}
//--------------------------------------------------------------------------
//Cleans the cache and get the datastores
//--------------------------------------------------------------------------
rc = dspool->set_up();
if ( rc != 0 )
{
return rc;
}
//--------------------------------------------------------------------------
//Cleans the cache and get the hosts ids
//--------------------------------------------------------------------------
@ -353,19 +363,13 @@ int Scheduler::set_up_pools()
return rc;
}
//--------------------------------------------------------------------------
//Get the matching hosts for each VM
//--------------------------------------------------------------------------
match();
return 0;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Scheduler::match()
void Scheduler::match_schedule()
{
VirtualMachineXML * vm;
@ -382,8 +386,11 @@ void Scheduler::match()
int n_error;
string reqs;
string ds_reqs;
HostXML * host;
DatastoreXML *ds;
char * error;
bool matched;
@ -392,8 +399,11 @@ void Scheduler::match()
map<int, ObjectXML*>::const_iterator vm_it;
map<int, ObjectXML*>::const_iterator h_it;
vector<SchedulerPolicy *>::iterator it;
const map<int, ObjectXML*> pending_vms = vmpool->get_objects();
const map<int, ObjectXML*> hosts = hpool->get_objects();
const map<int, ObjectXML*> datastores = dspool->get_objects();
for (vm_it=pending_vms.begin(); vm_it != pending_vms.end(); vm_it++)
{
@ -405,11 +415,20 @@ void Scheduler::match()
uid = vm->get_uid();
gid = vm->get_gid();
vm->get_requirements(vm_cpu,vm_memory,vm_disk);
n_hosts = 0;
n_matched = 0;
n_auth = 0;
n_error = 0;
// ---------------------------------------------------------------------
// Match hosts for this VM that:
// 1. Fulfills ACL
// 2. Meets user/policy requirements
// 3. Have enough capacity to host the VM
// ---------------------------------------------------------------------
for (h_it=hosts.begin(), matched=false; h_it != hosts.end(); h_it++)
{
host = static_cast<HostXML *>(h_it->second);
@ -462,7 +481,7 @@ void Scheduler::match()
// Evaluate VM requirements
// -----------------------------------------------------------------
if (reqs != "")
if (!reqs.empty())
{
rc = host->eval_bool(reqs,matched,&error);
@ -474,10 +493,11 @@ void Scheduler::match()
matched = false;
n_error++;
error_msg << "Error evaluating SCHED_REQUIREMENTS expression: '"
<< reqs << "', error: " << error;
error_msg << "Error in SCHED_REQUIREMENTS: '" << reqs
<< "', error: " << error;
oss << "VM " << oid << ": " << error_msg.str();
NebulaLog::log("SCHED",Log::ERROR,oss);
vm->log(error_msg.str());
@ -508,12 +528,9 @@ void Scheduler::match()
// -----------------------------------------------------------------
// Check host capacity
// -----------------------------------------------------------------
vm->get_requirements(vm_cpu,vm_memory,vm_disk);
if (host->test_capacity(vm_cpu,vm_memory,vm_disk) == true)
{
vm->add_host(host->get_hid());
vm->add_match_host(host->get_hid());
n_hosts++;
}
@ -546,7 +563,7 @@ void Scheduler::match()
}
else if (n_matched == 0)
{
vm->log("No host meets the SCHED_REQUIREMENTS expression");
vm->log("No host meets SCHED_REQUIREMENTS");
}
else
{
@ -555,85 +572,186 @@ void Scheduler::match()
}
vmpool->update(vm);
}
}
continue;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static float sum_operator (float i, float j)
{
return i+j;
}
/* -------------------------------------------------------------------------- */
int Scheduler::schedule()
{
vector<SchedulerHostPolicy *>::iterator it;
VirtualMachineXML * vm;
ostringstream oss;
vector<float> total;
vector<float> policy;
map<int, ObjectXML*>::const_iterator vm_it;
const map<int, ObjectXML*> pending_vms = vmpool->get_objects();
for (vm_it=pending_vms.begin(); vm_it != pending_vms.end(); vm_it++)
{
vm = static_cast<VirtualMachineXML*>(vm_it->second);
total.clear();
// ---------------------------------------------------------------------
// Schedule matched hosts
// ---------------------------------------------------------------------
for (it=host_policies.begin() ; it != host_policies.end() ; it++)
{
policy = (*it)->get(vm);
(*it)->schedule(vm);
}
if (total.empty() == true)
vm->sort_match_hosts();
if (vm->is_resched())
{
total = policy;
// Do not schedule storage for migrations, the VMs needs to be
// deployed in the same system DS
vm->add_match_datastore(vm->get_dsid());
continue;
}
// ---------------------------------------------------------------------
// Match datastores for this VM that:
// 2. Meets requirements
// 3. Have enough capacity to host the VM
// ---------------------------------------------------------------------
ds_reqs = vm->get_ds_requirements();
n_hosts = 0;
n_matched = 0;
n_error = 0;
for (h_it=datastores.begin(), matched=false; h_it != datastores.end(); h_it++)
{
ds = static_cast<DatastoreXML *>(h_it->second);
// -----------------------------------------------------------------
// Evaluate VM requirements
// -----------------------------------------------------------------
if (!ds_reqs.empty())
{
rc = ds->eval_bool(ds_reqs, matched, &error);
if ( rc != 0 )
{
ostringstream oss;
ostringstream error_msg;
matched = false;
n_error++;
error_msg << "Error in SCHED_DS_REQUIREMENTS: '" << ds_reqs
<< "', error: " << error;
oss << "VM " << oid << ": " << error_msg.str();
NebulaLog::log("SCHED",Log::ERROR,oss);
vm->log(error_msg.str());
free(error);
break;
}
}
else
{
transform(
total.begin(),
total.end(),
policy.begin(),
total.begin(),
sum_operator);
matched = true;
}
if ( matched == false )
{
ostringstream oss;
oss << "VM " << oid << ": Datastore " << ds->get_oid() <<
" filtered out. It does not fulfill SCHED_DS_REQUIREMENTS.";
NebulaLog::log("SCHED",Log::DEBUG,oss);
continue;
}
n_matched++;
// -----------------------------------------------------------------
// Check datastore capacity
// -----------------------------------------------------------------
if (ds->test_capacity(vm_disk))
{
vm->add_match_datastore(ds->get_oid());
n_hosts++;
}
else
{
ostringstream oss;
oss << "VM " << oid << ": Datastore " << ds->get_oid()
<< " filtered out. Not enough capacity.";
NebulaLog::log("SCHED",Log::DEBUG,oss);
}
}
vm->set_priorities(total);
// ---------------------------------------------------------------------
// Log scheduling errors to VM user if any
// ---------------------------------------------------------------------
if (n_hosts == 0) //No datastores assigned, let's see why
{
if (n_error == 0) //No syntax error
{
if (datastores.size() == 0)
{
vm->log("No system datastores found to run VMs");
}
else if (n_matched == 0)
{
vm->log("No system datastore meets SCHED_DS_REQUIREMENTS");
}
else
{
vm->log("No system datastore with enough capacity for the VM");
}
}
return 0;
};
vm->clear_match_hosts();
vmpool->update(vm);
continue;
}
// ---------------------------------------------------------------------
// Schedule matched datastores
// ---------------------------------------------------------------------
for (it=ds_policies.begin() ; it != ds_policies.end() ; it++)
{
(*it)->schedule(vm);
}
vm->sort_match_datastores();
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Scheduler::dispatch()
{
HostXML * host;
DatastoreXML * ds;
VirtualMachineXML * vm;
ostringstream oss;
int hid;
int rc;
unsigned int dispatched_vms;
int cpu, mem, dsk;
int hid, dsid, cid;
map<int, ObjectXML*>::const_iterator vm_it;
unsigned int dispatched_vms = 0;
map<int, unsigned int> host_vms;
pair<map<int,unsigned int>::iterator, bool> rc;
vector<Resource *>::const_reverse_iterator i, j;
const map<int, ObjectXML*> pending_vms = vmpool->get_objects();
map<int, int> host_vms;
//--------------------------------------------------------------------------
// Print the VMs to schedule and the selected hosts for each one
//--------------------------------------------------------------------------
oss << "Selected hosts:" << endl;
oss << "Scheduling Results:" << endl;
for (vm_it=pending_vms.begin(); vm_it != pending_vms.end(); vm_it++)
for (map<int, ObjectXML*>::const_iterator vm_it=pending_vms.begin();
vm_it != pending_vms.end(); vm_it++)
{
vm = static_cast<VirtualMachineXML*>(vm_it->second);
@ -642,24 +760,127 @@ void Scheduler::dispatch()
NebulaLog::log("SCHED", Log::INFO, oss);
dispatched_vms = 0;
for (vm_it=pending_vms.begin();
vm_it != pending_vms.end() && ( dispatch_limit <= 0 ||
dispatched_vms < dispatch_limit );
//--------------------------------------------------------------------------
// Dispatch each VM till we reach the dispatch limit
//--------------------------------------------------------------------------
for (map<int, ObjectXML*>::const_iterator vm_it=pending_vms.begin();
vm_it != pending_vms.end() &&
( dispatch_limit <= 0 || dispatched_vms < dispatch_limit );
vm_it++)
{
vm = static_cast<VirtualMachineXML*>(vm_it->second);
rc = vm->get_host(hid,hpool,host_vms,host_dispatch_limit);
vm->get_requirements(cpu,mem,dsk);
if (rc == 0)
{
rc = vmpool->dispatch(vm_it->first, hid, vm->is_resched());
//----------------------------------------------------------------------
// Get the highest ranked host and best System DS for it
//----------------------------------------------------------------------
const vector<Resource *> resources = vm->get_match_hosts();
if (rc == 0 && !vm->is_resched())
for (i = resources.rbegin() ; i != resources.rend() ; i++)
{
dispatched_vms++;
hid = (*i)->oid;
host = hpool->get(hid);
if ( host == 0 )
{
continue;
}
cid = host->get_cid();
//------------------------------------------------------------------
// Test host capcity
//------------------------------------------------------------------
if (host->test_capacity(cpu,mem,dsk) != true)
{
continue;
}
//------------------------------------------------------------------
// Test host dispatch limit (init counter if needed)
//------------------------------------------------------------------
rc = host_vms.insert(make_pair(hid,0));
if (rc.first->second >= host_dispatch_limit)
{
continue;
}
//------------------------------------------------------------------
// Get the highest ranked datastore
//------------------------------------------------------------------
const vector<Resource *> ds_resources = vm->get_match_datastores();
dsid = -1;
for (j = ds_resources.rbegin() ; j != ds_resources.rend() ; j++)
{
ds = dspool->get((*j)->oid);
if ( ds == 0 )
{
continue;
}
//--------------------------------------------------------------
// Test cluster membership for datastore and selected host
//--------------------------------------------------------------
if (ds->get_cid() != cid)
{
continue;
}
//--------------------------------------------------------------
// Test datastore capacity, but not for migrations
//--------------------------------------------------------------
if (!vm->is_resched() && ds->test_capacity(dsk) != true)
{
continue;
}
//--------------------------------------------------------------
//Select this DS to dispatch VM
//--------------------------------------------------------------
dsid = (*j)->oid;
break;
}
if (dsid == -1)
{
ostringstream oss;
oss << "No suitable System DS found for Host: " << hid
<< ". Filtering out host.";
NebulaLog::log("SCHED", Log::INFO, oss);
continue;
}
//------------------------------------------------------------------
// Dispatch and update host and DS capacity, and dispatch counters
//------------------------------------------------------------------
if (vmpool->dispatch(vm_it->first, hid, dsid, false) != 0)
{
continue;
}
// DS capacity is only added for new deployments, not for migrations
if (!vm->is_resched())
{
ds->add_capacity(dsk);
}
host->add_capacity(cpu,mem,dsk);
host_vms[hid]++;
dispatched_vms++;
break;
}
}
}
@ -782,12 +1003,7 @@ void Scheduler::do_action(const string &name, void *args)
return;
}
rc = schedule();
if ( rc != 0 )
{
return;
}
match_schedule();
dispatch();
}

View File

@ -41,6 +41,7 @@ void SchedulerTemplate::set_conf_default()
# MAX_DISPATCH
# MAX_HOST
# DEFAULT_SCHED
# DEFAULT_DS_SCHED
# LIVE_RESCHEDS
# HYPERVISOR_MEM
# LOG
@ -89,6 +90,13 @@ void SchedulerTemplate::set_conf_default()
vattribute = new VectorAttribute("DEFAULT_SCHED",vvalue);
conf_default.insert(make_pair(vattribute->name(),vattribute));
//DEFAULT_DS_SCHED
vvalue.clear();
vvalue.insert(make_pair("POLICY","1"));
vattribute = new VectorAttribute("DEFAULT_DS_SCHED",vvalue);
conf_default.insert(make_pair(vattribute->name(),vattribute));
//HYPERVISOR_MEM
value = "0.1";
@ -119,6 +127,11 @@ string SchedulerTemplate::get_policy() const
get("DEFAULT_SCHED", vsched);
if (vsched.empty())
{
return "";
}
sched = static_cast<const VectorAttribute *> (vsched[0]);
iss.str(sched->vector_value("POLICY"));
@ -148,3 +161,49 @@ string SchedulerTemplate::get_policy() const
return rank;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string SchedulerTemplate::get_ds_policy() const
{
int policy;
string rank;
istringstream iss;
vector<const Attribute *> vsched;
const VectorAttribute * sched;
get("DEFAULT_DS_SCHED", vsched);
if (vsched.empty())
{
return "";
}
sched = static_cast<const VectorAttribute *> (vsched[0]);
iss.str(sched->vector_value("POLICY"));
iss >> policy;
switch (policy)
{
case 0: //Packing
rank = "- FREE_MB";
break;
case 1: //Striping
rank = "FREE_MB";
break;
case 2: //Custom
rank = sched->vector_value("RANK");
break;
default:
rank = "";
}
return rank;
}

View File

@ -32,26 +32,35 @@ class RankScheduler : public Scheduler
{
public:
RankScheduler():Scheduler(),rp(0){};
RankScheduler():Scheduler(),rp_host(0),rp_ds(0){};
~RankScheduler()
{
if ( rp != 0 )
if ( rp_host != 0 )
{
delete rp;
delete rp_host;
}
if ( rp_ds != 0 )
{
delete rp_ds;
}
};
void register_policies(const SchedulerTemplate& conf)
{
rp = new RankPolicy(vmpool, hpool, conf.get_policy(), 1.0);
rp_host = new RankHostPolicy(hpool, conf.get_policy(), 1.0);
add_host_policy(rp);
add_host_policy(rp_host);
rp_ds = new RankDatastorePolicy(dspool, conf.get_ds_policy(), 1.0);
add_ds_policy(rp_ds);
};
private:
RankPolicy * rp;
RankPolicy * rp_host;
RankPolicy * rp_ds;
};
int main(int argc, char **argv)

View File

@ -88,7 +88,7 @@ module OpenNebulaJSON
end
def deploy(params=Hash.new)
super(params['host_id'])
super(params['host_id'], params['enforce'], params['ds_id'])
end
def undeploy(params=Hash.new)

View File

@ -704,7 +704,7 @@ var OpenNebula = {
OpenNebula.Action.show(params,OpenNebula.VM.resource,"log");
},
"deploy": function(params){
var action_obj = {"host_id": params.data.extra_param};
var action_obj = params.data.extra_param;
OpenNebula.Action.simple_action(params,OpenNebula.VM.resource,
"deploy",action_obj);
},

View File

@ -1366,6 +1366,28 @@ function update_datatable_template_hosts(datatable, fnDrawCallback) {
});
}
function update_datatable_template_datastores(datatable, fnDrawCallback) {
if (fnDrawCallback) {
datatable.unbind('draw');
datatable.on('draw', fnDrawCallback);
}
OpenNebula.Datastore.list({
timeout: true,
success: function (request, datastore_list){
var datastore_list_array = [];
$.each(datastore_list,function(){
//Grab table data from the datastore_list
datastore_list_array.push(datastoreElementArray(this));
});
updateView(datastore_list_array, datatable);
},
error: onError
});
}
function update_datatable_template_clusters(datatable, fnDrawCallback) {
if (fnDrawCallback) {
datatable.unbind('draw');
@ -3397,8 +3419,10 @@ function setupCreateTemplateDialog(){
'<dd class="active"><a href="#placement">'+tr("Placement")+'</a></dd>'+
'<dd><a href="#policy">'+tr("Policy")+'</a></dd>'+
'</dl>'+
'<ul class="tabs-content">'+
'<ul class="tabs-content row">'+
'<li class="requirements wizard_internal_tab active" id="placementTab">'+
'<fieldset>'+
'<legend>'+tr("Host Requirements")+'</legend>'+
'<div class="row">'+
'<div class="three columns push-three">'+
'<input type="radio" id="hosts_req" name="req_select" value="host_select" checked> '+tr("Select Hosts ")+
@ -3408,7 +3432,7 @@ function setupCreateTemplateDialog(){
'</div>'+
'</div>'+
'<hr>'+
'<div id="req_type" class="host_select row">'+
'<div id="req_type" class="host_select ">'+
'<div class="row collapse ">'+
'<div class="seven columns">' +
'<button id="refresh_hosts_placement" type="button" class="refresh button small radius secondary"><i class="icon-refresh" /></button>' +
@ -3445,7 +3469,7 @@ function setupCreateTemplateDialog(){
'</div>'+
'<br>'+
'</div>'+
'<div id="req_type" class="cluster_select hidden row">'+
'<div id="req_type" class="cluster_select hidden">'+
'<div class="row collapse ">'+
'<div class="seven columns">' +
'<button id="refresh_clusters_placement" type="button" class="refresh button small radius secondary"><i class="icon-refresh" /></button>' +
@ -3475,10 +3499,10 @@ function setupCreateTemplateDialog(){
'</div>'+
'<br>'+
'</div>'+
'<hr>'+
'<br>'+
'<div class="row vm_param">'+
'<div class="two columns">'+
'<label class="inline right" for="SCHED_REQUIREMENTS">'+tr("Requirements")+':</label>'+
'<label class="inline right" for="SCHED_REQUIREMENTS">'+tr("Expression")+':</label>'+
'</div>'+
'<div class="nine columns">'+
'<input type="text" id="SCHED_REQUIREMENTS" name="requirements" />'+
@ -3487,32 +3511,44 @@ function setupCreateTemplateDialog(){
'<div class="tip">'+tr("Boolean expression that rules out provisioning hosts from list of machines suitable to run this VM")+'.</div>'+
'</div>'+
'</div>'+
'</fieldset>'+
'<br>'+
'<fieldset>'+
'<legend>'+tr("Datastore Requirements")+'</legend>'+
'<div class="row vm_param">'+
'<div class="two columns">'+
'<label class="inline right" for="SCHED_DS_REQUIREMENTS">'+tr("Expression")+':</label>'+
'</div>'+
'<div class="nine columns">'+
'<input type="text" id="SCHED_DS_REQUIREMENTS" name="requirements" />'+
'</div>'+
'<div class="one columns">'+
'<div class="tip">'+tr("")+'.</div>'+
'</div>'+
'</div>'+
'</fieldset>'+
'</li>'+
'<li id="policyTab" class="wizard_internal_tab">'+
'<fieldset class="host_rank">'+
'<legend>'+tr("Host Rank")+'</legend>'+
'<div class="row">'+
'<div class="two columns push-two">'+
'<div class="four columns" style="text-align:center">'+
'<input type="radio" id="packingRadio" name="rank_select" value="RUNNING_VMS"> '+tr("Packing")+
'&nbsp;&nbsp;<span class="tip">'+tr("Pack the VMs in the cluster nodes to reduce VM fragmentation")+'</span>'+
'</div>'+
'<div class="one columns push-two">'+
'<div class="tip">'+tr("Pack the VMs in the cluster nodes to reduce VM fragmentation")+'</div>'+
'</div>'+
'<div class="two columns push-two">'+
'<div class="four columns" style="text-align:center">'+
'<input type="radio" id="stripingRadio" name="rank_select" value="-RUNNING_VMS"> '+tr("Stripping")+
'&nbsp;&nbsp;<span class="tip">'+tr("Spread the VMs in the cluster nodes")+'</span>'+
'</div>'+
'<div class="one columns push-two">'+
'<div class="tip">'+tr("Spread the VMs in the cluster nodes")+'</div>'+
'</div>'+
'<div class="two columns push-two">'+
'<div class="four columns" style="text-align:center">'+
'<input type="radio" id="loadawareRadio" name="rank_select" value="FREECPU"> '+tr("Load-aware")+
'</div>'+
'<div class="two columns">'+
'<div class="tip">'+tr("Maximize the resources available to VMs in a node")+'</div>'+
'&nbsp;&nbsp;<span class="tip">'+tr("Maximize the resources available to VMs in a node")+'</span>'+
'</div>'+
'</div>'+
'<hr>'+
'<div class="row vm_param">'+
'<div class="two columns">'+
'<label class="inline right" for="SCHED_RANK">'+tr("Rank")+':</label>'+
'<label class="inline right" for="SCHED_RANK">'+tr("Expression")+':</label>'+
'</div>'+
'<div class="nine columns">'+
'<input type="text" id="SCHED_RANK" name="RANK" />'+
@ -3521,6 +3557,33 @@ function setupCreateTemplateDialog(){
'<div class="tip">'+tr("This field sets which attribute will be used to sort the suitable hosts for this VM")+'.</div>'+
'</div>'+
'</div>'+
'</fieldset>'+
'<br>'+
'<fieldset class="ds_rank">'+
'<legend>'+tr("Datastore Rank")+'</legend>'+
'<div class="row">'+
'<div class="six columns" style="text-align:center">'+
'<input type="radio" id="packingRadio" name="ds_rank_select" value="-FREE_MB"> '+tr("Packing")+
'&nbsp;&nbsp;<span class="tip">'+tr("Tries to optimize storage usage by selecting the DS with less free space")+'</span>'+
'</div>'+
'<div class="six columns" style="text-align:center">'+
'<input type="radio" id="stripingRadio" name="ds_rank_select" value="FREE_MB"> '+tr("Stripping")+
'&nbsp;&nbsp;<span class="tip">'+tr("Striping. Tries to optimize I/O by distributing the VMs across datastores.")+'</span>'+
'</div>'+
'</div>'+
'<hr>'+
'<div class="row vm_param">'+
'<div class="two columns">'+
'<label class="inline right" for="SCHED_DS_RANK">'+tr("Expression")+':</label>'+
'</div>'+
'<div class="nine columns">'+
'<input type="text" id="SCHED_DS_RANK" name="RANK" />'+
'</div>'+
'<div class="one columns">'+
'<div class="tip">'+tr("This field sets which attribute will be used to sort the suitable datastores for this VM")+'.</div>'+
'</div>'+
'</div>'+
'</fieldset>'+
'</li>'+
'</ul>'+
'</form>'+
@ -3705,10 +3768,14 @@ function setupCreateTemplateDialog(){
}
});
$("input[name='rank_select']").change(function(){
$("input[name='rank_select']", $(".host_rank")).change(function(){
$("#SCHED_RANK", dialog).val(this.value);
});
$("input[name='ds_rank_select']", $(".ds_rank")).change(function(){
$("#SCHED_DS_RANK", dialog).val(this.value);
});
var generate_requirements = function() {
var req_string=[];
@ -4768,21 +4835,31 @@ function fillTemplatePopUp(request, response){
delete template.SCHED_REQUIREMENTS;
}
var ds_req = template.SCHED_DS_REQUIREMENTS;
var ds_req_section = $('li#schedulingTab', $create_template_dialog);
if (ds_req) {
ds_req = escapeDoubleQuotes(ds_req);
$('input#SCHED_DS_REQUIREMENTS', req_section).val(ds_req);
delete template.SCHED_DS_REQUIREMENTS;
}
var rank = template.SCHED_RANK;
if (rank) {
var striping_regexp = /-RUNNING_VMS/;
var packing_regexp = /RUNNING_VMS/;
var loadaware_regexp = /FREECPU/;
var striping_regexp = /^-RUNNING_VMS$/;
var packing_regexp = /^RUNNING_VMS$/;
var loadaware_regexp = /^FREECPU$/;
if (striping_regexp.test(rank)) {
$('input#stripingRadio', req_section).click()
$('input[name="rank_select"]#stripingRadio', req_section).click()
}
else if (packing_regexp.test(rank)) {
$('input#packingRadio', req_section).click()
$('input[name="rank_select"]#packingRadio', req_section).click()
}
else if (loadaware_regexp.test(rank)) {
$('input#loadawareRadio', req_section).click()
$('input[name="rank_select"]#loadawareRadio', req_section).click()
}
$('input#SCHED_RANK', req_section).val(rank);
@ -4790,6 +4867,24 @@ function fillTemplatePopUp(request, response){
delete template.SCHED_RANK;
}
var ds_rank = template.SCHED_DS_RANK;
if (ds_rank) {
var striping_regexp = /^FREE_MB$/;
var packing_regexp = /^-FREE_MB$/;
if (striping_regexp.test(ds_rank)) {
$('input[name="ds_rank_select"]#stripingRadio', req_section).click()
}
else if (packing_regexp.test(ds_rank)) {
$('input[name="ds_rank_select"]#packingRadio', req_section).click()
}
$('input#SCHED_DS_RANK', req_section).val(ds_rank);
delete template.SCHED_DS_RANK;
}
//
// RAW
//

View File

@ -251,9 +251,148 @@ var create_vm_tmpl ='\
</form>\
</div>';
var deploy_vm_tmpl ='\
<div class="panel">\
<h3>\
<small id="deploy_vm_header">'+tr("Deploy Virtual Machine")+'</small>\
</h3>\
</div>\
<div class="reveal-body">\
<form id="deploy_vm_form" action="">\
<div class="row">\
<fieldset>\
<legend>'+tr("Select a Host")+'</legend>\
<div class="row collapse">\
<div class="seven columns">\
<button id="refresh_deploy_hosts_table_button_class" type="button" class="button small radius secondary"><i class="icon-refresh" /></button>\
</div>\
<div class="five columns">\
<input id="deploy_hosts_table_search" type="text" placeholder="'+tr("Search")+'"/>\
</div>\
</div>\
<table id="deploy_datatable_hosts" class="datatable twelve">\
<thead>\
<tr>\
<th></th>\
<th>' + tr("ID") + '</th>\
<th>' + tr("Name") + '</th>\
<th>' + tr("Cluster") + '</th>\
<th>' + tr("RVMs") + '</th>\
<th>' + tr("Real CPU") + '</th>\
<th>' + tr("Allocated CPU") + '</th>\
<th>' + tr("Real MEM") + '</th>\
<th>' + tr("Allocated MEM") + '</th>\
<th>' + tr("Status") + '</th>\
<th>' + tr("IM MAD") + '</th>\
<th>' + tr("VM MAD") + '</th>\
<th>' + tr("Last monitored on") + '</th>\
</tr>\
</thead>\
<tbody id="tbodyhosts">\
</tbody>\
</table>\
<div class="row hidden">\
<div class="four columns">\
<label class="right inline" for="HOST_ID">'+tr("HOST_ID")+':</label>\
</div>\
<div class="six columns">\
<input type="text" id="HOST_ID" name="HOST_ID"/>\
</div>\
<div class="two columns">\
<div class="tip">\
</div>\
</div>\
</div>\
<br>\
<div id="selected_host" class="vm_param kvm_opt xen_opt vmware_opt">\
<span id="select_host" class="radius secondary label">'+tr("Please select a Host from the list")+'</span>\
<span id="host_selected" class="radius secondary label hidden">'+tr("You selected the following Host:")+'</span>\
<span class="radius label" type="text" id="HOST_NAME" name="host"></span>\
</div>\
</fieldset>\
</div>\
<br>\
<br>\
<div class="show_hide" id="advanced_toggle">\
<h4><small><i class=" icon-caret-down"/> '+tr("Advanced options")+'<a id="" class="icon_left" href="#"></a></small></h4>\
</div>\
<div id="advanced_deploy" class="row advanced">\
<div class="row">\
<div class="three columns">\
<label class="inline right" for="vm_id">'+tr("Enforce")+':</label>\
</div>\
<div class="two columns">\
<input type="checkbox" name="enforce" id="enforce"/>\
</div>\
<div class="one columns pull-seven tip">'
+ tr("If it is set to true, the host capacity will be checked. This will only affect oneadmin requests, regular users resize requests will always be enforced") +
'</div>\
</div>\
<br>\
<fieldset>\
<legend>'+tr("Select a datastore")+'</legend>\
<div class="row collapse">\
<div class="seven columns">\
<button id="refresh_deploy_datastores_table_button_class" type="button" class="button small radius secondary"><i class="icon-refresh" /></button>\
</div>\
<div class="five columns">\
<input id="deploy_datastores_table_search" type="text" placeholder="'+tr("Search")+'"/>\
</div>\
</div>\
<table id="deploy_datatable_datastores" class="datatable twelve">\
<thead>\
<tr>\
<th></th>\
<th>'+tr("ID")+'</th>\
<th>'+tr("Owner")+'</th>\
<th>'+tr("Group")+'</th>\
<th>'+tr("Name")+'</th>\
<th>'+tr("Capacity")+'</th>\
<th>'+tr("Cluster")+'</th>\
<th>'+tr("Basepath")+'</th>\
<th>'+tr("TM MAD")+'</th>\
<th>'+tr("DS MAD")+'</th>\
<th>'+tr("Type")+'</th>\
</tr>\
</thead>\
<tbody id="tbodydatastores">\
</tbody>\
</table>\
<div class="row hidden">\
<div class="four columns">\
<label class="right inline" for="DATASTORE_ID">'+tr("DATASTORE_ID")+':</label>\
</div>\
<div class="six columns">\
<input type="text" id="DATASTORE_ID" name="DATASTORE_ID"/>\
</div>\
<div class="two columns">\
<div class="tip">\
</div>\
</div>\
</div>\
<br>\
<div id="selected_datastore" class="vm_param kvm_opt xen_opt vmware_opt">\
<span id="select_datastore" class="radius secondary label">'+tr("Please select a datastore from the list")+'</span>\
<span id="datastore_selected" class="radius secondary label hidden">'+tr("You selected the following datastore:")+'</span>\
<span class="radius label" type="text" id="DATASTORE_NAME" name="datastore"></span>\
</div>\
</fieldset>\
</div>\
<div class="form_buttons reveal-footer">\
<hr>\
<div class="form_buttons">\
<button class="button radius right success" id="deploy_vm_proceed" value="VM.deploy">'+tr("Deploy")+'</button>\
<button class="close-reveal-modal button secondary radius" type="button" value="close">' + tr("Close") + '</button>\
</div>\
</div>\
<a class="close-reveal-modal">&#215;</a>\
</form>\
</div>';
var vmachine_list_json = {};
var dataTable_vMachines;
var $create_vm_dialog;
var $deploy_vm_dialog;
var $vnc_dialog;
var rfb;
@ -318,10 +457,16 @@ var vm_actions = {
},
"VM.deploy" : {
type: "multiple",
type: "custom",
call: function(){
popUpDeployVMDialog();
}
},
"VM.deploy_action" : {
type: "single",
call: OpenNebula.VM.deploy,
callback: vmShow,
elements: vmElements,
error: onError,
notify: true
},
@ -801,11 +946,10 @@ var vm_buttons = {
condition: mustBeAdmin
},
"VM.deploy" : {
type: "confirm_with_select",
type: "action",
text: tr("Deploy"),
tip: tr("This will deploy the selected VMs on the chosen host"),
layout: "vmsplanification_buttons",
select: hosts_sel,
condition: mustBeAdmin
},
"VM.migrate" : {
@ -3016,6 +3160,165 @@ function popUpCreateVMDialog(include_select_image){
$("input#vm_name",$create_vm_dialog).focus();
}
// Sets up the create-template dialog and all the processing associated to it,
// which is a lot.
function setupDeployVMDialog(){
dialogs_context.append('<div id="deploy_vm_dialog"></div>');
//Insert HTML in place
$deploy_vm_dialog = $('#deploy_vm_dialog')
var dialog = $deploy_vm_dialog;
dialog.html(deploy_vm_tmpl);
dialog.addClass("reveal-modal large max-height");
var dataTable_deploy_hosts = $('#deploy_datatable_hosts', dialog).dataTable({
"iDisplayLength": 4,
"bAutoWidth":false,
"sDom" : '<"H">t<"F"p>',
"aoColumnDefs": [
{ "bSortable": false, "aTargets": ["check",5,6,7,8] },
{ "sWidth": "35px", "aTargets": [0] }, //check, ID, RVMS, Status,
{ "bVisible": false, "aTargets": [3,5,7,10,11,12]}
],
"fnDrawCallback": function(oSettings) {
var nodes = this.fnGetNodes();
$.each(nodes, function(){
if ($(this).find("td:eq(0)").html() == $('#HOST_ID', dialog).val()) {
$("td", this).addClass('markrow');
$('input.check_item', this).attr('checked','checked');
}
})
}
});
// Retrieve the images to fill the datatable
update_datatable_template_hosts(dataTable_deploy_hosts);
$('#deploy_hosts_table_search', dialog).keyup(function(){
dataTable_deploy_hosts.fnFilter( $(this).val() );
})
$('#deploy_datatable_hosts tbody', dialog).delegate("tr", "click", function(e){
var aData = dataTable_deploy_hosts.fnGetData(this);
$("td.markrow", dataTable_deploy_hosts).removeClass('markrow');
$('tbody input.check_item', dataTable_deploy_hosts).removeAttr('checked');
$('#host_selected', dialog).show();
$('#select_host', dialog).hide();
$('.alert-box', dialog).hide();
$("td", this).addClass('markrow');
$('input.check_item', this).attr('checked','checked');
$('#HOST_NAME', dialog).text(aData[2]);
$('#HOST_ID', dialog).val(aData[1]);
return true;
});
$("#refresh_deploy_hosts_table_button_class").die();
$("#refresh_deploy_hosts_table_button_class").live('click', function(){
update_datatable_template_hosts($('#deploy_datatable_hosts').dataTable());
});
var dataTable_deploy_datastores = $('#deploy_datatable_datastores', dialog).dataTable({
"iDisplayLength": 4,
"bAutoWidth":false,
"sDom" : '<"H">t<"F"p>',
"aoColumnDefs": [
{ "sWidth": "35px", "aTargets": [0,1] },
{ "bVisible": false, "aTargets": [0,5,7,8,9,10] }
],
"fnDrawCallback": function(oSettings) {
var nodes = this.fnGetNodes();
$.each(nodes, function(){
if ($(this).find("td:eq(0)").html() == $('#DATASTORE_ID', dialog).val()) {
$("td", this).addClass('markrow');
$('input.check_item', this).attr('checked','checked');
}
})
}
});
// Retrieve the images to fill the datatable
update_datatable_template_datastores(dataTable_deploy_datastores);
$('#deploy_datastores_table_search', dialog).keyup(function(){
dataTable_deploy_datastores.fnFilter( $(this).val() );
})
$('#deploy_datatable_datastores tbody', dialog).delegate("tr", "click", function(e){
var aData = dataTable_deploy_datastores.fnGetData(this);
$("td.markrow", dataTable_deploy_datastores).removeClass('markrow');
$('tbody input.check_item', dataTable_deploy_datastores).removeAttr('checked');
$('#datastore_selected', dialog).show();
$('#select_datastore', dialog).hide();
$('.alert-box', dialog).hide();
$("td", this).addClass('markrow');
$('input.check_item', this).attr('checked','checked');
$('#DATASTORE_NAME', dialog).text(aData[4]);
$('#DATASTORE_ID', dialog).val(aData[1]);
return true;
});
$("#refresh_deploy_datastores_table_button_class").die();
$("#refresh_deploy_datastores_table_button_class").live('click', function(){
update_datatable_template_datastores($('#deploy_datatable_datastores').dataTable());
});
dataTable_deploy_datastores.fnFilter("system",10);
$('#advanced_deploy', dialog).hide();
$('#advanced_toggle',dialog).click(function(){
$('#advanced_deploy',dialog).toggle();
return false;
});
setupTips(dialog);
$('#deploy_vm_form',dialog).submit(function(){
var extra_info = {};
if ($('#HOST_ID', dialog).val()) {
extra_info['host_id'] = $('#HOST_ID', dialog).val();
} else {
notifyError(tr("You have not selected a host"));
return false;
}
extra_info['ds_id'] = $('#DATASTORE_ID', dialog).val() || -1
extra_info['enforce'] = $("#enforce", this).is(":checked") ? true : false
//notifySubmit("Template.instantiate",template_id, extra_msg);
$.each(getSelectedNodes(dataTable_vMachines), function(index, elem) {
Sunstone.runAction("VM.deploy_action", elem, extra_info);
});
$deploy_vm_dialog.trigger("reveal:close")
return false;
});
}
// Open creation dialog
function popUpDeployVMDialog(){
setupDeployVMDialog();
$deploy_vm_dialog.reveal();
}
//Prepares autorefresh
function setVMAutorefresh(){
setInterval(function(){

View File

@ -22,7 +22,7 @@
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
ObjectXML::ObjectXML(const string &xml_doc):xml(0),ctx(0)
ObjectXML::ObjectXML(const string &xml_doc):paths(0),num_paths(0),xml(0),ctx(0)
{
try
{
@ -37,7 +37,7 @@ ObjectXML::ObjectXML(const string &xml_doc):xml(0),ctx(0)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
ObjectXML::ObjectXML(const xmlNodePtr node):xml(0),ctx(0)
ObjectXML::ObjectXML(const xmlNodePtr node):paths(0),num_paths(0),xml(0),ctx(0)
{
xml = xmlNewDoc(reinterpret_cast<const xmlChar *>("1.0"));
@ -343,11 +343,17 @@ int ObjectXML::get_nodes (const char * xpath_expr, vector<xmlNodePtr>& content)
obj = xmlXPathEvalExpression(
reinterpret_cast<const xmlChar *>(xpath_expr), ctx);
if (obj == 0 || obj->nodesetval == 0)
if (obj == 0)
{
return 0;
}
if (obj->nodesetval == 0)
{
xmlXPathFreeObject(obj);
return 0;
}
xmlNodeSetPtr ns = obj->nodesetval;
int size = ns->nodeNr;
int num_nodes = 0;
@ -671,3 +677,110 @@ error_yy:
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
void ObjectXML::search(const char* name, vector<string>& results)
{
if (name[0] == '/')
{
results = (*this)[name];
}
else if (num_paths == 0)
{
results.clear();
}
else
{
ostringstream xpath;
xpath << paths[0] << name;
for (int i = 1; i < num_paths ; i++)
{
xpath << '|' << paths[i] << name;
}
results = (*this)[xpath.str().c_str()];
}
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int ObjectXML::search(const char *name, string& value)
{
vector<string> results;
value = "";
search(name, results);
if (results.size() != 0)
{
value = results[0];
return 0;
}
return -1;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int ObjectXML::search(const char *name, int& value)
{
vector<string> results;
value = 0;
search(name, results);
if (results.size() != 0)
{
istringstream iss(results[0]);
iss >> value;
if (iss.fail())
{
value = 0;
return -1;
}
return 0;
}
return -1;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int ObjectXML::search(const char *name, float& value)
{
vector<string> results;
value = 0.0;
search(name, results);
if (results.size() != 0)
{
istringstream iss(results[0]);
iss >> value;
if (iss.fail())
{
value = 0;
return -1;
}
return 0;
}
return -1;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

View File

@ -483,8 +483,8 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
0, 100, 100, 101, 104, 132, 133, 134, 135, 136,
137, 138, 139
0, 100, 100, 101, 104, 105, 106, 107, 108, 109,
110, 111, 112
};
#endif
@ -1380,87 +1380,60 @@ yyreduce:
case 4:
#line 104 "expr_arith.y" /* yacc.c:1646 */
{ float val = 0.0;
vector<string> results;
if ((yyvsp[0].val_str)[0] == '/')
{
results = (*oxml)[(yyvsp[0].val_str)];
}
else
{
ostringstream xpath_t;
xpath_t << "/HOST/TEMPLATE/" << (yyvsp[0].val_str)
<< "|/HOST/HOST_SHARE/" << (yyvsp[0].val_str)
<< "|/HOST/" << (yyvsp[0].val_str)
<< "|/HOST/CLUSTER_TEMPLATE/" << (yyvsp[0].val_str);
results = (*oxml)[xpath_t.str().c_str()];
}
if (results.size() != 0)
{
istringstream iss(results[0]);
iss >> val;
}
(yyval.val_float) = val;
}
#line 1412 "expr_arith.cc" /* yacc.c:1646 */
{ float val; oxml->search((yyvsp[0].val_str), val); (yyval.val_float) = val; }
#line 1385 "expr_arith.cc" /* yacc.c:1646 */
break;
case 5:
#line 132 "expr_arith.y" /* yacc.c:1646 */
#line 105 "expr_arith.y" /* yacc.c:1646 */
{ (yyval.val_float) = (yyvsp[0].val_float); }
#line 1418 "expr_arith.cc" /* yacc.c:1646 */
#line 1391 "expr_arith.cc" /* yacc.c:1646 */
break;
case 6:
#line 133 "expr_arith.y" /* yacc.c:1646 */
#line 106 "expr_arith.y" /* yacc.c:1646 */
{ (yyval.val_float) = static_cast<float>((yyvsp[0].val_int)); }
#line 1424 "expr_arith.cc" /* yacc.c:1646 */
#line 1397 "expr_arith.cc" /* yacc.c:1646 */
break;
case 7:
#line 134 "expr_arith.y" /* yacc.c:1646 */
#line 107 "expr_arith.y" /* yacc.c:1646 */
{ (yyval.val_float) = (yyvsp[-2].val_float) + (yyvsp[0].val_float);}
#line 1430 "expr_arith.cc" /* yacc.c:1646 */
#line 1403 "expr_arith.cc" /* yacc.c:1646 */
break;
case 8:
#line 135 "expr_arith.y" /* yacc.c:1646 */
#line 108 "expr_arith.y" /* yacc.c:1646 */
{ (yyval.val_float) = (yyvsp[-2].val_float) - (yyvsp[0].val_float);}
#line 1436 "expr_arith.cc" /* yacc.c:1646 */
#line 1409 "expr_arith.cc" /* yacc.c:1646 */
break;
case 9:
#line 136 "expr_arith.y" /* yacc.c:1646 */
#line 109 "expr_arith.y" /* yacc.c:1646 */
{ (yyval.val_float) = (yyvsp[-2].val_float) * (yyvsp[0].val_float);}
#line 1442 "expr_arith.cc" /* yacc.c:1646 */
#line 1415 "expr_arith.cc" /* yacc.c:1646 */
break;
case 10:
#line 137 "expr_arith.y" /* yacc.c:1646 */
#line 110 "expr_arith.y" /* yacc.c:1646 */
{ (yyval.val_float) = (yyvsp[-2].val_float) / (yyvsp[0].val_float);}
#line 1448 "expr_arith.cc" /* yacc.c:1646 */
#line 1421 "expr_arith.cc" /* yacc.c:1646 */
break;
case 11:
#line 138 "expr_arith.y" /* yacc.c:1646 */
#line 111 "expr_arith.y" /* yacc.c:1646 */
{ (yyval.val_float) = - (yyvsp[0].val_float);}
#line 1454 "expr_arith.cc" /* yacc.c:1646 */
#line 1427 "expr_arith.cc" /* yacc.c:1646 */
break;
case 12:
#line 139 "expr_arith.y" /* yacc.c:1646 */
#line 112 "expr_arith.y" /* yacc.c:1646 */
{ (yyval.val_float) = (yyvsp[-1].val_float);}
#line 1460 "expr_arith.cc" /* yacc.c:1646 */
#line 1433 "expr_arith.cc" /* yacc.c:1646 */
break;
#line 1464 "expr_arith.cc" /* yacc.c:1646 */
#line 1437 "expr_arith.cc" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@ -1695,7 +1668,7 @@ yyreturn:
#endif
return yyresult;
}
#line 142 "expr_arith.y" /* yacc.c:1906 */
#line 115 "expr_arith.y" /* yacc.c:1906 */
extern "C" void expr_arith__error(

View File

@ -101,34 +101,7 @@ stmt: expr { result = static_cast<int>($1);}
| { result = 0; }
;
expr: STRING { float val = 0.0;
vector<string> results;
if ($1[0] == '/')
{
results = (*oxml)[$1];
}
else
{
ostringstream xpath_t;
xpath_t << "/HOST/TEMPLATE/" << $1
<< "|/HOST/HOST_SHARE/" << $1
<< "|/HOST/" << $1
<< "|/HOST/CLUSTER_TEMPLATE/" << $1;
results = (*oxml)[xpath_t.str().c_str()];
}
if (results.size() != 0)
{
istringstream iss(results[0]);
iss >> val;
}
$$ = val;
}
expr: STRING { float val; oxml->search($1, val); $$ = val; }
| FLOAT { $$ = $1; }
| INTEGER { $$ = static_cast<float>($1); }
| expr '+' expr { $$ = $1 + $3;}

View File

@ -121,18 +121,7 @@ extern "C"
}
}
int get_xml_attribute(ObjectXML * oxml, const char* attr, int& val);
int get_xml_attribute(ObjectXML * oxml, const char* attr, float& val);
int get_xml_attribute(ObjectXML * oxml, const char* attr, string& val);
void get_xml_values(ObjectXML * oxml, const char* attr, vector<string>& results);
void get_vm_ids(ObjectXML * oxml, set<int>& vm_ids);
#line 136 "expr_bool.cc" /* yacc.c:339 */
#line 125 "expr_bool.cc" /* yacc.c:339 */
# ifndef YY_NULL
# if defined __cplusplus && 201103L <= __cplusplus
@ -178,13 +167,13 @@ extern int expr_bool__debug;
typedef union YYSTYPE YYSTYPE;
union YYSTYPE
{
#line 88 "expr_bool.y" /* yacc.c:355 */
#line 77 "expr_bool.y" /* yacc.c:355 */
char * val_str;
int val_int;
float val_float;
#line 188 "expr_bool.cc" /* yacc.c:355 */
#line 177 "expr_bool.cc" /* yacc.c:355 */
};
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
@ -212,7 +201,7 @@ int expr_bool__parse (mem_collector * mc, ObjectXML * oxml, bool&
/* Copy the second part of user declarations. */
#line 216 "expr_bool.cc" /* yacc.c:358 */
#line 205 "expr_bool.cc" /* yacc.c:358 */
#ifdef short
# undef short
@ -493,8 +482,8 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
0, 108, 108, 109, 112, 128, 144, 149, 154, 159,
164, 169, 174, 179, 184, 185, 186, 187
0, 97, 97, 98, 101, 110, 119, 126, 133, 140,
147, 154, 160, 168, 176, 177, 178, 179
};
#endif
@ -1380,155 +1369,158 @@ yyreduce:
switch (yyn)
{
case 2:
#line 108 "expr_bool.y" /* yacc.c:1646 */
#line 97 "expr_bool.y" /* yacc.c:1646 */
{ result=(yyvsp[0].val_int); }
#line 1386 "expr_bool.cc" /* yacc.c:1646 */
#line 1375 "expr_bool.cc" /* yacc.c:1646 */
break;
case 3:
#line 109 "expr_bool.y" /* yacc.c:1646 */
#line 98 "expr_bool.y" /* yacc.c:1646 */
{ result=true; }
#line 1392 "expr_bool.cc" /* yacc.c:1646 */
#line 1381 "expr_bool.cc" /* yacc.c:1646 */
break;
case 4:
#line 112 "expr_bool.y" /* yacc.c:1646 */
{ int val, rc;
if ((yyvsp[-2].val_str) == string("CURRENT_VMS"))
#line 101 "expr_bool.y" /* yacc.c:1646 */
{
set<int> vm_ids;
get_vm_ids(oxml, vm_ids);
int val = (yyvsp[0].val_int);
int rc;
rc = oxml->search((yyvsp[-2].val_str),val);
(yyval.val_int) = vm_ids.count((yyvsp[0].val_int)) > 0;
}
else
{
rc = get_xml_attribute(oxml,(yyvsp[-2].val_str),val);
(yyval.val_int) = (rc == 0 && val == (yyvsp[0].val_int));
}
}
#line 1412 "expr_bool.cc" /* yacc.c:1646 */
#line 1394 "expr_bool.cc" /* yacc.c:1646 */
break;
case 5:
#line 128 "expr_bool.y" /* yacc.c:1646 */
{ int val, rc;
if ((yyvsp[-3].val_str) == string("CURRENT_VMS"))
#line 110 "expr_bool.y" /* yacc.c:1646 */
{
set<int> vm_ids;
get_vm_ids(oxml, vm_ids);
int val = (yyvsp[0].val_int);
int rc;
rc = oxml->search((yyvsp[-3].val_str),val);
(yyval.val_int) = vm_ids.count((yyvsp[0].val_int)) == 0;
}
else
{
rc = get_xml_attribute(oxml,(yyvsp[-3].val_str),val);
(yyval.val_int) = (rc == 0 && val != (yyvsp[0].val_int));
}
}
#line 1432 "expr_bool.cc" /* yacc.c:1646 */
#line 1407 "expr_bool.cc" /* yacc.c:1646 */
break;
case 6:
#line 144 "expr_bool.y" /* yacc.c:1646 */
{ int val, rc;
#line 119 "expr_bool.y" /* yacc.c:1646 */
{
int val, rc;
rc = get_xml_attribute(oxml,(yyvsp[-2].val_str),val);
(yyval.val_int) = (rc == 0 && val > (yyvsp[0].val_int));}
#line 1441 "expr_bool.cc" /* yacc.c:1646 */
rc = oxml->search((yyvsp[-2].val_str),val);
(yyval.val_int) = (rc == 0 && val > (yyvsp[0].val_int));
}
#line 1418 "expr_bool.cc" /* yacc.c:1646 */
break;
case 7:
#line 149 "expr_bool.y" /* yacc.c:1646 */
{ int val, rc;
#line 126 "expr_bool.y" /* yacc.c:1646 */
{
int val, rc;
rc = get_xml_attribute(oxml,(yyvsp[-2].val_str),val);
(yyval.val_int) = (rc == 0 && val < (yyvsp[0].val_int));}
#line 1450 "expr_bool.cc" /* yacc.c:1646 */
rc = oxml->search((yyvsp[-2].val_str),val);
(yyval.val_int) = (rc == 0 && val < (yyvsp[0].val_int));
}
#line 1429 "expr_bool.cc" /* yacc.c:1646 */
break;
case 8:
#line 154 "expr_bool.y" /* yacc.c:1646 */
{ float val, rc;
#line 133 "expr_bool.y" /* yacc.c:1646 */
{
float val, rc;
rc = get_xml_attribute(oxml,(yyvsp[-2].val_str),val);
(yyval.val_int) = (rc == 0 && val == (yyvsp[0].val_float));}
#line 1459 "expr_bool.cc" /* yacc.c:1646 */
rc = oxml->search((yyvsp[-2].val_str),val);
(yyval.val_int) = (rc == 0 && val == (yyvsp[0].val_float));
}
#line 1440 "expr_bool.cc" /* yacc.c:1646 */
break;
case 9:
#line 159 "expr_bool.y" /* yacc.c:1646 */
{ float val, rc;
#line 140 "expr_bool.y" /* yacc.c:1646 */
{
float val, rc;
rc = get_xml_attribute(oxml,(yyvsp[-3].val_str),val);
(yyval.val_int) = (rc == 0 && val != (yyvsp[0].val_float));}
#line 1468 "expr_bool.cc" /* yacc.c:1646 */
rc = oxml->search((yyvsp[-3].val_str),val);
(yyval.val_int) = (rc == 0 && val != (yyvsp[0].val_float));
}
#line 1451 "expr_bool.cc" /* yacc.c:1646 */
break;
case 10:
#line 164 "expr_bool.y" /* yacc.c:1646 */
{ float val, rc;
#line 147 "expr_bool.y" /* yacc.c:1646 */
{
float val, rc;
rc = get_xml_attribute(oxml,(yyvsp[-2].val_str),val);
(yyval.val_int) = (rc == 0 && val > (yyvsp[0].val_float));}
#line 1477 "expr_bool.cc" /* yacc.c:1646 */
rc = oxml->search((yyvsp[-2].val_str),val);
(yyval.val_int) = (rc == 0 && val > (yyvsp[0].val_float));
}
#line 1462 "expr_bool.cc" /* yacc.c:1646 */
break;
case 11:
#line 169 "expr_bool.y" /* yacc.c:1646 */
{ float val, rc;
#line 154 "expr_bool.y" /* yacc.c:1646 */
{
float val, rc;
rc = get_xml_attribute(oxml,(yyvsp[-2].val_str),val);
rc = oxml->search((yyvsp[-2].val_str),val);
(yyval.val_int) = (rc == 0 && val < (yyvsp[0].val_float));}
#line 1486 "expr_bool.cc" /* yacc.c:1646 */
#line 1472 "expr_bool.cc" /* yacc.c:1646 */
break;
case 12:
#line 174 "expr_bool.y" /* yacc.c:1646 */
{ string val; int rc;
#line 160 "expr_bool.y" /* yacc.c:1646 */
{
string val;
int rc;
rc = get_xml_attribute(oxml,(yyvsp[-2].val_str),val);
(yyval.val_int) = (rc != 0 || (yyvsp[0].val_str)==0) ? false : fnmatch((yyvsp[0].val_str),val.c_str(),0)==0;}
#line 1495 "expr_bool.cc" /* yacc.c:1646 */
rc = oxml->search((yyvsp[-2].val_str),val);
(yyval.val_int) = (rc != 0 || (yyvsp[0].val_str)==0) ? false : fnmatch((yyvsp[0].val_str),val.c_str(),0)==0;
}
#line 1484 "expr_bool.cc" /* yacc.c:1646 */
break;
case 13:
#line 179 "expr_bool.y" /* yacc.c:1646 */
{ string val; int rc;
#line 168 "expr_bool.y" /* yacc.c:1646 */
{
string val;
int rc;
rc = get_xml_attribute(oxml,(yyvsp[-3].val_str),val);
(yyval.val_int) = (rc != 0 || (yyvsp[0].val_str)==0) ? false : fnmatch((yyvsp[0].val_str),val.c_str(),0)!=0;}
#line 1504 "expr_bool.cc" /* yacc.c:1646 */
rc = oxml->search((yyvsp[-3].val_str),val);
(yyval.val_int) = (rc != 0 || (yyvsp[0].val_str)==0) ? false : fnmatch((yyvsp[0].val_str),val.c_str(),0)!=0;
}
#line 1496 "expr_bool.cc" /* yacc.c:1646 */
break;
case 14:
#line 184 "expr_bool.y" /* yacc.c:1646 */
#line 176 "expr_bool.y" /* yacc.c:1646 */
{ (yyval.val_int) = (yyvsp[-2].val_int) && (yyvsp[0].val_int); }
#line 1510 "expr_bool.cc" /* yacc.c:1646 */
#line 1502 "expr_bool.cc" /* yacc.c:1646 */
break;
case 15:
#line 185 "expr_bool.y" /* yacc.c:1646 */
#line 177 "expr_bool.y" /* yacc.c:1646 */
{ (yyval.val_int) = (yyvsp[-2].val_int) || (yyvsp[0].val_int); }
#line 1516 "expr_bool.cc" /* yacc.c:1646 */
#line 1508 "expr_bool.cc" /* yacc.c:1646 */
break;
case 16:
#line 186 "expr_bool.y" /* yacc.c:1646 */
#line 178 "expr_bool.y" /* yacc.c:1646 */
{ (yyval.val_int) = ! (yyvsp[0].val_int); }
#line 1522 "expr_bool.cc" /* yacc.c:1646 */
#line 1514 "expr_bool.cc" /* yacc.c:1646 */
break;
case 17:
#line 187 "expr_bool.y" /* yacc.c:1646 */
#line 179 "expr_bool.y" /* yacc.c:1646 */
{ (yyval.val_int) = (yyvsp[-1].val_int); }
#line 1528 "expr_bool.cc" /* yacc.c:1646 */
#line 1520 "expr_bool.cc" /* yacc.c:1646 */
break;
#line 1532 "expr_bool.cc" /* yacc.c:1646 */
#line 1524 "expr_bool.cc" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@ -1763,7 +1755,7 @@ yyreturn:
#endif
return yyresult;
}
#line 190 "expr_bool.y" /* yacc.c:1906 */
#line 182 "expr_bool.y" /* yacc.c:1906 */
extern "C" void expr_bool__error(
@ -1793,111 +1785,3 @@ extern "C" void expr_bool__error(
result = false;
}
void get_xml_values(ObjectXML * oxml, const char* attr, vector<string> &results)
{
if (attr[0] == '/')
{
results = (*oxml)[attr];
}
else
{
ostringstream xpath;
xpath << "/HOST/TEMPLATE/" << attr
<< "|/HOST/HOST_SHARE/" << attr
<< "|/HOST/" << attr
<< "|/HOST/CLUSTER_TEMPLATE/" << attr;
results = (*oxml)[xpath.str().c_str()];
}
}
int get_xml_attribute(ObjectXML * oxml, const char* attr, int& val)
{
val = 0;
vector<string> results;
get_xml_values(oxml, attr, results);
if (results.size() != 0)
{
istringstream iss(results[0]);
iss >> val;
if (iss.fail())
{
val = 0;
return -1;
}
return 0;
}
return -1;
}
int get_xml_attribute(ObjectXML * oxml, const char* attr, float& val)
{
val = 0.0;
vector<string> results;
get_xml_values(oxml, attr, results);
if (results.size() != 0)
{
istringstream iss(results[0]);
iss >> val;
if (iss.fail())
{
val = 0;
return -1;
}
return 0;
}
return -1;
}
int get_xml_attribute(ObjectXML * oxml, const char* attr, string& val)
{
val = "";
vector<string> results;
get_xml_values(oxml, attr, results);
if (results.size() != 0)
{
val = results[0];
return 0;
}
return -1;
}
void get_vm_ids(ObjectXML * oxml, set<int>& vm_ids)
{
istringstream iss;
vector<string> results;
int id;
get_xml_values(oxml, "/HOST/VMS/ID", results);
for (vector<string>::iterator it=results.begin(); it!=results.end(); it++)
{
iss.clear();
iss.str(*it);
iss >> id;
if (!iss.fail())
{
vm_ids.insert(id);
}
}
}

View File

@ -56,7 +56,7 @@ extern int expr_bool__debug;
typedef union YYSTYPE YYSTYPE;
union YYSTYPE
{
#line 88 "expr_bool.y" /* yacc.c:1909 */
#line 77 "expr_bool.y" /* yacc.c:1909 */
char * val_str;
int val_int;

View File

@ -65,17 +65,6 @@ extern "C"
return rc;
}
}
int get_xml_attribute(ObjectXML * oxml, const char* attr, int& val);
int get_xml_attribute(ObjectXML * oxml, const char* attr, float& val);
int get_xml_attribute(ObjectXML * oxml, const char* attr, string& val);
void get_xml_values(ObjectXML * oxml, const char* attr, vector<string>& results);
void get_vm_ids(ObjectXML * oxml, set<int>& vm_ids);
%}
%parse-param {mem_collector * mc}
@ -109,77 +98,80 @@ stmt: expr { result=$1; }
| { result=true; } /* TRUE BY DEFAULT, ON EMPTY STRINGS */
;
expr: STRING '=' INTEGER { int val, rc;
expr: STRING '=' INTEGER {
int val = $3;
int rc;
if ($1 == string("CURRENT_VMS"))
{
set<int> vm_ids;
get_vm_ids(oxml, vm_ids);
rc = oxml->search($1,val);
$$ = vm_ids.count($3) > 0;
}
else
{
rc = get_xml_attribute(oxml,$1,val);
$$ = (rc == 0 && val == $3);
}
}
| STRING '!' '=' INTEGER { int val, rc;
| STRING '!' '=' INTEGER {
int val = $4;
int rc;
if ($1 == string("CURRENT_VMS"))
{
set<int> vm_ids;
get_vm_ids(oxml, vm_ids);
rc = oxml->search($1,val);
$$ = vm_ids.count($4) == 0;
}
else
{
rc = get_xml_attribute(oxml,$1,val);
$$ = (rc == 0 && val != $4);
}
| STRING '>' INTEGER {
int val, rc;
rc = oxml->search($1,val);
$$ = (rc == 0 && val > $3);
}
| STRING '>' INTEGER { int val, rc;
| STRING '<' INTEGER {
int val, rc;
rc = get_xml_attribute(oxml,$1,val);
$$ = (rc == 0 && val > $3);}
rc = oxml->search($1,val);
$$ = (rc == 0 && val < $3);
}
| STRING '<' INTEGER { int val, rc;
| STRING '=' FLOAT {
float val, rc;
rc = get_xml_attribute(oxml,$1,val);
rc = oxml->search($1,val);
$$ = (rc == 0 && val == $3);
}
| STRING '!' '=' FLOAT {
float val, rc;
rc = oxml->search($1,val);
$$ = (rc == 0 && val != $4);
}
| STRING '>' FLOAT {
float val, rc;
rc = oxml->search($1,val);
$$ = (rc == 0 && val > $3);
}
| STRING '<' FLOAT {
float val, rc;
rc = oxml->search($1,val);
$$ = (rc == 0 && val < $3);}
| STRING '=' FLOAT { float val, rc;
| STRING '=' STRING {
string val;
int rc;
rc = get_xml_attribute(oxml,$1,val);
$$ = (rc == 0 && val == $3);}
rc = oxml->search($1,val);
$$ = (rc != 0 || $3==0) ? false : fnmatch($3,val.c_str(),0)==0;
}
| STRING '!' '=' FLOAT { float val, rc;
| STRING '!''=' STRING {
string val;
int rc;
rc = get_xml_attribute(oxml,$1,val);
$$ = (rc == 0 && val != $4);}
| STRING '>' FLOAT { float val, rc;
rc = get_xml_attribute(oxml,$1,val);
$$ = (rc == 0 && val > $3);}
| STRING '<' FLOAT { float val, rc;
rc = get_xml_attribute(oxml,$1,val);
$$ = (rc == 0 && val < $3);}
| STRING '=' STRING { string val; int rc;
rc = get_xml_attribute(oxml,$1,val);
$$ = (rc != 0 || $3==0) ? false : fnmatch($3,val.c_str(),0)==0;}
| STRING '!''=' STRING { string val; int rc;
rc = get_xml_attribute(oxml,$1,val);
$$ = (rc != 0 || $4==0) ? false : fnmatch($4,val.c_str(),0)!=0;}
rc = oxml->search($1,val);
$$ = (rc != 0 || $4==0) ? false : fnmatch($4,val.c_str(),0)!=0;
}
| expr '&' expr { $$ = $1 && $3; }
| expr '|' expr { $$ = $1 || $3; }
@ -216,111 +208,3 @@ extern "C" void expr_bool__error(
result = false;
}
void get_xml_values(ObjectXML * oxml, const char* attr, vector<string> &results)
{
if (attr[0] == '/')
{
results = (*oxml)[attr];
}
else
{
ostringstream xpath;
xpath << "/HOST/TEMPLATE/" << attr
<< "|/HOST/HOST_SHARE/" << attr
<< "|/HOST/" << attr
<< "|/HOST/CLUSTER_TEMPLATE/" << attr;
results = (*oxml)[xpath.str().c_str()];
}
}
int get_xml_attribute(ObjectXML * oxml, const char* attr, int& val)
{
val = 0;
vector<string> results;
get_xml_values(oxml, attr, results);
if (results.size() != 0)
{
istringstream iss(results[0]);
iss >> val;
if (iss.fail())
{
val = 0;
return -1;
}
return 0;
}
return -1;
}
int get_xml_attribute(ObjectXML * oxml, const char* attr, float& val)
{
val = 0.0;
vector<string> results;
get_xml_values(oxml, attr, results);
if (results.size() != 0)
{
istringstream iss(results[0]);
iss >> val;
if (iss.fail())
{
val = 0;
return -1;
}
return 0;
}
return -1;
}
int get_xml_attribute(ObjectXML * oxml, const char* attr, string& val)
{
val = "";
vector<string> results;
get_xml_values(oxml, attr, results);
if (results.size() != 0)
{
val = results[0];
return 0;
}
return -1;
}
void get_vm_ids(ObjectXML * oxml, set<int>& vm_ids)
{
istringstream iss;
vector<string> results;
int id;
get_xml_values(oxml, "/HOST/VMS/ID", results);
for (vector<string>::iterator it=results.begin(); it!=results.end(); it++)
{
iss.clear();
iss.str(*it);
iss >> id;
if (!iss.fail())
{
vm_ids.insert(id);
}
}
}