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:
parent
3cf5d5e7cd
commit
532982b6fb
@ -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',
|
||||
|
@ -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_*/
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
/* ************************************************************************ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user