1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-22 18:50:08 +03:00

Merge branch 'feature-2347'

This commit is contained in:
Ruben S. Montero 2017-01-27 13:34:46 +01:00
commit 13ed081f14
61 changed files with 4424 additions and 165 deletions

View File

@ -65,6 +65,7 @@ main_env.Append(LIBPATH=[
cwd+'/src/pool',
cwd+'/src/template',
cwd+'/src/vm',
cwd+'/src/vm_group',
cwd+'/src/vm_template',
cwd+'/src/vmm',
cwd+'/src/lcm',
@ -221,6 +222,7 @@ build_scripts=[
'src/nebula/SConstruct',
'src/pool/SConstruct',
'src/vm/SConstruct',
'src/vm_group/SConstruct',
'src/vm_template/SConstruct',
'src/vmm/SConstruct',
'src/lcm/SConstruct',

View File

@ -37,6 +37,7 @@
#include "VirtualRouterPool.h"
#include "MarketPlacePool.h"
#include "MarketPlaceAppPool.h"
#include "VMGroupPool.h"
#include "VirtualMachineManager.h"
#include "LifeCycleManager.h"
@ -156,6 +157,11 @@ public:
return apppool;
};
VMGroupPool * get_vmgrouppool()
{
return vmgrouppool;
};
// --------------------------------------------------------------
// Manager Accessors
// --------------------------------------------------------------
@ -580,10 +586,10 @@ private:
"/DEFAULT_GROUP_QUOTAS/VM_QUOTA"),
system_db(0), db(0),
vmpool(0), hpool(0), vnpool(0), upool(0), ipool(0), gpool(0), tpool(0),
dspool(0), clpool(0), docpool(0), zonepool(0),
secgrouppool(0), vdcpool(0), vrouterpool(0), marketpool(0), apppool(0),
lcm(0), vmm(0), im(0), tm(0), dm(0), rm(0), hm(0), authm(0),
aclm(0), imagem(0), marketm(0), ipamm(0)
dspool(0), clpool(0), docpool(0), zonepool(0), secgrouppool(0),
vdcpool(0), vrouterpool(0), marketpool(0), apppool(0), vmgrouppool(0),
lcm(0), vmm(0), im(0), tm(0), dm(0), rm(0), hm(0), authm(0), aclm(0),
imagem(0), marketm(0), ipamm(0)
{
const char * nl = getenv("ONE_LOCATION");
@ -634,6 +640,7 @@ private:
delete vrouterpool;
delete marketpool;
delete apppool;
delete vmgrouppool;
delete vmm;
delete lcm;
delete im;
@ -718,6 +725,7 @@ private:
VirtualRouterPool * vrouterpool;
MarketPlacePool * marketpool;
MarketPlaceAppPool * apppool;
VMGroupPool * vmgrouppool;
// ---------------------------------------------------------------
// Nebula Managers

View File

@ -96,22 +96,14 @@ namespace one_util
* @param st string to split
* @param delim delimiter character
* @param result where the result will be saved
* @param clean_empty true to clean empty split parts.
* Example for st "a::b:c"
* clean_empty true will return ["a", "b", "c"]
* clean_empty fase will return ["a", "", "b", "c"]
*/
template <class T>
void split_unique(
const std::string& st,
char delim,
std::set<T>& result,
bool clean_empty=true)
void split_unique(const std::string& st, char delim, std::set<T>& result)
{
T elem;
std::vector<std::string>::const_iterator it;
std::vector<std::string> strings = split(st, delim, clean_empty);
std::vector<std::string> strings = split(st, delim, true);
for (it = strings.begin(); it != strings.end(); it++)
{
@ -127,6 +119,13 @@ namespace one_util
}
}
/**
* Explicit specialization for strings
*/
template <>
void split_unique(const std::string& st, char delim,
std::set<std::string>& result);
/**
* Joins the given element with the delimiter
*

View File

@ -66,7 +66,8 @@ public:
VDC = 0x0002000000000000LL,
VROUTER = 0x0004000000000000LL,
MARKETPLACE = 0x0008000000000000LL,
MARKETPLACEAPP = 0x0010000000000000LL
MARKETPLACEAPP = 0x0010000000000000LL,
VMGROUP = 0x0020000000000000LL
};
static string type_to_str(ObjectType ob)
@ -90,6 +91,7 @@ public:
case VROUTER: return "VROUTER" ; break;
case MARKETPLACE: return "MARKETPLACE" ; break;
case MARKETPLACEAPP: return "MARKETPLACEAPP" ; break;
case VMGROUP: return "VMGROUP" ; break;
default: return "";
}
};

View File

@ -679,4 +679,33 @@ private:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class VMGroupAllocate : public RequestManagerAllocate
{
public:
VMGroupAllocate():
RequestManagerAllocate("VMGroupAllocate",
"Allocates a new vm group",
"A:ss",
true)
{
Nebula& nd = Nebula::instance();
pool = nd.get_vmgrouppool();
auth_object = PoolObjectSQL::VMGROUP;
};
~VMGroupAllocate(){};
/* --------------------------------------------------------------------- */
Template * get_object_template()
{
return new Template;
};
Request::ErrorCode pool_allocate(xmlrpc_c::paramList const& paramList,
Template * tmpl,
int& id,
RequestAttributes& att);
};
#endif

View File

@ -250,4 +250,19 @@ public:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class VMGroupChmod: public RequestManagerChmod
{
public:
VMGroupChmod():
RequestManagerChmod("VMGroupChmod",
"Changes permission bits of a vm group")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vmgrouppool();
auth_object = PoolObjectSQL::VMGROUP;
};
~VMGroupChmod(){};
};
#endif

View File

@ -341,4 +341,24 @@ public:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class VMGroupChown: public RequestManagerChown
{
public:
VMGroupChown():
RequestManagerChown("VMGroupChown",
"Changes ownership of a vm group")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vmgrouppool();
auth_object = PoolObjectSQL::VMGROUP;
};
~VMGroupChown(){};
PoolObjectSQL * get(const string& name, int uid, bool lock)
{
return static_cast<VMGroupPool*>(pool)->get(name, uid, lock);
};
};
#endif

View File

@ -449,7 +449,24 @@ protected:
int drop(PoolObjectSQL * obj, bool resive, RequestAttributes& att);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VMGroupDelete : public RequestManagerDelete
{
public:
VMGroupDelete():
RequestManagerDelete("VMGroupDelete",
"Deletes a vm group")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vmgrouppool();
auth_object = PoolObjectSQL::VMGROUP;
};
~VMGroupDelete(){};
};
#endif

View File

@ -371,7 +371,23 @@ public:
~MarketPlaceAppInfo(){};
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class VMGroupInfo : public RequestManagerInfo
{
public:
VMGroupInfo():
RequestManagerInfo("VMGroupInfo",
"Returns vm group information")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vmgrouppool();
auth_object = PoolObjectSQL::VMGROUP;
};
~VMGroupInfo(){};
};
#endif

View File

@ -553,4 +553,23 @@ public:
~MarketPlaceAppPoolInfo(){};
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VMGroupPoolInfo : public RequestManagerPoolInfoFilter
{
public:
VMGroupPoolInfo():
RequestManagerPoolInfoFilter("VMGroupPoolInfo",
"Returns the vm group pool",
"A:siii")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vmgrouppool();
auth_object = PoolObjectSQL::VMGROUP;
};
~VMGroupPoolInfo(){};
};
#endif

View File

@ -405,4 +405,23 @@ public:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class VMGroupRename: public RequestManagerRename
{
public:
VMGroupRename():
RequestManagerRename("VMGroupRename", "Renames a vm group")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vmgrouppool();
auth_object = PoolObjectSQL::VMGROUP;
};
~VMGroupRename(){};
PoolObjectSQL * get(const string& name, int uid, bool lock)
{
return static_cast<VMGroupPool*>(pool)->get(name, uid, lock);
};
};
#endif

View File

@ -343,4 +343,19 @@ public:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class VMGroupUpdateTemplate : public RequestManagerUpdateTemplate
{
public:
VMGroupUpdateTemplate():
RequestManagerUpdateTemplate("VMGroupUpdateTemplate",
"Updates a vm group template")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vmgrouppool();
auth_object = PoolObjectSQL::VMGROUP;
};
~VMGroupUpdateTemplate(){};
};
#endif

View File

@ -326,15 +326,15 @@ public:
* @param name the attribute name.
* @return true first attribute or 0 if not found or wrong type
*/
inline const VectorAttribute * get(const string& name) const
{
return __get<VectorAttribute>(name);
}
inline const VectorAttribute * get(const string& name) const
{
return __get<VectorAttribute>(name);
}
inline VectorAttribute * get(const string& name)
{
return __get<VectorAttribute>(name);
}
inline VectorAttribute * get(const string& name)
{
return __get<VectorAttribute>(name);
}
/**
* Gets the value of a SingleAttribute with the given name and converts

215
include/VMGroup.h Normal file
View File

@ -0,0 +1,215 @@
/* ------------------------------------------------------------------------ */
/* 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_H_
#define VMGROUP_H_
#include "PoolObjectSQL.h"
#include "VMGroupRole.h"
#include "VMGroupRule.h"
class VMGroupPool;
enum class VMGroupPolicy;
/**
* A VM group is a set of related VMs that may impose placement constraints.
*
* Data model:
*
* NAME = "Web server"
* DESCRIPTION = "A multi-tier web server: frontend, apps servers, db"
*
* ROLE = [
* NAME = "frontend",
* ID = 0,
* VMS = "0,1"
* ]
*
* ROLE = [
* NAME = "db",
* ID = 1,
* POLICY = ANTI_AFFINED,
* VMS = "2,3,4,5"
* ]
*
* ANTI_AFFINED = "db, front_end"
*/
class VMGroup : public PoolObjectSQL
{
public:
/**
* Function to print the VMGroup object into a string in XML format
* @param xml the resulting XML string
* @return a reference to the generated string
*/
string& to_xml(string& xml) const;
/**
* Rebuilds the object from an xml formatted string
* @param xml_str The xml-formatted string
* @return 0 on success, -1 otherwise
*/
int from_xml(const string &xml_str);
/**
* Returns a copy of the Template
* @return A copy of the Template
*/
Template * clone_template() const
{
return new Template(*obj_template);
};
// -------------------------------------------------------------------------
// Role Management
// -------------------------------------------------------------------------
/**
* Adds a VM to a role
* @param role_name
* @param vmid
*
* @return 0 if VM was successfully added, -1 otherwise
*/
int add_vm(const std::string& role_name, int vmid)
{
return roles.add_vm(role_name, vmid);
}
/**
* Deletes a VM from a role
* @param role_name
* @param vmid
*
* @return 0 if VM was successfully added, -1 otherwise
*/
int del_vm(const std::string& role_name, int vmid)
{
return roles.del_vm(role_name, vmid);
}
private:
// -------------------------------------------------------------------------
// Friends
// -------------------------------------------------------------------------
friend class VMGroupPool;
// -------------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------------
VMGroup(int _uid, int _gid, const string& _uname, const string& _gname,
int _umask, Template * group_template);
~VMGroup();
// -------------------------------------------------------------------------
// Role Management
// -------------------------------------------------------------------------
/**
* 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(VMGroupPolicy policy, std::string& error_str);
/**
* Generate a rule_set from the AFFINED/ANTI_AFFINED rules
* @param p policy AFFINED or ANTIAFFINED
* @param rs rule_set with the rules
* @param error if some of the roles are not defined
*
* @return 0 if success -1 otherwise
*/
int get_rules(VMGroupPolicy p, VMGroupRule::rule_set& rs, std::string& err);
int check_rule_consistency(std::string& error);
// -------------------------------------------------------------------------
// DataBase implementation
// -------------------------------------------------------------------------
static const char * db_names;
static const char * db_bootstrap;
static const char * table;
/**
* Execute an INSERT or REPLACE Sql query.
* @param db The SQL DB
* @param replace Execute an INSERT or a REPLACE
* @param error_str Returns the error reason, if any
* @return 0 one success
*/
int insert_replace(SqlDB *db, bool replace, string& error_str);
/**
* Bootstraps the database table(s) associated to the VMGroup
* @return 0 on success
*/
static int bootstrap(SqlDB * db)
{
ostringstream oss(VMGroup::db_bootstrap);
return db->exec(oss);
};
/**
* Writes the VMGroup in the database.
* @param db pointer to the db
* @return 0 on success
*/
int insert(SqlDB *db, string& error_str);
/**
* Writes/updates the VMGroup's data fields in the database.
* @param db pointer to the db
* @return 0 on success
*/
int update(SqlDB *db)
{
string error_str;
return insert_replace(db, true, error_str);
}
/**
* Checks the new roles and affined/anti-affined cross-references
* @param error string describing the error if any
* @return 0 on success
*/
int post_update_template(string& error);
/**
* Factory method for VMGroup templates
*/
Template * get_new_template() const
{
return new Template;
}
// -------------------------------------------------------------------------
// VMGroup attributes
// -------------------------------------------------------------------------
/**
* The role set
*/
VMGroupRoles roles;
};
#endif /*VMGROUP_H_*/

158
include/VMGroupPool.h Normal file
View File

@ -0,0 +1,158 @@
/* -------------------------------------------------------------------------- */
/* 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_POOL_H_
#define VMGROUP_POOL_H_
#include "PoolSQL.h"
#include "VMGroup.h"
class AuthRequest;
class VMGroupPool : public PoolSQL
{
public:
VMGroupPool(SqlDB * db):PoolSQL(db, VMGroup::table, true, true){};
~VMGroupPool(){};
/* ---------------------------------------------------------------------- */
/* Methods for DB management */
/* ---------------------------------------------------------------------- */
/**
* Allocates a new VMGroup, writing it in the pool database. No memory is
* allocated for the object.
*
* @param uid user identifier
* @param gid the id of the group this object is assigned to
* @param uname user name
* @param gname group name
* @param umask permissions umask
* @param vmgroup_template a Template object
* @param oid the id assigned to the new VMGroup
* @param error_str Returns the error reason, if any
*
* @return the oid assigned to the object, -1 in case of failure
*/
int allocate(int uid, int gid, const std::string& uname,
const std::string& gname, int umask, Template * vmgrp_tmpl, int * oid,
std::string& error_str);
/**
* Function to get a VMGroup from the pool, if the object is not in memory
* it is loaded from the DB
* @param oid VMGroup unique id
* @param lock locks the VMGroup mutex
* @return a pointer to the VMGroup, 0 if the VMGroup could not be loaded
*/
VMGroup * get(int oid, bool lock)
{
return static_cast<VMGroup *>(PoolSQL::get(oid, lock));
};
/**
* Gets an object from the pool (if needed the object is loaded from the
* database).
* @param name of the object
* @param uid id of owner
* @param lock locks the object if true
*
* @return a pointer to the object, 0 in case of failure
*/
VMGroup * get(const std::string& name, int uid, bool lock)
{
return static_cast<VMGroup *>(PoolSQL::get(name, uid, lock));
};
/** Update a VMGroup
* @param vmgroup pointer to VMGroup
* @return 0 on success
*/
int update(VMGroup * vmgroup)
{
return vmgroup->update(db);
};
/**
* Bootstraps the database table(s) associated to the VMGroup pool
* @return 0 on success
*/
static int bootstrap(SqlDB * _db)
{
return VMGroup::bootstrap(_db);
};
/**
* Dumps the VMGroup pool in XML format. A filter can be added to the query
* @param os the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
*
* @return 0 on success
*/
int dump(std::ostringstream& os, const std::string& where,
const std::string& limit)
{
return PoolSQL::dump(os, "VM_GROUP_POOL", VMGroup::table, where, limit);
};
/**
* Parse the VMGROUP definition in a VM and fills the ROLE attributes. It
* also adds the VM to the role if found.
* @param va the vector attribute
* @param uid VM owner, used as default to look for the VMGroup
* @param vid of the VM
* @param err if any
*
* @return 0 on success
*/
int vmgroup_attribute(VectorAttribute * va, int uid, int vid, string& err);
/**
* Removes VM from the VMGroup
* @param va with VMGROUP
* @param vid of the VM to be removed
*/
void del_vm(const VectorAttribute * va, int vid);
/**
* Builds the AuthRequest for the VMGroup
* @param va with the VMGROUP
* @param uid VM owber, used as default to look for the VMGroup
* @param ar the authrequest
*/
void authorize(const VectorAttribute * va, int uid, AuthRequest* ar);
private:
/**
* Factory method to produce objects
* @return a pointer to the new object
*/
PoolObjectSQL * create()
{
return new VMGroup(-1,-1,"","",0,0);
};
/**
* Gest a VMGroup from its vector attribute description
* @param va the VectorAttribute
* @param _uid default uid to look for the VMGroup
*/
VMGroup * get_from_attribute(const VectorAttribute *va, int _uid);
};
#endif /*VMGROUP_POOL_H_*/

