mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-11 05:17:41 +03:00
F #2347: VMGroupRule class. Methods to check rule consistency
This commit is contained in:
parent
a1c1dee188
commit
97c5fcd2f2
@ -19,6 +19,7 @@
|
||||
|
||||
#include "PoolObjectSQL.h"
|
||||
#include "VMGroupRole.h"
|
||||
#include "VMGroupRule.h"
|
||||
|
||||
class VMGroupPool;
|
||||
|
||||
@ -39,6 +40,7 @@ class VMGroupPool;
|
||||
* ROLE = [
|
||||
* NAME = "db",
|
||||
* ID = 1,
|
||||
* POLICY = ANTI_AFFINED,
|
||||
* VMS = "2,3,4,5"
|
||||
* ]
|
||||
*
|
||||
@ -121,7 +123,12 @@ private:
|
||||
*
|
||||
* @return 0 if all roles are defined -1 otherwise
|
||||
*/
|
||||
int check_affinity(const std::string& aname, std::string& error_str);
|
||||
int check_rule_names(const std::string& aname, std::string& error_str);
|
||||
|
||||
int get_rules(const std::string& aname, VMGroupRule::Policy policy,
|
||||
VMGroupRule::rule_set& rules, std::string& error_str);
|
||||
|
||||
int check_rule_consistency(std::string& error);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// DataBase implementation
|
||||
|
@ -29,6 +29,7 @@ class VMGroupPool;
|
||||
* ROLE = [
|
||||
* NAME = "Web application servers",
|
||||
* ID = 12,
|
||||
* POLICY = AFFINED,
|
||||
* VMS = "1,2,45,21"
|
||||
* ]
|
||||
*
|
||||
@ -36,10 +37,35 @@ class VMGroupPool;
|
||||
class VMGroupRole
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Scheduling policy for the VMs within this role
|
||||
*/
|
||||
enum Policy
|
||||
{
|
||||
NONE = 0x00,
|
||||
AFFINED = 0x01,
|
||||
ANTI_AFFINED= 0x02
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
VMGroupRole(VectorAttribute *_va);
|
||||
|
||||
virtual ~VMGroupRole(){};
|
||||
|
||||
/**
|
||||
* @return the role id
|
||||
*/
|
||||
int id()
|
||||
{
|
||||
int rid;
|
||||
|
||||
va->vector_value("ID", rid);
|
||||
|
||||
return rid;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* VMS set Interface */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -52,6 +78,17 @@ public:
|
||||
|
||||
void del_vm(int vm_id);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Placement constraints */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/**
|
||||
* Generates a string with the boolean expresion to conform the role
|
||||
* policy
|
||||
* @param vm_id of the VM to generate the requirements for
|
||||
* @param requirements
|
||||
*/
|
||||
void vm_requirements(int vm_id, std::string requirements);
|
||||
|
||||
private:
|
||||
/**
|
||||
* The set of vms in the role
|
||||
@ -109,14 +146,12 @@ public:
|
||||
int add_role(VectorAttribute * vrole, string& error);
|
||||
|
||||
/**
|
||||
* Check that a key list is defined in the name map
|
||||
* @param key_str separated list of keys
|
||||
* @param true if the keys are in the map
|
||||
* Generates the ids corresponding to a set of role names
|
||||
* @param keys the set of names
|
||||
* @param keyi the set of ids
|
||||
* @return 0 if all the names were successfully translated
|
||||
*/
|
||||
bool in_map(const std::string& key_str)
|
||||
{
|
||||
return by_name.in_map(key_str);
|
||||
}
|
||||
int names_to_ids(const std::set<std::string> keys, std::set<int>& keyi);
|
||||
|
||||
/**
|
||||
* Adds a VM to a role
|
||||
@ -141,6 +176,11 @@ public:
|
||||
*/
|
||||
int vm_size();
|
||||
|
||||
/**
|
||||
* Max number of roles in a VMGroup
|
||||
*/
|
||||
const static int MAX_ROLES = 32;
|
||||
|
||||
private:
|
||||
/**
|
||||
* A role map indexed by different key types
|
||||
@ -205,36 +245,6 @@ private:
|
||||
return roles.erase(k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check id a set of keys are in the map.
|
||||
* @param key_str a comma separated list of keys
|
||||
* @return true if all the keys are in the map
|
||||
*/
|
||||
bool in_map(const string& key_str)
|
||||
{
|
||||
std::set<T> key_set;
|
||||
typename std::set<T>::iterator it;
|
||||
|
||||
one_util::split_unique(key_str, ',', key_set);
|
||||
|
||||
if ( key_set.empty() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for ( it = key_set.begin(); it != key_set.end() ; ++it )
|
||||
{
|
||||
string rname = one_util::trim(*it);
|
||||
|
||||
if ( roles.find(rname) == roles.end() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterators for the map
|
||||
*/
|
||||
|
138
include/VMGroupRule.h
Normal file
138
include/VMGroupRule.h
Normal file
@ -0,0 +1,138 @@
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems */
|
||||
/* */
|
||||
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
|
||||
/* not use this file except in compliance with the License. You may obtain */
|
||||
/* a copy of the License at */
|
||||
/* */
|
||||
/* http://www.apache.org/licenses/LICENSE-2.0 */
|
||||
/* */
|
||||
/* Unless required by applicable law or agreed to in writing, software */
|
||||
/* distributed under the License is distributed on an "AS IS" BASIS, */
|
||||
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
|
||||
/* See the License for the specific language governing permissions and */
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef VMGROUP_RULE_H_
|
||||
#define VMGROUP_RULE_H_
|
||||
|
||||
#include <bitset>
|
||||
#include "VMGroupRole.h"
|
||||
|
||||
struct VMGroupRule_compare;
|
||||
|
||||
/**
|
||||
* A rule represents a role placement policy
|
||||
*/
|
||||
class VMGroupRule
|
||||
{
|
||||
public:
|
||||
enum Policy
|
||||
{
|
||||
NONE = 0x00,
|
||||
AFFINED = 0x01,
|
||||
ANTI_AFFINED= 0x02
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
VMGroupRule():policy(NONE),roles(){};
|
||||
|
||||
VMGroupRule(Policy p, std::set<int> roles_id):policy(p)
|
||||
{
|
||||
std::set<int>::iterator it;
|
||||
|
||||
for ( it = roles_id.begin(); it != roles_id.end(); ++it )
|
||||
{
|
||||
if ( *it < VMGroupRoles::MAX_ROLES )
|
||||
{
|
||||
roles[*it] = 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VMGroupRule(Policy p, std::bitset<VMGroupRoles::MAX_ROLES> _roles)
|
||||
:policy(p), roles(_roles){};
|
||||
|
||||
VMGroupRule(const VMGroupRule& other)
|
||||
{
|
||||
policy = other.policy;
|
||||
roles = other.roles;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
typedef std::set<VMGroupRule, VMGroupRule_compare> rule_set;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
VMGroupRule& operator=(const VMGroupRule& other)
|
||||
{
|
||||
if ( this != &other )
|
||||
{
|
||||
policy = other.policy;
|
||||
roles = other.roles;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
VMGroupRule& operator&= (const VMGroupRule& other)
|
||||
{
|
||||
roles &= other.roles;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VMGroupRule operator& (const VMGroupRule& other)
|
||||
{
|
||||
return VMGroupRule(policy, other.roles & roles );
|
||||
}
|
||||
|
||||
VMGroupRule& operator|= (const VMGroupRule& other)
|
||||
{
|
||||
roles |= other.roles;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VMGroupRule operator| (const VMGroupRule& other)
|
||||
{
|
||||
return VMGroupRule(policy, other.roles | roles );
|
||||
}
|
||||
|
||||
bool none()
|
||||
{
|
||||
return roles.none();
|
||||
}
|
||||
|
||||
static bool compatible(rule_set& affined, rule_set& anti, VMGroupRule& err);
|
||||
|
||||
private:
|
||||
|
||||
friend class VMGroupRule_compare;
|
||||
|
||||
/**
|
||||
* Type of the rule
|
||||
*/
|
||||
Policy policy;
|
||||
|
||||
/**
|
||||
* Roles participating in the rule
|
||||
*/
|
||||
std::bitset<VMGroupRoles::MAX_ROLES> roles;
|
||||
};
|
||||
|
||||
struct VMGroupRule_compare
|
||||
{
|
||||
bool operator() (const VMGroupRule& lhs, const VMGroupRule& rhs) const
|
||||
{
|
||||
return lhs.roles.to_ullong() < rhs.roles.to_ullong();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /*VMGROUP_RULE_H_*/
|
||||
|
@ -16,6 +16,35 @@
|
||||
|
||||
#include "VMGroup.h"
|
||||
#include "VMGroupRole.h"
|
||||
#include "VMGroupRule.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* VMGroupRule */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool VMGroupRule::compatible(VMGroupRule::rule_set& affined,
|
||||
VMGroupRule::rule_set& anti, VMGroupRule& err)
|
||||
{
|
||||
VMGroupRule ta, taa;
|
||||
|
||||
rule_set::iterator it;
|
||||
|
||||
for (it=affined.begin() ; it != affined.end(); ++it)
|
||||
{
|
||||
ta |= *it;
|
||||
}
|
||||
|
||||
for (it=anti.begin() ; it != anti.end(); ++it)
|
||||
{
|
||||
taa |= *it;
|
||||
}
|
||||
|
||||
err = ta & taa;
|
||||
|
||||
return err.none();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -220,6 +249,30 @@ int VMGroupRoles::vm_size()
|
||||
return total;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VMGroupRoles::names_to_ids(const std::set<std::string> keys,
|
||||
std::set<int>& keyi)
|
||||
{
|
||||
std::set<std::string>::iterator it;
|
||||
|
||||
for ( it = keys.begin(); it != keys.end(); ++it )
|
||||
{
|
||||
VMGroupRole *r = by_name.get(*it);
|
||||
|
||||
if ( r == 0 )
|
||||
{
|
||||
keyi.clear();
|
||||
return -1;
|
||||
}
|
||||
|
||||
keyi.insert(r->id());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* VMGroup */
|
||||
@ -426,7 +479,7 @@ error_common:
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VMGroup::check_affinity(const std::string& aname, std::string& error_str)
|
||||
int VMGroup::check_rule_names(const std::string& aname, std::string& error_str)
|
||||
{
|
||||
vector<const SingleAttribute *> affined;
|
||||
vector<const SingleAttribute *>::const_iterator jt;
|
||||
@ -435,13 +488,23 @@ int VMGroup::check_affinity(const std::string& aname, std::string& error_str)
|
||||
|
||||
for ( jt = affined.begin() ; jt != affined.end() ; ++jt )
|
||||
{
|
||||
std::string a_str = (*jt)->value();
|
||||
std::set<std::string> a_set, key_set;
|
||||
std::set<std::string>::iterator s_it;
|
||||
|
||||
if ( !roles.in_map(a_str) )
|
||||
std::set<int> id_set;
|
||||
|
||||
one_util::split_unique((*jt)->value(), ',', a_set);
|
||||
|
||||
for (s_it = a_set.begin(); s_it != a_set.end() ; ++s_it)
|
||||
{
|
||||
key_set.insert(one_util::trim(*s_it));
|
||||
}
|
||||
|
||||
if ( roles.names_to_ids(key_set, id_set) != 0 )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Some roles used in " << aname << " attribute (" << a_str
|
||||
<< ") are not defined";
|
||||
oss << "Some roles used in " << aname << " attribute ("
|
||||
<< (*jt)->value() << ") are not defined";
|
||||
|
||||
error_str = oss.str();
|
||||
return -1;
|
||||
@ -451,6 +514,81 @@ int VMGroup::check_affinity(const std::string& aname, std::string& error_str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VMGroup::get_rules(const std::string& aname, VMGroupRule::Policy policy,
|
||||
VMGroupRule::rule_set& rules, std::string& error_str)
|
||||
{
|
||||
vector<const SingleAttribute *> affined;
|
||||
vector<const SingleAttribute *>::const_iterator jt;
|
||||
|
||||
obj_template->get(aname, affined);
|
||||
|
||||
for ( jt = affined.begin() ; jt != affined.end() ; ++jt )
|
||||
{
|
||||
std::set<std::string> a_set, key_set;
|
||||
std::set<std::string>::iterator s_it;
|
||||
|
||||
std::set<int> id_set;
|
||||
|
||||
std::pair<std::set<VMGroupRule>::iterator, bool> rc;
|
||||
|
||||
one_util::split_unique((*jt)->value(), ',', a_set);
|
||||
|
||||
for (s_it = a_set.begin(); s_it != a_set.end() ; ++s_it)
|
||||
{
|
||||
key_set.insert(one_util::trim(*s_it));
|
||||
}
|
||||
|
||||
roles.names_to_ids(key_set, id_set);
|
||||
|
||||
VMGroupRule rule(policy, id_set);
|
||||
|
||||
rc = rules.insert(rule);
|
||||
|
||||
if ( rc.second == false )
|
||||
{
|
||||
error_str = "Duplicated " + aname + " rule (" +
|
||||
(*jt)->value() + ") detected.";
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VMGroup::check_rule_consistency(std::string& error)
|
||||
{
|
||||
VMGroupRule::rule_set affined, anti;
|
||||
|
||||
VMGroupRule error_rule;
|
||||
|
||||
if ( get_rules("AFFINED", VMGroupRule::AFFINED, affined, error) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( get_rules("ANTI_AFFINED", VMGroupRule::ANTI_AFFINED, anti, error) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( !VMGroupRule::compatible(affined, anti, error_rule) )
|
||||
{
|
||||
error = "Some roles are defined in AFFINED and ANTI_AFFINED at the same"
|
||||
" time";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VMGroup::insert(SqlDB *db, string& error_str)
|
||||
@ -466,7 +604,17 @@ int VMGroup::insert(SqlDB *db, string& error_str)
|
||||
return -1;
|
||||
}
|
||||
|
||||
obj_template->remove("ROLE", va_roles);
|
||||
int num_role = obj_template->remove("ROLE", va_roles);
|
||||
|
||||
if ( num_role > VMGroupRoles::MAX_ROLES )
|
||||
{
|
||||
for ( it = va_roles.begin(); it != va_roles.end(); ++it )
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
|
||||
error_str = "Maximum number of roles in a VM Group reached";
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
|
||||
@ -492,12 +640,12 @@ int VMGroup::insert(SqlDB *db, string& error_str)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( check_affinity("AFFINED", error_str) == -1 )
|
||||
if ( check_rule_names("AFFINED", error_str) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( check_affinity("ANTI_AFFINED", error_str) == -1 )
|
||||
if ( check_rule_names("ANTI_AFFINED", error_str) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@ -529,12 +677,12 @@ int VMGroup::post_update_template(string& error)
|
||||
|
||||
obj_template->erase("ROLE");
|
||||
|
||||
if ( check_affinity("AFFINED", error) == -1 )
|
||||
if ( check_rule_names("AFFINED", error) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( check_affinity("ANTI_AFFINED", error) == -1 )
|
||||
if ( check_rule_names("ANTI_AFFINED", error) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user