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

Merge remote-tracking branch 'origin/feature-2672' into vdc-federation

Conflicts:
	include/AclManager.h
	src/acl/AclManager.cc
	src/nebula/Nebula.cc
This commit is contained in:
Carlos Martín 2014-01-27 17:51:54 +01:00
commit 758d9fdb8a
19 changed files with 341 additions and 45 deletions

View File

@ -28,15 +28,19 @@ using namespace std;
class PoolObjectAuth;
extern "C" void * acl_action_loop(void *arg);
/**
* This class manages the ACL rules and the authorization engine
*/
class AclManager : public Callbackable
class AclManager : public Callbackable, public ActionListener
{
public:
AclManager(SqlDB * _db, int zone_id);
AclManager(int _zone_id):zone_id(_zone_id),db(0),lastOID(0)
AclManager(SqlDB * _db, int zone_id, bool _refresh_cache, time_t timer_period);
AclManager(int _zone_id)
:zone_id(_zone_id), db(0),lastOID(0), refresh_cache(false)
{
pthread_mutex_init(&mutex, 0);
};
@ -44,11 +48,14 @@ public:
virtual ~AclManager();
/**
* Loads the ACL rule set from the DB
* Loads the ACL rule set from the DB, and starts the refresh loop is
* refresh_cache is set
* @return 0 on success.
*/
int start();
void finalize();
/* ---------------------------------------------------------------------- */
/* Rule management */
/* ---------------------------------------------------------------------- */
@ -181,6 +188,20 @@ public:
*/
virtual int dump(ostringstream& oss);
// ----------------------------------------
// Refresh loop thread
// ----------------------------------------
/**
* Gets the AclManager thread identification. The thread is only
* initialized if the refresh_cache flag is true.
* @return pthread_t for the manager thread (that in the action loop).
*/
pthread_t get_thread_id() const
{
return acl_thread;
};
protected:
// ----------------------------------------
@ -383,6 +404,45 @@ private:
* Callback to set the lastOID
*/
int init_cb(void *nil, int num, char **values, char **names);
// ----------------------------------------
// Refresh loop thread
// ----------------------------------------
/**
* Flag to refresh the cache periodically
*/
bool refresh_cache;
/**
* Timer period for the cache refresh loop.
*/
time_t timer_period;
/**
* Thread id for the ACL Manager
*/
pthread_t acl_thread;
/**
* Action engine for the Manager
*/
ActionManager am;
/**
* Function to execute the Manager action loop method within a new pthread
* (requires C linkage)
*/
friend void * acl_action_loop(void *arg);
/**
* The action function executed when an action is triggered.
* @param action the name of the action
* @param arg arguments for the action function
*/
void do_action(
const string & action,
void * arg);
};
#endif /*ACL_MANAGER_H*/

View File

@ -27,7 +27,7 @@ class DocumentPool : public PoolSQL
{
public:
DocumentPool(SqlDB * db) : PoolSQL(db, Document::table, false){};
DocumentPool(SqlDB * db) : PoolSQL(db, Document::table, true, false){};
~DocumentPool(){};

View File

@ -28,7 +28,8 @@ class GroupPool : public PoolSQL
public:
GroupPool(SqlDB * db,
vector<const Attribute *> hook_mads,
const string& remotes_location);
const string& remotes_location,
bool cache);
~GroupPool(){};

View File