417
include/VMGroupRole.h Normal file
View File

@ -0,0 +1,417 @@
/* ------------------------------------------------------------------------ */
/* 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_ROLE_H_
#define VMGROUP_ROLE_H_
#include "PoolObjectSQL.h"
#include "NebulaUtil.h"
class VMGroupPool;
enum class VMGroupPolicy;
/**
* A VMGroupRole defines a VM type that typically implements a role in a
* multi-vm application.
*
* ROLE = [
* NAME = "Web application servers",
* ID = 12,
* POLICY = AFFINED,
* VMS = "1,2,45,21"
* ]
*
*/
class VMGroupRole
{
public:
VMGroupRole(VectorAttribute *_va);
virtual ~VMGroupRole(){};
/**
* @return the role id
*/
int id()
{
int rid;
va->vector_value("ID", rid);
return rid;
}
/**
* @return the role name
*/
std::string name()
{
return va->vector_value("NAME");
}
/**
* @return the set of VMs in a string in a comma separated list
*/
std::string vms_s()
{
return va->vector_value("VMS");
}
/**
* @return the policy of this role
*/
VMGroupPolicy policy();
std::string policy_s()
{
return va->vector_value("POLICY");
};
/* ---------------------------------------------------------------------- */
/* VMS set Interface */
/* ---------------------------------------------------------------------- */
const std::set<int>& get_vms()
{
return vms;
};
int size_vms()
{
return vms.size();
}
void add_vm(int vm_id);
void del_vm(int vm_id);
/* ---------------------------------------------------------------------- */
/* Placement constraints */
/* ---------------------------------------------------------------------- */
/**
* Generates a string with the boolean expression to conform the role
* internal policy
* @param vm_id of the VM to generate the requirements for
* @param requirements
*/
void vm_role_requirements(int vm_id, std::string& requirements);
/**
* Generates a string with the boolean expression to conform an affinity
* constraint policy
* @param p policy to place VMs respect to this role VMs
* @param requirements
*/
void role_requirements(VMGroupPolicy p, std::string& requirements);
/**
* Gets the placement requirements for the affined HOSTS
* @param reqs string with the requirements expression
*/
void affined_host_requirements(std::string& reqs);
/**
* Gets the placement requirements for the antiaffined HOSTS
* @param reqs string with the requirements expression
*/
void antiaffined_host_requirements(std::string& reqs);
/**
* Generate generic requirements for a set of hosts
* @param hosts the set
* @param op1 operator for each host requirement = or !=
* @param op2 operator to join host requirements & or |
* @param oss stream where the requirement expression is output
*/
static void host_requirements(std::set<int>& hosts, const std::string& op1,
const std::string& op2, std::ostringstream& oss);
private:
/**
* The set of vms in the role
*/
std::set<int> vms;
/**
* The associated vector attribute
*/
VectorAttribute * va;
/**
* Set the VMS attribute for the role (list of VM IDs)
*/
void set_vms();
};
/**
* The VMGroupRoles class represents a set of ROLES stored in a Template
*/
class VMGroupRoles
{
public:
VMGroupRoles():roles_template(false,'=',"ROLES"), next_role(0){};
~VMGroupRoles()
{
by_id.delete_roles();
};
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/**
* Max number of roles in a VMGroup
*/
const static int MAX_ROLES = 32;
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/**
* Function to print the VMGroupRoles into a string in XML format
* @param xml the resulting XML string
* @return a reference to the generated string
*/
std::string& to_xml(std::string& xml_str) const
{
return roles_template.to_xml(xml_str);
}
/**
* Builds the object from an xml node
* @param node for the ROLES template
* @return 0 on success, -1 otherwise
*/
int from_xml_node(const xmlNodePtr node);
/**
* Adds a new role to the set
* @param vrole VectorAttribute of the role
* @param error string if any
*
* @return 0 on success
*/
int add_role(VectorAttribute * vrole, string& error);
/**
* Generates the ids corresponding to a set of role names
* @param rnames string with a comma separated list of role names
* @param keyi the set of ids
*
* @return 0 if all the names were successfully translated
*/
int names_to_ids(const std::string& rnames, std::set<int>& keyi);
/**
* Adds a VM to a role
* @param role_name
* @param vmid
*
* @return 0 if VM was successfully added, -1 otherwise
*/
int add_vm(const std::string& role_name, int vmid);
/**
* Deletes a VM from a role
* @param role_name
* @param vmid
*
* @return 0 if VM was successfully added, -1 otherwise
*/
int del_vm(const std::string& role_name, int vmid);
/**
* @return the total number of VMs in the group
*/
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);
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/**
* Iterator for the roles in the group
*/
class RoleIterator
{
public:
RoleIterator& operator=(const RoleIterator& rhs)
{
role_it = rhs.role_it;
return *this;
}
RoleIterator& operator++()
{
++role_it;
return *this;
}
bool operator!=(const RoleIterator& rhs)
{
return role_it != rhs.role_it;
}
VMGroupRole * operator*() const
{
return role_it->second;
}
RoleIterator(){};
RoleIterator(const RoleIterator& rit):role_it(rit.role_it){};
RoleIterator(const std::map<int, VMGroupRole *>::iterator& _role_it)
:role_it(_role_it){};
virtual ~RoleIterator(){};
private:
std::map<int, VMGroupRole *>::iterator role_it;
};
RoleIterator begin()
{
RoleIterator it(by_id.begin());
return it;
}
RoleIterator end()
{
RoleIterator it(by_id.end());
return it;
}
typedef class RoleIterator role_iterator;
private:
/**
* A role map indexed by different key types
*/
template<class T>
class RoleMap
{
public:
/**
* Inserts a new role in the map
* @param k the key
* @param r pointer to yhe VMGroupRole
* @return true if the role was successfully inserted
*/
bool insert(const T& k, VMGroupRole * r)
{
std::pair<T, VMGroupRole *> rpair(k, r);
std::pair<roles_it, bool> rc;
rc = roles.insert(rpair);
return rc.second;
}
/**
* Frees the memory associated to the map and clears it
*/
void delete_roles()
{
for (roles_it it = roles.begin() ; it != roles.end() ; ++it )
{
delete it->second;
}
clear();
}
VMGroupRole * get(T k)
{
typename std::map<T, VMGroupRole *>::iterator it;
it = roles.find(k);
if ( it == roles.end() )
{
return 0;
}
return it->second;
}
/**
* Clears the contents of the map
*/
void clear()
{
roles.clear();
}
size_t erase(const T& k)
{
return roles.erase(k);
}
/**
* Iterators for the map
*/
typedef typename std::map<T, VMGroupRole *>::iterator roles_it;
roles_it begin()
{
return roles.begin();
}
roles_it end()
{
return roles.end();
}
private:
std::map<T, VMGroupRole *> roles;
};
/**
* The role template to store the VMGroupRole
*/
Template roles_template;
/**
* The next role id
*/
int next_role;
/**
* Map to access the roles by their name
*/
RoleMap<std::string> by_name;
/**
* Map to access the roles by their id
*/
RoleMap<int> by_id;
};
#endif /*VMGROUP_ROLE_H*/

189
include/VMGroupRule.h Normal file
View File

@ -0,0 +1,189 @@
/* ------------------------------------------------------------------------ */
/* 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;
/**
* 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 class VMGroupPolicy
{
NONE = 0x00,
AFFINED = 0x01,
ANTI_AFFINED= 0x02
};
std::ostream& operator<<(std::ostream& os, VMGroupPolicy policy);
/**
* A rule represents a role placement policy
*/
class VMGroupRule
{
public:
/**
* A specialized set for rules
*/
typedef std::set<VMGroupRule, VMGroupRule_compare> rule_set;
typedef std::bitset<VMGroupRoles::MAX_ROLES> role_bitset;
/* ---------------------------------------------------------------------- */
/* Rule Constructors */
/* ---------------------------------------------------------------------- */
VMGroupRule():policy(VMGroupPolicy::NONE),roles(){};
VMGroupRule(VMGroupPolicy 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(VMGroupPolicy p, role_bitset _roles):policy(p), roles(_roles){};
VMGroupRule(const VMGroupRule& other)
{
policy = other.policy;
roles = other.roles;
}
/* ---------------------------------------------------------------------- */
/* Rule operators */
/* ---------------------------------------------------------------------- */
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) const
{
return VMGroupRule(policy, other.roles & roles );
}
VMGroupRule& operator|= (const VMGroupRule& other)
{
roles |= other.roles;
return *this;
}
VMGroupRule operator| (const VMGroupRule& other) const
{
return VMGroupRule(policy, other.roles | roles );
}
bool none()
{
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);
/**
* Reduce a set of affinity rules merging rules affecting the same roles
* Example:
* AFFINED = a, b
* AFFINED = b, c -------> AFFINED = a, b, c
* AFFINED = e, d AFFINED = e, d
*
* @param affined set of rules to be reduced
* @param reduced set
*/
static void reduce(rule_set affined, rule_set& reduced);
/**
* @return the roles in the rule as a bitset (1 roles is in)
*/
const role_bitset& get_roles() const
{
return roles;
}
VMGroupPolicy get_policy() const
{
return policy;
}
private:
friend class VMGroupRule_compare;
/**
* Type of the rule
*/
VMGroupPolicy policy;
/**
* Roles participating in the rule
*/
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
{
return lhs.roles.to_ullong() < rhs.roles.to_ullong();
}
};
#endif /*VMGROUP_RULE_H_*/

View File

@ -1085,6 +1085,14 @@ public:
*/
void remove_security_group(int sgid);
// ------------------------------------------------------------------------
// Virtual Machine Groups
// ------------------------------------------------------------------------
/**
* Remove this VM from its role and VM group if any
*/
void release_vmgroup();
// ------------------------------------------------------------------------
// Imported VM interface
// ------------------------------------------------------------------------
@ -1999,7 +2007,7 @@ private:
int parse_context_variables(VectorAttribute ** context, string& error_str);
// -------------------------------------------------------------------------
// NIC & DISK Management Helpers
// Management helpers: NIC, DISK and VMGROUP
// -------------------------------------------------------------------------
/**
* Get all network leases for this Virtual Machine
@ -2014,6 +2022,13 @@ private:
*/
int get_disk_images(string &error_str);
/**
* Adds the VM to the VM group if needed
* @param error_str Returns the error reason, if any
* @return 0 if success
*/
int get_vmgroup(string& error);
// ------------------------------------------------------------------------
// Public cloud templates related functions
// ------------------------------------------------------------------------

View File

@ -550,6 +550,7 @@ BIN_FILES="src/nebula/oned \
src/cli/oneflow \
src/cli/oneflow-template \
src/cli/onesecgroup \
src/cli/onevmgroup \
src/cli/onevdc \
src/cli/onevrouter \
src/cli/onemarket \
@ -1280,6 +1281,8 @@ RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/opennebula/acl_pool.rb \
src/oca/ruby/opennebula/pool.rb \
src/oca/ruby/opennebula/security_group_pool.rb \
src/oca/ruby/opennebula/security_group.rb \
src/oca/ruby/opennebula/vm_group_pool.rb \
src/oca/ruby/opennebula/vm_group.rb \
src/oca/ruby/opennebula/system.rb \
src/oca/ruby/opennebula/template_pool.rb \
src/oca/ruby/opennebula/template.rb \
@ -1440,6 +1443,7 @@ ONE_CLI_LIB_FILES="src/cli/one_helper/onegroup_helper.rb \
src/cli/one_helper/onevdc_helper.rb \
src/cli/one_helper/oneacct_helper.rb \
src/cli/one_helper/onesecgroup_helper.rb \
src/cli/one_helper/onevmgroup_helper.rb \
src/cli/one_helper/onevrouter_helper.rb \
src/cli/one_helper/onemarketapp_helper.rb \
src/cli/one_helper/onemarket_helper.rb"
@ -1459,6 +1463,7 @@ CLI_BIN_FILES="src/cli/onevm \
src/cli/oneflow-template \
src/cli/oneacct \
src/cli/onesecgroup \
src/cli/onevmgroup \
src/cli/oneshowback \
src/cli/onevdc \
src/cli/onevrouter \
@ -1478,6 +1483,7 @@ CLI_CONF_FILES="src/cli/etc/onegroup.yaml \
src/cli/etc/onezone.yaml \
src/cli/etc/oneacct.yaml \
src/cli/etc/onesecgroup.yaml \
src/cli/etc/onevmgroup.yaml \
src/cli/etc/oneshowback.yaml \
src/cli/etc/onevdc.yaml \
src/cli/etc/onevrouter.yaml \

View File

