mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-25 02:50:08 +03:00
F #2347: Add placement rules consistency checks
This commit is contained in:
parent
97c5fcd2f2
commit
b2f15970c9
@ -38,13 +38,13 @@ class VMGroupPool;
|
||||
* ]
|
||||
*
|
||||
* ROLE = [
|
||||
* NAME = "db",
|
||||
* ID = 1,
|
||||
* NAME = "db",
|
||||
* ID = 1,
|
||||
* POLICY = ANTI_AFFINED,
|
||||
* VMS = "2,3,4,5"
|
||||
* VMS = "2,3,4,5"
|
||||
* ]
|
||||
*
|
||||
* ANTI_AFFINED = "db", "front_end"
|
||||
* ANTI_AFFINED = "db, front_end"
|
||||
*/
|
||||
class VMGroup : public PoolObjectSQL
|
||||
{
|
||||
@ -117,16 +117,25 @@ private:
|
||||
// Role Management
|
||||
// -------------------------------------------------------------------------
|
||||
/**
|
||||
* Check if all the roles are defined in the group
|
||||
* @param aname attribute with a list (comma-separated) of role names
|
||||
* Check if all the roles in a AFFINED/ANTI_AFFINED rules are defined in
|
||||
* the group
|
||||
* @param policy attribute with a list (comma-separated) of role names
|
||||
* @param error_str if any
|
||||
*
|
||||
* @return 0 if all roles are defined -1 otherwise
|
||||
*/
|
||||
int check_rule_names(const std::string& aname, std::string& error_str);
|
||||
int check_rule_names(VMGroupRule::Policy policy, std::string& error_str);
|
||||
|
||||
int get_rules(const std::string& aname, VMGroupRule::Policy policy,
|
||||
VMGroupRule::rule_set& rules, std::string& error_str);
|
||||
/**
|
||||
* Generate a rule_set from the AFFINED/ANTI_AFFINED rules
|
||||
* @param policy AFFINED or ANTIAFFINED
|
||||
* @param rule_set with the rules
|
||||
* @param error_str if some of the roles are not defined
|
||||
*
|
||||
* @return 0 if success -1 otherwise
|
||||
*/
|
||||
int get_rules(VMGroupRule::Policy policy, VMGroupRule::rule_set& rules,
|
||||
std::string& error_str);
|
||||
|
||||
int check_rule_consistency(std::string& error);
|
||||
|
||||
|
@ -66,6 +66,32 @@ public:
|
||||
return rid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the role name
|
||||
*/
|
||||
std::string name()
|
||||
{
|
||||
return va->vector_value("NAME");
|
||||
}
|
||||
|
||||
Policy policy()
|
||||
{
|
||||
string p = va->vector_value("POLICY");
|
||||
|
||||
if ( p == "AFFINED" )
|
||||
{
|
||||
return AFFINED;
|
||||
}
|
||||
else if ( p == "ANTI_AFFINED" )
|
||||
{
|
||||
return ANTI_AFFINED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* VMS set Interface */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@ -176,6 +202,24 @@ public:
|
||||
*/
|
||||
int vm_size();
|
||||
|
||||
/**
|
||||
* @return the a VMGroupRole by its name
|
||||
* @param rname role name
|
||||
*/
|
||||
VMGroupRole * get(const std::string& rname)
|
||||
{
|
||||
return by_name.get(rname);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the a VMGroupRole by its id
|
||||
* @param rname role name
|
||||
*/
|
||||
VMGroupRole * get(int id)
|
||||
{
|
||||
return by_id.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Max number of roles in a VMGroup
|
||||
*/
|
||||
|
@ -29,6 +29,13 @@ struct VMGroupRule_compare;
|
||||
class VMGroupRule
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Placement policy rules for roles
|
||||
* AFFINED: VMs of all roles are placed in the same hypervisor
|
||||
* ANTI_AFFINED: VMs are placed in different hypervisors (role-wise)
|
||||
* NONE: No additional placement constraints
|
||||
*/
|
||||
enum Policy
|
||||
{
|
||||
NONE = 0x00,
|
||||
@ -36,9 +43,40 @@ public:
|
||||
ANTI_AFFINED= 0x02
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @return policy name
|
||||
*/
|
||||
static std::string policy_to_s(Policy policy)
|
||||
{
|
||||
std::string name;
|
||||
|
||||
switch(policy)
|
||||
{
|
||||
case AFFINED:
|
||||
name="AFFINED";
|
||||
break;
|
||||
|
||||
case ANTI_AFFINED:
|
||||
name="ANTI_AFFINED";
|
||||
break;
|
||||
|
||||
case NONE:
|
||||
name="NONE";
|
||||
break;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* A specialized set for rules
|
||||
*/
|
||||
typedef std::set<VMGroupRule, VMGroupRule_compare> rule_set;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Rule Constructors */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
VMGroupRule():policy(NONE),roles(){};
|
||||
|
||||
VMGroupRule(Policy p, std::set<int> roles_id):policy(p)
|
||||
@ -64,13 +102,8 @@ public:
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Rule operators */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
typedef std::set<VMGroupRule, VMGroupRule_compare> rule_set;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
VMGroupRule& operator=(const VMGroupRule& other)
|
||||
{
|
||||
if ( this != &other )
|
||||
@ -109,8 +142,29 @@ public:
|
||||
return roles.none();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Rule interface */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/**
|
||||
* Check if an affined and anti-affined rule set are compatible. Sets are
|
||||
* compatible if there isn't a role in the affined and anti-affined sets
|
||||
* at the same time
|
||||
* @param affined rule set
|
||||
* @param anti affined rule set
|
||||
* @param err a rule with the roles in both sets
|
||||
*
|
||||
* @return true if sets are compatible
|
||||
*/
|
||||
static bool compatible(rule_set& affined, rule_set& anti, VMGroupRule& err);
|
||||
|
||||
/**
|
||||
* @return the roles in the rule as a bitset (1 roles is in)
|
||||
*/
|
||||
const std::bitset<VMGroupRoles::MAX_ROLES>& get_roles() const
|
||||
{
|
||||
return roles;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class VMGroupRule_compare;
|
||||
@ -126,6 +180,10 @@ private:
|
||||
std::bitset<VMGroupRoles::MAX_ROLES> roles;
|
||||
};
|
||||
|
||||
/**
|
||||
* Functor to compre two rules. Two rules are considered equivalent if the
|
||||
* include the same roles.
|
||||
*/
|
||||
struct VMGroupRule_compare
|
||||
{
|
||||
bool operator() (const VMGroupRule& lhs, const VMGroupRule& rhs) const
|
||||
|
@ -479,11 +479,13 @@ error_common:
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VMGroup::check_rule_names(const std::string& aname, std::string& error_str)
|
||||
int VMGroup::check_rule_names(VMGroupRule::Policy policy, std::string& error)
|
||||
{
|
||||
vector<const SingleAttribute *> affined;
|
||||
vector<const SingleAttribute *>::const_iterator jt;
|
||||
|
||||
std::string aname = VMGroupRule::policy_to_s(policy);
|
||||
|
||||
obj_template->get(aname, affined);
|
||||
|
||||
for ( jt = affined.begin() ; jt != affined.end() ; ++jt )
|
||||
@ -506,7 +508,7 @@ int VMGroup::check_rule_names(const std::string& aname, std::string& error_str)
|
||||
oss << "Some roles used in " << aname << " attribute ("
|
||||
<< (*jt)->value() << ") are not defined";
|
||||
|
||||
error_str = oss.str();
|
||||
error = oss.str();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -517,12 +519,14 @@ int VMGroup::check_rule_names(const std::string& aname, std::string& error_str)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VMGroup::get_rules(const std::string& aname, VMGroupRule::Policy policy,
|
||||
VMGroupRule::rule_set& rules, std::string& error_str)
|
||||
int VMGroup::get_rules(VMGroupRule::Policy policy, VMGroupRule::rule_set& rules,
|
||||
std::string& error_str)
|
||||
{
|
||||
vector<const SingleAttribute *> affined;
|
||||
vector<const SingleAttribute *>::const_iterator jt;
|
||||
|
||||
std::string aname = VMGroupRule::policy_to_s(policy);
|
||||
|
||||
obj_template->get(aname, affined);
|
||||
|
||||
for ( jt = affined.begin() ; jt != affined.end() ; ++jt )
|
||||
@ -566,22 +570,62 @@ int VMGroup::check_rule_consistency(std::string& error)
|
||||
{
|
||||
VMGroupRule::rule_set affined, anti;
|
||||
|
||||
VMGroupRule::rule_set::iterator it;
|
||||
|
||||
VMGroupRule error_rule;
|
||||
|
||||
if ( get_rules("AFFINED", VMGroupRule::AFFINED, affined, error) == -1 )
|
||||
if ( get_rules(VMGroupRule::AFFINED, affined, error) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( get_rules("ANTI_AFFINED", VMGroupRule::ANTI_AFFINED, anti, error) == -1 )
|
||||
for (it=affined.begin() ; it != affined.end(); ++it)
|
||||
{
|
||||
const std::bitset<VMGroupRoles::MAX_ROLES> rs = (*it).get_roles();
|
||||
|
||||
for (int i = 0; i < VMGroupRoles::MAX_ROLES; ++i)
|
||||
{
|
||||
if ( rs[i] == 1 )
|
||||
{
|
||||
VMGroupRole * role = roles.get(i);
|
||||
|
||||
if ( role != 0 && role->policy() == VMGroupRole::ANTI_AFFINED )
|
||||
{
|
||||
error = "Role " + role->name() + " is in an AFFINED rule "
|
||||
"but the role policy is ANTI_AFFINED";
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( get_rules(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";
|
||||
ostringstream oss;
|
||||
const std::bitset<VMGroupRoles::MAX_ROLES> rs = error_rule.get_roles();
|
||||
|
||||
oss << "Roles defined in AFFINED and ANTI_AFFINED rules:";
|
||||
|
||||
for (int i = 0; i < VMGroupRoles::MAX_ROLES; ++i)
|
||||
{
|
||||
if ( rs[i] == 1 )
|
||||
{
|
||||
VMGroupRole * role = roles.get(i);
|
||||
|
||||
if ( role != 0 )
|
||||
{
|
||||
oss << " " << role->name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error = oss.str();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -640,12 +684,17 @@ int VMGroup::insert(SqlDB *db, string& error_str)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( check_rule_names("AFFINED", error_str) == -1 )
|
||||
if ( check_rule_names(VMGroupRule::AFFINED, error_str) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( check_rule_names("ANTI_AFFINED", error_str) == -1 )
|
||||
if ( check_rule_names(VMGroupRule::ANTI_AFFINED, error_str) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( check_rule_consistency(error_str) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@ -677,12 +726,17 @@ int VMGroup::post_update_template(string& error)
|
||||
|
||||
obj_template->erase("ROLE");
|
||||
|
||||
if ( check_rule_names("AFFINED", error) == -1 )
|
||||
if ( check_rule_names(VMGroupRule::AFFINED, error) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( check_rule_names("ANTI_AFFINED", error) == -1 )
|
||||
if ( check_rule_names(VMGroupRule::ANTI_AFFINED, error) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( check_rule_consistency(error) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user