1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-22 13:33:52 +03:00

feature #407: Prevent some deadlocks when adding/removing users from groups

This commit is contained in:
Ruben S. Montero 2011-06-03 13:31:11 +02:00
parent 3cf5d5e7cd
commit 532982b6fb
11 changed files with 84 additions and 281 deletions

View File

@ -57,7 +57,6 @@ main_env.Append(LIBPATH=[
cwd+'/src/log',
cwd+'/src/sql',
cwd+'/src/host',
cwd+'/src/cluster',
cwd+'/src/group',
cwd+'/src/mad',
cwd+'/src/nebula',
@ -187,7 +186,6 @@ build_scripts=[
'src/common/SConstruct',
'src/template/SConstruct',
'src/host/SConstruct',
'src/cluster/SConstruct',
'src/group/SConstruct',
'src/mad/SConstruct',
'src/nebula/SConstruct',
@ -235,7 +233,6 @@ if testing=='yes':
'src/authm/test/SConstruct',
'src/common/test/SConstruct',
'src/host/test/SConstruct',
'src/cluster/test/SConstruct',
'src/group/test/SConstruct',
'src/image/test/SConstruct',
'src/lcm/test/SConstruct',

View File

@ -50,23 +50,24 @@ public:
int from_xml(const string &xml_str);
/**
* Adds this object's ID to the set. The object MUST be a User, locked.
* The group's ID is added to the User's set.
* @param object The new object
*
* @return 0 on success, -1 if the ID was already in the set
* Adds this user's ID to the set.
* @param id of the user to be added to the group
* @return 0 on success
*/
int add_collection_id(PoolObjectSQL* object);
int add_user(int id)
{
return add_collection_id(id);
}
/**
* Deletes this object's ID from the set. The object MUST be a User,
* locked. The group's ID is deleted form the User's set.
* @param object The object
*
* @return 0 on success, -1 if the ID was not in the set
* Deletes this users's ID from the set.
* @param id of the user to be deleted from the group
* @return 0 on success
*/
int del_collection_id(PoolObjectSQL* object);
int del_user(int id)
{
return del_collection_id(id);
}
private:
@ -142,12 +143,6 @@ private:
{
return insert_replace(db, true);
}
// *************************************************************************
// ID Set management
// *************************************************************************
int add_del_collection_id(User* object, bool add);
};
#endif /*GROUP_H_*/

View File

@ -28,7 +28,7 @@ using namespace std;
*/
class ObjectCollection
{
public:
protected:
ObjectCollection(const string& _collection_name)
:collection_name(_collection_name){};
@ -36,26 +36,20 @@ public:
~ObjectCollection(){};
/**
* Adds this object's ID to the set.
* @param object The new object
* Adds an ID to the set.
* @param id The new id
*
* @return 0 on success, -1 if the ID was already in the set
*/
virtual int add_collection_id(PoolObjectSQL* object)
{
return add_collection_id(object->get_oid());
};
int add_collection_id(int id);
/**
* Deletes this object's ID from the set.
* @param object The object
* Deletes an ID from the set.
* @param id The id
*
* @return 0 on success, -1 if the ID was not in the set
*/
virtual int del_collection_id(PoolObjectSQL* object)
{
return del_collection_id(object->get_oid());
};
int del_collection_id(int id);
/**
* Returns how many IDs are there in the set.
@ -66,8 +60,6 @@ public:
return collection_set.size();
};
protected:
/**
* Rebuilds the object from an xml node
* @param node The xml node pointer
@ -84,21 +76,6 @@ protected:
*/
string& to_xml(string& xml) const;
/**
* Adds an ID to the set.
* @param id The new id
*
* @return 0 on success, -1 if the ID was already in the set
*/
int add_collection_id(int id);
/**
* Deletes an ID from the set.
* @param id The id
*
* @return 0 on success, -1 if the ID was not in the set
*/
int del_collection_id(int id);
/**
* Returns a copy of the IDs set

View File

@ -96,9 +96,12 @@ public:
static int split_secret(const string secret, string& user, string& pass);
/**
* Sets the User's gid and add the User's oid to that group
* Returns a copy of the groups for the user
*/
int set_gid(int _gid);
set<int> get_groups()
{
return get_collection_copy();
};
private:
// -------------------------------------------------------------------------

View File

@ -160,67 +160,6 @@ int Group::from_xml(const string& xml)
return 0;
}
/* ************************************************************************ */
/* Group :: User ID Set */
/* ************************************************************************ */
int Group::add_collection_id(PoolObjectSQL* object)
{
// TODO: make a dynamic cast and check if object is indeed a User ?
return add_del_collection_id( static_cast<User*>(object), true );
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Group::del_collection_id(PoolObjectSQL* object)
{
// TODO: make a dynamic cast and check if object is indeed a User ?
return add_del_collection_id( static_cast<User*>(object), false );
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Group::add_del_collection_id(User* object, bool add)
{
int rc = 0;
ObjectCollection * object_collection = 0;
// Get object id
int object_id = object->get_oid();
// Add/Remove object to the group
if(add)
{
rc = ObjectCollection::add_collection_id(object_id);
}
else
{
rc = ObjectCollection::del_collection_id(object_id);
}
if( rc != 0 )
{
return -1;
}
// Users can be in more than one group, it has to store the
// reverse relation
object_collection = static_cast<ObjectCollection*>(object);
if(add)
{
rc = object_collection->add_collection_id( this );
}
else
{
rc = object_collection->del_collection_id( this );
}
return rc;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

View File

@ -128,8 +128,6 @@ error_common:
int GroupPool::drop(Group * group)
{
int rc;
// Return error if the group is a default one.
if( group->get_oid() < 100 )
{
@ -147,7 +145,5 @@ int GroupPool::drop(Group * group)
return -1;
}
rc = group->drop(db);
return rc;
return group->drop(db);
}

View File

@ -30,12 +30,12 @@
Host::Host(
int id,
int cluster_id,
int gid,
const string& _hostname,
const string& _im_mad_name,
const string& _vmm_mad_name,
const string& _tm_mad_name):
PoolObjectSQL(id,_hostname,-1,cluster_id,table),
PoolObjectSQL(id,_hostname,-1,gid,table),
state(INIT),
im_mad_name(_im_mad_name),
vmm_mad_name(_vmm_mad_name),
@ -53,57 +53,6 @@ Host::~Host()
}
}
/* ************************************************************************** */
/* Host :: Cluster Management */
/* ************************************************************************** */
int Host::add_to_cluster()
{
return add_del_to_cluster(true);
}
int Host::delete_from_cluster()
{
return add_del_to_cluster(false);
}
int Host::add_del_to_cluster(bool add)
{
// Add this Host's ID to the Cluster
int rc = 0;
Nebula& nd = Nebula::instance();
ClusterPool * cpool = nd.get_cpool();
if( cpool == 0 )
{
return -1;
}
Cluster * cluster = cpool->get( get_gid(), true );
if( cluster == 0 )
{
return -1;
}
if( add )
{
rc = static_cast<ObjectCollection*>(cluster)->add_collection_id(this);
}
else
{
rc = static_cast<ObjectCollection*>(cluster)->del_collection_id(this);
}
if( rc == 0 )
{
cpool->update(cluster);
}
cluster->unlock();
return rc;
}
/* ************************************************************************ */
/* Host :: Database Access Functions */
/* ************************************************************************ */

View File

@ -256,7 +256,29 @@ int UserAllocate::pool_allocate(xmlrpc_c::paramList const& paramList,
UserPool * upool = static_cast<UserPool *>(pool);
return upool->allocate(&id,GroupPool::USERS_ID,uname,passwd,true,error_str);
int rc = upool->allocate(&id,GroupPool::USERS_ID,uname,passwd,true,error_str);
if ( rc < 0 )
{
return rc;
}
Nebula& nd = Nebula::instance();
GroupPool * gpool = nd.get_gpool();
Group * group = gpool->get(gid, true);
if( group == 0 )
{
return -1;
}
group->add_user(id);
gpool->update(group);
group->unlock();
return rc;
}
/* -------------------------------------------------------------------------- */

View File

@ -25,6 +25,7 @@ void RequestManagerDelete::request_execute(xmlrpc_c::paramList const& paramList)
{
int oid = xmlrpc_c::value_int(paramList.getInt(1));
PoolObjectSQL * object;
set<int> group_set;
if ( basic_authorization(oid) == false )
{
@ -39,6 +40,12 @@ void RequestManagerDelete::request_execute(xmlrpc_c::paramList const& paramList)
return;
}
if ( auth_ob == AuthRequest::USER )
{
User * user = static_cast<User *>(object);
group_set = user->get_groups();
}
int rc = pool->drop(object);
object->unlock();
@ -49,6 +56,31 @@ void RequestManagerDelete::request_execute(xmlrpc_c::paramList const& paramList)
return;
}
if ( auth_ob == AuthRequest::USER )
{
Nebula& nd = Nebula::instance();
GroupPool * gpool = nd.get_gpool();
Group * group;
set<int>::iterator it;
for ( it = group_set.begin(); it != group_set.end(); it++ )
{
group = gpool->get(*it, true);
if( group == 0 )
{
continue;
}
group->del_user(oid);
gpool->update(group);
group->unlock();
}
}
success_response(oid);
return;

View File

@ -26,95 +26,6 @@
#include "Nebula.h"
#include "Group.h"
/* ************************************************************************** */
/* User :: Group Set Management */
/* ************************************************************************** */
int User::add_to_group()
{
// Add this User's ID to the Main Group
int rc = 0;
Nebula& nd = Nebula::instance();
GroupPool * gpool = nd.get_gpool();
if( gpool == 0 )
{
return -1;
}
Group * group = gpool->get( get_gid(), true );
if( group == 0 )
{
return -1;
}
rc = group->add_collection_id(this);
if( rc == 0 )
{
gpool->update(group);
}
group->unlock();
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int User::set_gid(int _gid)
{
gid = _gid;
// The primary group is also kept in the Group Ids set.
// This method may return -1, because the Group could be a secondary group
// and be already in the set.
add_to_group();
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int User::delete_from_groups()
{
int rc = 0;
Nebula& nd = Nebula::instance();
GroupPool * gpool = nd.get_gpool();
Group * group;
// Get a copy of the set, because the original will be modified deleting
// elements from it.
set<int> group_set;
set<int>::iterator it;
group_set = get_collection_copy();
if( gpool == 0 )
{
return -1;
}
for ( it = group_set.begin(); it != group_set.end(); it++ )
{
group = gpool->get( *it, true );
if( group == 0 )
{
rc = -1;
continue;
}
rc += group->del_collection_id(this);
gpool->update(group);
group->unlock();
}
return rc;
}
/* ************************************************************************** */
/* User :: Database Access Functions */

View File

@ -144,26 +144,8 @@ int UserPool::allocate (
// Insert the Object in the pool
*oid = PoolSQL::allocate(user, error_str);
if( *oid != -1 )
{
// Add this User's ID to his group
user = get(*oid, true);
rc = user->add_to_group();
if( rc != 0 )
{
goto error_group;
}
update( user );
user->unlock();
}
return *oid;
error_name:
oss << "NAME cannot be empty.";
goto error_common;