@ -83,7 +83,7 @@ AclManager::AclManager(
string error_str;
// Users in group USERS can create standard resources
// @1 VM+IMAGE+TEMPLATE+DOCUMENT/* CREATE *
// @1 VM+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VMGROUP/* CREATE *
add_rule(AclRule::GROUP_ID |
1,
AclRule::ALL_ID |
@ -91,7 +91,8 @@ AclManager::AclManager(
PoolObjectSQL::IMAGE |
PoolObjectSQL::TEMPLATE |
PoolObjectSQL::DOCUMENT |
PoolObjectSQL::SECGROUP,
PoolObjectSQL::SECGROUP |
PoolObjectSQL::VMGROUP,
AuthRequest::CREATE,
AclRule::ALL_ID,
error_str);

View File

@ -28,7 +28,7 @@ const long long AclRule::CLUSTER_ID = 0x0000000800000000LL;
const long long AclRule::NONE_ID = 0x1000000000000000LL;
const int AclRule::num_pool_objects = 16;
const int AclRule::num_pool_objects = 17;
const PoolObjectSQL::ObjectType AclRule::pool_objects[] = {
PoolObjectSQL::VM,
PoolObjectSQL::HOST,
@ -45,7 +45,8 @@ const PoolObjectSQL::ObjectType AclRule::pool_objects[] = {
PoolObjectSQL::VDC,
PoolObjectSQL::VROUTER,
PoolObjectSQL::MARKETPLACE,
PoolObjectSQL::MARKETPLACEAPP
PoolObjectSQL::MARKETPLACEAPP,
PoolObjectSQL::VMGROUP
};
const int AclRule::num_auth_operations = 4;
@ -61,7 +62,8 @@ const long long AclRule::INVALID_CLUSTER_OBJECTS =
PoolObjectSQL::TEMPLATE | PoolObjectSQL::GROUP | PoolObjectSQL::ACL |
PoolObjectSQL::CLUSTER | PoolObjectSQL::DOCUMENT | PoolObjectSQL::ZONE |
PoolObjectSQL::SECGROUP | PoolObjectSQL::VDC | PoolObjectSQL::VROUTER |
PoolObjectSQL::MARKETPLACE | PoolObjectSQL::MARKETPLACEAPP;
PoolObjectSQL::MARKETPLACE | PoolObjectSQL::MARKETPLACEAPP |
PoolObjectSQL::VMGROUP;
const long long AclRule::INVALID_GROUP_OBJECTS =
PoolObjectSQL::HOST | PoolObjectSQL::GROUP | PoolObjectSQL::CLUSTER |
@ -237,7 +239,7 @@ bool AclRule::malformed(string& error_str) const
oss << "[resource] type is missing";
}
if ( (resource & 0xFFE0000000000000LL) != 0 )
if ( (resource & 0xFFC0000000000000LL) != 0 )
{
if ( error )
{

View File

@ -9,9 +9,9 @@
:size: 8
:right: true
:RES_VHNIUTGDCOZSvRMA:
:RES_VHNIUTGDCOZSvRMAP:
:desc: Which resource the rule applies to
:size: 20
:size: 21
:RID:
:desc: Resource ID
@ -31,7 +31,7 @@
:default:
- :ID
- :USER
- :RES_VHNIUTGDCOZSvRMA
- :RES_VHNIUTGDCOZSvRMAP
- :RID
- :OPE_UMAC
- :ZONE

View File

@ -0,0 +1,37 @@
---
:ID:
:desc: ONE identifier for the VM Group
:size: 4
:NAME:
:desc: Name of the VM Group
:size: 15
:left: true
:USER:
:desc: Username of the VM Group owner
:size: 8
:left: true
:GROUP:
:desc: Group of the VM Group
:size: 8
:left: true
:VMS:
:desc: Number of VMs in the VM Group
:size: 4
:lef: true
:ROLES:
:desc: Roles in the VM Group
:size: 36
:left: true
:default:
- :ID
- :USER
- :GROUP
- :NAME
- :VMS
- :ROLES

View File

@ -44,7 +44,7 @@ private
def self.resource_mask(str)
resource_type=str.split("/")[0]
mask = "----------------"
mask = "-----------------"
resource_type.split("+").each{|type|
case type
@ -80,6 +80,8 @@ private
mask[14] = "M"
when "MARKETPLACEAPP"
mask[15] = "A"
when "VMGROUP"
mask[16] = "P"
end
}
mask
@ -119,8 +121,8 @@ private
d['STRING'].split(" ")[0]
end
column :RES_VHNIUTGDCOZSvRMA, "Resource to which the rule applies",
:size => 20 do |d|
column :RES_VHNIUTGDCOZSvRMAP, "Resource to which the rule applies",
:size => 21 do |d|
OneAclHelper::resource_mask d['STRING'].split(" ")[1]
end
@ -137,7 +139,7 @@ private
OneAclHelper::right_mask d['STRING'].split(" ")[2]
end
default :ID, :USER, :RES_VHNIUTGDCOZSvRMA, :RID, :OPE_UMAC, :ZONE
default :ID, :USER, :RES_VHNIUTGDCOZSvRMAP, :RID, :OPE_UMAC, :ZONE
end
table

View File

@ -0,0 +1,170 @@
# -------------------------------------------------------------------------- #
# 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. #
#--------------------------------------------------------------------------- #
require 'one_helper'
class OneVMGroupHelper < OpenNebulaHelper::OneHelper
def self.rname
"VM_GROUP"
end
def self.conf_file
"onevmgroup.yaml"
end
def format_pool(options)
config_file = self.class.table_conf
table = CLIHelper::ShowTable.new(config_file, self) do
column :ID, "ONE identifier for the VM Group", :size=>4 do |d|
d["ID"]
end
column :NAME, "Name of the VM Group", :left, :size=>15 do |d|
d["NAME"]
end
column :USER, "Username of the VM Group owner", :left,
:size=>8 do |d|
helper.user_name(d, options)
end
column :GROUP, "Group of the VM Group", :left, :size=>8 do |d|
helper.group_name(d, options)
end
column :VMS, "Number of VMs in the VM Group", :left, :size=>4 do |d|
roles = [d["ROLES"]["ROLE"]].flatten
vms = 0
if !roles.nil?
roles.each { |r|
vms += r["VMS"].split(',').size if !r["VMS"].nil?
}
end
vms
end
column :ROLES, "Roles in the VM Group", :left, :size=>36 do |d|
roles = [d["ROLES"]["ROLE"]].flatten
roles_names = ""
if !roles.nil?
rnames = roles.collect { |i| i["NAME"] }
roles_names = rnames.join(", ") if !rnames.empty?
end
roles_names
end
default :ID, :USER, :GROUP, :NAME, :VMS, :ROLES
end
table
end
private
def factory(id=nil)
if id
OpenNebula::VMGroup.new_with_id(id, @client)
else
xml=OpenNebula::VMGroup.build_xml
OpenNebula::VMGroup.new(xml, @client)
end
end
def factory_pool(user_flag=-2)
OpenNebula::VMGroupPool.new(@client, user_flag)
end
def format_resource(vmgroup, options = {})
str="%-15s: %-20s"
str_h1="%-80s"
CLIHelper.print_header(
str_h1 % "VM GROUP #{vmgroup['ID']} INFORMATION")
puts str % ["ID", vmgroup.id.to_s]
puts str % ["NAME", vmgroup.name]
puts str % ["USER", vmgroup['UNAME']]
puts str % ["GROUP", vmgroup['GNAME']]
CLIHelper.print_header(str_h1 % "PERMISSIONS",false)
puts
["OWNER", "GROUP", "OTHER"].each { |e|
mask = "---"
mask[0] = "u" if vmgroup["PERMISSIONS/#{e}_U"] == "1"
mask[1] = "m" if vmgroup["PERMISSIONS/#{e}_M"] == "1"
mask[2] = "a" if vmgroup["PERMISSIONS/#{e}_A"] == "1"
puts str % [e, mask]
}
puts
CLIHelper.print_header(str_h1 % "ROLES", false)
if !vmgroup.to_hash['VM_GROUP']['ROLES']['ROLE'].nil?
roles = [vmgroup.to_hash['VM_GROUP']['ROLES']['ROLE']].flatten
end
CLIHelper::ShowTable.new(nil, self) do
column :ID, "", :left, :size=>4 do |d|
d["ID"]
end
column :NAME, "", :left, :size=>8 do |d|
d["NAME"]
end
column :POLICY, "", :left, :size=>12 do |d|
if d["POLICY"].nil?
'-'
else
d["POLICY"]
end
end
column :AFFINED_HOSTS, "", :left, :size=>18 do |d|
if d["HOST_AFFINED"].nil?
'-'
else
d["HOST_AFFINED"]
end
end
column :ANTI_AFFINED_HOST, "", :left, :size=>18 do |d|
if d["HOST_ANTI_AFFINED"].nil?
'-'
else
d["HOST_ANTI_AFFINED"]
end
end
column :VIRTUAL_MACHINES, "", :left, :size=>20 do |d|
d["VMS"]
end
end.show(roles, {})
puts
CLIHelper.print_header(str_h1 % "TEMPLATE CONTENTS",false)
puts vmgroup.template_str
end
end

185
src/cli/onevmgroup Executable file
View File

@ -0,0 +1,185 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# 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. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << RUBY_LIB_LOCATION+"/cli"
require 'command_parser'
require 'one_helper/onevmgroup_helper'
cmd=CommandParser::CmdParser.new(ARGV) do
usage "`onevmgroup` <command> [<args>] [<options>]"
version OpenNebulaHelper::ONE_VERSION
helper = OneVMGroupHelper.new
before_proc do
helper.set_client(options)
end
########################################################################
# Global Options
########################################################################
set :option, CommandParser::OPTIONS+OpenNebulaHelper::CLIENT_OPTIONS
list_options = CLIHelper::OPTIONS
list_options << OpenNebulaHelper::XML
list_options << OpenNebulaHelper::NUMERIC
list_options << OpenNebulaHelper::DESCRIBE
########################################################################
# Formatters for arguments
########################################################################
set :format, :groupid, OpenNebulaHelper.rname_to_id_desc("GROUP") do |arg|
OpenNebulaHelper.rname_to_id(arg, "GROUP")
end
set :format, :userid, OpenNebulaHelper.rname_to_id_desc("USER") do |arg|
OpenNebulaHelper.rname_to_id(arg, "USER")
end
set :format, :vmgroupid, OneVMGroupHelper.to_id_desc do |arg|
helper.to_id(arg)
end
set :format, :vmgroupid_list, OneVMGroupHelper.list_to_id_desc do |arg|
helper.list_to_id(arg)
end
set :format, :filterflag, OneVMGroupHelper.filterflag_to_i_desc do |arg|
helper.filterflag_to_i(arg)
end
########################################################################
# Commands
########################################################################
create_desc = <<-EOT.unindent
Creates a new VM Group from the given description
EOT
command :create, create_desc, :file do
helper.create_resource(options) do |obj|
begin
template = File.read(args[0])
obj.allocate(template)
rescue => e
STDERR.puts e.messsage
exit -1
end
end
end
delete_desc = <<-EOT.unindent
Deletes the VM Group
EOT
command :delete, delete_desc, [:range, :vmgroupid_list] do
helper.perform_actions(args[0],options,"deleted") do |obj|
obj.delete
end
end
list_desc = <<-EOT.unindent
Lists VM Group in the pool
EOT
command :list, list_desc, [:filterflag, nil], :options=>list_options do
helper.list_pool(options, false, args[0])
end
show_desc = <<-EOT.unindent
Shows information for the given VM Group
EOT
command :show, show_desc, :vmgroupid, :options=>OpenNebulaHelper::XML do
helper.show_resource(args[0],options)
end
chgrp_desc = <<-EOT.unindent
Changes the VM Group's group
EOT
command :chgrp, chgrp_desc,[:range, :vmgroupid_list], :groupid do
helper.perform_actions(args[0],options,"Group changed") do |obj|
obj.chown(-1, args[1].to_i)
end
end
chown_desc = <<-EOT.unindent
Changes the VM Group's owner and group
EOT
command :chown, chown_desc, [:range, :vmgroupid_list], :userid,
[:groupid,nil] do
gid = args[2].nil? ? -1 : args[2].to_i
helper.perform_actions(args[0],options,"Owner/Group changed") do |obj|
obj.chown(args[1].to_i, gid)
end
end
chmod_desc = <<-EOT.unindent
Changes the VM Group permissions
EOT
command :chmod, chmod_desc, [:range, :vmgroupid_list], :octet do
helper.perform_actions(args[0],options, "Permissions changed") do |t|
t.chmod_octet(args[1])
end
end
update_desc = <<-EOT.unindent
Update the template contents. If a path is not provided the editor will
be launched to modify the current content.
EOT
command :update, update_desc, :vmgroupid, [:file, nil],
:options=>OpenNebulaHelper::APPEND do
helper.perform_action(args[0],options,"modified") do |obj|
if options[:append]
str = OpenNebulaHelper.append_template(args[0], obj, args[1])
else
str = OpenNebulaHelper.update_template(args[0], obj, args[1])
end
helper.set_client(options)
obj = helper.retrieve_resource(obj.id)
obj.update(str, options[:append])
end
end
rename_desc = <<-EOT.unindent
Renames the VM Group
EOT
command :rename, rename_desc, :vmgroupid, :name do
helper.perform_action(args[0],options,"renamed") do |o|
o.rename(args[1])
end
end
end

View File

@ -339,6 +339,25 @@ std::string one_util::gsub(const std::string& st, const std::string& sfind,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
namespace one_util
{
template<>
void split_unique(const std::string& st, char delim, std::set<std::string>& res)
{
std::vector<std::string>::const_iterator it;
std::vector<std::string> strings = split(st, delim, true);
for (it = strings.begin(); it != strings.end(); it++)
{
res.insert(*it);
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/**
* Buffer length for zlib inflate/deflate
*/

View File

@ -223,6 +223,7 @@ void DispatchManager::free_vm_resources(VirtualMachine * vm)
int vmid;
vm->release_network_leases();
vm->release_vmgroup();
vm->release_disk_images(ds_quotas);
vm->set_exit_time(time(0));

View File

@ -230,6 +230,8 @@ void DispatchManager::done_action(int vid)
{
vm->release_network_leases();
vm->release_vmgroup();
vm->release_disk_images(ds_quotas);
vm->set_state(VirtualMachine::DONE);

View File

@ -353,7 +353,7 @@ void Group::add_admin_rules(int user_id)
NebulaLog::log("GROUP",Log::ERROR,error_msg);
}
// #<uid> VM+NET+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VROUTER/@<gid> USE+MANAGE *
// #<uid> VM+NET+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VROUTER+VMGROUP/@<gid> USE+MANAGE *
if ( aclm->add_rule(
AclRule::INDIVIDUAL_ID |
user_id,
@ -365,6 +365,7 @@ void Group::add_admin_rules(int user_id)
PoolObjectSQL::DOCUMENT |
PoolObjectSQL::SECGROUP |
PoolObjectSQL::VROUTER |
PoolObjectSQL::VMGROUP |
AclRule::GROUP_ID |
oid,
@ -449,7 +450,7 @@ void Group::del_admin_rules(int user_id)
NebulaLog::log("GROUP",Log::ERROR,error_msg);
}
// #<uid> VM+NET+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VROUTER/@<gid> USE+MANAGE *
// #<uid> VM+NET+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VROUTER+VMGROUP/@<gid> USE+MANAGE *
if ( aclm->del_rule(
AclRule::INDIVIDUAL_ID |
user_id,
@ -461,6 +462,7 @@ void Group::del_admin_rules(int user_id)
PoolObjectSQL::DOCUMENT |
PoolObjectSQL::SECGROUP |
PoolObjectSQL::VROUTER |
PoolObjectSQL::VMGROUP |
AclRule::GROUP_ID |
oid,

View File

@ -323,6 +323,7 @@ void Nebula::start(bool bootstrap_only)
rc += GroupQuotas::bootstrap(db);
rc += SecurityGroupPool::bootstrap(db);
rc += VirtualRouterPool::bootstrap(db);
rc += VMGroupPool::bootstrap(db);
// Create the system tables only if bootstrap went well
if (rc == 0)
@ -597,6 +598,8 @@ void Nebula::start(bool bootstrap_only)
marketpool = new MarketPlacePool(db, is_federation_slave());
apppool = new MarketPlaceAppPool(db, is_federation_slave());
vmgrouppool = new VMGroupPool(db);
default_user_quota.select();
default_group_quota.select();
}

View File

@ -67,6 +67,7 @@ env.Prepend(LIBS=[
'nebula_vrouter',
'nebula_marketplace',
'nebula_ipamm',
'nebula_vmgroup',
'crypto',
'xml2'
])

View File

@ -62,6 +62,8 @@ require 'opennebula/marketplace'
require 'opennebula/marketplace_pool'
require 'opennebula/marketplaceapp'
require 'opennebula/marketplaceapp_pool'
require 'opennebula/vm_group'
require 'opennebula/vm_group_pool'
module OpenNebula

View File

@ -23,19 +23,23 @@ module OpenNebula
# @<num>
# ALL
# RESOURCE -> + separated list and "/{#,@,%}<num>|ALL"
# VM,
# VM
# HOST
# NET
# IMAGE
# USER
# TEMPLATE
# GROUP
# ACL
# DATASTORE
# CLUSTER
# DOCUMENT
# ZONE
# SECGROUP
# VDC
# VROUTER
# MARKETPLACE
# MARKETPLACEAPP
# VMGROUP
# RIGHTS -> + separated list
# USE
# MANAGE
@ -67,7 +71,8 @@ module OpenNebula
"VDC" => 0x2000000000000,
"VROUTER" => 0x4000000000000,
"MARKETPLACE" => 0x8000000000000,
"MARKETPLACEAPP"=> 0x10000000000000
"MARKETPLACEAPP"=> 0x10000000000000,
"VMGROUP" => 0x20000000000000
}
RIGHTS =

View File

@ -37,7 +37,7 @@ module OpenNebula
SELF = -1
# Default resource ACL's for group users (create)
GROUP_DEFAULT_ACLS = "VM+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VROUTER"
GROUP_DEFAULT_ACLS = "VM+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VROUTER+VMGROUP"
# The default view for group and group admins, must be defined in
# sunstone_views.yaml

View File

@ -0,0 +1,151 @@
# -------------------------------------------------------------------------- #
# 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. #
#--------------------------------------------------------------------------- #
require 'opennebula/pool_element'
module OpenNebula
class VMGroup < PoolElement
#######################################################################
# Constants and Class Methods
#######################################################################
VMGROUP_METHODS = {
:allocate => "vmgroup.allocate",
:info => "vmgroup.info",
:update => "vmgroup.update",
:delete => "vmgroup.delete",
:chown => "vmgroup.chown",
:chmod => "vmgroup.chmod",
:rename => "vmgroup.rename"
}
# Creates a VMGroup description with just its identifier
# this method should be used to create plain VMGroup objects.
# @param pe_id [Integer] the id of the object
def VMGroup.build_xml(pe_id=nil)
if pe_id
obj_xml = "<VM_GROUP><ID>#{pe_id}</ID></VM_GROUP>"
else
obj_xml = "<VM_GROUP></VM_GROUP>"
end
XMLElement.build_xml(obj_xml,'VM_GROUP')
end
# Class constructor
def initialize(xml, client)
super(xml,client)
@client = client
end
#######################################################################
# XML-RPC Methods for the VMGroup Object
#######################################################################
# Retrieves the information of the VMGroup.
def info()
super(VMGROUP_METHODS[:info], 'VM_GROUP')
end
alias_method :info!, :info
# Allocates a new VMGroup in OpenNebula
#
# @param description [String] The contents of the VMGroup.
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def allocate(description)
super(VMGROUP_METHODS[:allocate], description)
end
# Deletes the SecurityGroup
def delete()
super(VMGROUP_METHODS[:delete])
end
# Replaces the vm group contents
#
# @param new_vmgroup [String] New vmgroup contents
# @param append [true, false] True to append new attributes instead of
# replace the whole securitygroup
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def update(new_vmgroup, append=false)
super(VMGROUP_METHODS[:update], new_vmgroup, append ? 1 : 0)
end
# Changes the owner/group
#
# @param uid [Integer] the new owner id. Set to -1 to leave the current one
# @param gid [Integer] the new group id. Set to -1 to leave the current one
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def chown(uid, gid)
super(VMGROUP_METHODS[:chown], uid, gid)
end
# Changes the SecurityGroup permissions.
#
# @param octet [String] Permissions octed , e.g. 640
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def chmod_octet(octet)
super(VMGROUP_METHODS[:chmod], octet)
end
# Changes the SecurityGroup permissions.
# Each [Integer] argument must be 1 to allow, 0 deny, -1 do not change
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def chmod(owner_u, owner_m, owner_a, group_u, group_m, group_a, other_u,
other_m, other_a)
super(VMGROUP_METHODS[:chmod], owner_u, owner_m, owner_a, group_u,
group_m, group_a, other_u, other_m, other_a)
end
# Renames this VMGroup
#
# @param name [String] New name for the VMGroup.
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def rename(name)
return call(VMGROUP_METHODS[:rename], @pe_id, name)
end
#######################################################################
# Helpers to get VMGroup information
#######################################################################
# Returns the group identifier
# [return] _Integer_ the element's group ID
def gid
self['GID'].to_i
end
def owner_id
self['UID'].to_i
end
# [return] _Array_ with the name of roles
def role_names
self.retrieve_elements('ROLES/ROLE/NAME')
end
end
end

View File

@ -0,0 +1,78 @@
# -------------------------------------------------------------------------- #
# 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. #
#--------------------------------------------------------------------------- #
require 'opennebula/pool'
module OpenNebula
class VMGroupPool < Pool
#######################################################################
# Constants and Class attribute accessors
#######################################################################
VMGROUP_POOL_METHODS = {
:info => "vmgrouppool.info"
}
#######################################################################
# Class constructor & Pool Methods
#######################################################################
# +client+ a Client object that represents an XML-RPC connection
# +user_id+ used to refer to a Pool with Templates from that user
def initialize(client, user_id=-1)
super('VM_GROUP_POOL','VM_GROUP',client)
@user_id = user_id
end
# Factory method to create Template objects
def factory(element_xml)
OpenNebula::VMGroup.new(element_xml,@client)
end
#######################################################################
# XML-RPC Methods for the Template Object
#######################################################################
# Retrieves all or part of the objects in the pool.
def info(*args)
case args.size
when 0
info_filter(VMGROUP_POOL_METHODS[:info], @user_id, -1, -1)
when 3
info_filter(VMGROUP_POOL_METHODS[:info], args[0], args[1],
args[2])
end
end
def info_all()
return super(VMGROUP_POOL_METHODS[:info])
end
def info_mine()
return super(VMGROUP_POOL_METHODS[:info])
end
def info_group()
return super(VMGROUP_POOL_METHODS[:info])
end
alias_method :info!, :info
alias_method :info_all!, :info_all
alias_method :info_mine!, :info_mine
alias_method :info_group!, :info_group
end
end

View File

@ -63,6 +63,8 @@ string Request::object_name(PoolObjectSQL::ObjectType ob)
return "marketplace";
case PoolObjectSQL::MARKETPLACEAPP:
return "marketplaceapp";
case PoolObjectSQL::VMGROUP:
return "vm group";
default:
return "-";
}

View File

@ -366,6 +366,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr cluster_update(new ClusterUpdateTemplate());
xmlrpc_c::methodPtr secg_update(new SecurityGroupUpdateTemplate());
xmlrpc_c::methodPtr vrouter_update(new VirtualRouterUpdateTemplate());
xmlrpc_c::methodPtr vmg_update(new VMGroupUpdateTemplate());
// Allocate Methods
xmlrpc_c::methodPtr vm_allocate(new VirtualMachineAllocate());
@ -378,6 +379,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr doc_allocate(new DocumentAllocate());
xmlrpc_c::methodPtr secg_allocate(new SecurityGroupAllocate());
xmlrpc_c::methodPtr vrouter_allocate(new VirtualRouterAllocate());
xmlrpc_c::methodPtr vmg_allocate(new VMGroupAllocate());
// Clone Methods
xmlrpc_c::methodPtr template_clone(new VMTemplateClone());
@ -394,6 +396,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr doc_delete(new DocumentDelete());
xmlrpc_c::methodPtr secg_delete(new SecurityGroupDelete());
xmlrpc_c::methodPtr vrouter_delete(new VirtualRouterDelete());
xmlrpc_c::methodPtr vmg_delete(new VMGroupDelete());
// Info Methods
xmlrpc_c::methodPtr vm_info(new VirtualMachineInfo());
@ -406,6 +409,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr doc_info(new DocumentInfo());
xmlrpc_c::methodPtr secg_info(new SecurityGroupInfo());
xmlrpc_c::methodPtr vrouter_info(new VirtualRouterInfo());
xmlrpc_c::methodPtr vmg_info(new VMGroupInfo());
// Lock Methods
xmlrpc_c::methodPtr doc_lock(new DocumentLock());
@ -421,6 +425,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr clusterpool_info(new ClusterPoolInfo());
xmlrpc_c::methodPtr docpool_info(new DocumentPoolInfo());
xmlrpc_c::methodPtr secgpool_info(new SecurityGroupPoolInfo());
xmlrpc_c::methodPtr vmgpool_info(new VMGroupPoolInfo());
xmlrpc_c::methodPtr vrouter_pool_info(new VirtualRouterPoolInfo());
// Host Methods
@ -449,6 +454,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr doc_chown(new DocumentChown());
xmlrpc_c::methodPtr secg_chown(new SecurityGroupChown());
xmlrpc_c::methodPtr vrouter_chown(new VirtualRouterChown());
xmlrpc_c::methodPtr vmg_chown(new VMGroupChown());
// Chmod Methods
xmlrpc_c::methodPtr vm_chmod(new VirtualMachineChmod());
@ -459,6 +465,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr doc_chmod(new DocumentChmod());
xmlrpc_c::methodPtr secg_chmod(new SecurityGroupChmod());
xmlrpc_c::methodPtr vrouter_chmod(new VirtualRouterChmod());
xmlrpc_c::methodPtr vmg_chmod(new VMGroupChmod());
// Cluster Methods
xmlrpc_c::methodPtr cluster_addhost(new ClusterAddHost());
@ -483,6 +490,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr host_rename(new HostRename());
xmlrpc_c::methodPtr secg_rename(new SecurityGroupRename());
xmlrpc_c::methodPtr vrouter_rename(new VirtualRouterRename());
xmlrpc_c::methodPtr vmg_rename(new VMGroupRename());
// Virtual Router Methods
xmlrpc_c::methodPtr vrouter_instantiate(new VirtualRouterInstantiate());
@ -829,6 +837,18 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.secgrouppool.info",secgpool_info);
/* VM Group objects related methods*/
RequestManagerRegistry.addMethod("one.vmgroup.allocate", vmg_allocate);
RequestManagerRegistry.addMethod("one.vmgroup.delete", vmg_delete);
RequestManagerRegistry.addMethod("one.vmgroup.info", vmg_info);
RequestManagerRegistry.addMethod("one.vmgroup.chown", vmg_chown);
RequestManagerRegistry.addMethod("one.vmgroup.chmod", vmg_chmod);
RequestManagerRegistry.addMethod("one.vmgroup.rename", vmg_rename);
RequestManagerRegistry.addMethod("one.vmgroup.update", vmg_update);
RequestManagerRegistry.addMethod("one.vmgrouppool.info", vmgpool_info);
/* Vdc related methods */
xmlrpc_c::method * vdc_allocate_pt;

View File

@ -1195,3 +1195,25 @@ Request::ErrorCode MarketPlaceAppAllocate::pool_allocate(
return Request::SUCCESS;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
Request::ErrorCode VMGroupAllocate::pool_allocate(
xmlrpc_c::paramList const& paramList,
Template * tmpl,
int& id,
RequestAttributes& att)
{
VMGroupPool * vmgpool = static_cast<VMGroupPool *>(pool);
int rc = vmgpool->allocate(att.uid, att.gid, att.uname, att.gname, att.umask
,tmpl, &id, att.resp_msg);
if (rc < 0)
{
return Request::INTERNAL;
}
return Request::SUCCESS;
}

View File

@ -19,6 +19,7 @@
#define HOST_XML_H_
#include <map>
#include <set>
#include "ObjectXML.h"
#include "HostShare.h"
#include "PoolObjectAuth.h"
@ -48,6 +49,11 @@ public:
return cluster_id;
};
unsigned int dispatched() const
{
return dispatched_vms.size();
}
/**
* Tests whether a new VM can be hosted by the host or not
* @param cpu needed by the VM (percentage)
@ -56,8 +62,8 @@ public:
* @param error error message
* @return true if the share can host the VM
*/
bool test_capacity(long long cpu, long long mem, vector<VectorAttribute *> &pci,
string & error);
bool test_capacity(long long cpu, long long mem,
vector<VectorAttribute *> &pci, string & error);
/**
* Tests whether a new VM can be hosted by the host or not
@ -87,6 +93,8 @@ public:
pci.add(p, vmid);
dispatched_vms.insert(vmid);
running_vms++;
};
@ -171,28 +179,51 @@ private:
int cluster_id;
// Host share values
long long mem_usage; /**< Memory allocated to VMs (in KB) */
long long cpu_usage; /**< CPU allocated to VMs (in percentage) */
long long mem_usage; /**< Memory allocated to VMs (in KB) */
long long cpu_usage; /**< CPU allocated to VMs (in percentage)*/
long long max_mem; /**< Total memory capacity (in KB) */
long long max_cpu; /**< Total cpu capacity (in percentage) */
long long max_mem; /**< Total memory capacity (in KB) */
long long max_cpu; /**< Total cpu capacity (in percentage)*/
long long free_disk; /**< Free disk capacity (in MB) */
HostSharePCI pci; /**< PCI devices of the host */
long long free_disk; /**< Free disk capacity (in MB)*/
map<int, long long> ds_free_disk; /**< Free MB for local system DS */
long long running_vms; /**< Number of running VMs in this Host */
long long running_vms; /**< Number of running VMs in this Host */
set<int> dispatched_vms; /**< Dispatched VMs to this host in this cycle */
bool public_cloud;
HostSharePCI pci;
bool public_cloud; /**< This host is a public cloud */
// Configuration attributes
static const char *host_paths[]; /**< paths for search function */
static int host_num_paths; /**< number of paths */
static int host_num_paths; /**< number of paths*/
/* ---------------------------------------------------------------------- */
/* Functions to search for values in the HostXML object */
/* ---------------------------------------------------------------------- */
bool is_dispatched(const std::string& vm_id) const
{
std::istringstream iss(vm_id);
void init_attributes();
int vm_id_i;
iss >> vm_id_i;
return dispatched_vms.find(vm_id_i) != dispatched_vms.end();
}
bool is_dispatched(int vm_id) const
{
return dispatched_vms.find(vm_id) != dispatched_vms.end();
}
template<typename T>
bool is_dispatched(const T& vm_id) const
{
return false;
}
/**
* Search the Object for a given attribute in a set of object specific
@ -221,6 +252,11 @@ private:
}
}
if ( is_dispatched(value) )
{
return 0;
}
value = -1; //VMID not found in VMS value is -1
return 0;
@ -230,6 +266,11 @@ private:
return ObjectXML::search(name, value);
}
};
/**
* Bootstrap the HostXML internal attributes
*/
void init_attributes();
};
#endif /* HOST_XML_H_ */

View File

@ -46,15 +46,15 @@ public:
{
int rc;
// -------------------------------------------------------------------------
// ---------------------------------------------------------------------
// Clean the pool to get updated data from OpenNebula
// -------------------------------------------------------------------------
// ---------------------------------------------------------------------
flush();
// -------------------------------------------------------------------------
// ---------------------------------------------------------------------
// Load the ids (to get an updated list of the pool)
// -------------------------------------------------------------------------
// ---------------------------------------------------------------------
xmlrpc_c::value result;
@ -124,8 +124,49 @@ public:
}
};
protected:
/**
* Gets an object and removes it from the pool. The calling function
* needs to free the object memory
* @param oid of the object
*
* @return pointer of the object 0 if not found
*/
virtual ObjectXML * erase(int oid)
{
map<int, ObjectXML *>::iterator it;
it = objects.find(oid);
if ( it == objects.end() )
{
return 0;
}
else
{
ObjectXML * obj = it->second;
objects.erase(it);
return obj;
}
}
/**
* Inserts a new object in the pool
* @param obj pointer to the XML object to be inserted
*
* @return true if the object was successfully inserted
*/
virtual bool insert(int oid, ObjectXML * obj)
{
pair<map<int, ObjectXML *>::iterator, bool> rc;
rc = objects.insert(pair<int,ObjectXML*>(oid, obj));
return rc.second;
}
protected:
// ------------------------------------------------------------------------
PoolXML(Client* client, unsigned int pool_limit = 0):ObjectXML()
@ -140,7 +181,6 @@ protected:
};
// ------------------------------------------------------------------------
/**
* Inserts a new ObjectXML into the objects map
*/
@ -156,10 +196,24 @@ protected:
*/
virtual int load_info(xmlrpc_c::value &result) = 0;
/**
* Deletes pool objects and frees resources.
*/
void flush()
{
map<int,ObjectXML*>::iterator it;
for (it=objects.begin();it!=objects.end();it++)
{
delete it->second;
}
objects.clear();
}
// ------------------------------------------------------------------------
// Attributes
// ------------------------------------------------------------------------
/**
* XML-RPC client
*/
@ -175,23 +229,6 @@ protected:
* Hash map contains the suitable [id, object] pairs.
*/
map<int, ObjectXML *> objects;
private:
/**
* Deletes pool objects and frees resources.
*/
void flush()
{
map<int,ObjectXML*>::iterator it;
for (it=objects.begin();it!=objects.end();it++)
{
delete it->second;
}
objects.clear();
}
};
#endif /* POOL_XML_H_ */

View File

@ -19,6 +19,7 @@
#include "Log.h"
#include "HostPoolXML.h"
#include "VMGroupPoolXML.h"
#include "UserPoolXML.h"
#include "ClusterPoolXML.h"
#include "DatastorePoolXML.h"
@ -49,14 +50,16 @@ public:
protected:
Scheduler():
acls(0),
upool(0),
hpool(0),
clpool(0),
vmpool(0),
vmapool(0),
dspool(0),
img_dspool(0),
upool(0),
acls(0),
vmpool(0),
vm_roles_pool(0),
vmgpool(0),
vmapool(0),
timer(0),
one_xmlrpc(""),
machines_limit(0),
@ -72,12 +75,14 @@ protected:
delete clpool;
delete vmpool;
delete vm_roles_pool;
delete vmapool;
delete dspool;
delete img_dspool;
delete upool;
delete vmgpool;
delete acls;
};
@ -85,17 +90,21 @@ protected:
// ---------------------------------------------------------------
// Pools
// ---------------------------------------------------------------
AclXML * acls;
UserPoolXML * upool;
HostPoolXML * hpool;
ClusterPoolXML * clpool;
VirtualMachinePoolXML * vmpool;
VirtualMachineActionsPoolXML* vmapool;
SystemDatastorePoolXML * dspool;
ImageDatastorePoolXML * img_dspool;
UserPoolXML * upool;
ImageDatastorePoolXML * img_dspool;
AclXML * acls;
VirtualMachinePoolXML * vmpool;
VirtualMachineRolePoolXML * vm_roles_pool;
VMGroupPoolXML * vmgpool;
VirtualMachineActionsPoolXML* vmapool;
// ---------------------------------------------------------------
// Scheduler Policies
@ -135,6 +144,8 @@ protected:
virtual int do_scheduled_actions();
virtual void do_vm_groups();
private:
Scheduler(Scheduler const&){};

View File

@ -0,0 +1,51 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2016, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* 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_POOL_XML_H_
#define VMGROUP_POOL_XML_H_
#include <vector>
#include "PoolXML.h"
#include "VMGroupXML.h"
class VMGroupPoolXML : public PoolXML
{
public:
VMGroupPoolXML(Client* client):PoolXML(client){};
~VMGroupPoolXML(){};
VMGroupXML * get(int oid) const
{
return static_cast<VMGroupXML *>(PoolXML::get(oid));
};
protected:
int get_suitable_nodes(std::vector<xmlNodePtr>& content)
{
return get_nodes("/VM_GROUP_POOL/VM_GROUP", content);
};
void add_object(xmlNodePtr node);
int load_info(xmlrpc_c::value &result);
};
#endif /* VMGROUP_POOL_XML_H_ */

View File

@ -0,0 +1,103 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2016, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* 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_XML_H_
#define VMGROUP_XML_H_
#include "ObjectXML.h"
#include "VMGroupRole.h"
#include "VMGroupRule.h"
class VirtualMachinePoolXML;
class VirtualMachineRolePoolXML;
class VMGroupXML : public ObjectXML
{
public:
VMGroupXML(const std::string &xml_doc):ObjectXML(xml_doc)
{
init_attributes();
};
VMGroupXML(const xmlNodePtr node):ObjectXML(node)
{
init_attributes();
};
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
int get_oid() const
{
return oid;
};
const std::string& get_name() const
{
return name;
};
/**
* Dumps a Group, its roles and affinity rules to an output stream
*/
friend ostream& operator<<(ostream& os, VMGroupXML& vmg);
/**
* Adds the internal role placement rules to each VM in the role
* @params vmpool VM set of pending VMs
* @params oss stream to output debug information
*/
void set_antiaffinity_requirements(VirtualMachinePoolXML * vmpool,
std::ostringstream& oss);
/**
* Adds the internal role placement rules to each VM in the role
* @params vmpool VM set of pending VMs
* @params oss stream to output debug information
*/
void set_affinity_requirements(VirtualMachinePoolXML * vmpool,
VirtualMachineRolePoolXML * vm_roles_pool, std::ostringstream& oss);
/**
* Adds host affinity rules to each VM in the roles
* @params vmp the VM set of pending VMs
* @params oss stream to output debug information
*/
void set_host_requirements(VirtualMachinePoolXML * vmp,
std::ostringstream& oss);
private:
// ------------------------------------------------------------------------
// VMGroup Attributes
// ------------------------------------------------------------------------
int oid;
std::string name;
VMGroupRoles roles;
VMGroupRule::rule_set affined;
VMGroupRule::rule_set anti_affined;
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
/**
* Bootstrap VMGroup roles ans rules
*/
void init_attributes();
};
#endif /* VMGROUP_XML_H_ */

View File

@ -84,6 +84,15 @@ public:
return update(vm->get_oid(), vm->get_template(xml));
};
/**
*
*
*/
void clear()
{
flush();
}
protected:
int get_suitable_nodes(vector<xmlNodePtr>& content)
@ -149,4 +158,36 @@ protected:
}
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class VirtualMachineRolePoolXML : public VirtualMachinePoolXML
{
public:
VirtualMachineRolePoolXML(Client * client, unsigned int machines_limit):
VirtualMachinePoolXML(client, machines_limit, false){};
virtual ~VirtualMachineRolePoolXML(){};
/**
* Retrieves the VMs part of a role
*
* @return 0 on success
* -1 on error
* -2 if no VMs in a role
*/
int set_up();
protected:
int get_suitable_nodes(vector<xmlNodePtr>& content)
{
ostringstream oss;
oss << "/VM_POOL/VM[TEMPLATE/VMGROUP/ROLE]";
return get_nodes(oss.str().c_str(), content);
}
};
#endif /* VM_POOL_XML_H_ */

View File

@ -60,7 +60,6 @@ public:
//--------------------------------------------------------------------------
// Get Methods for VirtualMachineXML class
//--------------------------------------------------------------------------
int get_oid() const
{
return oid;
@ -116,9 +115,23 @@ public:
return ds_requirements;
}
void get_requirements (int& cpu, int& memory, long long& disk,
/**
* Return VM usage requirments
*/
void get_requirements(int& cpu, int& memory, long long& disk,
vector<VectorAttribute *> &pci);
/**
* Return the requirements of this VM (as is) and reset them
* @param cpu in unit
* @param memory in kb
* @param disk in mb (system ds usage)
*/
void reset_requirements(float& cpu, int& memory, long long& disk);
/**
* @return the usage requirements in image ds.
*/
map<int,long long> get_storage_usage();
/**
@ -130,10 +143,45 @@ public:
return public_cloud;
};
/**
* Adds usage requirements to this VM
* @param cpu in unit form
* @param m memory in kb
* @param d in mb (system ds usage)
*/
void add_requirements(float c, int m, long long d);
/**
* Adds (logical AND) new placement requirements to the current ones
* @param reqs additional requirements
*/
void add_requirements(const string& reqs)
{
if ( reqs.empty() )
{
return;
}
else if ( requirements.empty() )
{
requirements = reqs;
}
else
{
requirements += " & (" + reqs + ")";
}
}
/**
* Check if the VM is ACTIVE state
*/
bool is_active() const
{
return state == 3;
}
//--------------------------------------------------------------------------
// Matched Resources Interface
//--------------------------------------------------------------------------
/**
* Adds a matching host if it is not equal to the actual one
* @param oid of the host
@ -214,6 +262,23 @@ public:
*/
bool is_only_public_cloud() const;
/**
* Add a VM to the set of affined VMs. This is used for the VM leader
* when scheduling a group.
*
* @param vmid of the affined vm
*
*/
void add_affined(int vmid)
{
affined_vms.insert(vmid);
}
const set<int>& get_affined_vms() const
{
return affined_vms;
}
//--------------------------------------------------------------------------
// Capacity Interface
//--------------------------------------------------------------------------
@ -313,12 +378,16 @@ protected:
void init_storage_usage();
/* ------------------- SCHEDULER INFORMATION --------------------------- */
ResourceMatch match_hosts;
ResourceMatch match_datastores;
bool only_public_cloud;
set<int> affined_vms;
/* ----------------------- VIRTUAL MACHINE ATTRIBUTES ------------------- */
int oid;
@ -331,6 +400,8 @@ protected:
int resched;
bool resume;
int state;
int memory;
float cpu;
long long system_ds_usage;
@ -347,6 +418,7 @@ protected:
VirtualMachineTemplate * vm_template; /**< The VM template */
VirtualMachineTemplate * user_template; /**< The VM user template */
};
#endif /* VM_XML_H_ */

View File

@ -28,6 +28,8 @@ source_files=[
'VirtualMachineXML.cc',
'ClusterPoolXML.cc',
'UserPoolXML.cc',
'VMGroupPoolXML.cc',
'VMGroupXML.cc',
'DatastorePoolXML.cc',
'DatastoreXML.cc']

View File

@ -0,0 +1,50 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2016, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* 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 "VMGroupPoolXML.h"
void VMGroupPoolXML::add_object(xmlNodePtr node)
{
if ( node == 0 || node->children == 0 )
{
NebulaLog::log("VM_GROUP", Log::ERROR, "XML Node does not represent a "
"valid user");
return;
}
VMGroupXML * vmg = new VMGroupXML(node);
objects.insert( pair<int,ObjectXML*>(vmg->get_oid(), vmg) );
}
int VMGroupPoolXML::load_info(xmlrpc_c::value &result)
{
try
{
client->call("one.vmgrouppool.info", "iii", &result, -2, -1, -1);
return 0;
}
catch (exception const& e)
{
ostringstream oss;
oss << "Exception raised: " << e.what();
NebulaLog::log("VMGROUP", Log::ERROR, oss);
return -1;
}
}

View File

@ -0,0 +1,524 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2016, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* 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 "VMGroupXML.h"
#include "VirtualMachinePoolXML.h"
#include <iomanip>
static ostream& operator<<(ostream& os, VMGroupRule::rule_set rules);
void VMGroupXML::init_attributes()
{
vector<xmlNodePtr> content;
std::vector<std::string> srules;
std::vector<std::string>::iterator it;
xpath(oid, "/VM_GROUP/ID", -1);
xpath(name,"/VM_GROUP/NAME", "undefined");
// VMGroup roles
get_nodes("/VM_GROUP/ROLES", content);
if (!content.empty())
{
roles.from_xml_node(content[0]);
}
free_nodes(content);
content.clear();
xpaths(srules, "/VM_GROUP/TEMPLATE/AFFINED");
for ( it = srules.begin() ; it != srules.end(); ++it )
{
std::set<int> id_set;
roles.names_to_ids(*it, id_set);
VMGroupRule rule(VMGroupPolicy::AFFINED, id_set);
affined.insert(rule);
}
srules.clear();
xpaths(srules, "/VM_GROUP/TEMPLATE/ANTI_AFFINED");
for ( it = srules.begin() ; it != srules.end(); ++it )
{
std::set<int> id_set;
roles.names_to_ids(*it, id_set);
VMGroupRule rule(VMGroupPolicy::ANTI_AFFINED, id_set);
anti_affined.insert(rule);
}
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VMGroupXML::set_antiaffinity_requirements(VirtualMachinePoolXML * vmpool,
std::ostringstream& oss)
{
VMGroupRoles::role_iterator it;
oss << "\n";
oss << setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
oss << "Intra-role Anti-affinity rules \n";
oss << left << setw(8)<< "ROLE" << " " << left << setw(8) <<"VM"
<< " " << left << "ANTI_AFFINITY REQUIRMENTS\n"
<< setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
/* ---------------------------------------------------------------------- */
/* Intra-role anti-affinity placement rule */
/* ---------------------------------------------------------------------- */
for ( it = roles.begin(); it != roles.end() ; ++it )
{
VMGroupRole * r = *it;
if ( r->policy() != VMGroupPolicy::ANTI_AFFINED || r->size_vms() <= 1 )
{
continue;
}
const std::set<int>& vms = r->get_vms();
std::set<int>::const_iterator jt;
for ( jt = vms.begin() ; jt != vms.end(); ++jt )
{
std::string reqs;
VirtualMachineXML * vm = vmpool->get(*jt);
if ( vm == 0 )
{
continue;
}
r->vm_role_requirements(*jt, reqs);
if ( !reqs.empty() )
{
vm->add_requirements(reqs);
}
oss << left << setw(8) << r->id() << left << setw(8) << *jt << reqs
<< "\n";
}
}
/* ---------------------------------------------------------------------- */
/* Inter-role anti-affinity placement rule */
/* ---------------------------------------------------------------------- */
oss << "\n";
oss << setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
oss << "Inter-role Anti-affinity rules \n";
oss << left << setw(8)<< "ROLE" << " " << left << setw(8) <<"VM"
<< " " << left << "ANTI_AFFINITY REQUIRMENTS\n"
<< setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
VMGroupRule::rule_set::iterator rt;
for ( rt = anti_affined.begin() ; rt != anti_affined.end() ; ++rt )
{
VMGroupRule::role_bitset rroles = (*rt).get_roles();
for ( int i=0 ; i < VMGroupRoles::MAX_ROLES; ++i)
{
string role_reqs;
if ( rroles[i] == 0 )
{
continue;
}
for ( int j = 0 ; j < VMGroupRoles::MAX_ROLES ; ++j )
{
if ( j == i || rroles[j] == 0 )
{
continue;
}
VMGroupRole * r = roles.get(j);
if ( r == 0 )
{
continue;
}
std::string reqs;
r->role_requirements(VMGroupPolicy::ANTI_AFFINED, reqs);
if ( reqs.empty() )
{
continue;
}
if ( role_reqs.empty() )
{
role_reqs = reqs;
}
else
{
role_reqs += " & " + reqs;
}
}
VMGroupRole * r = roles.get(i);
const std::set<int>& vms = r->get_vms();
std::set<int>::const_iterator vt;
for ( vt=vms.begin() ; vt!=vms.end(); ++vt )
{
VirtualMachineXML * vm = vmpool->get(*vt);
if ( vm == 0 )
{
continue;
}
vm->add_requirements(role_reqs);
oss << left << setw(8) << r->id() << left << setw(8) << *vt
<< vm->get_requirements() << "\n";
}
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VMGroupXML::set_host_requirements(VirtualMachinePoolXML * vmpool,
std::ostringstream& oss)
{
VMGroupRoles::role_iterator it;
oss << "\n";
oss << setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
oss << "Host affinity rules \n";
oss << left << setw(8)<< "ROLE" << " " << left << setw(8) <<"VM"
<< " " << left << "AFFINITY REQUIRMENTS\n"
<< setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
for ( it = roles.begin(); it != roles.end() ; ++it )
{
std::string areqs, aareqs;
VMGroupRole * r = *it;
r->affined_host_requirements(areqs);
r->antiaffined_host_requirements(aareqs);
if ( r->size_vms() == 0 || (areqs.empty() && aareqs.empty()) )
{
continue;
}
const std::set<int>& vms = r->get_vms();
for (std::set<int>::const_iterator jt=vms.begin(); jt!=vms.end(); ++jt)
{
VirtualMachineXML * vm = vmpool->get(*jt);
if ( vm == 0 )
{
continue;
}
if ( !areqs.empty() )
{
vm->add_requirements(areqs);
}
if ( !aareqs.empty() )
{
vm->add_requirements(aareqs);
}
oss << left << setw(8) << r->id() << left << setw(8) << *jt
<< vm->get_requirements() << "\n";
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static void schecule_affined_set(const std::set<int>& vms,
VirtualMachinePoolXML * vmpool, VirtualMachineRolePoolXML * vm_roles_pool,
std::ostringstream& oss)
{
std::set<int>::iterator it;
std::set<int> hosts;
if ( vms.size() <= 1 )
{
return;
}
/* ---------------------------------------------------------------------- */
/* Get hosts where the affined set is running */
/* ---------------------------------------------------------------------- */
for ( it = vms.begin() ; it != vms.end() ; ++it )
{
VirtualMachineXML * vm = vm_roles_pool->get(*it);
if ( vm == 0 )
{
continue;
}
int hid = vm->get_hid();
if ( vm->is_active() && hid != -1 )
{
hosts.insert(hid);
}
}
if ( hosts.size() == 0 )
{
/* ------------------------------------------------------------------ */
/* No VMs of the set are running: */
/* 1. Select a set leader */
/* 2. Allocate VMs in the same host as the leader */
/* 3. Aggregate requirements in the leader for scheduling */
/* ------------------------------------------------------------------ */
VirtualMachineXML * vm;
for ( it = vms.begin(); it != vms.end() ; ++it )
{
vm = vmpool->get(*it);
if ( vm != 0 )
{
break;
}
}
if ( vm == 0 )
{
return;
}
std::ostringstream areqs;
std::string areqs_s;
areqs << "CURRENT_VMS = " << *it;
areqs_s = areqs.str();
for ( ++it ; it != vms.end() ; ++it )
{
float cpu;
int memory;
long long disk;
VirtualMachineXML * tmp = vmpool->get(*it);
if ( tmp == 0 )
{
continue;
}
tmp->reset_requirements(cpu, memory, disk);
vm->add_requirements(cpu, memory, disk);
vm->add_requirements(tmp->get_requirements());
vm->add_affined(*it);
tmp->add_requirements(areqs_s);
oss << left << setw(8) << tmp->get_oid() << " "
<< tmp->get_requirements() << "\n";
}
oss << left << setw(8) << vm->get_oid() << " "
<< vm->get_requirements() << "\n";
}
else
{
/* ------------------------------------------------------------------ */
/* VMs in the group already running */
/* 1. Assign VMs to one of the hosts used by the affined set */
/* ------------------------------------------------------------------ */
std::ostringstream oss_reqs;
std::string reqs;
VMGroupRole::host_requirements(hosts, "=", "|", oss_reqs);
reqs = oss_reqs.str();
for ( it = vms.begin() ; it != vms.end() ; ++it )
{
VirtualMachineXML * vm = vmpool->get(*it);
if ( vm == 0 || reqs.empty())
{
continue;
}
vm->add_requirements(reqs);
oss << left << setw(8) << vm->get_oid() << " "
<< vm->get_requirements() << "\n";
}
}
}
/* -------------------------------------------------------------------------- */
void VMGroupXML::set_affinity_requirements(VirtualMachinePoolXML * vmpool,
VirtualMachineRolePoolXML * vm_roles_pool, std::ostringstream& oss)
{
VMGroupRoles::role_iterator it;
/* ---------------------------------------------------------------------- */
/* Intra-role affinity placement rule */
/* ---------------------------------------------------------------------- */
oss << "\n";
oss << setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
oss << "Intra-role affinity requirements\n";
oss << left << setw(8) << "VMID" << " " << left << "REQUIREMENTS\n";
oss << setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
for ( it = roles.begin(); it != roles.end() ; ++it )
{
VMGroupRole * r = *it;
if ( r->policy() != VMGroupPolicy::AFFINED || r->size_vms() <= 1 )
{
continue;
}
const std::set<int>& vms = r->get_vms();
schecule_affined_set(vms, vmpool, vm_roles_pool, oss);
}
/* ---------------------------------------------------------------------- */
/* Inter-role affinity placement rule */
/* 1. Build the reduced set of affinity rules */
/* 2. Build the set of VMs affected by each rule */
/* 3. Schedule the resulting set */
/* ---------------------------------------------------------------------- */
VMGroupRule::rule_set reduced;
VMGroupRule::rule_set::iterator rit;
oss << "\n";
oss << setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
oss << "Inter-role affinity requirements\n";
oss << left << setw(8) << "VMID" << " " << left << "REQUIREMENTS\n";
oss << setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
VMGroupRule::reduce(affined, reduced);
for ( rit = reduced.begin() ; rit != reduced.end(); ++rit )
{
const VMGroupRule::role_bitset rroles = (*rit).get_roles();
std::set<int> rule_vms;
for (int i = 0 ; i <VMGroupRoles::MAX_ROLES ; ++i)
{
if ( rroles[i] == 0 )
{
continue;
}
VMGroupRole * r = roles.get(i);
if ( r == 0 )
{
continue;
}
const std::set<int>& role_vms = r->get_vms();
rule_vms.insert(role_vms.begin(), role_vms.end());
}
schecule_affined_set(rule_vms, vmpool, vm_roles_pool, oss);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static ostream& operator<<(ostream& os, VMGroupRule::rule_set rules)
{
VMGroupRule::rule_set::iterator rit;
for ( rit = rules.begin() ; rit != rules.end(); ++rit )
{
const VMGroupRule::role_bitset rroles = (*rit).get_roles();
os << left << setw(14) << (*rit).get_policy() << " ";
for (int i = 0 ; i <VMGroupRoles::MAX_ROLES ; ++i)
{
if ( rroles[i] == 1 )
{
os << right << setw(2) << i << " ";
}
}
os << "\n";
}
return os;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
ostream& operator<<(ostream& os, VMGroupXML& vmg)
{
VMGroupRoles::role_iterator it;
os << left << setw(7)<< "ROLE ID" << " " << left << setw(8) << "NAME" << " "
<< setw(12) << "POLICY" << " " << left << "VMS\n"
<< setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
for ( it = vmg.roles.begin() ; it != vmg.roles.end() ; ++it )
{
os << left << setw(7) << (*it)->id() << " "
<< left << setw(8) << (*it)->name() << " "
<< left << setw(12)<< (*it)->policy_s() << " "
<< left << (*it)->vms_s() << "\n";
}
os << "\n";
os << left << "RULES" << "\n"
<< setfill('-') << setw(80) << '-' << setfill(' ') << "\n";
os << vmg.affined;
os << vmg.anti_affined;
return os;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -33,6 +33,8 @@ int VirtualMachinePoolXML::set_up()
if (NebulaLog::log_level() >= Log::DDDEBUG)
{
map<int,ObjectXML*>::iterator it;
oss << "Pending/rescheduling VM and capacity requirements:" << endl;
oss << right << setw(8) << "ACTION" << " "
@ -44,7 +46,7 @@ int VirtualMachinePoolXML::set_up()
<< " Image DS" << endl
<< setw(60) << setfill('-') << "-" << setfill(' ') << endl;
for (map<int,ObjectXML*>::iterator it=objects.begin();it!=objects.end();it++)
for (it = objects.begin() ; it != objects.end() ; ++it)
{
int cpu, mem;
long long disk;
@ -52,7 +54,9 @@ int VirtualMachinePoolXML::set_up()
string action = "DEPLOY";
VirtualMachineXML * vm = static_cast<VirtualMachineXML *>(it->second);
VirtualMachineXML * vm;
vm = static_cast<VirtualMachineXML *>(it->second);
vm->get_requirements(cpu, mem, disk, pci);
@ -73,11 +77,11 @@ int VirtualMachinePoolXML::set_up()
<< right << setw(11) << disk << " ";
map<int,long long> ds_usage = vm->get_storage_usage();
map<int,long long>::const_iterator ds_it;
for (map<int,long long>::const_iterator ds_it = ds_usage.begin();
ds_it != ds_usage.end(); ds_it++)
for ( ds_it = ds_usage.begin(); ds_it != ds_usage.end(); ds_it++)
{
oss << " DS " << ds_it->first << ": " << ds_it->second << " ";
oss << " DS " << ds_it->first << ": " << ds_it->second <<" ";
}
oss << endl;
@ -231,6 +235,7 @@ int VirtualMachinePoolXML::update(int vid, const string &st) const
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -263,6 +268,7 @@ int VirtualMachineActionsPoolXML::set_up()
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -304,3 +310,30 @@ int VirtualMachineActionsPoolXML::action(
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachineRolePoolXML::set_up()
{
int rc = PoolXML::set_up();
if ( rc == 0 )
{
ostringstream oss;
oss << "VMs in VMGroups:" << endl;
map<int,ObjectXML*>::iterator it;
for (it=objects.begin();it!=objects.end();it++)
{
oss << " " << it->first;
}
NebulaLog::log("VM", Log::DEBUG, oss);
}
return rc;
}

View File

@ -36,6 +36,8 @@ void VirtualMachineXML::init_attributes()
xpath(uid, "/VM/UID", -1);
xpath(gid, "/VM/GID", -1);
xpath(state, "/VM/STATE", -1);
xpath(memory, "/VM/TEMPLATE/MEMORY", 0);
xpath<float>(cpu, "/VM/TEMPLATE/CPU", 0);
@ -202,6 +204,30 @@ ostream& operator<<(ostream& os, VirtualMachineXML& vm)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineXML::add_requirements(float c, int m, long long d)
{
cpu += c;
memory += m;
system_ds_usage += d;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineXML::reset_requirements(float& c, int& m, long long& d)
{
c = cpu;
m = memory;
d = system_ds_usage;
cpu = 0;
memory = 0;
system_ds_usage = 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineXML::get_requirements (int& cpu, int& memory,
long long& disk, vector<VectorAttribute *> &pci)
{
@ -406,14 +432,14 @@ int VirtualMachineXML::parse_action_name(string& action_st)
bool VirtualMachineXML::test_image_datastore_capacity(
ImageDatastorePoolXML * img_dspool, string & error_msg) const
{
map<int,long long>::const_iterator ds_usage_it;
map<int,long long>::const_iterator ds_it;
DatastoreXML* ds;
for (ds_usage_it = ds_usage.begin(); ds_usage_it != ds_usage.end(); ds_usage_it++)
for (ds_it = ds_usage.begin(); ds_it != ds_usage.end(); ++ds_it)
{
ds = img_dspool->get(ds_usage_it->first);
ds = img_dspool->get(ds_it->first);
if (ds == 0 || !ds->test_capacity(ds_usage_it->second))
if (ds == 0 || !ds->test_capacity(ds_it->second))
{
ostringstream oss;
@ -434,20 +460,20 @@ bool VirtualMachineXML::test_image_datastore_capacity(
void VirtualMachineXML::add_image_datastore_capacity(
ImageDatastorePoolXML * img_dspool)
{
map<int,long long>::const_iterator ds_usage_it;
map<int,long long>::const_iterator ds_it;
DatastoreXML *ds;
for (ds_usage_it = ds_usage.begin(); ds_usage_it != ds_usage.end(); ds_usage_it++)
for (ds_it = ds_usage.begin(); ds_it != ds_usage.end(); ++ds_it)
{
ds = img_dspool->get(ds_usage_it->first);
ds = img_dspool->get(ds_it->first);
if (ds == 0) //Should never reach here
{
continue;
}
ds->add_capacity(ds_usage_it->second);
ds->add_capacity(ds_it->second);
}
}

View File

@ -30,6 +30,7 @@ sched_env.StaticLibrary(lib_name, source_files)
sched_env.Prepend(LIBS=[
'scheduler_sched',
'scheduler_pool',
'nebula_vmgroup_roles',
'nebula_log',
'nebula_client',
'nebula_acl',

View File

@ -26,6 +26,7 @@
#include <pthread.h>
#include <cmath>
#include <iomanip>
#include "Scheduler.h"
#include "SchedulerTemplate.h"
@ -308,19 +309,23 @@ void Scheduler::start()
// -------------------------------------------------------------------------
// Pools
// -------------------------------------------------------------------------
Client * client = Client::client();
hpool = new HostPoolXML(Client::client());
upool = new UserPoolXML(Client::client());
clpool = new ClusterPoolXML(Client::client());
vmpool = new VirtualMachinePoolXML(Client::client(), machines_limit,
live_rescheds==1);
acls = new AclXML(client, zone_id);
upool = new UserPoolXML(client);
vmapool = new VirtualMachineActionsPoolXML(Client::client(), machines_limit);
hpool = new HostPoolXML(client);
clpool = new ClusterPoolXML(client);
dspool = new SystemDatastorePoolXML(Client::client());
img_dspool = new ImageDatastorePoolXML(Client::client());
dspool = new SystemDatastorePoolXML(client);
img_dspool = new ImageDatastorePoolXML(client);
acls = new AclXML(Client::client(), zone_id);
vm_roles_pool = new VirtualMachineRolePoolXML(client, machines_limit);
vmpool = new VirtualMachinePoolXML(client, machines_limit, live_rescheds==1);
vmgpool = new VMGroupPoolXML(client);
vmapool = new VirtualMachineActionsPoolXML(client, machines_limit);
// -----------------------------------------------------------
// Load scheduler policies
@ -407,7 +412,7 @@ int Scheduler::set_up_pools()
map<int, int> shares;
//--------------------------------------------------------------------------
//Cleans the cache and get the pending VMs
//Cleans the cache and get the pools
//--------------------------------------------------------------------------
rc = vmpool->set_up();
@ -417,10 +422,6 @@ int Scheduler::set_up_pools()
return rc;
}
//--------------------------------------------------------------------------
//Cleans the cache and get the datastores
//--------------------------------------------------------------------------
rc = dspool->set_up();
if ( rc != 0 )
@ -435,10 +436,6 @@ int Scheduler::set_up_pools()
return rc;
}
//--------------------------------------------------------------------------
//Cleans the cache and get the hosts ids
//--------------------------------------------------------------------------
rc = upool->set_up();
if ( rc != 0 )
@ -446,10 +443,6 @@ int Scheduler::set_up_pools()
return rc;
}
//--------------------------------------------------------------------------
//Cleans the cache and get the hosts ids
//--------------------------------------------------------------------------
rc = hpool->set_up();
if ( rc != 0 )
@ -457,10 +450,6 @@ int Scheduler::set_up_pools()
return rc;
}
//--------------------------------------------------------------------------
//Cleans the cache and get the cluster information
//--------------------------------------------------------------------------
rc = clpool->set_up();
if ( rc != 0 )
@ -468,16 +457,8 @@ int Scheduler::set_up_pools()
return rc;
}
//--------------------------------------------------------------------------
//Add to each host the corresponding cluster template
//--------------------------------------------------------------------------
hpool->merge_clusters(clpool);
//--------------------------------------------------------------------------
//Cleans the cache and get the ACLs
//--------------------------------------------------------------------------
rc = acls->set_up();
if ( rc != 0 )
@ -485,6 +466,20 @@ int Scheduler::set_up_pools()
return rc;
}
rc = vmgpool->set_up();
if ( rc != 0 )
{
return rc;
}
rc = vm_roles_pool->set_up();
if ( rc != 0 )
{
return rc;
}
return 0;
};
@ -603,7 +598,8 @@ static bool match_host(AclXML * acls, UserPoolXML * upool, VirtualMachineXML* vm
if (matched == false)
{
error = "It does not fulfill SCHED_REQUIREMENTS.";
error = "It does not fulfill SCHED_REQUIREMENTS: " +
vm->get_requirements();
return false;
}
}
@ -878,7 +874,8 @@ void Scheduler::match_schedule()
vmpool->update(vm);
log_match(vm->get_oid(), "Cannot schedule VM, there is no suitable host.");
log_match(vm->get_oid(),
"Cannot schedule VM, there is no suitable host.");
continue;
}
@ -1022,13 +1019,20 @@ void Scheduler::match_schedule()
ostringstream oss;
oss << "Match Making statistics:\n"
<< "\tNumber of VMs: " << pending_vms.size() << endl
<< "\tTotal time: " << one_util::float_to_str(time(0) - stime) << "s" << endl
<< "\tTotal Cluster Match time: " << one_util::float_to_str(total_cl_match_time) << "s" << endl
<< "\tTotal Host Match time: " << one_util::float_to_str(total_host_match_time) << "s" << endl
<< "\tTotal Host Ranking time: " << one_util::float_to_str(total_host_rank_time) << "s" << endl
<< "\tTotal DS Match time: " << one_util::float_to_str(total_ds_match_time) << "s" << endl
<< "\tTotal DS Ranking time: " << one_util::float_to_str(total_ds_rank_time) << "s" << endl;
<< "\tNumber of VMs: "
<< pending_vms.size() << endl
<< "\tTotal time: "
<< one_util::float_to_str(time(0) - stime) << "s" << endl
<< "\tTotal Cluster Match time: "
<< one_util::float_to_str(total_cl_match_time) << "s" << endl
<< "\tTotal Host Match time: "
<< one_util::float_to_str(total_host_match_time) << "s" << endl
<< "\tTotal Host Ranking time: "
<< one_util::float_to_str(total_host_rank_time) << "s" << endl
<< "\tTotal DS Match time: "
<< one_util::float_to_str(total_ds_match_time) << "s" << endl
<< "\tTotal DS Ranking time: "
<< one_util::float_to_str(total_ds_rank_time) << "s" << endl;
NebulaLog::log("SCHED", Log::DDEBUG, oss);
}
@ -1070,10 +1074,8 @@ void Scheduler::dispatch()
int hid, dsid, cid;
unsigned int dispatched_vms = 0;
bool dispatched;
map<int, unsigned int> host_vms;
pair<map<int,unsigned int>::iterator, bool> rc;
bool dispatched, matched;
char * estr;
map<int, ObjectXML*>::const_iterator vm_it;
@ -1138,6 +1140,32 @@ void Scheduler::dispatch()
cid = host->get_cid();
//------------------------------------------------------------------
// Check host still match requirements with CURRENT_VMS
//------------------------------------------------------------------
matched = true;
if ( one_util::regex_match("CURRENT_VMS",
vm->get_requirements().c_str()) == 0 )
{
if (host->eval_bool(vm->get_requirements(), matched, &estr)!=0)
{
free(estr);
continue;
}
}
if (matched == false)
{
std::ostringstream mss;
mss << "Host " << hid << " no longer meets requirements for VM "
<< vm->get_oid();
NebulaLog::log("SCHED", Log::DEBUG, mss);
continue;
}
//------------------------------------------------------------------
// Test host capacity
//------------------------------------------------------------------
@ -1155,11 +1183,9 @@ void Scheduler::dispatch()
}
//------------------------------------------------------------------
// Test host dispatch limit (init counter if needed)
// Test host dispatch limit
//------------------------------------------------------------------
rc = host_vms.insert(make_pair(hid,0));
if (rc.first->second >= host_dispatch_limit)
if (host->dispatched() >= host_dispatch_limit)
{
continue;
}
@ -1277,9 +1303,33 @@ void Scheduler::dispatch()
}
}
host->add_capacity(vm->get_oid(), cpu, mem, pci);
//------------------------------------------------------------------
// VM leaders needs to add the select host to the affined VMs
//------------------------------------------------------------------
const set<int>& affined_vms = vm->get_affined_vms();
host_vms[hid]++;
if ( affined_vms.size() > 0 )
{
set<int>::const_iterator it;
for ( it = affined_vms.begin(); it != affined_vms.end(); ++it )
{
VirtualMachineXML * avm = vmpool->get(*it);
if ( avm == 0 )
{
continue;
}
avm->add_match_host(hid);
avm->add_match_datastore(dsid);
}
}
//------------------------------------------------------------------
// Update usage and statistics counters
//------------------------------------------------------------------
host->add_capacity(vm->get_oid(), cpu, mem, pci);
dispatched_vms++;
@ -1405,6 +1455,39 @@ int Scheduler::do_scheduled_actions()
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Scheduler::do_vm_groups()
{
map<int, ObjectXML*>::const_iterator it;
const map<int, ObjectXML*> vmgrps = vmgpool->get_objects();
ostringstream oss;
oss << "VM Group Scheduling information\n";
for (it = vmgrps.begin(); it != vmgrps.end() ; ++it)
{
VMGroupXML * grp = static_cast<VMGroupXML*>(it->second);
oss << setfill('*') << setw(80) << '*' << setfill(' ') << "\n"
<< "SCHEDULING RESULTS FOR VM GROUP " << grp->get_oid() << ", "
<< grp->get_name() <<"\n"
<< setfill('*') << setw(80) << '*' << setfill(' ') << "\n";
oss << *grp << "\n";
grp->set_affinity_requirements(vmpool, vm_roles_pool, oss);
grp->set_antiaffinity_requirements(vmpool, oss);
grp->set_host_requirements(vmpool, oss);
}
NebulaLog::log("VMGRP", Log::DDDEBUG, oss);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Scheduler::do_action(const string &name, void *args)
{
int rc;
@ -1431,6 +1514,10 @@ void Scheduler::do_action(const string &name, void *args)
return;
}
profile(true);
do_vm_groups();
profile(false,"Setting VM groups placement constraints.");
match_schedule();
profile(true);

View File

@ -56,6 +56,8 @@ SecurityGroup::SecurityGroup(
{
obj_template = new Template;
}
set_umask(_umask);
}
/* -------------------------------------------------------------------------- */

View File

@ -741,12 +741,8 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
// ------------------------------------------------------------------------
// Set a name if the VM has not got one and VM_ID
// ------------------------------------------------------------------------
oss << oid;
value = oss.str();
user_obj_template->erase("VMID");
obj_template->add("VMID", value);
obj_template->add("VMID", oid);
user_obj_template->get("TEMPLATE_ID", value);
user_obj_template->erase("TEMPLATE_ID");
@ -1019,6 +1015,14 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
}
}
// ------------------------------------------------------------------------
// Associate to VM Group
// ------------------------------------------------------------------------
if ( get_vmgroup(error_str) == -1 )
{
goto error_rollback;
}
// ------------------------------------------------------------------------
parse_well_known_attributes();
@ -1909,6 +1913,15 @@ void VirtualMachine::set_auth_request(int uid,
{
(*nic)->authorize(uid, &ar);
}
const VectorAttribute * vmgroup = tmpl->get("VMGROUP");
if ( vmgroup != 0 )
{
VMGroupPool * vmgrouppool = Nebula::instance().get_vmgrouppool();
vmgrouppool->authorize(vmgroup, uid, &ar);
}
}
/* -------------------------------------------------------------------------- */
@ -2883,6 +2896,74 @@ int VirtualMachine::set_detach_nic(int nic_id)
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* VirtualMachine VMGroup interface */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::get_vmgroup(string& error)
{
vector<Attribute *> vmgroups;
vector<Attribute*>::iterator it;
bool found;
VectorAttribute * thegroup = 0;
user_obj_template->remove("VMGROUP", vmgroups);
for (it = vmgroups.begin(), found = false; it != vmgroups.end(); )
{
if ( (*it)->type() != Attribute::VECTOR || found )
{
delete *it;
it = vmgroups.erase(it);
}
else
{
thegroup = dynamic_cast<VectorAttribute *>(*it);
found = true;
++it;
}
}
if ( thegroup == 0 )
{
return 0;
}
VMGroupPool * vmgrouppool = Nebula::instance().get_vmgrouppool();
int rc;
rc = vmgrouppool->vmgroup_attribute(thegroup, get_uid(), get_oid(), error);
if ( rc != 0 )
{
delete thegroup;
return -1;
}
obj_template->set(thegroup);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::release_vmgroup()
{
VectorAttribute * thegroup = obj_template->get("VMGROUP");
if ( thegroup == 0 )
{
return;
}
VMGroupPool * vmgrouppool = Nebula::instance().get_vmgrouppool();
vmgrouppool->del_vm(thegroup, get_oid());
}

42
src/vm_group/SConstruct Normal file
View File

@ -0,0 +1,42 @@
# SConstruct for src/secgroup
# -------------------------------------------------------------------------- #
# 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. #
#--------------------------------------------------------------------------- #
Import('env')
lib_name='nebula_vmgroup'
# Sources to generate the library
source_files=[
'VMGroupPool.cc',
'VMGroup.cc',
'VMGroupRole.cc',
'VMGroupRule.cc'
]
# Build library
env.StaticLibrary(lib_name, source_files)
# Stripped library for scheduler with role logic
lib_name='nebula_vmgroup_roles'
source_files=[
'VMGroupRole.cc',
'VMGroupRule.cc'
]
env.StaticLibrary(lib_name, source_files)

485
src/vm_group/VMGroup.cc Normal file
View File

@ -0,0 +1,485 @@
/* ------------------------------------------------------------------------ */
/* 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. */
/* -------------------------------------------------------------------------*/
#include "VMGroup.h"
#include "VMGroupRole.h"
#include "VMGroupRule.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* VMGroup */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
const char * VMGroup::table = "vmgroup_pool";
const char * VMGroup::db_names = "oid, name, body, uid, gid, owner_u, group_u, "
"other_u";
const char * VMGroup::db_bootstrap = "CREATE TABLE IF NOT EXISTS vmgroup_pool "
"(oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, "
"uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, "
"other_u INTEGER, UNIQUE(name,uid))";
/* ------------------------------------------------------------------------ */
VMGroup::VMGroup(int _uid, int _gid, const string& _uname, const string& _gname,
int _umask, Template * group_template):
PoolObjectSQL(-1, VMGROUP, "", _uid, _gid, _uname, _gname, table)
{
if (group_template != 0)
{
obj_template = group_template;
}
else
{
obj_template = new Template;
}
set_umask(_umask);
}
VMGroup::~VMGroup()
{
delete obj_template;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& VMGroup::to_xml(string& xml) const
{
ostringstream oss;
string template_xml;
string perms_xml;
string roles_xml;
oss <<
"<VM_GROUP>" <<
"<ID>" << oid << "</ID>" <<
"<UID>" << uid << "</UID>" <<
"<GID>" << gid << "</GID>" <<
"<UNAME>" << uname << "</UNAME>" <<
"<GNAME>" << gname << "</GNAME>" <<
"<NAME>" << name << "</NAME>" <<
perms_to_xml(perms_xml) <<
roles.to_xml(roles_xml) <<
obj_template->to_xml(template_xml) <<
"</VM_GROUP>";
xml = oss.str();
return xml;
}
/* -------------------------------------------------------------------------- */
int VMGroup::from_xml(const string &xml_str)
{
vector<xmlNodePtr> content;
int rc = 0;
// Initialize the internal XML object
update_from_str(xml_str);
// Get class base attributes
rc += xpath(oid, "/VM_GROUP/ID", -1);
rc += xpath(uid, "/VM_GROUP/UID", -1);
rc += xpath(gid, "/VM_GROUP/GID", -1);
rc += xpath(uname, "/VM_GROUP/UNAME","not_found");
rc += xpath(gname, "/VM_GROUP/GNAME","not_found");
rc += xpath(name, "/VM_GROUP/NAME", "not_found");
// Permissions
rc += perms_from_xml();
// Get associated template
ObjectXML::get_nodes("/VM_GROUP/TEMPLATE", content);
if (content.empty())
{
return -1;
}
rc += obj_template->from_xml_node(content[0]);
ObjectXML::free_nodes(content);
content.clear();
// VMGroup roles
ObjectXML::get_nodes("/VM_GROUP/ROLES", content);
if (!content.empty())
{
rc += roles.from_xml_node(content[0]);
}
ObjectXML::free_nodes(content);
content.clear();
if (rc != 0)
{
return -1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroup::insert_replace(SqlDB *db, bool replace, string& error_str)
{
ostringstream oss;
int rc;
string xml_body;
char * sql_name;
char * sql_xml;
sql_name = db->escape_str(name.c_str());
if ( sql_name == 0 )
{
goto error_name;
}
sql_xml = db->escape_str(to_xml(xml_body).c_str());
if ( sql_xml == 0 )
{
goto error_body;
}
if ( validate_xml(sql_xml) != 0 )
{
goto error_xml;
}
if ( replace )
{
oss << "REPLACE";
}
else
{
oss << "INSERT";
}
// Construct the SQL statement to Insert or Replace
oss <<" INTO "<<table <<" ("<< db_names <<") VALUES ("
<< oid << ","
<< "'" << sql_name << "',"
<< "'" << sql_xml << "',"
<< uid << ","
<< gid << ","
<< owner_u << ","
<< group_u << ","
<< other_u << ")";
rc = db->exec(oss);
db->free_str(sql_name);
db->free_str(sql_xml);
return rc;
error_xml:
db->free_str(sql_name);
db->free_str(sql_xml);
error_str = "Error transforming the VM group to XML.";
goto error_common;
error_body:
db->free_str(sql_name);
goto error_generic;
error_name:
goto error_generic;
error_generic:
error_str = "Error inserting VM group in DB.";
error_common:
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroup::check_rule_names(VMGroupPolicy policy, std::string& error)
{
vector<const SingleAttribute *> affined;
vector<const SingleAttribute *>::const_iterator jt;
std::ostringstream oss;
oss << policy;
std::string aname = oss.str();
obj_template->get(aname, affined);
for ( jt = affined.begin() ; jt != affined.end() ; ++jt )
{
std::set<int> id_set;
if ( roles.names_to_ids((*jt)->value(), id_set) != 0 )
{
std::ostringstream oss;
oss << "Some roles used in " << aname << " attribute ("
<< (*jt)->value() << ") are not defined";
error = oss.str();
return -1;
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroup::get_rules(VMGroupPolicy policy, VMGroupRule::rule_set& rules,
std::string& error_str)
{
vector<const SingleAttribute *> affined;
vector<const SingleAttribute *>::const_iterator jt;
std::ostringstream oss;
oss << policy;
std::string aname = oss.str();
obj_template->get(aname, affined);
for ( jt = affined.begin() ; jt != affined.end() ; ++jt )
{
std::set<int> id_set;
std::pair<std::set<VMGroupRule>::iterator, bool> rc;
roles.names_to_ids((*jt)->value(), id_set);
VMGroupRule rule(policy, id_set);
rc = rules.insert(rule);
if ( rc.second == false )
{
std::ostringstream oss;
oss << "Duplicated " << aname << " rule (" << (*jt)->value()
<< ") detected.";
error_str = oss.str();
return -1;
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroup::check_rule_consistency(std::string& error)
{
VMGroupRule::rule_set affined, anti;
VMGroupRule::rule_set::iterator it;
VMGroupRule error_rule;
if ( get_rules(VMGroupPolicy::AFFINED, affined, error) == -1 )
{
return -1;
}
for (it=affined.begin() ; it != affined.end(); ++it)
{
const VMGroupRule::role_bitset 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() == VMGroupPolicy::ANTI_AFFINED )
{
error = "Role " + role->name() + " is in an AFFINED rule "
"but the role policy is ANTI_AFFINED";
return -1;
}
}
}
}
if ( get_rules(VMGroupPolicy::ANTI_AFFINED, anti, error) == -1 )
{
return -1;
}
if ( !VMGroupRule::compatible(affined, anti, error_rule) )
{
ostringstream oss;
const VMGroupRule::role_bitset 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;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroup::insert(SqlDB *db, string& error_str)
{
vector<Attribute*> va_roles;
vector<Attribute*>::iterator it;
erase_template_attribute("NAME", name);
if (name.empty())
{
error_str = "No NAME in template for VM group.";
return -1;
}
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;
for ( it = va_roles.begin(); it != va_roles.end(); ++it )
{
VectorAttribute * vatt = dynamic_cast<VectorAttribute *>(*it);
if (vatt == 0 || error)
{
delete *it;
continue;
}
if ( roles.add_role(vatt, error_str) == -1 )
{
delete *it;
error = true;
}
}
if ( error )
{
return -1;
}
if ( check_rule_names(VMGroupPolicy::AFFINED, error_str) == -1 )
{
return -1;
}
if ( check_rule_names(VMGroupPolicy::ANTI_AFFINED, error_str) == -1 )
{
return -1;
}
if ( check_rule_consistency(error_str) == -1 )
{
return -1;
}
if ( insert_replace(db, false, error_str) != 0 )
{
return -1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroup::post_update_template(string& error)
{
int vms = roles.vm_size();
if ( vms > 0 )
{
ostringstream oss;
oss << "VM Group has " << vms << " VMs";
error = oss.str();
return -1;
}
obj_template->erase("ROLE");
if ( check_rule_names(VMGroupPolicy::AFFINED, error) == -1 )
{
return -1;
}
if ( check_rule_names(VMGroupPolicy::ANTI_AFFINED, error) == -1 )
{
return -1;
}
if ( check_rule_consistency(error) == -1 )
{
return -1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

185
src/vm_group/VMGroupPool.cc Normal file
View File

@ -0,0 +1,185 @@
/* -------------------------------------------------------------------------- */
/* 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. */
/* -------------------------------------------------------------------------- */
#include "VMGroupPool.h"
#include "AuthRequest.h"
int VMGroupPool::allocate(int uid, int gid, const string& uname,
const string& gname, int umask, Template * vmgroup_template, int * oid,
string& error_str)
{
VMGroup * vmgrp;
VMGroup * vmgrp_aux = 0;
string name;
ostringstream os;
vmgrp = new VMGroup(uid, gid, uname, gname, umask, vmgroup_template);
vmgrp->get_template_attribute("NAME", name);
if ( !PoolObjectSQL::name_is_valid(name, error_str) )
{
goto error_name;
}
vmgrp_aux = get(name, uid, false);
if( vmgrp_aux != 0 )
{
goto error_duplicated;
}
*oid = PoolSQL::allocate(vmgrp, error_str);
return *oid;
error_duplicated:
os << "NAME is already taken by VMGroup " << vmgrp_aux->get_oid() << ".";
error_str = os.str();
error_name:
delete vmgrp;
*oid = -1;
return *oid;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VMGroup * VMGroupPool::get_from_attribute(const VectorAttribute *va, int _uid)
{
VMGroup * vmgroup = 0;
string vmg_name = va->vector_value("VMGROUP_NAME");
int vmg_id;
if ( !vmg_name.empty() )
{
int vmg_uid;
if ( va->vector_value("VMGROUP_UID", vmg_uid) == -1 )
{
vmg_uid = _uid;
}
vmgroup = get(vmg_name, vmg_uid, true);
}
else if ( va->vector_value("VMGROUP_ID", vmg_id) == 0 )
{
vmgroup = get(vmg_id, true);
}
return vmgroup;
}
/* -------------------------------------------------------------------------- */
int VMGroupPool::vmgroup_attribute(VectorAttribute * va, int uid, int vid,
string& error)
{
string vmg_role = va->vector_value("ROLE");
if ( vmg_role.empty() )
{
error = "Missing role name in VM Group definition";
return -1;
}
VMGroup * vmgroup = get_from_attribute(va, uid);
if ( vmgroup == 0 )
{
error = "Cannot find VM Group to associate the VM";
return -1;
}
va->replace("VMGROUP_ID", vmgroup->get_oid());
int rc = vmgroup->add_vm(vmg_role, vid);
if ( rc != 0 )
{
error = "Role does not exist in VM Group";
}
else
{
update(vmgroup);
}
vmgroup->unlock();
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VMGroupPool::del_vm(const VectorAttribute * va, int vid)
{
int vmg_id;
if ( va->vector_value("VMGROUP_ID", vmg_id) == -1 )
{
return;
}
string vmg_role = va->vector_value("ROLE");
if ( vmg_role.empty() )
{
return;
}
VMGroup * vmgroup = get(vmg_id, true);
if ( vmgroup == 0 )
{
return;
}
vmgroup->del_vm(vmg_role, vid);
update(vmgroup);
vmgroup->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VMGroupPool::authorize(const VectorAttribute * va, int uid,AuthRequest* ar)
{
PoolObjectAuth perm;
VMGroup * vmgroup = get_from_attribute(va, uid);
if ( vmgroup == 0 )
{
return;
}
vmgroup->get_permissions(perm);
vmgroup->unlock();
ar->add_auth(AuthRequest::USE, perm);
}

405
src/vm_group/VMGroupRole.cc Normal file
View File

@ -0,0 +1,405 @@
/* ------------------------------------------------------------------------ */
/* 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. */
/* -------------------------------------------------------------------------*/
#include "VMGroupRole.h"
#include "VMGroupRule.h"
#include <iomanip>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* VMGroupRole */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VMGroupRole::VMGroupRole(VectorAttribute *_va):va(_va)
{
string vms_str = va->vector_value("VMS");
if ( !vms_str.empty() )
{
one_util::split_unique(vms_str, ',', vms);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VMGroupPolicy VMGroupRole::policy()
{
string p = va->vector_value("POLICY");
one_util::toupper(p);
if ( p == "AFFINED" )
{
return VMGroupPolicy::AFFINED;
}
else if ( p == "ANTI_AFFINED" )
{
return VMGroupPolicy::ANTI_AFFINED;
}
else
{
return VMGroupPolicy::NONE;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VMGroupRole::add_vm(int vm_id)
{
std::pair<std::set<int>::iterator, bool> rc;
rc = vms.insert(vm_id);
if ( rc.second == false )
{
return;
}
set_vms();
}
void VMGroupRole::del_vm(int vm_id)
{
size_t rc = vms.erase(vm_id);
if ( rc == 0 )
{
return;
}
set_vms();
}
void VMGroupRole::set_vms()
{
if ( vms.empty() )
{
va->remove("VMS");
return;
}
std::string vms_str = one_util::join(vms.begin(), vms.end(), ',');
va->replace("VMS", vms_str);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static void affinity_requirements(int vm_id, std::string& requirements,
VMGroupPolicy policy, const std::set<int>& vms)
{
string op, op2;
requirements = "";
switch(policy)
{
case VMGroupPolicy::AFFINED:
op = "=";
op2= " | ";
break;
case VMGroupPolicy::ANTI_AFFINED:
op = "!=";
op2= " & ";
break;
case VMGroupPolicy::NONE:
return;
}
std::ostringstream oss;
std::set<int>::const_iterator it;
bool first = true;
for ( it = vms.begin(); it != vms.end(); ++it )
{
if ( vm_id == -1 || vm_id != *it )
{
if ( !first )
{
oss << op2;
}
first = false;
oss << "(CURRENT_VMS " << op << " " << *it << ")";
}
}
requirements = oss.str();
}
void VMGroupRole::vm_role_requirements(int vm_id, std::string& requirements)
{
affinity_requirements(vm_id, requirements, policy(), vms);
}
void VMGroupRole::role_requirements(VMGroupPolicy pol, std::string& reqs)
{
affinity_requirements(-1, reqs, pol, vms);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VMGroupRole::host_requirements(std::set<int>& hosts, const std::string& op1,
const std::string& op2, std::ostringstream& oss)
{
std::set<int>::const_iterator jt;
bool empty = true;
for ( jt = hosts.begin() ; jt != hosts.end() ; ++jt )
{
if ( empty == true )
{
empty = false;
oss << "(ID" << op1 << *jt << ")";
}
else
{
oss << " " << op2 << " (ID" << op1 << *jt << ")";
}
}
}
/* -------------------------------------------------------------------------- */
void VMGroupRole::affined_host_requirements(std::string& reqs)
{
std::ostringstream oss;
std::set<int> hosts;
string shosts = va->vector_value("HOST_AFFINED");
if ( !shosts.empty() )
{
one_util::split_unique(shosts, ',', hosts);
}
host_requirements(hosts, "=", "|", oss);
reqs = oss.str();
}
/* -------------------------------------------------------------------------- */
void VMGroupRole::antiaffined_host_requirements(std::string& reqs)
{
std::ostringstream oss;
std::set<int> hosts;
string shosts = va->vector_value("HOST_ANTI_AFFINED");
if ( !shosts.empty() )
{
one_util::split_unique(shosts, ',', hosts);
}
host_requirements(hosts, "!=", "&", oss);
reqs = oss.str();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* VMGroupRoles */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroupRoles::from_xml_node(const xmlNodePtr node)
{
std::vector<VectorAttribute *> roles;
std::vector<VectorAttribute *>::iterator it;
if ( roles_template.from_xml_node(node) == -1 )
{
return -1;
}
roles_template.get("ROLE", roles);
for (it = roles.begin(); it != roles.end(); ++it)
{
std::string rname = (*it)->vector_value("NAME");
int rid;
int rc = (*it)->vector_value("ID", rid);
if ( rname.empty() || rc == -1 )
{
return -1;
}
if ( rid >= next_role )
{
next_role = rid + 1;
}
VMGroupRole * role = new VMGroupRole((*it));
if ( by_id.insert(rid, role) == false )
{
delete role;
return -1;
}
if ( by_name.insert(rname, role) == false )
{
by_id.erase(rid);
delete role;
return -1;
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroupRoles::add_role(VectorAttribute * vrole, string& error)
{
std::string rname = vrole->vector_value("NAME");
if ( rname.empty() )
{
error = "Missing NAME in VM group role";
return -1;
}
// Remove internal attributes before inserting
vrole->replace("ID", next_role);
vrole->remove("VMS");
VMGroupRole * role = new VMGroupRole(vrole);
if ( by_id.insert(next_role, role) == false )
{
delete role;
error = "Role ID already exists";
return -1;
}
if ( by_name.insert(rname, role) == false )
{
by_id.erase(next_role);
delete role;
error = "Role NAME already exists";
return -1;
}
next_role += 1;
roles_template.set(vrole);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroupRoles::add_vm(const std::string& role_name, int vmid)
{
VMGroupRole * role;
role = by_name.get(role_name);
if ( role == 0 )
{
return -1;
}
role->add_vm(vmid);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroupRoles::del_vm(const std::string& role_name, int vmid)
{
VMGroupRole * role;
role = by_name.get(role_name);
if ( role == 0 )
{
return -1;
}
role->del_vm(vmid);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroupRoles::vm_size()
{
int total = 0;
for ( role_iterator it = begin(); it != end() ; ++it )
{
total += (*it)->get_vms().size();
}
return total;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VMGroupRoles::names_to_ids(const std::string& rnames, std::set<int>& keyi)
{
std::set<std::string> a_set, key_set;
std::set<std::string>::iterator it;
one_util::split_unique(rnames, ',', a_set);
for ( it = a_set.begin(); it != a_set.end() ; ++it )
{
key_set.insert(one_util::trim(*it));
}
for ( it = key_set.begin(); it != key_set.end(); ++it )
{
VMGroupRole *r = by_name.get(*it);
if ( r == 0 )
{
keyi.clear();
return -1;
}
keyi.insert(r->id());
}
return 0;
}

114
src/vm_group/VMGroupRule.cc Normal file
View File

@ -0,0 +1,114 @@
/* ------------------------------------------------------------------------ */
/* 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. */
/* -------------------------------------------------------------------------*/
#include "VMGroup.h"
#include "VMGroupRole.h"
#include "VMGroupRule.h"
#include <iomanip>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* VMGroupRule */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool VMGroupRule::compatible(rule_set& affined, 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();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VMGroupRule::reduce(rule_set affined, rule_set& reduced_set)
{
VMGroupRule::rule_set::iterator it, jt;
VMGroupRule reduced_rule;
for ( it = affined.begin(), reduced_rule = (*it) ; it != affined.end() ; )
{
bool reduced = false;
for ( jt = affined.begin() ; jt != affined.end() ; )
{
VMGroupRule tmp = *it;
tmp &= *jt;
if ( it == jt || (reduced_rule & *jt).none() )
{
++jt;
}
else
{
reduced_rule |= *jt;
jt = affined.erase(jt);
reduced = true;
}
}
if (!reduced)
{
reduced_set.insert(reduced_rule);
reduced_rule = *(++it);
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
std::ostream& operator<<(std::ostream& os, VMGroupPolicy policy)
{
switch(policy)
{
case VMGroupPolicy::AFFINED:
os << "AFFINED";
break;
case VMGroupPolicy::ANTI_AFFINED:
os << "ANTI_AFFINED";
break;
case VMGroupPolicy::NONE:
os << "NONE";
break;
}
return os;
}