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:
commit
5899820844
@ -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)
|
||||
// *************************************************************************
|
||||
|
@ -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_*/
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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)"
|
||||
|
@ -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)
|
||||
|
57
src/scheduler/include/DatastorePoolXML.h
Normal file
57
src/scheduler/include/DatastorePoolXML.h
Normal 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_ */
|
84
src/scheduler/include/DatastoreXML.h
Normal file
84
src/scheduler/include/DatastoreXML.h
Normal 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_ */
|
@ -33,6 +33,8 @@ public:
|
||||
HostXML::set_hypervisor_mem(mem);
|
||||
};
|
||||
|
||||
~HostPoolXML(){};
|
||||
|
||||
int set_up();
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
@ -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_*/
|
||||
|
114
src/scheduler/include/Resource.h
Normal file
114
src/scheduler/include/Resource.h
Normal 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_*/
|
@ -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
|
||||
|
@ -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_*/
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
|
||||
string get_policy() const;
|
||||
|
||||
string get_ds_policy() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Name for the configuration file, oned.conf
|
||||
|
@ -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
|
||||
|
@ -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_ */
|
||||
|
@ -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 )
|
||||
|
64
src/scheduler/src/pool/DatastorePoolXML.cc
Normal file
64
src/scheduler/src/pool/DatastorePoolXML.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
47
src/scheduler/src/pool/DatastoreXML.cc
Normal file
47
src/scheduler/src/pool/DatastoreXML.cc
Normal 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;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
},
|
||||
|
@ -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")+
|
||||
' <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")+
|
||||
' <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>'+
|
||||
' <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")+
|
||||
' <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")+
|
||||
' <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
|
||||
//
|
||||
|
@ -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">×</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(){
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
@ -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(
|
||||
|
@ -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;}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user