mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-23 22:50:09 +03:00
Merge branch 'feature-687' of git.opennebula.org:one into feature-687
This commit is contained in:
commit
b37b4be45e
@ -78,7 +78,7 @@ private:
|
||||
// *************************************************************************
|
||||
|
||||
Group(int id, const string& name):
|
||||
PoolObjectSQL(id,name,-1,-1,table),
|
||||
PoolObjectSQL(id,name,-1,-1,"","",table),
|
||||
ObjectCollection("USERS"){};
|
||||
|
||||
virtual ~Group(){};
|
||||
|
@ -332,6 +332,8 @@ protected:
|
||||
|
||||
Image(int uid,
|
||||
int gid,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
ImageTemplate* img_template);
|
||||
|
||||
virtual ~Image();
|
||||
|
@ -48,6 +48,8 @@ public:
|
||||
* Function to allocate a new Image object
|
||||
* @param uid the user id of the image's owner
|
||||
* @param gid the id of the group this object is assigned to
|
||||
* @param uname name of the user
|
||||
* @param gname name of the group
|
||||
* @param img_template template associated with the image
|
||||
* @param oid the id assigned to the Image
|
||||
* @param error_str Returns the error reason, if any
|
||||
@ -58,6 +60,8 @@ public:
|
||||
int allocate (
|
||||
int uid,
|
||||
int gid,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
ImageTemplate * img_template,
|
||||
int * oid,
|
||||
string& error_str);
|
||||
@ -172,7 +176,7 @@ private:
|
||||
*/
|
||||
PoolObjectSQL * create()
|
||||
{
|
||||
return new Image(-1,-1,0);
|
||||
return new Image(-1,-1,"","",0);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -36,11 +36,25 @@ using namespace std;
|
||||
class PoolObjectSQL : public ObjectSQL, public ObjectXML
|
||||
{
|
||||
public:
|
||||
|
||||
PoolObjectSQL(int id, const string& _name, int _uid,
|
||||
int _gid, const char *_table)
|
||||
:ObjectSQL(),ObjectXML(),oid(id),name(_name),uid(_uid),gid(_gid),
|
||||
valid(true),public_obj(0),obj_template(0),table(_table)
|
||||
PoolObjectSQL(int id,
|
||||
const string& _name,
|
||||
int _uid,
|
||||
int _gid,
|
||||
const string& _uname,
|
||||
const string& _gname,
|
||||
const char * _table)
|
||||
:ObjectSQL(),
|
||||
ObjectXML(),
|
||||
oid(id),
|
||||
name(_name),
|
||||
uid(_uid),
|
||||
gid(_gid),
|
||||
uname(_uname),
|
||||
gname(_gname),
|
||||
valid(true),
|
||||
public_obj(0),
|
||||
obj_template(0),
|
||||
table(_table)
|
||||
{
|
||||
pthread_mutex_init(&mutex,0);
|
||||
};
|
||||
@ -84,21 +98,25 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the object's owner id
|
||||
* Changes the object's owner
|
||||
* @param _uid New User ID
|
||||
* @param _uname Name of the new user
|
||||
*/
|
||||
void set_uid(int _uid)
|
||||
void set_user(int _uid, const string& _uname)
|
||||
{
|
||||
uid = _uid;
|
||||
uid = _uid;
|
||||
uname = _uname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the object's group id
|
||||
* @param _gid New Group ID
|
||||
* @param _gname Name of the new group
|
||||
*/
|
||||
void set_gid(int _gid)
|
||||
void set_group(int _gid, const string& _gname)
|
||||
{
|
||||
gid = _gid;
|
||||
gid = _gid;
|
||||
gname = _gname;
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -360,6 +378,16 @@ protected:
|
||||
*/
|
||||
int gid;
|
||||
|
||||
/**
|
||||
* Name of the object's owner, empty if owner is not used
|
||||
*/
|
||||
string uname;
|
||||
|
||||
/**
|
||||
* Name of the object's group,, empty if group is not used
|
||||
*/
|
||||
string gname;
|
||||
|
||||
/**
|
||||
* The contents of this object are valid
|
||||
*/
|
||||
|
@ -59,10 +59,12 @@ protected:
|
||||
|
||||
/* ------------------- Attributes of the Request ---------------------- */
|
||||
|
||||
int uid; /**< id of the user performing the request */
|
||||
|
||||
int uid; /**< id of the user */
|
||||
int gid; /**< id of the user's group */
|
||||
|
||||
string uname; /**< name of the user */
|
||||
string gname; /**< name of the user's group */
|
||||
|
||||
set<int> group_ids; /**< set of user's group ids */
|
||||
|
||||
PoolSQL * pool; /**< Pool of objects */
|
||||
@ -70,8 +72,7 @@ protected:
|
||||
string method_name; /**< The name of the XML-RPC method */
|
||||
|
||||
AuthRequest::Object auth_object; /**< Auth object for the request */
|
||||
|
||||
AuthRequest::Operation auth_op; /**< Auth operation for the request */
|
||||
AuthRequest::Operation auth_op; /**< Auth operation for the request */
|
||||
|
||||
|
||||
/* -------------------- Constructors ---------------------------------- */
|
||||
|
@ -35,6 +35,7 @@ protected:
|
||||
:Request(method_name,params,help)
|
||||
{
|
||||
auth_object = AuthRequest::ACL;
|
||||
auth_op = AuthRequest::MANAGE;
|
||||
};
|
||||
|
||||
~RequestManagerAcl(){};
|
||||
@ -58,9 +59,7 @@ public:
|
||||
RequestManagerAcl("AclAddRule",
|
||||
"Adds a new ACL rule",
|
||||
"A:ssss")
|
||||
{
|
||||
// TODO: auth_op ?
|
||||
};
|
||||
{};
|
||||
|
||||
~AclAddRule(){};
|
||||
|
||||
@ -77,9 +76,7 @@ public:
|
||||
RequestManagerAcl("AclDelRule",
|
||||
"Deletes an existing ACL rule",
|
||||
"A:si")
|
||||
{
|
||||
// TODO: auth_op ?
|
||||
};
|
||||
{};
|
||||
|
||||
~AclDelRule(){};
|
||||
|
||||
@ -96,9 +93,7 @@ public:
|
||||
RequestManagerAcl("AclInfo",
|
||||
"Returns the ACL rule set",
|
||||
"A:s")
|
||||
{
|
||||
// TODO: auth_op ?
|
||||
};
|
||||
{};
|
||||
|
||||
~AclInfo(){};
|
||||
|
||||
|
@ -189,11 +189,16 @@ protected:
|
||||
// Constructor
|
||||
// *************************************************************************
|
||||
|
||||
User(int id, int _gid, const string& _username, const string& _password, bool _enabled):
|
||||
PoolObjectSQL(id,_username,-1,_gid,table),
|
||||
User(int id,
|
||||
int _gid,
|
||||
const string& _uname,
|
||||
const string& _gname,
|
||||
const string& _password,
|
||||
bool _enabled):
|
||||
PoolObjectSQL(id,_uname,-1,_gid,"",_gname,table),
|
||||
ObjectCollection("GROUPS"),
|
||||
password(_password), enabled(_enabled)
|
||||
{ };
|
||||
password(_password),
|
||||
enabled(_enabled){};
|
||||
|
||||
virtual ~User(){};
|
||||
|
||||
|
@ -51,8 +51,9 @@ public:
|
||||
int allocate (
|
||||
int * oid,
|
||||
int gid,
|
||||
string username,
|
||||
string password,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
const string& password,
|
||||
bool enabled,
|
||||
string& error_str);
|
||||
|
||||
@ -102,13 +103,17 @@ public:
|
||||
* @param session, colon separated username and password string
|
||||
* @param uid of the user if authN succeeded -1 otherwise
|
||||
* @param gid of the user if authN succeeded -1 otherwise
|
||||
* @param uname of the user if authN succeeded "" otherwise
|
||||
* @param gname of the group if authN succeeded "" otherwise
|
||||
* @param group_ids the user groups if authN succeeded, is empty otherwise
|
||||
* @return false if authn failed, true otherwise
|
||||
*/
|
||||
bool authenticate(const string& session, int& uid, int& gid,
|
||||
set<int>& group_ids);
|
||||
|
||||
|
||||
bool authenticate(const string& session,
|
||||
int& uid,
|
||||
int& gid,
|
||||
string& uname,
|
||||
string& gname,
|
||||
set<int>& group_ids);
|
||||
/**
|
||||
* Returns whether there is a user with given username/password or not
|
||||
* @param ar, an Authorization Request
|
||||
@ -136,7 +141,7 @@ private:
|
||||
*/
|
||||
PoolObjectSQL * create()
|
||||
{
|
||||
return new User(-1,-1,"","",true);
|
||||
return new User(-1,-1,"","","",true);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -129,7 +129,11 @@ protected:
|
||||
// *************************************************************************
|
||||
// Constructor
|
||||
// *************************************************************************
|
||||
VMTemplate(int id, int uid, int gid,
|
||||
VMTemplate(int id,
|
||||
int uid,
|
||||
int gid,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
VirtualMachineTemplate * _template_contents);
|
||||
|
||||
~VMTemplate();
|
||||
|
@ -44,6 +44,8 @@ public:
|
||||
*/
|
||||
int allocate(int uid,
|
||||
int gid,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
VirtualMachineTemplate * template_contents,
|
||||
int * oid,
|
||||
string& error_str);
|
||||
@ -109,26 +111,13 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------------
|
||||
// Configuration Attributes for Images
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// TODO
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Pool Attributes
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// TODO
|
||||
|
||||
|
||||
/**
|
||||
* Factory method to produce Image objects
|
||||
* @return a pointer to the new Image
|
||||
*/
|
||||
PoolObjectSQL * create()
|
||||
{
|
||||
return new VMTemplate(-1,-1,-1,0);
|
||||
return new VMTemplate(-1,-1,-1,"","",0);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -865,8 +865,12 @@ protected:
|
||||
// Constructor
|
||||
//**************************************************************************
|
||||
|
||||
VirtualMachine(int id, int uid,
|
||||
int gid, VirtualMachineTemplate * _vm_template);
|
||||
VirtualMachine(int id,
|
||||
int uid,
|
||||
int gid,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
VirtualMachineTemplate * _vm_template);
|
||||
|
||||
virtual ~VirtualMachine();
|
||||
|
||||
|
@ -52,6 +52,8 @@ public:
|
||||
int allocate (
|
||||
int uid,
|
||||
int gid,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
VirtualMachineTemplate * vm_template,
|
||||
int * oid,
|
||||
string& error_str,
|
||||
@ -160,7 +162,7 @@ private:
|
||||
*/
|
||||
PoolObjectSQL * create()
|
||||
{
|
||||
return new VirtualMachine(-1,-1,-1,0);
|
||||
return new VirtualMachine(-1,-1,-1,"","",0);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -269,6 +269,8 @@ private:
|
||||
|
||||
VirtualNetwork(int uid,
|
||||
int gid,
|
||||
const string& _uname,
|
||||
const string& _gname,
|
||||
VirtualNetworkTemplate * _vn_template = 0);
|
||||
|
||||
~VirtualNetwork();
|
||||
|
@ -51,6 +51,8 @@ public:
|
||||
int allocate (
|
||||
int uid,
|
||||
int gid,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
VirtualNetworkTemplate * vn_template,
|
||||
int * oid,
|
||||
string& error_str);
|
||||
@ -156,7 +158,7 @@ private:
|
||||
*/
|
||||
PoolObjectSQL * create()
|
||||
{
|
||||
return new VirtualNetwork(-1,-1, 0);
|
||||
return new VirtualNetwork(-1,-1,"","",0);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "AclManager.h"
|
||||
#include "NebulaLog.h"
|
||||
#include "GroupPool.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -105,6 +106,12 @@ const bool AclManager::authorize(int uid, const set<int> &user_groups,
|
||||
|
||||
bool auth = false;
|
||||
|
||||
// Only oneadmin, or someone in the oneadmin group can manage acl rules
|
||||
if ( obj_type == AuthRequest::ACL )
|
||||
{
|
||||
return ( uid == 0 || user_groups.count( GroupPool::ONEADMIN_ID ) == 1 );
|
||||
}
|
||||
|
||||
// Build masks for request
|
||||
long long user_req;
|
||||
long long resource_oid_req = obj_type + AclRule::INDIVIDUAL_ID + obj_id;
|
||||
|
@ -34,7 +34,7 @@ Host::Host(
|
||||
const string& _im_mad_name,
|
||||
const string& _vmm_mad_name,
|
||||
const string& _tm_mad_name):
|
||||
PoolObjectSQL(id,_hostname,-1,-1,table),
|
||||
PoolObjectSQL(id,_hostname,-1,-1,"","",table),
|
||||
state(INIT),
|
||||
im_mad_name(_im_mad_name),
|
||||
vmm_mad_name(_vmm_mad_name),
|
||||
|
@ -36,8 +36,10 @@
|
||||
|
||||
Image::Image(int _uid,
|
||||
int _gid,
|
||||
const string& _uname,
|
||||
const string& _gname,
|
||||
ImageTemplate * _image_template):
|
||||
PoolObjectSQL(-1,"",_uid,_gid,table),
|
||||
PoolObjectSQL(-1,"",_uid,_gid,_uname,_gname,table),
|
||||
type(OS),
|
||||
regtime(time(0)),
|
||||
source("-"),
|
||||
@ -324,6 +326,8 @@ string& Image::to_xml(string& xml) const
|
||||
"<ID>" << oid << "</ID>" <<
|
||||
"<UID>" << uid << "</UID>" <<
|
||||
"<GID>" << gid << "</GID>" <<
|
||||
"<UNAME>" << uname << "</UNAME>" <<
|
||||
"<GNAME>" << gname << "</GNAME>" <<
|
||||
"<NAME>" << name << "</NAME>" <<
|
||||
"<TYPE>" << type << "</TYPE>" <<
|
||||
"<PUBLIC>" << public_obj << "</PUBLIC>" <<
|
||||
@ -332,7 +336,7 @@ string& Image::to_xml(string& xml) const
|
||||
"<SOURCE>" << source << "</SOURCE>" <<
|
||||
"<STATE>" << state << "</STATE>" <<
|
||||
"<RUNNING_VMS>" << running_vms << "</RUNNING_VMS>" <<
|
||||
obj_template->to_xml(template_xml) <<
|
||||
obj_template->to_xml(template_xml) <<
|
||||
"</IMAGE>";
|
||||
|
||||
xml = oss.str();
|
||||
@ -355,9 +359,13 @@ int Image::from_xml(const string& xml)
|
||||
update_from_str(xml);
|
||||
|
||||
// Get class base attributes
|
||||
rc += xpath(oid, "/IMAGE/ID", -1);
|
||||
rc += xpath(oid, "/IMAGE/ID", -1);
|
||||
rc += xpath(uid, "/IMAGE/UID", -1);
|
||||
rc += xpath(gid, "/IMAGE/GID", -1);
|
||||
|
||||
rc += xpath(uname, "/IMAGE/UNAME", "not_found");
|
||||
rc += xpath(gname, "/IMAGE/GNAME", "not_found");
|
||||
|
||||
rc += xpath(name, "/IMAGE/NAME", "not_found");
|
||||
|
||||
rc += xpath(int_type, "/IMAGE/TYPE", 0);
|
||||
|
@ -57,6 +57,8 @@ ImagePool::ImagePool(SqlDB * db,
|
||||
int ImagePool::allocate (
|
||||
int uid,
|
||||
int gid,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
ImageTemplate* img_template,
|
||||
int * oid,
|
||||
string& error_str)
|
||||
@ -66,7 +68,7 @@ int ImagePool::allocate (
|
||||
string name;
|
||||
ostringstream oss;
|
||||
|
||||
img = new Image(uid, gid, img_template);
|
||||
img = new Image(uid, gid, uname, gname, img_template);
|
||||
|
||||
// Check name
|
||||
img->get_template_attribute("NAME", name);
|
||||
|
@ -33,7 +33,12 @@ void Request::execute(
|
||||
|
||||
NebulaLog::log("ReM",Log::DEBUG, method_name + " method invoked");
|
||||
|
||||
if ( upool->authenticate(session, uid, gid, group_ids) == false )
|
||||
if ( upool->authenticate(session,
|
||||
uid,
|
||||
gid,
|
||||
uname,
|
||||
gname,
|
||||
group_ids) == false )
|
||||
{
|
||||
failure_response(AUTHENTICATION, authenticate_error());
|
||||
}
|
||||
@ -166,6 +171,8 @@ string Request::object_name(AuthRequest::Object ob)
|
||||
return "virtual machine template";
|
||||
case AuthRequest::GROUP:
|
||||
return "group";
|
||||
case AuthRequest::ACL:
|
||||
return "ACL";
|
||||
default:
|
||||
return "-";
|
||||
}
|
||||
|
@ -55,11 +55,8 @@ void AclAddRule::request_execute(xmlrpc_c::paramList const& paramList)
|
||||
|
||||
string error_msg;
|
||||
|
||||
// TODO: Only oneadmin can manage ACL
|
||||
if ( uid != 0 )
|
||||
if ( basic_authorization(-1) == false )
|
||||
{
|
||||
failure_response(AUTHORIZATION,
|
||||
authorization_error("Only oneadmin can manage ACL rules"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -89,11 +86,8 @@ void AclDelRule::request_execute(xmlrpc_c::paramList const& paramList)
|
||||
|
||||
string error_msg;
|
||||
|
||||
// TODO: Only oneadmin can manage ACL
|
||||
if ( uid != 0 )
|
||||
if ( basic_authorization(-1) == false )
|
||||
{
|
||||
failure_response(AUTHORIZATION,
|
||||
authorization_error("Only oneadmin can manage ACL rules"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -121,11 +115,8 @@ void AclInfo::request_execute(xmlrpc_c::paramList const& paramList)
|
||||
ostringstream oss;
|
||||
int rc;
|
||||
|
||||
// TODO: Only oneadmin can manage ACL
|
||||
if ( uid != 0 )
|
||||
if ( basic_authorization(-1) == false )
|
||||
{
|
||||
failure_response(AUTHORIZATION,
|
||||
authorization_error("Only oneadmin can manage ACL rules"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -133,10 +133,10 @@ int VirtualMachineAllocate::pool_allocate(xmlrpc_c::paramList const& paramList,
|
||||
int& id,
|
||||
string& error_str)
|
||||
{
|
||||
VirtualMachineTemplate * ttmpl = static_cast<VirtualMachineTemplate *>(tmpl);
|
||||
VirtualMachinePool * vmpool = static_cast<VirtualMachinePool *>(pool);
|
||||
VirtualMachineTemplate * ttmpl= static_cast<VirtualMachineTemplate *>(tmpl);
|
||||
VirtualMachinePool * vmpool = static_cast<VirtualMachinePool *>(pool);
|
||||
|
||||
return vmpool->allocate(uid, gid, ttmpl, &id, error_str, false);
|
||||
return vmpool->allocate(uid, gid, uname, gname, ttmpl, &id,error_str,false);
|
||||
}
|
||||
|
||||
|
||||
@ -151,7 +151,7 @@ int VirtualNetworkAllocate::pool_allocate(xmlrpc_c::paramList const& _paramList,
|
||||
VirtualNetworkPool * vpool = static_cast<VirtualNetworkPool *>(pool);
|
||||
VirtualNetworkTemplate * vtmpl=static_cast<VirtualNetworkTemplate *>(tmpl);
|
||||
|
||||
return vpool->allocate(uid, gid, vtmpl, &id, error_str);
|
||||
return vpool->allocate(uid, gid, uname, gname, vtmpl, &id, error_str);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -165,7 +165,7 @@ int ImageAllocate::pool_allocate(xmlrpc_c::paramList const& _paramList,
|
||||
ImagePool * ipool = static_cast<ImagePool *>(pool);
|
||||
ImageTemplate * itmpl = static_cast<ImageTemplate *>(tmpl);
|
||||
|
||||
return ipool->allocate(uid, gid, itmpl, &id, error_str);
|
||||
return ipool->allocate(uid, gid, uname, gname, itmpl, &id, error_str);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -180,7 +180,7 @@ int TemplateAllocate::pool_allocate(xmlrpc_c::paramList const& _paramList,
|
||||
|
||||
VirtualMachineTemplate * ttmpl=static_cast<VirtualMachineTemplate *>(tmpl);
|
||||
|
||||
return tpool->allocate(uid, gid, ttmpl, &id, error_str);
|
||||
return tpool->allocate(uid, gid, uname, gname, ttmpl, &id, error_str);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -213,14 +213,17 @@ int UserAllocate::pool_allocate(xmlrpc_c::paramList const& paramList,
|
||||
string passwd = xmlrpc_c::value_string(paramList.getString(2));
|
||||
|
||||
UserPool * upool = static_cast<UserPool *>(pool);
|
||||
int users_group = gid;
|
||||
|
||||
int ugid = gid;
|
||||
string ugname = gname;
|
||||
|
||||
if ( gid == GroupPool::ONEADMIN_ID )
|
||||
{
|
||||
users_group = GroupPool::USERS_ID;
|
||||
ugid = GroupPool::USERS_ID;
|
||||
ugname = GroupPool::USERS_NAME;
|
||||
}
|
||||
|
||||
return upool->allocate(&id,users_group,uname,passwd,true,error_str);
|
||||
return upool->allocate(&id,ugid,uname,ugname,passwd,true,error_str);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -28,6 +28,9 @@ void RequestManagerChown::request_execute(xmlrpc_c::paramList const& paramList)
|
||||
int noid = xmlrpc_c::value_int(paramList.getInt(2));
|
||||
int ngid = xmlrpc_c::value_int(paramList.getInt(3));
|
||||
|
||||
string nuname;
|
||||
string ngname;
|
||||
|
||||
Nebula& nd = Nebula::instance();
|
||||
GroupPool * gpool = nd.get_gpool();
|
||||
UserPool * upool = nd.get_upool();
|
||||
@ -41,18 +44,36 @@ void RequestManagerChown::request_execute(xmlrpc_c::paramList const& paramList)
|
||||
|
||||
// ------------- Check new user and group id's ---------------------
|
||||
|
||||
if ( noid > -1 && upool->get(noid,false) == 0 )
|
||||
if ( noid > -1 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
User * user;
|
||||
|
||||
if ((user = upool->get(noid,true)) == 0)
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(AuthRequest::USER),noid));
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
nuname = user->get_name();
|
||||
|
||||
user->unlock();
|
||||
}
|
||||
|
||||
if ( ngid > -1 && gpool->get(ngid,false) == 0 )
|
||||
if ( ngid > -1 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
Group * group;
|
||||
|
||||
if ((group = gpool->get(ngid,true)) == 0)
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(AuthRequest::GROUP),ngid));
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
ngname = group->get_name();
|
||||
|
||||
group->unlock();
|
||||
}
|
||||
|
||||
// ------------- Update the object ---------------------
|
||||
@ -67,12 +88,12 @@ void RequestManagerChown::request_execute(xmlrpc_c::paramList const& paramList)
|
||||
|
||||
if ( noid != -1 )
|
||||
{
|
||||
object->set_uid(noid);
|
||||
object->set_user(noid,nuname);
|
||||
}
|
||||
|
||||
if ( ngid != -1 )
|
||||
{
|
||||
object->set_gid(ngid);
|
||||
object->set_group(ngid,ngname);
|
||||
}
|
||||
|
||||
pool->update(object);
|
||||
@ -93,7 +114,7 @@ void UserChown::request_execute(xmlrpc_c::paramList const& paramList)
|
||||
int ngid = xmlrpc_c::value_int(paramList.getInt(2));
|
||||
int old_gid;
|
||||
|
||||
string str;
|
||||
string ngname;
|
||||
|
||||
Nebula& nd = Nebula::instance();
|
||||
GroupPool * gpool = nd.get_gpool();
|
||||
@ -114,13 +135,18 @@ void UserChown::request_execute(xmlrpc_c::paramList const& paramList)
|
||||
failure_response(XML_RPC_API,request_error("Wrong group ID",""));
|
||||
return;
|
||||
}
|
||||
else if ( gpool->get(ngid,false) == 0 )
|
||||
|
||||
if ( (group = gpool->get(ngid,true)) == 0 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(AuthRequest::GROUP),ngid));
|
||||
return;
|
||||
}
|
||||
|
||||
ngname = group->get_name();
|
||||
|
||||
group->unlock();
|
||||
|
||||
// ------------- Change users primary group ---------------------
|
||||
|
||||
user = upool->get(oid,true);
|
||||
@ -139,7 +165,7 @@ void UserChown::request_execute(xmlrpc_c::paramList const& paramList)
|
||||
return;
|
||||
}
|
||||
|
||||
user->set_gid(ngid);
|
||||
user->set_group(ngid,ngname);
|
||||
|
||||
user->add_group(ngid);
|
||||
user->del_group(old_gid);
|
||||
@ -154,7 +180,8 @@ void UserChown::request_execute(xmlrpc_c::paramList const& paramList)
|
||||
|
||||
if( group == 0 )
|
||||
{
|
||||
get_error(object_name(AuthRequest::GROUP),ngid); //TODO Rollback
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(AuthRequest::GROUP),ngid));//TODO Rollback
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
|
||||
}
|
||||
}
|
||||
|
||||
rc = vmpool->allocate(uid, gid, tmpl, &vid, error_str, false);
|
||||
rc = vmpool->allocate(uid, gid, uname, gname, tmpl, &vid, error_str, false);
|
||||
|
||||
if ( rc < 0 )
|
||||
{
|
||||
|
@ -398,7 +398,7 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
|
||||
|
||||
// ------------------ Create the image ------------------
|
||||
|
||||
rc = ipool->allocate(uid, gid, itemplate, &iid,error_str);
|
||||
rc = ipool->allocate(uid, gid, uname, gname, itemplate, &iid,error_str);
|
||||
|
||||
if ( rc < 0 )
|
||||
{
|
||||
|
@ -128,12 +128,13 @@ string& User::to_xml(string& xml) const
|
||||
|
||||
oss <<
|
||||
"<USER>"
|
||||
"<ID>" << oid <<"</ID>" <<
|
||||
"<GID>" << gid <<"</GID>" <<
|
||||
"<NAME>" << name <<"</NAME>" <<
|
||||
"<PASSWORD>" << password <<"</PASSWORD>" <<
|
||||
"<ENABLED>" << enabled_int <<"</ENABLED>" <<
|
||||
collection_xml <<
|
||||
"<ID>" << oid <<"</ID>" <<
|
||||
"<GID>" << gid <<"</GID>" <<
|
||||
"<GNAME>" << gname <<"</GNAME>" <<
|
||||
"<NAME>" << name <<"</NAME>" <<
|
||||
"<PASSWORD>" << password <<"</PASSWORD>"<<
|
||||
"<ENABLED>" << enabled_int <<"</ENABLED>" <<
|
||||
collection_xml <<
|
||||
"</USER>";
|
||||
|
||||
xml = oss.str();
|
||||
@ -155,6 +156,7 @@ int User::from_xml(const string& xml)
|
||||
|
||||
rc += xpath(oid, "/USER/ID", -1);
|
||||
rc += xpath(gid, "/USER/GID", -1);
|
||||
rc += xpath(gname, "/USER/GNAME", "not_found");
|
||||
rc += xpath(name, "/USER/NAME", "not_found");
|
||||
rc += xpath(password, "/USER/PASSWORD", "not_found");
|
||||
rc += xpath(int_enabled, "/USER/ENABLED", 0);
|
||||
|
@ -88,8 +88,13 @@ UserPool::UserPool(SqlDB * db):PoolSQL(db,User::table)
|
||||
string error_str;
|
||||
string sha1_pass = SSLTools::sha1_digest(one_pass);
|
||||
|
||||
allocate(&one_uid,GroupPool::ONEADMIN_ID,one_name,sha1_pass,
|
||||
true, error_str);
|
||||
allocate(&one_uid,
|
||||
GroupPool::ONEADMIN_ID,
|
||||
one_name,
|
||||
GroupPool::ONEADMIN_NAME,
|
||||
sha1_pass,
|
||||
true,
|
||||
error_str);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -117,8 +122,9 @@ UserPool::UserPool(SqlDB * db):PoolSQL(db,User::table)
|
||||
int UserPool::allocate (
|
||||
int * oid,
|
||||
int gid,
|
||||
string username,
|
||||
string password,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
const string& password,
|
||||
bool enabled,
|
||||
string& error_str)
|
||||
{
|
||||
@ -130,12 +136,12 @@ int UserPool::allocate (
|
||||
|
||||
ostringstream oss;
|
||||
|
||||
if ( username.empty() )
|
||||
if ( uname.empty() )
|
||||
{
|
||||
goto error_name;
|
||||
}
|
||||
|
||||
user = get(username,false);
|
||||
user = get(uname,false);
|
||||
|
||||
if ( user !=0 )
|
||||
{
|
||||
@ -143,7 +149,7 @@ int UserPool::allocate (
|
||||
}
|
||||
|
||||
// Build a new User object
|
||||
user = new User(-1, gid, username, password, enabled);
|
||||
user = new User(-1, gid, uname, gname, password, enabled);
|
||||
|
||||
user->add_collection_id(gid); //Adds the primary group to the collection
|
||||
|
||||
@ -190,9 +196,12 @@ error_common:
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
//bool UserPool::authenticate(const string& session, int& user_id, int& group_id)
|
||||
bool UserPool::authenticate(const string& session, int& user_id, int& group_id,
|
||||
set<int>& group_ids)
|
||||
bool UserPool::authenticate(const string& session,
|
||||
int& user_id,
|
||||
int& group_id,
|
||||
string& uname,
|
||||
string& gname,
|
||||
set<int>& group_ids)
|
||||
{
|
||||
map<string, int>::iterator index;
|
||||
|
||||
@ -200,6 +209,9 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id,
|
||||
string username;
|
||||
string secret, u_pass;
|
||||
|
||||
string tuname;
|
||||
string tgname;
|
||||
|
||||
int uid, gid;
|
||||
int rc;
|
||||
bool result;
|
||||
@ -209,6 +221,8 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id,
|
||||
|
||||
user_id = -1;
|
||||
group_id = -1;
|
||||
uname = "";
|
||||
gname = "";
|
||||
result = false;
|
||||
|
||||
rc = User::split_secret(session,username,secret);
|
||||
@ -226,6 +240,9 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id,
|
||||
uid = user->oid;
|
||||
gid = user->gid;
|
||||
|
||||
tuname = user->name;
|
||||
tgname = user->gname;
|
||||
|
||||
group_ids = user->get_groups();
|
||||
|
||||
user->unlock();
|
||||
@ -245,8 +262,12 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id,
|
||||
{
|
||||
if (ar.plain_authenticate())
|
||||
{
|
||||
user_id = 0;
|
||||
group_id = GroupPool::ONEADMIN_ID;
|
||||
user_id = uid;
|
||||
group_id = gid;
|
||||
|
||||
uname = tuname;
|
||||
gname = tgname;
|
||||
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
@ -256,6 +277,10 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id,
|
||||
{
|
||||
user_id = uid;
|
||||
group_id = gid;
|
||||
|
||||
uname = tuname;
|
||||
gname = tgname;
|
||||
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
@ -270,6 +295,10 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id,
|
||||
{
|
||||
user_id = uid;
|
||||
group_id = gid;
|
||||
|
||||
uname = tuname;
|
||||
gname = tgname;
|
||||
|
||||
result = true;
|
||||
}
|
||||
else //External user, username & pass in driver message
|
||||
@ -290,6 +319,7 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id,
|
||||
allocate(&user_id,
|
||||
GroupPool::USERS_ID,
|
||||
mad_name,
|
||||
GroupPool::USERS_NAME,
|
||||
mad_pass,
|
||||
true,
|
||||
error_str);
|
||||
@ -308,6 +338,10 @@ bool UserPool::authenticate(const string& session, int& user_id, int& group_id,
|
||||
{
|
||||
group_ids.insert( GroupPool::USERS_ID );
|
||||
group_id = GroupPool::USERS_ID;
|
||||
|
||||
uname = mad_name;
|
||||
gname = GroupPool::USERS_NAME;
|
||||
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
@ -37,11 +37,13 @@
|
||||
/* Virtual Machine :: Constructor/Destructor */
|
||||
/* ************************************************************************** */
|
||||
|
||||
VirtualMachine::VirtualMachine(int id,
|
||||
int _uid,
|
||||
int _gid,
|
||||
VirtualMachine::VirtualMachine(int id,
|
||||
int _uid,
|
||||
int _gid,
|
||||
const string& _uname,
|
||||
const string& _gname,
|
||||
VirtualMachineTemplate * _vm_template):
|
||||
PoolObjectSQL(id,"",_uid,_gid,table),
|
||||
PoolObjectSQL(id,"",_uid,_gid,_uname,_gname,table),
|
||||
last_poll(0),
|
||||
state(INIT),
|
||||
lcm_state(LCM_INIT),
|
||||
@ -1153,6 +1155,8 @@ string& VirtualMachine::to_xml(string& xml) const
|
||||
<< "<ID>" << oid << "</ID>"
|
||||
<< "<UID>" << uid << "</UID>"
|
||||
<< "<GID>" << gid << "</GID>"
|
||||
<< "<UNAME>" << uname << "</UNAME>"
|
||||
<< "<GNAME>" << gname << "</GNAME>"
|
||||
<< "<NAME>" << name << "</NAME>"
|
||||
<< "<LAST_POLL>" << last_poll << "</LAST_POLL>"
|
||||
<< "<STATE>" << state << "</STATE>"
|
||||
@ -1185,34 +1189,38 @@ int VirtualMachine::from_xml(const string &xml_str)
|
||||
{
|
||||
vector<xmlNodePtr> content;
|
||||
|
||||
int int_state;
|
||||
int int_lcmstate;
|
||||
int istate;
|
||||
int ilcmstate;
|
||||
int rc = 0;
|
||||
|
||||
// Initialize the internal XML object
|
||||
update_from_str(xml_str);
|
||||
|
||||
// Get class base attributes
|
||||
rc += xpath(oid, "/VM/ID", -1);
|
||||
rc += xpath(uid, "/VM/UID", -1);
|
||||
rc += xpath(gid, "/VM/GID", -1);
|
||||
rc += xpath(name, "/VM/NAME", "not_found");
|
||||
rc += xpath(oid, "/VM/ID", -1);
|
||||
|
||||
rc += xpath(last_poll, "/VM/LAST_POLL",0);
|
||||
rc += xpath(int_state, "/VM/STATE", 0);
|
||||
rc += xpath(int_lcmstate,"/VM/LCM_STATE", 0);
|
||||
rc += xpath(uid, "/VM/UID", -1);
|
||||
rc += xpath(gid, "/VM/GID", -1);
|
||||
|
||||
rc += xpath(stime, "/VM/STIME", 0);
|
||||
rc += xpath(etime, "/VM/ETIME", 0);
|
||||
rc += xpath(deploy_id, "/VM/DEPLOY_ID","");
|
||||
rc += xpath(uname, "/VM/UNAME", "not_found");
|
||||
rc += xpath(gname, "/VM/GNAME", "not_found");
|
||||
rc += xpath(name, "/VM/NAME", "not_found");
|
||||
|
||||
rc += xpath(memory, "/VM/MEMORY", 0);
|
||||
rc += xpath(cpu, "/VM/CPU", 0);
|
||||
rc += xpath(net_tx, "/VM/NET_TX", 0);
|
||||
rc += xpath(net_rx, "/VM/NET_RX", 0);
|
||||
rc += xpath(last_poll, "/VM/LAST_POLL", 0);
|
||||
rc += xpath(istate, "/VM/STATE", 0);
|
||||
rc += xpath(ilcmstate, "/VM/LCM_STATE", 0);
|
||||
|
||||
state = static_cast<VmState>( int_state );
|
||||
lcm_state = static_cast<LcmState>( int_lcmstate );
|
||||
rc += xpath(stime, "/VM/STIME", 0);
|
||||
rc += xpath(etime, "/VM/ETIME", 0);
|
||||
rc += xpath(deploy_id, "/VM/DEPLOY_ID","");
|
||||
|
||||
rc += xpath(memory, "/VM/MEMORY", 0);
|
||||
rc += xpath(cpu, "/VM/CPU", 0);
|
||||
rc += xpath(net_tx, "/VM/NET_TX", 0);
|
||||
rc += xpath(net_rx, "/VM/NET_RX", 0);
|
||||
|
||||
state = static_cast<VmState>(istate);
|
||||
lcm_state = static_cast<LcmState>(ilcmstate);
|
||||
|
||||
// Get associated classes
|
||||
ObjectXML::get_nodes("/VM/TEMPLATE", content);
|
||||
|
@ -178,6 +178,8 @@ VirtualMachinePool::VirtualMachinePool(SqlDB * db,
|
||||
int VirtualMachinePool::allocate (
|
||||
int uid,
|
||||
int gid,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
VirtualMachineTemplate * vm_template,
|
||||
int * oid,
|
||||
string& error_str,
|
||||
@ -188,7 +190,7 @@ int VirtualMachinePool::allocate (
|
||||
// ------------------------------------------------------------------------
|
||||
// Build a new Virtual Machine object
|
||||
// ------------------------------------------------------------------------
|
||||
vm = new VirtualMachine(-1, uid, gid, vm_template);
|
||||
vm = new VirtualMachine(-1, uid, gid, uname, gname, vm_template);
|
||||
|
||||
if (on_hold == true)
|
||||
{
|
||||
|
@ -26,8 +26,10 @@
|
||||
VMTemplate::VMTemplate(int id,
|
||||
int _uid,
|
||||
int _gid,
|
||||
const string& _uname,
|
||||
const string& _gname,
|
||||
VirtualMachineTemplate * _template_contents):
|
||||
PoolObjectSQL(id,"",_uid,_gid,table),
|
||||
PoolObjectSQL(id,"",_uid,_gid,_uname,_gname,table),
|
||||
regtime(time(0))
|
||||
{
|
||||
if (_template_contents != 0)
|
||||
@ -190,6 +192,8 @@ string& VMTemplate::to_xml(string& xml) const
|
||||
<< "<ID>" << oid << "</ID>"
|
||||
<< "<UID>" << uid << "</UID>"
|
||||
<< "<GID>" << gid << "</GID>"
|
||||
<< "<UNAME>" << uname << "</UNAME>"
|
||||
<< "<GNAME>" << gname << "</GNAME>"
|
||||
<< "<NAME>" << name << "</NAME>"
|
||||
<< "<PUBLIC>" << public_obj << "</PUBLIC>"
|
||||
<< "<REGTIME>" << regtime << "</REGTIME>"
|
||||
@ -216,6 +220,8 @@ int VMTemplate::from_xml(const string& xml)
|
||||
rc += xpath(oid, "/VMTEMPLATE/ID", -1);
|
||||
rc += xpath(uid, "/VMTEMPLATE/UID", -1);
|
||||
rc += xpath(gid, "/VMTEMPLATE/GID", -1);
|
||||
rc += xpath(uname, "/VMTEMPLATE/UNAME", "not_found");
|
||||
rc += xpath(gname, "/VMTEMPLATE/GNAME", "not_found");
|
||||
rc += xpath(name, "/VMTEMPLATE/NAME", "not_found");
|
||||
rc += xpath(public_obj, "/VMTEMPLATE/PUBLIC", 0);
|
||||
rc += xpath(regtime, "/VMTEMPLATE/REGTIME", 0);
|
||||
|
@ -26,6 +26,8 @@
|
||||
int VMTemplatePool::allocate (
|
||||
int uid,
|
||||
int gid,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
VirtualMachineTemplate * template_contents,
|
||||
int * oid,
|
||||
string& error_str)
|
||||
@ -38,7 +40,7 @@ int VMTemplatePool::allocate (
|
||||
// ------------------------------------------------------------------------
|
||||
// Build a new VMTemplate object
|
||||
// ------------------------------------------------------------------------
|
||||
vm_template = new VMTemplate(-1, uid, gid, template_contents);
|
||||
vm_template = new VMTemplate(-1, uid, gid, uname, gname,template_contents);
|
||||
|
||||
// Check name
|
||||
vm_template->get_template_attribute("NAME", name);
|
||||
|
@ -29,10 +29,12 @@
|
||||
/* Virtual Network :: Constructor/Destructor */
|
||||
/* ************************************************************************** */
|
||||
|
||||
VirtualNetwork::VirtualNetwork(int _uid,
|
||||
int _gid,
|
||||
VirtualNetworkTemplate *_vn_template):
|
||||
PoolObjectSQL(-1,"",_uid,_gid,table),
|
||||
VirtualNetwork::VirtualNetwork(int _uid,
|
||||
int _gid,
|
||||
const string& _uname,
|
||||
const string& _gname,
|
||||
VirtualNetworkTemplate * _vn_template):
|
||||
PoolObjectSQL(-1,"",_uid,_gid,_uname,_gname,table),
|
||||
bridge(""),
|
||||
type(UNINITIALIZED),
|
||||
leases(0)
|
||||
@ -514,12 +516,14 @@ string& VirtualNetwork::to_xml_extended(string& xml, bool extended) const
|
||||
|
||||
os <<
|
||||
"<VNET>" <<
|
||||
"<ID>" << oid << "</ID>" <<
|
||||
"<UID>" << uid << "</UID>" <<
|
||||
"<GID>" << gid << "</GID>" <<
|
||||
"<NAME>" << name << "</NAME>" <<
|
||||
"<TYPE>" << type << "</TYPE>" <<
|
||||
"<BRIDGE>" << bridge << "</BRIDGE>";
|
||||
"<ID>" << oid << "</ID>" <<
|
||||
"<UID>" << uid << "</UID>" <<
|
||||
"<GID>" << gid << "</GID>" <<
|
||||
"<UNAME>" << uname << "</UNAME>" <<
|
||||
"<GNAME>" << gname << "</GNAME>" <<
|
||||
"<NAME>" << name << "</NAME>" <<
|
||||
"<TYPE>" << type << "</TYPE>" <<
|
||||
"<BRIDGE>" << bridge << "</BRIDGE>";
|
||||
|
||||
if (!phydev.empty())
|
||||
{
|
||||
@ -531,7 +535,7 @@ string& VirtualNetwork::to_xml_extended(string& xml, bool extended) const
|
||||
os << "<VLAN_ID>" << vlan_id << "</VLAN_ID>";
|
||||
}
|
||||
|
||||
os << "<PUBLIC>" << public_obj << "</PUBLIC>" <<
|
||||
os << "<PUBLIC>" << public_obj << "</PUBLIC>" <<
|
||||
"<TOTAL_LEASES>"<< total_leases << "</TOTAL_LEASES>"<<
|
||||
obj_template->to_xml(template_xml);
|
||||
|
||||
@ -561,18 +565,20 @@ int VirtualNetwork::from_xml(const string &xml_str)
|
||||
update_from_str(xml_str);
|
||||
|
||||
// Get class base attributes
|
||||
rc += xpath(oid, "/VNET/ID", -1);
|
||||
rc += xpath(uid, "/VNET/UID", -1);
|
||||
rc += xpath(gid, "/VNET/GID", -1);
|
||||
rc += xpath(name, "/VNET/NAME", "not_found");
|
||||
rc += xpath(int_type, "/VNET/TYPE", -1);
|
||||
rc += xpath(bridge, "/VNET/BRIDGE", "not_found");
|
||||
rc += xpath(public_obj, "/VNET/PUBLIC", 0);
|
||||
rc += xpath(oid, "/VNET/ID", -1);
|
||||
rc += xpath(uid, "/VNET/UID", -1);
|
||||
rc += xpath(gid, "/VNET/GID", -1);
|
||||
rc += xpath(uname, "/VNET/UNAME", "not_found");
|
||||
rc += xpath(gname, "/VNET/GNAME", "not_found");
|
||||
rc += xpath(name, "/VNET/NAME", "not_found");
|
||||
rc += xpath(int_type, "/VNET/TYPE", -1);
|
||||
rc += xpath(bridge, "/VNET/BRIDGE", "not_found");
|
||||
rc += xpath(public_obj, "/VNET/PUBLIC", 0);
|
||||
|
||||
xpath(phydev, "/VNET/PHYDEV", "");
|
||||
xpath(vlan_id, "/VNET/VLAN_ID", "");
|
||||
xpath(vlan_id, "/VNET/VLAN_ID","");
|
||||
|
||||
type = static_cast<NetworkType>( int_type );
|
||||
type = static_cast<NetworkType>(int_type);
|
||||
|
||||
// Get associated classes
|
||||
ObjectXML::get_nodes("/VNET/TEMPLATE", content);
|
||||
|
@ -72,6 +72,8 @@ VirtualNetworkPool::VirtualNetworkPool(SqlDB * db,
|
||||
int VirtualNetworkPool::allocate (
|
||||
int uid,
|
||||
int gid,
|
||||
const string& uname,
|
||||
const string& gname,
|
||||
VirtualNetworkTemplate * vn_template,
|
||||
int * oid,
|
||||
string& error_str)
|
||||
@ -80,7 +82,7 @@ int VirtualNetworkPool::allocate (
|
||||
VirtualNetwork * vn_aux;
|
||||
string name;
|
||||
|
||||
vn = new VirtualNetwork(uid, gid, vn_template);
|
||||
vn = new VirtualNetwork(uid, gid, uname, gname, vn_template);
|
||||
|
||||
// Check for duplicates
|
||||
vn->get_template_attribute("NAME", name);
|
||||
|
Loading…
x
Reference in New Issue
Block a user