1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-27 14:03:40 +03:00

feature #1712: Make Scheduler class more general to accomodate Storage Policies

This commit is contained in:
Ruben S. Montero 2013-08-08 18:10:33 +02:00
parent 642965e5c1
commit a38afa7abc
7 changed files with 305 additions and 286 deletions

View File

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

View File

@ -0,0 +1,112 @@
/* -------------------------------------------------------------------------- */
/* 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 SCHEDULABLE_H_
#define SCHEDULABLE_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 Schedulable
{
public:
Schedulable(){};
virtual ~Schedulable()
{
vector<Resource *>::iterator jt;
for (jt=resources.begin(); jt!=resources.end(); jt++)
{
delete *jt;
}
};
/**
* 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);
}
void sort_resources()
{
sort(resources.begin(), resources.end(), Resource::cmp);
}
/**
* Selects a resource among the matched and prioritized resources, in a
* scheduling step.
* @param oid of the selected resource.
* @param pool storing the resources.
* @param current number of schedules for each resource in this step.
* @param max number of schedules per resource in this step.
*
* @return 0 if success -1 otherwise
*/
virtual int get_resource(int& oid, PoolXML *pool, map<int,int>& current, int max) = 0;
/**
* Return a reference to the resources of the object
* @return vector of resources.
*/
const vector<Resource *>& get_resources() const
{
return resources;
};
protected:
vector<Resource *> resources;
};
#endif /*SCHEDULABLE_H_*/

View File

@ -119,7 +119,7 @@ protected:
// Scheduler Policies
// ---------------------------------------------------------------
void add_host_policy(SchedulerHostPolicy *policy)
void add_host_policy(SchedulerPolicy *policy)
{
host_policies.push_back(policy);
}
@ -162,7 +162,7 @@ private:
// Scheduling Policies
// ---------------------------------------------------------------
vector<SchedulerHostPolicy *> host_policies;
vector<SchedulerPolicy *> host_policies;
// ---------------------------------------------------------------
// Configuration attributes

View File

@ -17,70 +17,77 @@
#ifndef SCHEDULER_POLICY_H_
#define SCHEDULER_POLICY_H_
#include "HostPoolXML.h"
#include "VirtualMachinePoolXML.h"
#include "Schedulable.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(Schedulable * obj)
{
priority.clear();
vector<float> priority;
const vector<Resource *> resources = obj->get_resources();
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;
virtual void policy(VirtualMachineXML * vm) = 0;
VirtualMachinePoolXML * vmpool;
HostPoolXML * hpool;
virtual void policy(Schedulable * 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:
ScaleWeight(float _weight):weight(_weight){};
ScaleWeight(float _weight):weight(_weight){};
~ScaleWeight(){};
@ -96,17 +103,10 @@ private:
}
};
private:
friend class SchedulerHostPolicy;
float weight;
float weight;
float max;
};
//--------------------------------------------------------------------------
ScaleWeight sw;
float max;
} sw;
};
/* -------------------------------------------------------------------------- */
#endif /*SCHEDULER_POLICY_H_*/

View File