@ -45,9 +45,10 @@ public:
* @param _db a pointer to the database
* @param _table the name of the table supporting the pool (to set the oid
* counter). If null the OID counter is not updated.
* @param cache True to enable the cache
* @param cache_by_name True if the objects can be retrieved by name
*/
PoolSQL(SqlDB * _db, const char * _table, bool cache_by_name);
PoolSQL(SqlDB * _db, const char * _table, bool cache, bool cache_by_name);
virtual ~PoolSQL();
@ -368,6 +369,11 @@ private:
*/
map<int,PoolObjectSQL *> pool;
/**
* Whether or not this pool uses the cache
*/
bool cache;
/**
* Whether or not this pool uses the name_pool index
*/
@ -415,6 +421,23 @@ private:
*/
void replace();
/**
* Cleans all the objects in the cache, except the ones locked.
* The object with the given oid will not be ignored if locked, the
* method will wait for it to be unlocked and ensure it is erased from
* the cache
*
* @param oid
*/
void flush_cache(int oid);
/**
* Same as flush_cache(int), but with the object name-uid key
*
* @param name_key
*/
void flush_cache(const string& name_key);
/**
* Generate an index key for the object
* @param name of the object

View File

@ -42,7 +42,8 @@ public:
UserPool(SqlDB * db,
time_t __session_expiration_time,
vector<const Attribute *> hook_mads,
const string& remotes_location);
const string& remotes_location,
bool cache);
~UserPool(){};

View File

@ -27,7 +27,7 @@ class VMTemplatePool : public PoolSQL
{
public:
VMTemplatePool(SqlDB * db) : PoolSQL(db, VMTemplate::table, true){};
VMTemplatePool(SqlDB * db) : PoolSQL(db, VMTemplate::table, true, true){};
~VMTemplatePool(){};

View File

@ -26,7 +26,8 @@ using namespace std;
class ZonePool : public PoolSQL
{
public:
ZonePool(SqlDB * db);
ZonePool(SqlDB * db,
bool cache);
~ZonePool(){};

View File

@ -48,8 +48,13 @@ int AclManager::init_cb(void *nil, int num, char **values, char **names)
/* -------------------------------------------------------------------------- */
AclManager::AclManager(SqlDB * _db, int _zone_id)
: zone_id(_zone_id), db(_db), lastOID(-1)
AclManager::AclManager(
SqlDB * _db,
int _zone_id,
bool _refresh_cache,
time_t _timer_period)
:zone_id(_zone_id), db(_db), lastOID(-1), refresh_cache(_refresh_cache),
timer_period(_timer_period)
{
ostringstream oss;
@ -100,6 +105,31 @@ AclManager::AclManager(SqlDB * _db, int _zone_id)
error_str);
}
am.addListener(this);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
extern "C" void * acl_action_loop(void *arg)
{
AclManager * aclm;
if ( arg == 0 )
{
return 0;
}
NebulaLog::log("ACL",Log::INFO,"ACL Manager started.");
aclm = static_cast<AclManager *>(arg);
aclm->am.loop(aclm->timer_period,0);
NebulaLog::log("ACL",Log::INFO,"ACL Manager stopped.");
return 0;
}
/* -------------------------------------------------------------------------- */
@ -107,10 +137,42 @@ AclManager::AclManager(SqlDB * _db, int _zone_id)
int AclManager::start()
{
acl_rules.clear();
acl_rules_oids.clear();
int rc;
return select();
NebulaLog::log("ACL",Log::INFO,"Starting ACL Manager...");
rc = select();
if (refresh_cache)
{
pthread_attr_t pattr;
pthread_attr_init (&pattr);
pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE);
rc += pthread_create(&acl_thread,&pattr,acl_action_loop,(void *) this);
}
else
{
NebulaLog::log("ACL",Log::INFO,"ACL Manager started.");
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AclManager::finalize()
{
if (refresh_cache)
{
am.trigger(ACTION_FINALIZE,0);
}
else
{
NebulaLog::log("ACL",Log::INFO,"ACL Manager stopped.");
}
}
/* -------------------------------------------------------------------------- */
@ -1008,8 +1070,15 @@ int AclManager::select()
set_callback(static_cast<Callbackable::Callback>(&AclManager::select_cb));
lock();
acl_rules.clear();
acl_rules_oids.clear();
rc = db->exec(oss,this);
unlock();
unset_callback();
return rc;
@ -1080,3 +1149,25 @@ int AclManager::dump(ostringstream& oss)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AclManager::do_action(const string &action, void * arg)
{
if (action == ACTION_TIMER)
{
select();
}
else if (action == ACTION_FINALIZE)
{
NebulaLog::log("ACL",Log::INFO,"Stopping ACL Manager...");
}
else
{
ostringstream oss;
oss << "Unknown action name: " << action;
NebulaLog::log("ACL", Log::ERROR, oss);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -33,7 +33,7 @@ const int ClusterPool::ALL_RESOURCES = 10;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
ClusterPool::ClusterPool(SqlDB * db):PoolSQL(db, Cluster::table, true)
ClusterPool::ClusterPool(SqlDB * db):PoolSQL(db, Cluster::table, true, true)
{
ostringstream oss;
string error_str;

View File

@ -39,7 +39,7 @@ const int DatastorePool::FILE_DS_ID = 2;
/* -------------------------------------------------------------------------- */
DatastorePool::DatastorePool(SqlDB * db):
PoolSQL(db, Datastore::table, true)
PoolSQL(db, Datastore::table, true, true)
{
ostringstream oss;
string error_str;

View File

@ -39,8 +39,9 @@ const int GroupPool::USERS_ID = 1;
GroupPool::GroupPool(SqlDB * db,
vector<const Attribute *> hook_mads,
const string& remotes_location)
:PoolSQL(db, Group::table, true)
const string& remotes_location,
bool cache)
:PoolSQL(db, Group::table, cache, true)
{
ostringstream oss;
string error_str;

View File

@ -41,7 +41,7 @@ HostPool::HostPool(SqlDB* db,
const string& hook_location,
const string& remotes_location,
time_t expire_time)
: PoolSQL(db, Host::table, true)
: PoolSQL(db, Host::table, true, true)
{
_monitor_expiration = expire_time;

View File

@ -41,7 +41,7 @@ ImagePool::ImagePool(
const string& remotes_location,
const vector<const Attribute *>& _inherit_image_attrs,
const vector<const Attribute *>& _inherit_datastore_attrs)
:PoolSQL(db, Image::table, true)
:PoolSQL(db, Image::table, true, true)
{
// Init static defaults
_default_type = __default_type;

View File

@ -607,6 +607,8 @@ void Nebula::start(bool bootstrap_only)
bool vm_submit_on_hold;
bool cache = !is_federation_slave();
vector<const Attribute *> vm_hooks;
vector<const Attribute *> host_hooks;
vector<const Attribute *> vnet_hooks;
@ -623,7 +625,7 @@ void Nebula::start(bool bootstrap_only)
clpool = new ClusterPool(db);
docpool = new DocumentPool(db);
zonepool= new ZonePool(db);
zonepool= new ZonePool(db, cache);
nebula_configuration->get("VM_HOOK", vm_hooks);
nebula_configuration->get("HOST_HOOK", host_hooks);
@ -667,10 +669,10 @@ void Nebula::start(bool bootstrap_only)
remotes_location,
inherit_vnet_attrs);
gpool = new GroupPool(db, group_hooks, remotes_location);
gpool = new GroupPool(db, group_hooks, remotes_location, cache);
nebula_configuration->get("SESSION_EXPIRATION_TIME", expiration_time);
upool = new UserPool(db, expiration_time, user_hooks, remotes_location);
upool = new UserPool(db, expiration_time, user_hooks, remotes_location, cache);
nebula_configuration->get("DEFAULT_IMAGE_TYPE", default_image_type);
nebula_configuration->get("DEFAULT_DEVICE_PREFIX",
@ -909,9 +911,11 @@ void Nebula::start(bool bootstrap_only)
}
// ---- ACL Manager ----
bool refresh_acl_cache = is_federation_slave();
try
{
aclm = new AclManager(db, zone_id);
aclm = new AclManager(db, zone_id, refresh_acl_cache, timer_period);
}
catch (bad_alloc&)
{
@ -1058,6 +1062,7 @@ void Nebula::start(bool bootstrap_only)
rm->finalize();
hm->finalize();
imagem->finalize();
aclm->finalize();
//sleep to wait drivers???
@ -1071,6 +1076,11 @@ void Nebula::start(bool bootstrap_only)
pthread_join(hm->get_thread_id(),0);
pthread_join(imagem->get_thread_id(),0);
if(refresh_acl_cache)
{
pthread_join(aclm->get_thread_id(),0);
}
//XML Library
xmlCleanupParser();

View File

@ -51,8 +51,8 @@ int PoolSQL::init_cb(void *nil, int num, char **values, char **names)
/* -------------------------------------------------------------------------- */
PoolSQL::PoolSQL(SqlDB * _db, const char * _table, bool cache_by_name):
db(_db), lastOID(-1), table(_table), uses_name_pool(cache_by_name)
PoolSQL::PoolSQL(SqlDB * _db, const char * _table, bool _cache, bool cache_by_name):
db(_db), lastOID(-1), table(_table), cache(_cache), uses_name_pool(cache_by_name)
{
ostringstream oss;
@ -176,6 +176,11 @@ PoolObjectSQL * PoolSQL::get(
lock();
if (!cache)
{
flush_cache(oid);
}
index = pool.find(oid);
if ( index != pool.end() )
@ -252,11 +257,14 @@ PoolObjectSQL * PoolSQL::get(
objectsql->lock();
}
oid_queue.push(objectsql->oid);
if ( pool.size() > MAX_POOL_SIZE )
if (cache)
{
replace();
oid_queue.push(objectsql->oid);
if ( pool.size() > MAX_POOL_SIZE )
{
replace();
}
}
unlock();
@ -274,16 +282,23 @@ PoolObjectSQL * PoolSQL::get(const string& name, int ouid, bool olock)
PoolObjectSQL * objectsql;
int rc;
lock();
string name_key;
if ( uses_name_pool == false )
{
unlock();
return 0;
}
index = name_pool.find(key(name,ouid));
lock();
name_key = key(name,ouid);
if (!cache)
{
flush_cache(name_key);
}
index = name_pool.find(name_key);
if ( index != name_pool.end() && index->second->isValid() == true )
{
@ -342,11 +357,14 @@ PoolObjectSQL * PoolSQL::get(const string& name, int ouid, bool olock)
objectsql->lock();
}
oid_queue.push(objectsql->oid);
if ( pool.size() > MAX_POOL_SIZE )
if (cache)
{
replace();
oid_queue.push(objectsql->oid);
if ( pool.size() > MAX_POOL_SIZE )
{
replace();
}
}
unlock();
@ -446,6 +464,95 @@ void PoolSQL::replace()
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void PoolSQL::flush_cache(int oid)
{
int rc;
PoolObjectSQL * tmp_ptr;
map<int,PoolObjectSQL *>::iterator it;
for (it = pool.begin(); it != pool.end(); )
{
// The object we are looking for in ::get(). Will wait until it is
// unlocked()
if (it->second->oid == oid)
{
it->second->lock();
}
else
{
// Any other locked object is just ignored
rc = pthread_mutex_trylock(&(it->second->mutex));
if ( rc == EBUSY ) // In use by other thread
{
it++;
continue;
}
}
tmp_ptr = it->second;
// map::erase does not invalidate the iterator, except for the current
// one
pool.erase(it++);
if ( uses_name_pool )
{
string okey = key(tmp_ptr->name,tmp_ptr->uid);
name_pool.erase(okey);
}
delete tmp_ptr;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void PoolSQL::flush_cache(const string& name_key)
{
int rc;
PoolObjectSQL * tmp_ptr;
map<string,PoolObjectSQL *>::iterator it;
for (it = name_pool.begin(); it != name_pool.end(); )
{
string okey = key(it->second->name, it->second->uid);
// The object we are looking for in ::get(). Will wait until it is
// unlocked()
if (name_key == okey)
{
it->second->lock();
}
else
{
// Any other locked object is just ignored
rc = pthread_mutex_trylock(&(it->second->mutex));
if ( rc == EBUSY ) // In use by other thread
{
it++;
continue;
}
}
tmp_ptr = it->second;
// map::erase does not invalidate the iterator, except for the current
// one
name_pool.erase(it++);
pool.erase(tmp_ptr->oid);
delete tmp_ptr;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void PoolSQL::clean()
{
map<int,PoolObjectSQL *>::iterator it;

View File

@ -55,8 +55,9 @@ string UserPool::oneadmin_name;
UserPool::UserPool(SqlDB * db,
time_t __session_expiration_time,
vector<const Attribute *> hook_mads,
const string& remotes_location):
PoolSQL(db, User::table, true)
const string& remotes_location,
bool cache):
PoolSQL(db, User::table, cache, true)
{
int one_uid = -1;
int server_uid = -1;

View File

@ -38,7 +38,7 @@ VirtualMachinePool::VirtualMachinePool(
vector<const Attribute *>& restricted_attrs,
time_t expire_time,
bool on_hold)
: PoolSQL(db, VirtualMachine::table, false)
: PoolSQL(db, VirtualMachine::table, true, false)
{
const VectorAttribute * vattr;

View File

@ -38,7 +38,7 @@ VirtualNetworkPool::VirtualNetworkPool(
vector<const Attribute *> hook_mads,
const string& remotes_location,
const vector<const Attribute *>& _inherit_attrs):
PoolSQL(db, VirtualNetwork::table, true)
PoolSQL(db, VirtualNetwork::table, true, true)
{
istringstream iss;
size_t pos = 0;

View File

@ -20,8 +20,8 @@
/* -------------------------------------------------------------------------- */
ZonePool::ZonePool(SqlDB * db)
:PoolSQL(db, Zone::table, true)
ZonePool::ZonePool(SqlDB * db, bool cache)
:PoolSQL(db, Zone::table, cache, true)
{
if (get_lastOID() == -1) //lastOID is set in PoolSQL::init_cb
{