@ -22,27 +22,37 @@
#include "ObjectXML.h"
#include "HostPoolXML.h"
#include "Schedulable.h"
#include "VirtualMachineTemplate.h"
using namespace std;
class VirtualMachineXML : public ObjectXML
class VirtualMachineXML : public ObjectXML, public Schedulable
{
public:
VirtualMachineXML(const string &xml_doc):
ObjectXML(xml_doc)
VirtualMachineXML(const string &xml_doc): ObjectXML(xml_doc), Schedulable()
{
init_attributes();
};
VirtualMachineXML(const xmlNodePtr node):
ObjectXML(node)
VirtualMachineXML(const xmlNodePtr node): ObjectXML(node), Schedulable()
{
init_attributes();
}
~VirtualMachineXML();
~VirtualMachineXML()
{
if (vm_template != 0)
{
delete vm_template;
}
}
//--------------------------------------------------------------------------
// Get Methods for VirtualMachineXML class
//--------------------------------------------------------------------------
int get_oid() const
{
@ -69,33 +79,6 @@ public:
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;
@ -106,6 +89,33 @@ public:
return requirements;
};
void get_requirements (int& cpu, int& memory, int& disk);
//--------------------------------------------------------------------------
// Schedulable Interface
//--------------------------------------------------------------------------
/**
* Adds a matching resource to the object. Overwrite Schedulable method.
*/
void add_resource(int oid)
{
if (( resched == 1 && hid != oid ) || ( resched == 0 ))
{
Schedulable::add_resource(oid);
}
};
/**
* Selects a resource among the matched and prioritized resources, in a
* scheduling step. Overwrite Schedulable method.
*/
int get_resource(int& oid, PoolXML *pool, map<int,int>& current, int max);
//--------------------------------------------------------------------------
// Action Interface
//--------------------------------------------------------------------------
/**
* Get the user template of the VM
* @return the template as a XML string
@ -158,28 +168,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,34 +183,8 @@ protected:
*/
void init_attributes();
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
struct Host
{
int hid;
float priority;
Host(int _hid):
hid(_hid),
priority(0){};
~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;
@ -238,11 +201,6 @@ protected:
string rank;
string requirements;
/**
* Matching hosts
*/
vector<VirtualMachineXML::Host *> hosts;
/**
* The VM user template
*/

View File

@ -137,117 +137,78 @@ void VirtualMachineXML::init_attributes()
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VirtualMachineXML::~VirtualMachineXML()
ostream& operator<<(ostream& os, VirtualMachineXML& vm)
{
vector<VirtualMachineXML::Host *>::iterator jt;
for (jt=hosts.begin();jt!=hosts.end();jt++)
if (vm.resources.empty())
{
delete *jt;
return os;
}
hosts.clear();
vector<Resource *>::reverse_iterator i;
vector<int>::iterator j;
if (vm_template != 0)
os << "\t PRI\tHID VM: " << vm.oid << endl
<< "\t-----------------------" << endl;
for (i = vm.resources.rbegin(); i != vm.resources.rend() ; i++)
{
delete vm_template;
os << "\t" << (*i)->priority << "\t" << (*i)->oid << endl;
}
}
os << endl;
return os;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineXML::add_host(int host_id)
int VirtualMachineXML::get_resource(int& oid,
PoolXML * pool,
map<int,int>& current,
int max)
{
if (( resched == 1 && host_id != hid ) || ( resched == 0 ))
{
VirtualMachineXML::Host * ss;
vector<Resource *>::reverse_iterator i;
vector<int>::iterator j;
ss = new VirtualMachineXML::Host(host_id);
hosts.push_back(ss);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
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;
HostXML * host;
HostPoolXML * hpool = dynamic_cast<HostPoolXML *>(pool);
int cpu;
int mem;
int dsk;
pair<map<int,int>::iterator,bool> rc;
pair<map<int,int>::iterator, bool> rc;
get_requirements(cpu,mem,dsk);
for (i=hosts.rbegin();i!=hosts.rend();i++)
for (i = resources.rbegin() ; i != resources.rend() ; i++)
{
host = hpool->get( (*i)->hid );
host = hpool->get( (*i)->oid );
if ( host == 0 )
{
continue;
}
if (host->test_capacity(cpu,mem,dsk)==true)
if ( host->test_capacity(cpu,mem,dsk) == true )
{
rc = host_vms.insert(make_pair((*i)->hid,0));
rc = current.insert(make_pair((*i)->oid,0));
if ( rc.first->second < max_vms )
if ( rc.first->second < max )
{
host->add_capacity(cpu,mem,dsk);
hid = (*i)->hid;
oid = (*i)->oid;
rc.first->second++;
return 0;
}
}
}
hid = -1;
oid = -1;
return -1;
}

View File

@ -519,7 +519,7 @@ void Scheduler::match()
if (host->test_capacity(vm_cpu,vm_memory,vm_disk) == true)
{
vm->add_host(host->get_hid());
vm->add_resource(host->get_hid());
n_hosts++;
}
@ -568,53 +568,25 @@ void Scheduler::match()
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static float sum_operator (float i, float j)
{
return i+j;
}
/* -------------------------------------------------------------------------- */
int Scheduler::schedule()
{
vector<SchedulerHostPolicy *>::iterator it;
vector<SchedulerPolicy *>::iterator it;
map<int, ObjectXML*>::const_iterator vm_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++)
for (vm_it = pending_vms.begin(); vm_it != pending_vms.end(); vm_it++)
{
vm = static_cast<VirtualMachineXML*>(vm_it->second);
vm = dynamic_cast<VirtualMachineXML*>(vm_it->second);
total.clear();
for ( it=host_policies.begin();it!=host_policies.end();it++)
for ( it =host_policies.begin() ; it != host_policies.end() ; it++)
{
policy = (*it)->get(vm);
if (total.empty() == true)
{
total = policy;
}
else
{
transform(
total.begin(),
total.end(),
policy.begin(),
total.begin(),
sum_operator);
}
(*it)->schedule(vm);
}
vm->set_priorities(total);
vm->sort_resources();
}
return 0;
@ -628,15 +600,15 @@ void Scheduler::dispatch()
VirtualMachineXML * vm;
ostringstream oss;
int hid;
int rc;
unsigned int dispatched_vms;
map<int, ObjectXML*>::const_iterator vm_it;
const map<int, ObjectXML*> pending_vms = vmpool->get_objects();
int hid;
int rc;
unsigned int dispatched_vms = 0;
map<int, int> host_vms;
const map<int, ObjectXML*> pending_vms = vmpool->get_objects();
map<int, ObjectXML*>::const_iterator vm_it;
oss << "Selected hosts:" << endl;
for (vm_it=pending_vms.begin(); vm_it != pending_vms.end(); vm_it++)
@ -648,15 +620,14 @@ 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 );
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);
rc = vm->get_resource(hid, hpool, host_vms, host_dispatch_limit);
if (rc == 0)
{