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

Merge branch 'feature-687'

This commit is contained in:
Ruben S. Montero 2011-07-06 18:12:03 +02:00
commit cc4d9ea380
122 changed files with 4589 additions and 806 deletions

View File

@ -75,6 +75,7 @@ main_env.Append(LIBPATH=[
cwd+'/src/hm',
cwd+'/src/um',
cwd+'/src/authm',
cwd+'/src/acl',
cwd+'/src/xml',
])
@ -204,6 +205,7 @@ build_scripts=[
'src/hm/SConstruct',
'src/um/SConstruct',
'src/authm/SConstruct',
'src/acl/SConstruct',
'src/xml/SConstruct',
'share/man/SConstruct'
]

254
include/AclManager.h Normal file
View File

@ -0,0 +1,254 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 ACL_MANAGER_H_
#define ACL_MANAGER_H_
#include "AuthManager.h"
#include "AclRule.h"
#include "SqlDB.h"
using namespace std;
/**
* This class manages the ACL rules and the authorization engine
*/
class AclManager : public Callbackable
{
public:
AclManager(SqlDB * _db);
AclManager():db(0),lastOID(0)
{
pthread_mutex_init(&mutex, 0);
};
virtual ~AclManager();
/**
* Loads the ACL rule set from the DB
* @return 0 on success.
*/
int start();
/* ---------------------------------------------------------------------- */
/* Rule management */
/* ---------------------------------------------------------------------- */
/**
* Takes an authorization request and checks if any rule in the ACL
* authorizes the operation.
*
* @param uid The user ID requesting to be authorized
* @param user_groups Set of group IDs that the user is part of
* @param obj_type The object over which the operation will be performed
* @param obj_id The object ID
* @param obj_gid The object's group ID
* @param op The operation to be authorized
* @return true if the authorization is granted by any rule
*/
const bool authorize(int uid,
const set<int>& user_groups,
AuthRequest::Object obj_type,
int obj_id,
int obj_gid,
AuthRequest::Operation op);
/**
* Adds a new rule to the ACL rule set
*
* @param user 64 bit ID and flags
* @param resource 64 bit ID and flags
* @param rights 64 bit flags
* @param error_str Returns the error reason, if any
*
* @return the oid assigned to the rule on success,
* -1 if the rule exists,
* -2 if the rule is malformed,
* -3 if the DB insert failed
*/
virtual int add_rule(long long user,
long long resource,
long long rights,
string& error_str);
/**
* Deletes a rule from the ACL rule set
*
* @param oid Rule id
* @param error_str Returns the error reason, if any
* @return 0 on success
*/
virtual int del_rule(int oid, string& error_str);
/* ---------------------------------------------------------------------- */
/* DB management */
/* ---------------------------------------------------------------------- */
/**
* Bootstraps the database table(s) associated to the ACL Manager
*/
static void bootstrap(SqlDB * _db);
/**
* Dumps the rule set in XML format.
* @param oss The output stream to dump the rule set contents
* @return 0 on success
*/
virtual int dump(ostringstream& oss);
protected:
// ----------------------------------------
// ACL rules management
// ----------------------------------------
/**
* ACL rules. Each rule is indexed by its 'user' long long attibute,
* several rules can apply to the same user
*/
multimap<long long, AclRule*> acl_rules;
/**
* Rules indexed by oid. Stores the same rules as acl_rules
*/
map<int, AclRule *> acl_rules_oids;
private:
/**
* Gets all rules that apply to the user_req and, if any of them grants
* permission, returns true.
*
* @param user_req user/group id and flags
* @param resource_oid_req 64 bit request, ob. type and individual oid
* @param resource_gid_req 64 bit request, ob. type and group id
* @param resource_all_req 64 bit request, ob. type and all flag
* @param rights_req Requested rights
* @param individual_obj_type Mask with ob. type and individual flags
* @param group_obj_type Mask with ob. type and gropu flags
*
* @return true if any rule grants permission
*/
bool match_rules(
long long user_req,
long long resource_oid_req,
long long resource_gid_req,
long long resource_all_req,
long long rights_req,
long long individual_obj_type,
long long group_obj_type);
// ----------------------------------------
// Mutex synchronization
// ----------------------------------------
pthread_mutex_t mutex;
/**
* Function to lock the manager
*/
void lock()
{
pthread_mutex_lock(&mutex);
};
/**
* Function to unlock the manager
*/
void unlock()
{
pthread_mutex_unlock(&mutex);
};
// ----------------------------------------
// DataBase implementation variables
// ----------------------------------------
/**
* Pointer to the database.
*/
SqlDB * db;
/**
* Last object ID assigned to a rule.
*/
int lastOID;
/**
* Tablename for the ACL rules
*/
static const char * table;
static const char * db_names;
static const char * db_bootstrap;
/**
* Inserts the last oid into the pool_control table
*/
void update_lastOID();
/**
* Callback function to unmarshall the ACL rules
* @param num the number of columns read from the DB
* @param names the column names
* @param vaues the column values
* @return 0 on success
*/
int select_cb(void *nil, int num, char **values, char **names);
/**
* Reads the ACL rule set from the database.
* @param db pointer to the db
* @return 0 on success
*/
int select();
/**
* Inserts the ACL rule in the database.
* @param rule to insert
* @return 0 on success
*/
int insert(AclRule * rule)
{
return insert(rule, db);
};
/**
* Inserts the ACL rule in the database.
* @param rule to insert
* @db db pointer
*
* @return 0 on success
*/
static int insert(AclRule * rule, SqlDB * db);
/**
* Drops an ACL rule from the database
*
* @param oid Rule id
* @return 0 on success
*/
int drop(int oid);
/**
* Callback to set the lastOID
*/
int init_cb(void *nil, int num, char **values, char **names);
};
#endif /*ACL_MANAGER_H*/

202
include/AclRule.h Normal file
View File

@ -0,0 +1,202 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 ACL_RULE_H_
#define ACL_RULE_H_
#include <set>
#include <string>
#include <libxml/tree.h>
using namespace std;
/**
* An ACL Rule is composed of three 64 bit numbers: user, resource and rights.
* These attributes store a combination of IDs and flags
*/
class AclRule
{
public:
// ------------------------------------------------------------------------
static const long long INDIVIDUAL_ID;
static const long long GROUP_ID;
static const long long ALL_ID;
// ------------------------------------------------------------------------
AclRule(int _oid,
long long _user,
long long _resource,
long long _rights):
oid(_oid), user(_user), resource(_resource), rights(_rights)
{
build_str();
};
bool operator ==(const AclRule& other) const
{
return (user == other.user &&
resource == other.resource &&
rights == other.rights);
};
/**
* Returns a human readable string for this rule
*
* @return a human readable string for this rule
*/
const string& to_str() const
{
return str;
};
/**
* Returns whether or not the rule is malformed.
*
* @param error_str Returns the error message, if any
* @return true if the rule is wrong
*/
bool malformed(string& error_str) const;
/**
* Function to print the 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 rule from an xml formatted string
*
* @param node xml node for the ACL rule
* @return 0 on success, -1 otherwise
*/
int from_xml(xmlNodePtr node);
/**
* Returns the 32 less significant bits of the user long long attribute
*
* @return the user or group ID
*/
int user_id() const
{
return user;
};
/**
* Returns the 64 bit user attribute with the ID cleared (the 32 less
* significant bits are set to 0)
*
* @return the user flags
*/
long long user_code() const
{
return user & 0xFFFFFFFF00000000LL;
};
/**
* Returns the 32 less significant bits of the resource long long attribute
*
* @return the resource ID
*/
int resource_id() const
{
return resource;
};
/**
* Returns the 64 bit resource attribute with the ID cleared (the 32 less
* significant bits are set to 0)
*
* @return the resource flags
*/
long long resource_code() const
{
return resource & 0xFFFFFFFF00000000LL;
};
// ------------------------------------------------------------------------
// Functions needed by the Scheduler ACL engine
// ------------------------------------------------------------------------
long long get_user() const
{
return user;
}
long long get_oid() const
{
return oid;
}
private:
// NONE_ID can never be used in a rule. It is useful to create masks that
// will never match any existing rule
static const long long NONE_ID;
friend class AclManager;
/**
* Rule unique identifier
*/
int oid;
/**
* 64 bit integer holding a user compound:
*
* 32 bits 32 bits
* +-----------------------+-----------------------+
* | Type (user,group,all) | user/group ID |
* +-----------------------+-----------------------+
*/
long long user;
/**
* 64 bit integer holding a resource compound
*
* 32 bits 32 bits
* +-----------------------+-----------------------+
* | Type (VM, Host...) | resource ID |
* +-----------------------+-----------------------+
*/
long long resource;
/**
* 64 bit integer containing the rights flags
*
* 64 bits
* +-----------------------------------------------+
* | Actions (MANAGE, CREATE, USE, DELETE... |
* +-----------------------------------------------+
*/
long long rights;
/**
* Human readable representation of the rule
*/
string str;
/**
* Builds the human representation of the ACL
*/
void build_str();
};
#endif /*ACL_RULE_H*/

View File

@ -18,6 +18,7 @@
#define AUTH_MANAGER_H_
#include <time.h>
#include <set>
#include "MadManager.h"
#include "ActionManager.h"
@ -259,10 +260,11 @@ private:
class AuthRequest : public ActionListener
{
public:
AuthRequest(int _uid):
AuthRequest(int _uid, set<int> _gids):
result(false),
timeout(false),
uid(_uid),
gids(_gids),
time_out(0),
self_authorize(true)
{
@ -276,15 +278,32 @@ public:
*/
enum Operation
{
CREATE, /** Authorization to create an object */
DELETE, /** Authorization to delete an object */
USE, /** Authorization to use an object */
MANAGE, /** Authorization to manage an object */
INFO, /** Authorization to view an object */
INFO_POOL, /** Authorization to view any object in the pool */
INFO_POOL_MINE, /** Authorization to view user and/or group objects */
INSTANTIATE, /** Authorization to instantiate a VM from a TEMPLATE */
CHOWN /** Authorization to change ownership of an object */
CREATE = 0x1LL, /**< Auth. to create an object */
DELETE = 0x2LL, /**< Auth. to delete an object */
USE = 0x4LL, /**< Auth. to use an object */
MANAGE = 0x8LL, /**< Auth. to manage an object */
INFO = 0x10LL, /**< Auth. to view an object */
INFO_POOL = 0x20LL, /**< Auth. to view any object in the pool */
INFO_POOL_MINE= 0x40LL, /**< Auth. to view user and/or group objects */
INSTANTIATE = 0x80LL, /**< Auth. to instantiate a VM from a TEMPLATE*/
CHOWN = 0x100LL /**< Auth. to change ownership of an object */
};
static string Operation_to_str(Operation op)
{
switch (op)
{
case CREATE: return "CREATE";
case DELETE: return "DELETE";
case USE: return "USE";
case MANAGE: return "MANAGE";
case INFO: return "INFO";
case INFO_POOL: return "INFO_POOL";
case INFO_POOL_MINE: return "INFO_POOL_MINE";
case INSTANTIATE: return "INSTANTIATE";
case CHOWN: return "CHOWN";
default: return "";
}
};
/**
@ -292,13 +311,29 @@ public:
*/
enum Object
{
VM,
HOST,
NET,
IMAGE,
USER,
TEMPLATE,
GROUP
VM = 0x0000001000000000LL,
HOST = 0x0000002000000000LL,
NET = 0x0000004000000000LL,
IMAGE = 0x0000008000000000LL,
USER = 0x0000010000000000LL,
TEMPLATE = 0x0000020000000000LL,
GROUP = 0x0000040000000000LL,
ACL = 0x0000080000000000LL
};
static string Object_to_str(Object ob)
{
switch (ob)
{
case VM: return "VM" ; break;
case HOST: return "HOST" ; break;
case NET: return "NET" ; break;
case IMAGE: return "IMAGE" ; break;
case USER: return "USER" ; break;
case TEMPLATE: return "TEMPLATE" ; break;
case GROUP: return "GROUP" ; break;
default: return "";
}
};
/**
@ -328,6 +363,7 @@ public:
*/
void add_auth(Object ob,
const string& ob_id,
int ob_gid,
Operation op,
int owner,
bool pub);
@ -337,6 +373,7 @@ public:
*/
void add_auth(Object ob,
int ob_id,
int ob_gid,
Operation op,
int owner,
bool pub)
@ -344,7 +381,7 @@ public:
ostringstream oss;
oss << ob_id;
add_auth(ob,oss.str(),op,owner,pub);
add_auth(ob,oss.str(),ob_gid,op,owner,pub);
};
/**
@ -425,6 +462,11 @@ private:
*/
int uid;
/**
* The user groups ID set
*/
set<int> gids;
/**
* Timeout for this request
*/

View File

@ -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(){};

View File

@ -332,6 +332,8 @@ protected:
Image(int uid,
int gid,
const string& uname,
const string& gname,
ImageTemplate* img_template);
virtual ~Image();

View File

@ -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);
};
};

View File

@ -36,6 +36,7 @@
#include "RequestManager.h"
#include "HookManager.h"
#include "AuthManager.h"
#include "AclManager.h"
#include "ImageManager.h"
#include "Callbackable.h"
@ -134,6 +135,11 @@ public:
return imagem;
};
AclManager * get_aclm()
{
return aclm;
};
// --------------------------------------------------------------
// Environment & Configuration
// --------------------------------------------------------------
@ -249,7 +255,7 @@ private:
Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0),
upool(0),ipool(0),gpool(0),tpool(0),lcm(0),vmm(0),im(0),tm(0),
dm(0),rm(0),hm(0),authm(0),imagem(0)
dm(0),rm(0),hm(0),authm(0),aclm(0),imagem(0)
{
const char * nl = getenv("ONE_LOCATION");
@ -357,6 +363,11 @@ private:
delete authm;
}
if ( aclm != 0)
{
delete aclm;
}
if ( imagem != 0)
{
delete imagem;
@ -423,6 +434,7 @@ private:
RequestManager * rm;
HookManager * hm;
AuthManager * authm;
AclManager * aclm;
ImageManager * imagem;
// ---------------------------------------------------------------

View File

@ -124,6 +124,20 @@ public:
*/
int get_nodes(const char * xpath_expr, vector<xmlNodePtr>& content);
/**
* Frees a vector of XMLNodes, as returned by the get_nodes function
* @param content the vector of xmlNodePtr
*/
void free_nodes(vector<xmlNodePtr>& content)
{
vector<xmlNodePtr>::iterator it;
for (it = content.begin(); it < content.end(); it++)
{
xmlFreeNode(*it);
}
};
/**
* Updates the object representation with a new XML document. Previous
* XML resources are freed

View File

@ -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
*/

View File

@ -59,17 +59,20 @@ 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 */
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 ---------------------------------- */
@ -88,15 +91,32 @@ protected:
/* -------------------------------------------------------------------- */
/**
* Performs a basic autorization for this request using the uid/gid
* Performs a basic authorization for this request using the uid/gid
* from the request. The function gets the object from the pool to get
* the public attribute and its owner. The authorization is based on
* object and type of operation for the request.
* @param oid of the object.
* @param oid of the object, can be -1 for objects to be created, or
* pools.
*
* @return true if the user is authorized.
*/
bool basic_authorization(int oid);
bool basic_authorization(int oid)
{
return basic_authorization(oid, auth_op);
};
/**
* Performs a basic authorization for this request using the uid/gid
* from the request. The function gets the object from the pool to get
* the public attribute and its owner. The authorization is based on
* object and type of operation for the request.
* @param oid of the object, can be -1 for objects to be created, or
* pools.
* @param op operation of the request.
*
* @return true if the user is authorized.
*/
bool basic_authorization(int oid, AuthRequest::Operation op);
/**
* Actual Execution method for the request. Must be implemented by the

110
include/RequestManagerAcl.h Normal file
View File

@ -0,0 +1,110 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 REQUEST_MANAGER_ACL_H
#define REQUEST_MANAGER_ACL_H
#include "Request.h"
#include "Nebula.h"
using namespace std;
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class RequestManagerAcl: public Request
{
protected:
RequestManagerAcl( const string& method_name,
const string& help,
const string& params)
:Request(method_name,params,help)
{
auth_object = AuthRequest::ACL;
auth_op = AuthRequest::MANAGE;
Nebula& nd = Nebula::instance();
aclm = nd.get_aclm();
};
~RequestManagerAcl(){};
/* -------------------------------------------------------------------- */
virtual void request_execute(xmlrpc_c::paramList const& _paramList) = 0;
/* -------------------------------------------------------------------- */
AclManager * aclm;
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class AclAddRule : public RequestManagerAcl
{
public:
AclAddRule():
RequestManagerAcl("AclAddRule",
"Adds a new ACL rule",
"A:ssss")
{};
~AclAddRule(){};
void request_execute(xmlrpc_c::paramList const& _paramList);
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class AclDelRule : public RequestManagerAcl
{
public:
AclDelRule():
RequestManagerAcl("AclDelRule",
"Deletes an existing ACL rule",
"A:si")
{};
~AclDelRule(){};
void request_execute(xmlrpc_c::paramList const& _paramList);
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class AclInfo: public RequestManagerAcl
{
public:
AclInfo():
RequestManagerAcl("AclInfo",
"Returns the ACL rule set",
"A:s")
{};
~AclInfo(){};
void request_execute(xmlrpc_c::paramList const& _paramList);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#endif

View File

@ -104,7 +104,7 @@ class VirtualNetworkAllocate: public RequestManagerAllocate
{
public:
VirtualNetworkAllocate():
RequestManagerAllocate("VirtualNetworkInfo",
RequestManagerAllocate("VirtualNetworkAllocate",
"Allocates a new virtual network",
"A:ss",
true)
@ -200,7 +200,7 @@ class HostAllocate : public RequestManagerAllocate
{
public:
HostAllocate():
RequestManagerAllocate("HostInfo",
RequestManagerAllocate("HostAllocate",
"Allocates a new host",
"A:sssss",
false)
@ -225,7 +225,7 @@ class UserAllocate: public RequestManagerAllocate
{
public:
UserAllocate():
RequestManagerAllocate("UserInfo",
RequestManagerAllocate("UserAllocate",
"Returns user information",
"A:sss",
false)

View File

@ -66,6 +66,14 @@ public:
};
~VirtualMachineInfo(){};
/* -------------------------------------------------------------------- */
void to_xml(PoolObjectSQL * object, string& str)
{
VirtualMachine * vm = static_cast<VirtualMachine *>(object);
vm->to_xml_extended(str);
};
};
/* ------------------------------------------------------------------------- */

View File

@ -31,8 +31,9 @@ class RequestManagerPoolInfoFilter: public Request
{
protected:
RequestManagerPoolInfoFilter(const string& method_name,
const string& help)
:Request(method_name,"A:si",help)
const string& help,
const string& signature)
:Request(method_name,signature,help)
{
auth_op = AuthRequest::INFO_POOL;
};
@ -41,9 +42,9 @@ protected:
/* -------------------------------------------------------------------- */
static const int ALL; /**< Secify all objects in the pool (-2) */
static const int MINE; /**< Secify user's objects in the pool (-3)*/
static const int MINE_GROUP; /**< Secify users + group objects (-1) */
static const int ALL; /**< Specify all objects in the pool (-2) */
static const int MINE; /**< Specify user's objects in the pool (-3)*/
static const int MINE_GROUP; /**< Specify users + group objects (-1) */
/* -------------------------------------------------------------------- */
@ -56,9 +57,17 @@ protected:
class VirtualMachinePoolInfo : public RequestManagerPoolInfoFilter
{
public:
/* -------------------------------------------------------------------- */
static const int ALL_VM; /**< VMs in any state (-2) */
static const int NOT_DONE; /**< VMs in any state expect DONE (-1)*/
/* -------------------------------------------------------------------- */
VirtualMachinePoolInfo():
RequestManagerPoolInfoFilter("VirtualMachinePoolInfo",
"Returns the virtual machine instances pool")
"Returns the virtual machine instances pool",
"A:siiii")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vmpool();
@ -76,7 +85,8 @@ class TemplatePoolInfo : public RequestManagerPoolInfoFilter
public:
TemplatePoolInfo():
RequestManagerPoolInfoFilter("TemplatePoolInfo",
"Returns the virtual machine template pool")
"Returns the virtual machine template pool",
"A:siii")
{
Nebula& nd = Nebula::instance();
pool = nd.get_tpool();
@ -89,13 +99,13 @@ public:
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VirtualNetworkPoolInfo: public RequestManagerPoolInfoFilter
{
public:
VirtualNetworkPoolInfo():
RequestManagerPoolInfoFilter("VirtualNetworkPoolInfo",
"Returns the virtual network pool")
"Returns the virtual network pool",
"A:siii")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vnpool();
@ -113,7 +123,8 @@ class ImagePoolInfo: public RequestManagerPoolInfoFilter
public:
ImagePoolInfo():
RequestManagerPoolInfoFilter("ImagePoolInfo",
"Returns the image pool")
"Returns the image pool",
"A:siii")
{
Nebula& nd = Nebula::instance();
pool = nd.get_ipool();
@ -123,7 +134,6 @@ public:
~ImagePoolInfo(){};
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -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(){};

View File

@ -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,10 +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);
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
@ -133,7 +141,7 @@ private:
*/
PoolObjectSQL * create()
{
return new User(-1,-1,"","",true);
return new User(-1,-1,"","","",true);
};
};

View File

@ -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();

View File

@ -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);
};
};

View File

@ -124,6 +124,14 @@ public:
*/
string& to_xml(string& xml) const;
/**
* Function to print the VirtualMachine object into a string in
* XML format, with extended information (full history records)
* @param xml the resulting XML string
* @return a reference to the generated string
*/
string& to_xml_extended(string& xml) const;
/**
* Rebuilds the object from an xml formatted string
* @param xml_str The xml-formatted string
@ -752,6 +760,12 @@ private:
*/
History * previous_history;
/**
* Complete set of history records for the VM
*/
vector<History *> history_records;
// -------------------------------------------------------------------------
// Logging
// -------------------------------------------------------------------------
@ -859,14 +873,27 @@ private:
*/
void parse_graphics();
/**
* Function that renders the VM in XML format optinally including
* extended information (all history records)
* @param xml the resulting XML string
* @param extended include additional info if true
* @return a reference to the generated string
*/
string& to_xml_extended(string& xml, bool extended) const;
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();

View File

@ -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,
@ -137,22 +139,9 @@ public:
*/
int dump(ostringstream& oss, const string& where)
{
return dump(oss, -1, where);
return PoolSQL::dump(oss, "VM_POOL", VirtualMachine::table, where);
}
/**
* Dumps the VM pool in XML format. A filter can be also added to the query
* Also the hostname where the VirtualMachine is running is added to the
* pool
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param state include only VMs in this state. -1 means any state,
* except DONE
*
* @return 0 on success
*/
int dump(ostringstream& oss, int state, const string& where);
private:
/**
* Factory method to produce VM objects
@ -160,7 +149,7 @@ private:
*/
PoolObjectSQL * create()
{
return new VirtualMachine(-1,-1,-1,0);
return new VirtualMachine(-1,-1,-1,"","",0);
};
};

View File

@ -269,6 +269,8 @@ private:
VirtualNetwork(int uid,
int gid,
const string& _uname,
const string& _gname,
VirtualNetworkTemplate * _vn_template = 0);
~VirtualNetwork();

View File

@ -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);
};
};

View File

@ -35,6 +35,7 @@
#include "RequestManager.h"
#include "HookManager.h"
#include "AuthManager.h"
#include "AclManager.h"
#include "ImageManager.h"
class NebulaTest
@ -49,7 +50,7 @@ protected:
need_im(false), need_tm(false),
need_lcm(false), need_dm(false),
need_rm(false), need_hm(false),
need_authm(false), need_imagem(false)
need_authm(false), need_aclm(false), need_imagem(false)
{};
virtual ~NebulaTest(){};
@ -75,6 +76,7 @@ public:
bool need_rm;
bool need_hm;
bool need_authm;
bool need_aclm;
bool need_imagem;
static NebulaTest * instance()
@ -132,6 +134,8 @@ public:
virtual AuthManager* create_authm(time_t timer_period);
virtual AclManager* create_aclm(SqlDB* db);
virtual ImageManager* create_imagem(ImagePool * ipool);
};

View File

@ -377,6 +377,7 @@ BIN_FILES="src/nebula/oned \
src/cli/oneimage \
src/cli/onegroup \
src/cli/onetemplate \
src/cli/oneacl \
src/onedb/onedb \
share/scripts/one \
src/authm_mad/oneauth"
@ -673,6 +674,8 @@ RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/OpenNebula/Host.rb \
src/oca/ruby/OpenNebula/TemplatePool.rb \
src/oca/ruby/OpenNebula/Group.rb \
src/oca/ruby/OpenNebula/GroupPool.rb \
src/oca/ruby/OpenNebula/Acl.rb \
src/oca/ruby/OpenNebula/AclPool.rb \
src/oca/ruby/OpenNebula/XMLUtils.rb"
#-------------------------------------------------------------------------------
@ -768,7 +771,8 @@ ONE_CLI_LIB_FILES="src/cli/one_helper/onegroup_helper.rb \
src/cli/one_helper/onetemplate_helper.rb \
src/cli/one_helper/oneuser_helper.rb \
src/cli/one_helper/onevm_helper.rb \
src/cli/one_helper/onevnet_helper.rb"
src/cli/one_helper/onevnet_helper.rb \
src/cli/one_helper/oneacl_helper.rb"
CLI_BIN_FILES="src/cli/onevm \
src/cli/onehost \
@ -776,7 +780,8 @@ CLI_BIN_FILES="src/cli/onevm \
src/cli/oneuser \
src/cli/oneimage \
src/cli/onetemplate \
src/cli/onegroup"
src/cli/onegroup \
src/cli/oneacl"
CLI_CONF_FILES="src/cli/etc/onegroup.yaml \
src/cli/etc/onehost.yaml \
@ -784,7 +789,8 @@ CLI_CONF_FILES="src/cli/etc/onegroup.yaml \
src/cli/etc/onetemplate.yaml \
src/cli/etc/oneuser.yaml \
src/cli/etc/onevm.yaml \
src/cli/etc/onevnet.yaml"
src/cli/etc/onevnet.yaml \
src/cli/etc/oneacl.yaml"
#-----------------------------------------------------------------------------
# Sunstone files

629
src/acl/AclManager.cc Normal file
View File

@ -0,0 +1,629 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 <climits>
#include "AclManager.h"
#include "NebulaLog.h"
#include "GroupPool.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
const char * AclManager::table = "acl";
const char * AclManager::db_names = "oid, user, resource, rights";
const char * AclManager::db_bootstrap = "CREATE TABLE IF NOT EXISTS "
"acl (oid INT PRIMARY KEY, user BIGINT, resource BIGINT, rights BIGINT)";
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclManager::init_cb(void *nil, int num, char **values, char **names)
{
lastOID = -1;
if ( values[0] != 0 )
{
lastOID = atoi(values[0]);
}
return 0;
}
/* -------------------------------------------------------------------------- */
AclManager::AclManager(SqlDB * _db) : db(_db), lastOID(-1)
{
ostringstream oss;
pthread_mutex_init(&mutex, 0);
set_callback(static_cast<Callbackable::Callback> (&AclManager::init_cb));
oss << "SELECT last_oid FROM pool_control WHERE tablename='" << table
<< "'";
db->exec(oss, this);
unset_callback();
if (lastOID == -1)
{
// Add a default rule
// @1 VM+NET+IMAGE+TEMPLATE/* CREATE+INFO_POOL_MINE
string error_str;
add_rule(0x200000001LL, 0x2d400000000LL, 0x41LL, error_str);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclManager::start()
{
return select();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
AclManager::~AclManager()
{
multimap<long long, AclRule *>::iterator it;
lock();
for ( it = acl_rules.begin(); it != acl_rules.end(); it++ )
{
delete it->second;
}
unlock();
pthread_mutex_destroy(&mutex);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
const bool AclManager::authorize(
int uid,
const set<int>& user_groups,
AuthRequest::Object obj_type,
int obj_id,
int obj_gid,
AuthRequest::Operation op)
{
ostringstream oss;
multimap<long long, AclRule *>::iterator it;
pair<multimap<long long, AclRule *>::iterator,
multimap<long long, AclRule *>::iterator> index;
bool auth = false;
// Build masks for request
long long user_req;
long long resource_oid_req;
if ( obj_id >= 0 )
{
resource_oid_req = obj_type | AclRule::INDIVIDUAL_ID | obj_id;
}
else
{
resource_oid_req = AclRule::NONE_ID;
}
long long resource_gid_req;
if ( obj_gid >= 0 )
{
resource_gid_req = obj_type | AclRule::GROUP_ID | obj_gid;
}
else
{
resource_gid_req = AclRule::NONE_ID;
}
long long resource_all_req = obj_type | AclRule::ALL_ID;
long long rights_req = op;
long long resource_oid_mask =
( obj_type | AclRule::INDIVIDUAL_ID | 0x00000000FFFFFFFFLL );
long long resource_gid_mask =
( obj_type | AclRule::GROUP_ID | 0x00000000FFFFFFFFLL );
// Create a temporal rule, to log the request
long long log_resource;
if ( obj_id >= 0 )
{
log_resource = resource_oid_req;
}
else if ( obj_gid >= 0 )
{
log_resource = resource_gid_req;
}
else
{
log_resource = resource_all_req;
}
AclRule log_rule(-1,
AclRule::INDIVIDUAL_ID | uid,
log_resource,
rights_req);
oss << "Request " << log_rule.to_str();
NebulaLog::log("ACL",Log::DEBUG,oss);
// ---------------------------------------------------
// Look for rules that apply to everyone
// ---------------------------------------------------
user_req = AclRule::ALL_ID;
auth = match_rules(user_req,
resource_oid_req,
resource_gid_req,
resource_all_req,
rights_req,
resource_oid_mask,
resource_gid_mask);
if ( auth == true )
{
return true;
}
// ---------------------------------------------------
// Look for rules that apply to the individual user id
// ---------------------------------------------------
user_req = AclRule::INDIVIDUAL_ID | uid;
auth = match_rules(user_req,
resource_oid_req,
resource_gid_req,
resource_all_req,
rights_req,
resource_oid_mask,
resource_gid_mask);
if ( auth == true )
{
return true;
}
// ----------------------------------------------------------
// Look for rules that apply to each one of the user's groups
// ----------------------------------------------------------
set<int>::iterator g_it;
for (g_it = user_groups.begin(); g_it != user_groups.end(); g_it++)
{
user_req = AclRule::GROUP_ID | *g_it;
auth = match_rules(user_req,
resource_oid_req,
resource_gid_req,
resource_all_req,
rights_req,
resource_oid_mask,
resource_gid_mask);
if ( auth == true )
{
return true;
}
}
oss.str("No more rules, permission not granted ");
NebulaLog::log("ACL",Log::DEBUG,oss);
return false;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool AclManager::match_rules(
long long user_req,
long long resource_oid_req,
long long resource_gid_req,
long long resource_all_req,
long long rights_req,
long long resource_oid_mask,
long long resource_gid_mask)
{
bool auth = false;
ostringstream oss;
multimap<long long, AclRule *>::iterator it;
pair<multimap<long long, AclRule *>::iterator,
multimap<long long, AclRule *>::iterator> index;
lock();
index = acl_rules.equal_range( user_req );
for ( it = index.first; it != index.second; it++)
{
oss.str("");
oss << "> Rule " << it->second->to_str();
NebulaLog::log("ACL",Log::DEBUG,oss);
auth =
// Rule grants the requested rights
( ( it->second->rights & rights_req ) == rights_req )
&&
(
// Rule grants permission for all objects of this type
( ( it->second->resource & resource_all_req ) == resource_all_req )
||
// Or rule's object type and group object ID match
( ( it->second->resource & resource_gid_mask ) == resource_gid_req )
||
// Or rule's object type and individual object ID match
( ( it->second->resource & resource_oid_mask ) == resource_oid_req )
);
if ( auth == true )
{
oss.str("Permission granted");
NebulaLog::log("ACL",Log::DEBUG,oss);
break;
}
}
unlock();
return auth;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclManager::add_rule(long long user, long long resource, long long rights,
string& error_str)
{
lock();
if (lastOID == INT_MAX)
{
lastOID = -1;
}
AclRule * rule = new AclRule(++lastOID, user, resource, rights);
ostringstream oss;
int rc;
multimap<long long, AclRule *>::iterator it;
pair<multimap<long long, AclRule *>::iterator,
multimap<long long, AclRule *>::iterator> index;
bool found = false;
index = acl_rules.equal_range( user );
for ( it = index.first; (it != index.second && !found); it++)
{
found = *(it->second) == *rule;
}
if ( found )
{
goto error_duplicated;
}
if ( rule->malformed(error_str) )
{
goto error_malformed;
}
rc = insert(rule);
if ( rc != 0 )
{
goto error_insert;
}
acl_rules.insert( make_pair(rule->user, rule) );
acl_rules_oids.insert( make_pair(rule->oid, rule) );
update_lastOID();
unlock();
return lastOID;
error_duplicated:
oss << "Rule " << rule->to_str() << " already exists";
rc = -1;
goto error_common;
error_malformed:
oss << "Rule " << rule->to_str() << " is malformed: " << error_str;
rc = -2;
goto error_common;
error_insert:
oss << "Error inserting rule in DB";
rc = -3;
goto error_common;
error_common:
error_str = oss.str();
delete rule;
lastOID--;
unlock();
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclManager::del_rule(int oid, string& error_str)
{
multimap<long long, AclRule *>::iterator it;
pair<multimap<long long, AclRule *>::iterator,
multimap<long long, AclRule *>::iterator> index;
AclRule * rule;
int rc;
bool found = false;
lock();
// Check the rule exists
found = acl_rules_oids.count(oid) > 0;
if ( !found )
{
ostringstream oss;
oss << "Rule " << oid << " does not exist";
error_str = oss.str();
unlock();
return -1;
}
rule = acl_rules_oids[oid];
// Look for it in the multimap
found = false;
index = acl_rules.equal_range( rule->user );
it = index.first;
while ( !found && it != index.second )
{
found = *rule == *(it->second);
if ( !found )
{
it++;
}
}
if ( !found )
{
ostringstream oss;
oss << "Internal error: ACL Rule " << oid
<< " indexed by oid, but not in by user attribute";
NebulaLog::log("ACL",Log::ERROR,oss);
unlock();
return -1;
}
rc = drop( oid );
if ( rc != 0 )
{
error_str = "SQL DB error";
unlock();
return -1;
}
delete it->second;
acl_rules.erase( it );
acl_rules_oids.erase( oid );
unlock();
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AclManager::bootstrap(SqlDB * _db)
{
ostringstream oss(db_bootstrap);
_db->exec(oss);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AclManager::update_lastOID()
{
// db->escape_str is not used for 'table' since its name can't be set in
// any way by the user, it is hardcoded.
ostringstream oss;
oss << "REPLACE INTO pool_control (tablename, last_oid) VALUES ("
<< "'" << table << "',"
<< lastOID << ")";
db->exec(oss);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclManager::select_cb(void *nil, int num, char **values, char **names)
{
if ( (num != 4) ||
(!values[0]) ||
(!values[1]) ||
(!values[2]) ||
(!values[3]) )
{
return -1;
}
ostringstream oss;
istringstream iss;
int oid = atoi(values[0]);
long long rule_values[3];
for ( int i = 0; i < 3; i++ )
{
iss.str( values[i+1] );
iss >> rule_values[i];
if ( iss.fail() == true )
{
return -1;
}
iss.clear();
}
AclRule * rule = new AclRule(oid,
rule_values[0],
rule_values[1],
rule_values[2]);
oss << "Loading ACL Rule " << rule->to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
acl_rules.insert( make_pair(rule->user, rule) );
acl_rules_oids.insert( make_pair(rule->oid, rule) );
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclManager::select()
{
ostringstream oss;
int rc;
oss << "SELECT " << db_names << " FROM " << table;
set_callback(static_cast<Callbackable::Callback>(&AclManager::select_cb));
rc = db->exec(oss,this);
unset_callback();
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclManager::insert(AclRule * rule, SqlDB * db)
{
ostringstream oss;
int rc;
// Construct the SQL statement to Insert
oss << "INSERT INTO " << table <<" ("<< db_names <<") VALUES ("
<< rule->oid << ","
<< rule->user << ","
<< rule->resource << ","
<< rule->rights << ")";
rc = db->exec(oss);
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclManager::drop(int oid)
{
ostringstream oss;
int rc;
oss << "DELETE FROM " << table << " WHERE "
<< "oid=" << oid;
rc = db->exec(oss);
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclManager::dump(ostringstream& oss)
{
map<int, AclRule *>::iterator it;
string xml;
lock();
oss << "<ACL_POOL>";
for ( it = acl_rules_oids.begin() ; it != acl_rules_oids.end(); it++ )
{
oss << it->second->to_xml(xml);
}
oss << "</ACL_POOL>";
unlock();
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

403
src/acl/AclRule.cc Normal file
View File

@ -0,0 +1,403 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 "AclRule.h"
#include "AuthManager.h"
#include "ObjectXML.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
const long long AclRule::INDIVIDUAL_ID = 0x0000000100000000LL;
const long long AclRule::GROUP_ID = 0x0000000200000000LL;
const long long AclRule::ALL_ID = 0x0000000400000000LL;
const long long AclRule::NONE_ID = 0x1000000000000000LL;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool AclRule::malformed(string& error_str) const
{
ostringstream oss;
bool error = false;
// Check user
if ( (user & INDIVIDUAL_ID) != 0 && (user & GROUP_ID) != 0 )
{
error = true;
oss << "[user] INDIVIDUAL (#) and GROUP (@) bits are exclusive";
}
if ( (user & INDIVIDUAL_ID) != 0 && (user & ALL_ID) != 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[user] INDIVIDUAL (#) and ALL (*) bits are exclusive";
}
if ( (user & GROUP_ID) != 0 && (user & ALL_ID) != 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[user] GROUP (@) and ALL (*) bits are exclusive";
}
if ( (user & 0x700000000LL) == 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[user] is missing one of the INDIVIDUAL, GROUP or ALL bits";
}
if ( user_id() < 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[user] ID cannot be negative";
}
if ( (user & ALL_ID) != 0 && user_id() != 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "when using the ALL bit, [user] ID must be 0";
}
// Check resource
if ( (resource & INDIVIDUAL_ID) != 0 && (resource & GROUP_ID) != 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[resource] INDIVIDUAL (#) and GROUP (@) bits are exclusive";
}
if ( (resource & INDIVIDUAL_ID) != 0 && (resource & ALL_ID) != 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[resource] INDIVIDUAL (#) and ALL (*) bits are exclusive";
}
if ( (resource & GROUP_ID) != 0 && (resource & ALL_ID) != 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[resource] GROUP (@) and ALL (*) bits are exclusive";
}
if ( (resource & 0x700000000LL) == 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[resource] is missing one of the INDIVIDUAL, GROUP or ALL bits";
}
if ( resource_id() < 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[resource] ID cannot be negative";
}
if ( (resource & ALL_ID) != 0 && resource_id() != 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "when using the ALL bit, [resource] ID must be 0";
}
if ( (resource & 0xFF000000000LL) == 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "[resource] type is missing";
}
if ( (resource & 0xFFFFF00000000000LL) != 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "wrong [resource] type";
}
// Check rights
if ( rights == 0 )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "wrong [rights], it cannot be 0";
}
if ( rights > 0x1FFLL )
{
if ( error )
{
oss << "; ";
}
error = true;
oss << "wrong [rights], it cannot be bigger than 0x1FF";
}
if ( error )
{
error_str = oss.str();
}
return error;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AclRule::build_str()
{
ostringstream oss;
if ( (user & GROUP_ID) != 0 )
{
oss << "@" << user_id();
}
else if ( (user & INDIVIDUAL_ID) != 0 )
{
oss << "#" << user_id();
}
else if ( (user & ALL_ID) != 0 )
{
oss << "*";
}
else
{
oss << "??";
}
oss << " ";
AuthRequest::Object objects[] = {
AuthRequest::VM,
AuthRequest::HOST,
AuthRequest::NET,
AuthRequest::IMAGE,
AuthRequest::USER,
AuthRequest::TEMPLATE,
AuthRequest::GROUP
};
bool prefix = false;
for ( int i = 0; i < 7; i++ )
{
if ( (resource & objects[i]) != 0 )
{
if ( prefix )
{
oss << "+";
}
oss << AuthRequest::Object_to_str( objects[i] );
prefix = true;
}
}
oss << "/";
if ( (resource & GROUP_ID) != 0 )
{
oss << "@" << resource_id();
}
else if ( (resource & INDIVIDUAL_ID) != 0 )
{
oss << "#" << resource_id();
}
else if ( (resource & ALL_ID) != 0 )
{
oss << "*";
}
else
{
oss << "??";
}
oss << " ";
AuthRequest::Operation operations[] = {
AuthRequest::CREATE,
AuthRequest::DELETE,
AuthRequest::USE,
AuthRequest::MANAGE,
AuthRequest::INFO,
AuthRequest::INFO_POOL,
AuthRequest::INFO_POOL_MINE,
AuthRequest::INSTANTIATE,
AuthRequest::CHOWN
};
prefix = false;
for ( int i = 0; i < 9; i++ )
{
if ( (rights & operations[i]) != 0 )
{
if ( prefix )
{
oss << "+";
}
oss << AuthRequest::Operation_to_str( operations[i] );
prefix = true;
}
}
str = oss.str();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& AclRule::to_xml(string& xml) const
{
ostringstream oss;
oss <<
"<ACL>"
"<ID>" << oid << "</ID>" <<
"<USER>" << hex << user << "</USER>" <<
"<RESOURCE>" << hex << resource << "</RESOURCE>" <<
"<RIGHTS>" << hex << rights << "</RIGHTS>" <<
"<STRING>" << str << "</STRING>" <<
"</ACL>";
xml = oss.str();
return xml;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclRule::from_xml(xmlNodePtr node)
{
int rc = 0;
for (xmlNodePtr acl = node->children ; acl != 0 ; acl = acl->next)
{
if ( acl->type != XML_ELEMENT_NODE )
{
rc = -1;
break;
}
xmlNodePtr elem = acl->children;
if ( elem->type != XML_TEXT_NODE )
{
rc = -1;
break;
}
string name = reinterpret_cast<const char*>(acl->name);
istringstream iss(reinterpret_cast<const char*>(elem->content));
if (name == "ID")
{
iss >> oid;
}
else if (name == "USER")
{
iss >> hex >> user;
}
else if (name == "RESOURCE")
{
iss >> hex >> resource;
}
else if (name == "RIGHTS")
{
iss >> hex >> rights;
}
else if (name == "STRING")
{
str = iss.str();
}
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

30
src/acl/SConstruct Normal file
View File

@ -0,0 +1,30 @@
# SConstruct for src/authm
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, 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. #
#--------------------------------------------------------------------------- #
Import('env')
lib_name='nebula_acl'
# Sources to generate the library
source_files=[
'AclManager.cc',
'AclRule.cc'
]
# Build library
env.StaticLibrary(lib_name, source_files)

View File

@ -32,6 +32,7 @@ const char * AuthManager::auth_driver_name = "auth_exe";
void AuthRequest::add_auth(Object ob,
const string& ob_id,
int ob_gid,
Operation op,
int owner,
bool pub)
@ -39,16 +40,9 @@ void AuthRequest::add_auth(Object ob,
ostringstream oss;
bool auth;
switch (ob)
{
case VM: oss << "VM:" ; break;
case HOST: oss << "HOST:" ; break;
case NET: oss << "NET:" ; break;
case IMAGE: oss << "IMAGE:" ; break;
case USER: oss << "USER:" ; break;
case TEMPLATE: oss << "TEMPLATE:" ; break;
case GROUP: oss << "GROUP:" ; break;
}
int ob_id_int = -1;
oss << Object_to_str(ob) << ":";
if (op == CREATE || op == INSTANTIATE) //encode the ob_id, it is a template
{
@ -67,130 +61,51 @@ void AuthRequest::add_auth(Object ob,
else
{
oss << ob_id << ":";
istringstream iss(ob_id);
iss >> ob_id_int;
}
switch (op)
{
case CREATE:
oss << "CREATE:" ;
break;
oss << Operation_to_str(op) << ":";
case DELETE:
oss << "DELETE:" ;
break;
case USE:
oss << "USE:" ;
break;
case MANAGE:
oss << "MANAGE:" ;
break;
case INFO:
oss << "INFO:" ;
break;
case INFO_POOL:
oss << "INFO_POOL:" ;
break;
case INFO_POOL_MINE:
oss << "INFO_POOL_MINE:" ;
break;
case INSTANTIATE:
oss << "INSTANTIATE:" ;
break;
case CHOWN:
oss << "CHOWN:" ;
break;
}
oss << owner << ":" << pub;
oss << owner << ":" << pub << ":";
// -------------------------------------------------------------------------
// Authorize the request for self authorization
// -------------------------------------------------------------------------
if ( uid == 0 )
// There are some default conditions that grant permission without
// consulting the ACL manager
if (
// User is oneadmin, or is in the oneadmin group
uid == 0 ||
gids.count( GroupPool::ONEADMIN_ID ) == 1 ||
// User is the owner of the object, for certain operations
( owner == uid &&
( op == DELETE || op == USE || op == MANAGE ||
op == INFO || op == INSTANTIATE )
) ||
// Object is public and user is in its group, for certain operations
( pub && ( gids.count( ob_gid ) == 1 ) &&
(op == USE || op == INSTANTIATE || op == INFO ) &&
(ob == NET || ob == IMAGE || ob == TEMPLATE)
)
)
{
auth = true;
}
else
{
auth = false;
Nebula& nd = Nebula::instance();
AclManager* aclm = nd.get_aclm();
switch (op)
{
case CREATE:
if ( ob == VM || ob == NET || ob == IMAGE || ob == TEMPLATE )
{
auth = true;
}
break;
case INSTANTIATE:
if ( ob == VM )
{
auth = true;
}
break;
case DELETE:
auth = owner == uid;
break;
case USE:
if (ob == NET || ob == IMAGE || ob == TEMPLATE)
{
auth = (owner == uid) || pub;
}
else if (ob == HOST)
{
auth = true;
}
break;
case MANAGE:
auth = owner == uid;
break;
case INFO:
if ( ob != USER ) // User info only for root or owner
{
auth = true;
}
else
{
istringstream iss(ob_id);
int ob_id_int;
iss >> ob_id_int;
if (ob_id_int == uid)
{
auth = true;
}
}
break;
case INFO_POOL:
if ( ob != USER ) // User pool only for oneadmin
{
auth = true;
}
break;
case INFO_POOL_MINE:
auth = true;
break;
case CHOWN: //true only for oneadmin
break;
}
auth = aclm->authorize(uid, gids, ob, ob_id_int, ob_gid, op);
}
oss << auth; // Store the ACL authorization result in the request
self_authorize = self_authorize && auth;
auths.push_back(oss.str());

View File

@ -20,6 +20,8 @@
#include <unistd.h>
#include <pthread.h>
#include "Nebula.h"
#include "NebulaTest.h"
#include "test/OneUnitTest.h"
#include "AuthManager.h"
#include "Template.h"
@ -34,11 +36,45 @@ using namespace std;
/* ************************************************************************* */
/* ************************************************************************* */
class NebulaTestAuth: public NebulaTest
{
public:
NebulaTestAuth():NebulaTest()
{
NebulaTest::the_tester = this;
need_authm = true;
need_aclm = true;
};
AuthManager* create_authm(time_t timer_period)
{
ostringstream oss;
vector<const Attribute *> am_mads;
char *error = 0;
oss << "AUTH_MAD = [ executable=\"/" << getenv("PWD")
<< "/dummy\"]" << endl;
Template * t = new Template();
t->parse(oss.str(),&error);
t->get("AUTH_MAD", am_mads);
return new AuthManager(1,3,am_mads);
};
};
/* ************************************************************************* */
/* ************************************************************************* */
class AuthManagerTest : public OneUnitTest
{
CPPUNIT_TEST_SUITE (AuthManagerTest);
CPPUNIT_TEST (load);
CPPUNIT_TEST (timeout);
CPPUNIT_TEST (authenticate);
CPPUNIT_TEST (authorize);
@ -48,75 +84,70 @@ class AuthManagerTest : public OneUnitTest
CPPUNIT_TEST_SUITE_END ();
private:
NebulaTestAuth * tester;
AuthManager * am;
public:
AuthManagerTest(){};
AuthManagerTest()
{
xmlInitParser();
};
~AuthManagerTest(){
/*OpenSSL internal tables are allocated when an application starts up.
Since such tables do not grow in size over time they are harmless. */
~AuthManagerTest()
{
xmlCleanupParser();
EVP_cleanup() ;
CRYPTO_cleanup_all_ex_data();
// OpenSSL internal tables are allocated when an application starts up.
// Since such tables do not grow in size over time they are harmless.
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
};
/* ********************************************************************* */
/* ********************************************************************* */
void setUp()
{
create_db();
ostringstream oss;
vector<const Attribute *> am_mads;
char *error = 0;
tester = new NebulaTestAuth();
MadManager::mad_manager_system_init();
Nebula& neb = Nebula::instance();
neb.start();
oss << "AUTH_MAD = [ executable=\"/" << getenv("PWD")
<< "/dummy\"]" << endl;
t = new Template();
t->parse(oss.str(),&error);
t->get("AUTH_MAD", am_mads);
am = new AuthManager(1,3,am_mads);
am = neb.get_authm();
};
void tearDown()
{
delete am;
delete t;
};
void load()
{
int rc;
rc = am->start();
CPPUNIT_ASSERT(rc==0);
am->load_mads(0);
// -----------------------------------------------------------
// Stop the managers & free resources
// -----------------------------------------------------------
am->trigger(AuthManager::FINALIZE,0);
pthread_join(am->get_thread_id(),0);
CPPUNIT_ASSERT(0==0);
}
//XML Library
xmlCleanupParser();
delete_db();
delete tester;
};
/* ********************************************************************* */
/* ********************************************************************* */
//This test needs a driver that takes more than 3 secs to AUTHENTICATE
void timeout()
{
int rc;
AuthRequest ar(2);
rc = am->start();
CPPUNIT_ASSERT(rc==0);
am->load_mads(0);
set<int> empty_set;
AuthRequest ar(2, empty_set);
ar.add_authenticate("timeout","the_pass","the_secret");
@ -128,24 +159,12 @@ public:
CPPUNIT_ASSERT(ar.timeout==true);
am->discard_request(ar.id);
am->trigger(AuthManager::FINALIZE,0);
pthread_join(am->get_thread_id(),0);
CPPUNIT_ASSERT(0==0);
}
void authenticate()
{
int rc;
AuthRequest ar(2);
rc = am->start();
CPPUNIT_ASSERT(rc==0);
am->load_mads(0);
set<int> empty_set;
AuthRequest ar(2, empty_set);
ar.add_authenticate("the_user","the_pass","the_secret");
@ -153,53 +172,45 @@ public:
ar.wait();
CPPUNIT_ASSERT(ar.result==true);
am->trigger(AuthManager::FINALIZE,0);
pthread_join(am->get_thread_id(),0);
CPPUNIT_ASSERT(0==0);
}
void authorize()
{
int rc;
AuthRequest ar(2);
set<int> empty_set;
AuthRequest ar(2, empty_set);
rc = am->start();
//OBJECT:OBJECT_ID:ACTION:OWNER:PUBLIC:CORE_RESULT
CPPUNIT_ASSERT(rc==0);
am->load_mads(0);
//OBJECT:OBJECT_ID:ACTION:OWNER:PUBLIC
string astr="VM:VGhpcyBpcyBhIHRlbXBsYXRlCg==:CREATE:-1:0 "
"IMAGE:2:USE:3:0 "
"NET:4:DELETE:5:1 "
"HOST:6:MANAGE:7:1";
string astr = "VM:VGhpcyBpcyBhIHRlbXBsYXRlCg==:CREATE:-1:0:0 "
"IMAGE:2:USE:3:0:0 "
"NET:4:DELETE:5:1:0 "
"HOST:6:MANAGE:7:1:0";
ar.add_auth(AuthRequest::VM,
"This is a template\n",
0,
AuthRequest::CREATE,
-1,
false);
ar.add_auth(AuthRequest::IMAGE,
2,
0,
AuthRequest::USE,
3,
false);
ar.add_auth(AuthRequest::NET,
4,
0,
AuthRequest::DELETE,
5,
true);
ar.add_auth(AuthRequest::HOST,
6,
0,
AuthRequest::MANAGE,
7,
true);
@ -207,59 +218,71 @@ public:
am->trigger(AuthManager::AUTHORIZE,&ar);
ar.wait();
/*
if ( ar.result != false )
{
cout << endl << "ar.result: " << ar.result << endl;
}
if ( ar.message != astr )
{
cout << endl << "ar.message: " << ar.message;
cout << endl << "expected: " << astr << endl;
}
//*/
CPPUNIT_ASSERT(ar.result==false);
CPPUNIT_ASSERT(ar.message==astr);
am->trigger(AuthManager::FINALIZE,0);
pthread_join(am->get_thread_id(),0);
CPPUNIT_ASSERT(0==0);
}
void self_authorize()
{
AuthRequest ar(2);
AuthRequest ar1(2);
AuthRequest ar2(3);
AuthRequest ar3(4);
AuthRequest ar4(2);
AuthRequest ar5(0);
AuthRequest ar6(0);
// Make all users belong to the USERS (1) group
set<int> gid_set;
gid_set.insert(1);
ar.add_auth(AuthRequest::VM,"dGhpcy",AuthRequest::CREATE,2,false);
ar.add_auth(AuthRequest::NET,2,AuthRequest::USE,2,false);
ar.add_auth(AuthRequest::IMAGE,3,AuthRequest::USE,4,true);
AuthRequest ar(2, gid_set);
AuthRequest ar1(2, gid_set);
AuthRequest ar2(3, gid_set);
AuthRequest ar3(4, gid_set);
AuthRequest ar4(2, gid_set);
AuthRequest ar5(0, gid_set);
AuthRequest ar6(0, gid_set);
ar.add_auth(AuthRequest::VM,"dGhpcy",-1,AuthRequest::CREATE,2,false);
ar.add_auth(AuthRequest::NET,2,1,AuthRequest::USE,2,false);
ar.add_auth(AuthRequest::IMAGE,3,1,AuthRequest::USE,4,true);
CPPUNIT_ASSERT(ar.plain_authorize() == true);
ar1.add_auth(AuthRequest::VM,"dGhpcy",AuthRequest::CREATE,2,false);
ar1.add_auth(AuthRequest::NET,2,AuthRequest::USE,2,false);
ar1.add_auth(AuthRequest::IMAGE,3,AuthRequest::USE,4,false);
ar1.add_auth(AuthRequest::VM,"dGhpcy",-1,AuthRequest::CREATE,2,false);
ar1.add_auth(AuthRequest::NET,2,1,AuthRequest::USE,2,false);
ar1.add_auth(AuthRequest::IMAGE,3,1,AuthRequest::USE,4,false);
CPPUNIT_ASSERT(ar1.plain_authorize() == false);
ar2.add_auth(AuthRequest::HOST,"dGhpcy",AuthRequest::CREATE,0,false);
ar2.add_auth(AuthRequest::HOST,"dGhpcy",-1,AuthRequest::CREATE,0,false);
CPPUNIT_ASSERT(ar2.plain_authorize() == false);
ar3.add_auth(AuthRequest::VM,5,AuthRequest::MANAGE,2,false);
ar3.add_auth(AuthRequest::VM,5,1,AuthRequest::MANAGE,2,false);
CPPUNIT_ASSERT(ar3.plain_authorize() == false);
ar4.add_auth(AuthRequest::VM,4,AuthRequest::MANAGE,2,false);
ar4.add_auth(AuthRequest::VM,4,1,AuthRequest::MANAGE,2,false);
CPPUNIT_ASSERT(ar4.plain_authorize() == true);
ar5.add_auth(AuthRequest::HOST,4,AuthRequest::MANAGE,0,false);
ar5.add_auth(AuthRequest::HOST,4,-1,AuthRequest::MANAGE,0,false);
CPPUNIT_ASSERT(ar5.plain_authorize() == true);
ar6.add_auth(AuthRequest::HOST,4,AuthRequest::CREATE,0,false);
ar6.add_auth(AuthRequest::HOST,4,-1,AuthRequest::CREATE,0,false);
CPPUNIT_ASSERT(ar6.plain_authorize() == true);
}
void self_authenticate()
{
AuthRequest ar(2);
AuthRequest ar1(2);
set<int> empty_set;
AuthRequest ar(2, empty_set);
AuthRequest ar1(2,empty_set);
ar.add_authenticate("the_user","the_pass","the_secret");
CPPUNIT_ASSERT(ar.plain_authenticate() == false);
@ -267,11 +290,6 @@ public:
ar1.add_authenticate("the_user","the_pass","the_pass");
CPPUNIT_ASSERT(ar1.plain_authenticate() == true);
}
private:
AuthManager * am;
Template * t;
};

View File

@ -16,13 +16,30 @@
Import('env')
env.Prepend(LIBS=[
'nebula_template',
'nebula_core_test',
'nebula_vmm',
'nebula_lcm',
'nebula_im',
'nebula_hm',
'nebula_rm',
'nebula_dm',
'nebula_tm',
'nebula_um',
'nebula_authm',
'nebula_common',
'nebula_core',
'nebula_group',
'nebula_acl',
'nebula_mad',
'nebula_template',
'nebula_image',
'nebula_pool',
'nebula_host',
'nebula_vnm',
'nebula_vm',
'nebula_vmtemplate',
'nebula_common',
'nebula_sql',
'nebula_log',
'nebula_xml',
'crypto'
])

31
src/cli/etc/oneacl.yaml Normal file
View File

@ -0,0 +1,31 @@
---
:ID:
:desc: To which resource owner the rule applies to
:size: 5
:right: true
:USER:
:desc: To which resource owner the rule applies to
:size: 8
:right: true
:RES_VHNIUTG:
:desc: Which resource the rule applies to
:size: 11
:RID:
:desc: Resource ID
:size: 5
:right: true
:OPE_CDUMIPpTW:
:desc: Operation to which the rule applies
:size: 13
:right: true
:default:
- :ID
- :USER
- :RES_VHNIUTG
- :RID
- :OPE_CDUMIPpTW

View File

@ -0,0 +1,133 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, 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. #
#--------------------------------------------------------------------------- #
require 'one_helper'
class OneAclHelper < OpenNebulaHelper::OneHelper
def self.rname
"ACL"
end
def self.conf_file
"oneacl.yaml"
end
private
def factory(id = nil)
if id
OpenNebula::Acl.new_with_id(id, @client)
else
xml = OpenNebula::Acl.build_xml
OpenNebula::Acl.new(xml, @client)
end
end
def factory_pool(filter)
OpenNebula::AclPool.new(@client)
end
# TODO check that @content[:resources_str] is valid
def self.resource_mask(str)
resource_type=str.split("/")[0]
mask = "-------"
resource_type.split("+").each{|type|
case type
when "VM"
mask[0] = "V"
when "HOST"
mask[1] = "H"
when "NET"
mask[2] = "N"
when "IMAGE"
mask[3] = "I"
when "USER"
mask[4] = "U"
when "TEMPLATE"
mask[5] = "T"
when "GROUP"
mask[6] = "G"
end
}
mask
end
# TODO check that @content[:resources_str] is valid
def self.right_mask(str)
mask = "---------"
str.split("+").each{|type|
case type
when "CREATE"
mask[0] = "C"
when "DELETE"
mask[1] = "D"
when "USE"
mask[2] = "U"
when "MANAGE"
mask[3] = "M"
when "INFO"
mask[4] = "I"
when "INFO_POOL"
mask[5] = "P"
when "INFO_POOL_MINE"
mask[6] = "p"
when "INSTANTIATE"
mask[8] = "T"
when "CHOWN"
mask[9] = "W"
end
}
mask
end
def format_pool(pool, options, top=false)
config_file=self.class.table_conf
table=CLIHelper::ShowTable.new(config_file, self) do
column :ID, "Rule Identifier",
:size=>5 do |d|
d['ID']
end
column :USER, "To which resource owner the rule applies to",
:size=>8 do |d|
d['STRING'].split(" ")[0]
end
column :RES_VHNIUTG, "Resource to which the rule applies" do |d|
OneAclHelper::resource_mask d['STRING'].split(" ")[1]
end
column :RID, "Resource ID", :right, :size=>8 do |d|
d['STRING'].split(" ")[1].split("/")[1]
end
column :OPE_CDUMIPpTW, "Operation to which the rule applies" do |d|
OneAclHelper::right_mask d['STRING'].split(" ")[2]
end
default :ID, :USER, :RES_VHNIUTG, :RID, :OPE_CDUMIPpTW
end
table.show(pool, options)
end
end

105
src/cli/oneacl Executable file
View File

@ -0,0 +1,105 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, 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. #
#--------------------------------------------------------------------------- #
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/oneacl_helper'
cmd = CommandParser::CmdParser.new(ARGV) do
usage "oneacl COMMAND [args..] [options..]"
version OpenNebulaHelper::ONE_VERSION
helper = OneAclHelper.new
########################################################################
# Global Options
########################################################################
set :option, CommandParser::OPTIONS
########################################################################
# Formatters for arguments
########################################################################
set :format, :aclid_list, OneAclHelper.list_to_id_desc do |arg|
helper.list_to_id(arg)
end
########################################################################
# Commands
########################################################################
addrule_desc = <<-EOT.unindent
Adds a new ACL rule
EOT
command :create, addrule_desc, [:user,:rulestr], [:resource, nil], [:rights, nil] do
case args.length
when 1
new_args=Acl.parse_rule(args[0])
when 3
new_args=args
else
next -1, "Wrong number of arguments, must be 1 or 3"
end
errors=new_args.map do |arg|
if OpenNebula.is_error?(arg)
arg.message
else
nil
end
end
errors.compact!
if errors.length>0
next -1, errors.join(', ')
end
helper.create_resource(options) do |rule|
rule.allocate(*new_args)
end
end
delrule_desc = <<-EOT.unindent
Deletes an existing ACL rule
EOT
command :delete, delrule_desc, [:range] do
helper.perform_actions(args[0],options,"deleted") do |obj|
obj.delete
end
end
list_desc = <<-EOT.unindent
Lists the ACL rule set
EOT
command :list, list_desc,:options=>OpenNebulaHelper::XML do
helper.list_pool( options )
end
end

View File

@ -129,7 +129,7 @@ int Group::from_xml(const string& xml)
// Get associated classes
ObjectXML::get_nodes("/GROUP/USERS", content);
if( content.size() < 1 )
if (content.empty())
{
return -1;
}
@ -137,6 +137,8 @@ int Group::from_xml(const string& xml)
// Set of IDs
rc += ObjectCollection::from_xml_node(content[0]);
ObjectXML::free_nodes(content);
if (rc != 0)
{
return -1;

View File

@ -44,6 +44,7 @@ env.Prepend(LIBS=[
'nebula_pool',
'nebula_hm',
'nebula_authm',
'nebula_acl',
'nebula_common',
'nebula_lcm',
'nebula_dm',

View File

@ -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),
@ -240,24 +240,27 @@ int Host::from_xml(const string& xml)
// Get associated classes
ObjectXML::get_nodes("/HOST/HOST_SHARE", content);
if( content.size() < 1 )
if (content.empty())
{
return -1;
}
rc += host_share.from_xml_node( content[0] );
ObjectXML::free_nodes(content);
content.clear();
ObjectXML::get_nodes("/HOST/TEMPLATE", content);
if( content.size() < 1 )
if( content.empty())
{
return -1;
}
rc += obj_template->from_xml_node( content[0] );
ObjectXML::free_nodes(content);
if (rc != 0)
{
return -1;

View File

@ -37,6 +37,7 @@ env.Prepend(LIBS=[
'nebula_pool',
'nebula_hm',
'nebula_authm',
'nebula_acl',
'nebula_common',
'nebula_lcm',
'nebula_dm',

View File

@ -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);
@ -374,13 +382,16 @@ int Image::from_xml(const string& xml)
// Get associated classes
ObjectXML::get_nodes("/IMAGE/TEMPLATE", content);
if( content.size() < 1 )
if (content.empty())
{
return -1;
}
rc += obj_template->from_xml_node(content[0]);
ObjectXML::free_nodes(content);
if (rc != 0)
{
return -1;

View File

@ -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);
@ -252,6 +254,7 @@ void ImagePool::authorize_disk(VectorAttribute * disk,int uid, AuthRequest * ar)
ar->add_auth(AuthRequest::IMAGE,
img->get_oid(),
img->get_gid(),
AuthRequest::USE,
img->get_uid(),
img->isPublic());

View File

@ -25,6 +25,10 @@ using namespace std;
const int uids[] = {0,1,2};
const char* unames[] = {"one","two","three"};
const char* gnames[] = {"oneadmin","oneadmin","users"};
const string names[] = {"Image one", "Second Image", "The third image"};
const string templates[] =
@ -49,20 +53,19 @@ const string templates[] =
const string xmls[] =
{
"<IMAGE><ID>0</ID><UID>0</UID><GID>1</GID><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Image one]]></NAME><PATH><![CDATA[/tmp/image_test]]></PATH></TEMPLATE></IMAGE>",
"<IMAGE><ID>0</ID><UID>0</UID><GID>1</GID><UNAME>one</UNAME><GNAME>oneadmin</GNAME><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Image one]]></NAME><PATH><![CDATA[/tmp/image_test]]></PATH></TEMPLATE></IMAGE>",
"<IMAGE><ID>1</ID><UID>1</UID><GID>1</GID><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a rather short description.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Second Image]]></NAME><PATH><![CDATA[/tmp/image_second_test]]></PATH></TEMPLATE></IMAGE>",
"<IMAGE><ID>1</ID><UID>1</UID><GID>1</GID><UNAME>two</UNAME><GNAME>oneadmin</GNAME><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a rather short description.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Second Image]]></NAME><PATH><![CDATA[/tmp/image_second_test]]></PATH></TEMPLATE></IMAGE>",
"<IMAGE><ID>0</ID><UID>2</UID><GID>1</GID><NAME>The third image</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><BUS><![CDATA[SCSI]]></BUS><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[The third image]]></NAME><PATH><![CDATA[/tmp/image_test]]></PATH><PROFILE><![CDATA[STUDENT]]></PROFILE></TEMPLATE></IMAGE>"
"<IMAGE><ID>0</ID><UID>2</UID><GID>1</GID><UNAME>three</UNAME><GNAME>users</GNAME><NAME>The third image</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><BUS><![CDATA[SCSI]]></BUS><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[The third image]]></NAME><PATH><![CDATA[/tmp/image_test]]></PATH><PROFILE><![CDATA[STUDENT]]></PROFILE></TEMPLATE></IMAGE>"
};
// This xml dump result has the STIMEs modified to 0000000000
const string xml_dump =
"<IMAGE_POOL><IMAGE><ID>0</ID><UID>0</UID><GID>1</GID><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Image one]]></NAME><PATH><![CDATA[/tmp/image_test]]></PATH></TEMPLATE></IMAGE><IMAGE><ID>1</ID><UID>1</UID><GID>1</GID><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a rather short description.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Second Image]]></NAME><PATH><![CDATA[/tmp/image_second_test]]></PATH></TEMPLATE></IMAGE><IMAGE><ID>2</ID><UID>2</UID><GID>1</GID><NAME>The third image</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><BUS><![CDATA[SCSI]]></BUS><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[The third image]]></NAME><PATH><![CDATA[/tmp/image_test]]></PATH><PROFILE><![CDATA[STUDENT]]></PROFILE></TEMPLATE></IMAGE></IMAGE_POOL>";
"<IMAGE_POOL><IMAGE><ID>0</ID><UID>0</UID><GID>1</GID><UNAME>one</UNAME><GNAME>oneadmin</GNAME><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Image one]]></NAME><PATH><![CDATA[/tmp/image_test]]></PATH></TEMPLATE></IMAGE><IMAGE><ID>1</ID><UID>1</UID><GID>1</GID><UNAME>two</UNAME><GNAME>oneadmin</GNAME><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a rather short description.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Second Image]]></NAME><PATH><![CDATA[/tmp/image_second_test]]></PATH></TEMPLATE></IMAGE><IMAGE><ID>2</ID><UID>2</UID><GID>1</GID><UNAME>three</UNAME><GNAME>users</GNAME><NAME>The third image</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><BUS><![CDATA[SCSI]]></BUS><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[The third image]]></NAME><PATH><![CDATA[/tmp/image_test]]></PATH><PROFILE><![CDATA[STUDENT]]></PROFILE></TEMPLATE></IMAGE></IMAGE_POOL>";
const string xml_dump_where =
"<IMAGE_POOL><IMAGE><ID>0</ID><UID>0</UID><GID>1</GID><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Image one]]></NAME><PATH><![CDATA[/tmp/image_test]]></PATH></TEMPLATE></IMAGE><IMAGE><ID>1</ID><UID>1</UID><GID>1</GID><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a rather short description.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Second Image]]></NAME><PATH><![CDATA[/tmp/image_second_test]]></PATH></TEMPLATE></IMAGE></IMAGE_POOL>";
"<IMAGE_POOL><IMAGE><ID>0</ID><UID>0</UID><GID>1</GID><UNAME>one</UNAME><GNAME>oneadmin</GNAME><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Image one]]></NAME><PATH><![CDATA[/tmp/image_test]]></PATH></TEMPLATE></IMAGE><IMAGE><ID>1</ID><UID>1</UID><GID>1</GID><UNAME>two</UNAME><GNAME>oneadmin</GNAME><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a rather short description.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Second Image]]></NAME><PATH><![CDATA[/tmp/image_second_test]]></PATH></TEMPLATE></IMAGE></IMAGE_POOL>";
/* ************************************************************************* */
/* ************************************************************************* */
@ -106,7 +109,10 @@ public:
if( rc == 0 )
{
return ImagePool::allocate(uid, 1, img_template, oid, err);
string uname = unames[uid];
string gname = gnames[uid];
return ImagePool::allocate(uid, 1, uname, gname, img_template, oid, err);
}
else
{

View File

@ -36,6 +36,7 @@ env.Prepend(LIBS=[
'nebula_pool',
'nebula_hm',
'nebula_authm',
'nebula_acl',
'nebula_common',
'nebula_lcm',
'nebula_dm',

View File

@ -24,6 +24,9 @@ using namespace std;
const int uids[] = {123, 261, 123};
const int gids[] = {150, 164, 175};
const char* unames[] = {"one", "two", "three"};
const char* gnames[] = {"oneadmin", "oneadmin", "users"};
const string names[] = {"VM one", "Second VM", "VM 3"};
const string templates[] =
@ -186,8 +189,17 @@ private:
if( rc == 0 )
{
return vmpool->allocate(uids[index], gids[index], vm_template, &oid,
err, false);
string uname = unames[index];
string gname = gnames[index];
return vmpool->allocate(uids[index],
gids[index],
uname,
gname,
vm_template,
&oid,
err,
false);
}
else
{

View File

@ -36,6 +36,7 @@ env.Prepend(LIBS=[
'nebula_xml',
'nebula_hm',
'nebula_authm',
'nebula_acl',
'nebula_common',
'nebula_sql',
'nebula_log',

View File

@ -251,6 +251,7 @@ void Nebula::start()
UserPool::bootstrap(db);
ImagePool::bootstrap(db);
VMTemplatePool::bootstrap(db);
AclManager::bootstrap(db);
}
}
catch (exception&)
@ -445,28 +446,6 @@ void Nebula::start()
throw runtime_error("Could not start the Dispatch Manager");
}
// ---- Request Manager ----
try
{
int rm_port = 0;
nebula_configuration->get("PORT", rm_port);
rm = new RequestManager(rm_port, log_location + "one_xmlrpc.log");
}
catch (bad_alloc&)
{
NebulaLog::log("ONE", Log::ERROR, "Error starting RM");
throw;
}
rc = rm->start();
if ( rc != 0 )
{
throw runtime_error("Could not start the Request Manager");
}
// ---- Hook Manager ----
try
{
@ -520,6 +499,23 @@ void Nebula::start()
}
}
// ---- ACL Manager ----
try
{
aclm = new AclManager(db);
}
catch (bad_alloc&)
{
throw;
}
rc = aclm->start();
if ( rc != 0 )
{
throw runtime_error("Could not start the ACL Manager");
}
// ---- Image Manager ----
try
{
@ -541,6 +537,28 @@ void Nebula::start()
throw runtime_error("Could not start the Image Manager");
}
// ---- Request Manager ----
try
{
int rm_port = 0;
nebula_configuration->get("PORT", rm_port);
rm = new RequestManager(rm_port, log_location + "one_xmlrpc.log");
}
catch (bad_alloc&)
{
NebulaLog::log("ONE", Log::ERROR, "Error starting RM");
throw;
}
rc = rm->start();
if ( rc != 0 )
{
throw runtime_error("Could not start the Request Manager");
}
// -----------------------------------------------------------
// Load mads
// -----------------------------------------------------------

View File

@ -43,6 +43,7 @@ env.Prepend(LIBS=[
'nebula_um',
'nebula_group',
'nebula_authm',
'nebula_acl',
'nebula_mad',
'nebula_template',
'nebula_image',

View File

@ -39,6 +39,8 @@ require 'OpenNebula/Template'
require 'OpenNebula/TemplatePool'
require 'OpenNebula/Group'
require 'OpenNebula/GroupPool'
require 'OpenNebula/Acl'
require 'OpenNebula/AclPool'
module OpenNebula

View File

@ -0,0 +1,250 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, 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. #
#--------------------------------------------------------------------------- #
module OpenNebula
# Abstract rules of the type USER RESOURCE RIGHTS
# which are:
# USER -> #<num>
# @<num>
# ALL
# RESOURCE -> + separated list and "/{#,@}<num>|ALL"
# VM,
# HOST
# NET
# IMAGE
# USER
# TEMPLATE
# GROUP
# ACL
# RIGHTS -> + separated list
# CREATE
# DELETE
# USE
# MANAGE
# INFO
# INFO_POOL
# INFO_POOL_MINE
# INSTANTIATE
# CHOWN
class Acl < PoolElement
USERS = {
"UID" => 0x100000000,
"GID" => 0x200000000,
"ALL" => 0x400000000
}
RESOURCES =
{
"VM" => 0x1000000000,
"HOST" => 0x2000000000,
"NET" => 0x4000000000,
"IMAGE" => 0x8000000000,
"USER" => 0x10000000000,
"TEMPLATE" => 0x20000000000,
"GROUP" => 0x40000000000
}
RIGHTS =
{
"CREATE" => 0x1, # Auth. to create an object
"DELETE" => 0x2, # Auth. to delete an object
"USE" => 0x4, # Auth. to use an object
"MANAGE" => 0x8, # Auth. to manage an object
"INFO" => 0x10, # Auth. to view an object
"INFO_POOL" => 0x20, # Auth. to view any object in the pool
"INFO_POOL_MINE"=> 0x40, # Auth. to view user and/or group objects
"INSTANTIATE" => 0x80, # Auth. to instantiate a VM from a TEMPLATE
"CHOWN" => 0x100 # Auth. to change ownership of an object
}
# Constructor
#
# @param xml [String] must be an xml built with {#build_xml}
# @param client [Client] represents an XML-RPC connection
def initialize(xml, client)
super(xml,client)
end
# Creates an empty XML representation. It contains the id, if it is
# specified.
#
# @param pe_id [Integer] rule ID
# @param client [Client] represents an XML-RPC connection
#
# @return [String] an empty XML representation
def self.build_xml(pe_id=nil)
if pe_id
acl_xml = "<ACL><ID>#{pe_id}</ID></ACL>"
else
acl_xml = "<ACL></ACL>"
end
XMLElement.build_xml(acl_xml,'ACL')
end
# Creates a new ACL rule.
#
# @param user [String]
# A string containing a hex number, e.g. 0x100000001
# @param resource [String]
# A string containing a hex number, e.g. 0x2100000001
# @param rights [String]
# A string containing a hex number, e.g. 0x10
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def allocate(user, resource, rights)
return super( AclPool::ACL_POOL_METHODS[:addrule],
user,
resource,
rights )
end
# Deletes the Acl rule
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def delete()
super(AclPool::ACL_POOL_METHODS[:delrule])
end
# Does nothing, individual ACL rules info can't be retrieved from
# OpenNebula
#
# @return [nil] nil
def info()
return nil
end
# Parses a rule string, e.g. "#5 HOST+VM/@12 INFO+CREATE+DELETE"
#
# @param rule_str [String] an ACL rule in string format
#
# @return [Array] an Array containing 3 strings (hex 64b numbers),
# or OpenNebula::Error objects
def self.parse_rule(rule_str)
ret = Array.new
rule_str = rule_str.split(" ")
if rule_str.length != 3
return [OpenNebula::Error.new(
"String needs three components: User, Resource, Rights")]
end
ret << parse_users(rule_str[0])
ret << parse_resources(rule_str[1])
ret << parse_rights(rule_str[2])
return ret
end
private
# Converts a string in the form [#<id>, @<id>, *] to a hex. number
#
# @param users [String] Users component string
#
# @return [String] A string containing a hex number
def self.parse_users(users)
begin
return calculate_ids(users).to_i.to_s(16)
rescue Exception => e
return OpenNebula::Error.new(e.message)
end
end
# Converts a resources string to a hex. number
#
# @param resources [String] Resources component string
#
# @return [String] A string containing a hex number
def self.parse_resources(resources)
begin
ret = 0
resources = resources.split("/")
if resources.size != 2
raise "Resource '#{resources}' malformed"
end
resources[0].split("+").each{ |resource|
if !RESOURCES[resource.upcase]
raise "Resource '#{resource}' does not exist"
end
ret += RESOURCES[resource.upcase]
}
ret += calculate_ids(resources[1])
return ret.to_i.to_s(16)
rescue Exception => e
return OpenNebula::Error.new(e.message)
end
end
# Converts a rights string to a hex. number
#
# @param rights [String] Rights component string
#
# @return [String] A string containing a hex number
def self.parse_rights(rights)
begin
ret = 0
rights = rights.split("+")
rights.each{ |right|
raise "Right '#{right}' does not exist" if !RIGHTS[right.upcase]
ret += RIGHTS[right.upcase]
}
return ret.to_i.to_s(16)
rescue Exception => e
return OpenNebula::Error.new(e.message)
end
end
# Calculates the numeric value for a String containing an individual
# (#<id>), group (@<id>) or all (*) ID component
#
# @param id_str [String] Rule Id string
#
# @return [Integer] the numeric value for the given id_str
def self.calculate_ids(id_str)
raise "ID string '#{id_str}' malformed" if
!id_str.match(/^([\#@]\d+|\*)$/)
value = 0
case id_str[0..0]
when "#"
value = USERS["UID"]
users_value = id_str[1..-1].to_i + value
when "@"
value = USERS["GID"]
users_value = id_str[1..-1].to_i + value
when "*"
users_value = USERS["ALL"]
end
return users_value
end
end
end

View File

@ -0,0 +1,53 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, 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. #
#--------------------------------------------------------------------------- #
require 'OpenNebula/Pool'
module OpenNebula
class AclPool < Pool
#######################################################################
# Constants and Class Methods
#######################################################################
ACL_POOL_METHODS = {
:info => "acl.info",
:addrule => "acl.addrule",
:delrule => "acl.delrule"
}
#######################################################################
# Class constructor
#######################################################################
def initialize(client)
super('ACL_POOL','ACL',client)
end
def factory(element_xml)
acl=REXML::Document.new(element_xml).root
OpenNebula::Acl.new(acl['USER'], acl['RESOURCE'], acl['RIGHTS'])
end
#######################################################################
# XML-RPC Methods
#######################################################################
# Retrieves the ACL Pool
def info()
# Retrieves all the Acls in the pool.
super(ACL_POOL_METHODS[:info])
end
end
end

View File

@ -47,9 +47,26 @@ module OpenNebula
# XML-RPC Methods for the Image Object
#######################################################################
# Retrieves all or part of the Images in the pool.
def info()
super(IMAGE_POOL_METHODS[:info],@user_id)
# Retrieves all or part of the VirtualMachines in the pool.
def info(*args)
case args.size
when 0
info_filter(IMAGE_POOL_METHODS[:info],@user_id,-1,-1)
when 3
info_filter(IMAGE_POOL_METHODS[:info],args[0],args[1],args[2])
end
end
def info_all()
return super(IMAGE_POOL_METHODS[:info])
end
def info_mine()
return super(IMAGE_POOL_METHODS[:info])
end
def info_group()
return super(IMAGE_POOL_METHODS[:info])
end
end
end

View File

@ -22,7 +22,6 @@ module OpenNebula
include Enumerable
protected
#pool:: _String_ XML name of the root element
#element:: _String_ XML name of the Pool elements
#client:: _Client_ represents a XML-RPC connection
@ -48,13 +47,36 @@ module OpenNebula
#######################################################################
# Common XML-RPC Methods for all the Pool Types
#######################################################################
#Gets the pool without any filter. Host, Group and User Pools
# xml_method:: _String_ the name of the XML-RPC method
def info(xml_method)
return xmlrpc_info(xml_method)
end
def info_all(xml_method)
return xmlrpc_info(xml_method,INFO_ALL,-1,-1)
end
def info_mine(xml_method)
return xmlrpc_info(xml_method,INFO_MINE,-1,-1)
end
def info_group(xml_method)
return xmlrpc_info(xml_method,INFO_GROUP,-1,-1)
end
def info_filter(xml_method, who, start_id, end_id)
return xmlrpc_info(xml_method,who, start_id, end_id)
end
private
# Calls to the corresponding info method to retreive the pool
# representation in XML format
# xml_method:: _String_ the name of the XML-RPC method
# args:: _Array_ with additional arguments for the info call
# [return] nil in case of success or an Error object
def info(xml_method,*args)
def xmlrpc_info(xml_method,*args)
rc = @client.call(xml_method,*args)
if !OpenNebula.is_error?(rc)
@ -66,6 +88,10 @@ module OpenNebula
end
public
# Constants for info queries (include/RequestManagerPoolInfoFilter.h)
INFO_GROUP = -1
INFO_ALL = -2
INFO_MINE = -3
# Iterates over every PoolElement in the Pool and calls the block with a
# a PoolElement obtained calling the factory method

View File

@ -46,10 +46,26 @@ module OpenNebula
# ---------------------------------------------------------------------
# XML-RPC Methods for the Template Object
# ---------------------------------------------------------------------
# Retrieves all or part of the VirtualMachines in the pool.
def info(*args)
case args.size
when 0
info_filter(TEMPLATE_POOL_METHODS[:info],@user_id,-1,-1)
when 3
info_filter(TEMPLATE_POOL_METHODS[:info],args[0],args[1],args[2])
end
end
# Retrieves all the Templates in the pool.
def info()
super(TEMPLATE_POOL_METHODS[:info], @user_id)
def info_all()
return super(TEMPLATE_POOL_METHODS[:info])
end
def info_mine()
return super(TEMPLATE_POOL_METHODS[:info])
end
def info_group()
return super(TEMPLATE_POOL_METHODS[:info])
end
end
end
end

View File

@ -26,6 +26,10 @@ module OpenNebula
:info => "vmpool.info"
}
# Constants for info queries (include/RequestManagerPoolInfoFilter.h)
INFO_NOT_DONE = -1
INFO_ALL_VM = -2
#######################################################################
# Class constructor & Pool Methods
#######################################################################
@ -48,8 +52,66 @@ module OpenNebula
#######################################################################
# Retrieves all or part of the VirtualMachines in the pool.
def info()
super(VM_POOL_METHODS[:info],@user_id)
# No arguments, returns the not-in-done VMs for the user
# [user_id, start_id, end_id]
# [user_id, start_id, end_id, state]
def info(*args)
case args.size
when 0
info_filter(VM_POOL_METHODS[:info],
@user_id,
-1,
-1,
INFO_NOT_DONE)
when 1
info_filter(VM_POOL_METHODS[:info],
args[0],
-1,
-1,
INFO_NOT_DONE)
when 3
info_filter(VM_POOL_METHODS[:info],
args[0],
args[1],
args[2],
INFO_NOT_DONE)
when 4
info_filter(VM_POOL_METHODS[:info],
args[0],
args[1],
args[2],
args[3])
end
end
def info_all()
return info_filter(VM_POOL_METHODS[:info],
INFO_ALL,
-1,
-1,
INFO_NOT_DONE)
end
def info_mine()
return info_filter(VM_POOL_METHODS[:info],
INFO_MINE,
-1,
-1,
INFO_NOT_DONE)
end
def info_group()
return info_filter(VM_POOL_METHODS[:info],
INFO_GROUP,
-1,
-1,
INFO_NOT_DONE)
end
private
def info_filter(xml_method, who, start_id, end_id, state)
return xmlrpc_info(xml_method, who, start_id, end_id, state)
end
end
end

View File

@ -47,9 +47,26 @@ module OpenNebula
# XML-RPC Methods for the Virtual Network Object
#######################################################################
# Retrieves all or part of the VirtualNetwork in the pool.
def info()
super(VN_POOL_METHODS[:info],@user_id)
# Retrieves all or part of the VirtualMachines in the pool.
def info(*args)
case args.size
when 0
info_filter(VN_POOL_METHODS[:info],@user_id,-1,-1)
when 3
info_filter(VN_POOL_METHODS[:info],args[0],args[1],args[2])
end
end
def info_all()
return super(VN_POOL_METHODS[:info])
end
def info_mine()
return super(VN_POOL_METHODS[:info])
end
def info_group()
return super(VN_POOL_METHODS[:info])
end
end
end

View File

@ -1,4 +1,5 @@
$: << '../'
$: << '../' \
<< './'
require 'OpenNebula'
require 'helpers/MockClient'
@ -78,4 +79,4 @@ module OpenNebula
}
end
end
end
end

View File

@ -1,4 +1,5 @@
$: << '../'
$: << '../' \
<< './'
require 'OpenNebula'
require 'helpers/MockClient'
@ -216,4 +217,4 @@ module OpenNebula
end
end
end
end

View File

@ -1,4 +1,5 @@
$: << '../'
$: << '../' \
<< './'
require 'OpenNebula'
require 'helpers/MockClient'
@ -62,4 +63,4 @@ module OpenNebula
}
end
end
end
end

View File

@ -1,4 +1,5 @@
$: << '../'
$: << '../' \
<< './'
require 'OpenNebula'
require 'helpers/MockClient'
@ -142,4 +143,4 @@ module OpenNebula
end
end
end
end

View File

@ -1,4 +1,5 @@
$: << '../'
$: << '../' \
<< './'
require 'OpenNebula'
require 'helpers/MockClient'
@ -114,4 +115,4 @@ module OpenNebula
}
end
end
end
end

View File

@ -1,4 +1,5 @@
$: << '../'
$: << '../' \
<< './'
require 'OpenNebula'
require 'helpers/MockClient'
@ -469,4 +470,4 @@ module OpenNebula
@vm.name.should eql(nil)
end
end
end
end

View File

@ -1,4 +1,5 @@
$: << '../'
$: << '../' \
<< './'
require 'OpenNebula'
require 'helpers/MockClient'
@ -84,4 +85,4 @@ module OpenNebula
}
end
end
end
end

View File

@ -1,4 +1,5 @@
$: << '../'
$: << '../' \
<< './'
require 'OpenNebula'
require 'helpers/MockClient'
@ -152,4 +153,4 @@ module OpenNebula
end
end
end
end

View File

@ -21,32 +21,38 @@
int ObjectCollection::from_xml_node(const xmlNodePtr node)
{
ObjectXML xml(node);
int rc = 0;
int id;
xmlNodePtr cur_node = 0;
istringstream iss;
int id;
int rc = 0;
vector<string> values;
vector<string>::iterator it;
istringstream iss;
string xpath_expr = "/" + collection_name + "/ID";
values = xml[xpath_expr.c_str()];
for ( it = values.begin() ; it < values.end(); it++ )
{
iss.str(*it);
iss >> dec >> id;
if ( iss.fail() )
for (cur_node = node->children; cur_node != 0; cur_node = cur_node->next)
{
if ((cur_node->type == XML_ELEMENT_NODE) &&
(cur_node->children != 0) &&
((cur_node->children->type == XML_TEXT_NODE ) ||
(cur_node->children->type == XML_CDATA_SECTION_NODE)))
{
rc = -1;
iss.clear();
iss.str(reinterpret_cast<const char *>(cur_node->children->content));
iss >> dec >> id;
if ( iss.fail() )
{
rc = -1;
break;
}
else
{
collection_set.insert(id);
}
}
else
{
collection_set.insert(id);
rc = -1;
break;
}
}
}
return rc;
};

View File

@ -30,7 +30,7 @@ class TestObjectSQL : public PoolObjectSQL
{
public:
//OBJECT ATTRIBUTES
TestObjectSQL(int n=-1, string t="default"):PoolObjectSQL(-1,"",0,0,0),number(n),text(t){};
TestObjectSQL(int n=-1, string t="default"):PoolObjectSQL(-1,"",0,0,"","",0),number(n),text(t){};
~TestObjectSQL(){};

View File

@ -33,7 +33,12 @@ void Request::execute(
NebulaLog::log("ReM",Log::DEBUG, method_name + " method invoked");
if ( upool->authenticate(session, uid, gid) == false )
if ( upool->authenticate(session,
uid,
gid,
uname,
gname,
group_ids) == false )
{
failure_response(AUTHENTICATION, authenticate_error());
}
@ -46,24 +51,20 @@ void Request::execute(
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool Request::basic_authorization(int oid)
bool Request::basic_authorization(int oid, AuthRequest::Operation op)
{
PoolObjectSQL * object;
bool pub;
int ouid;
bool pub = false;
int ouid = 0;
int ogid = -1;
if ( uid == 0 )
{
return true;
}
if ( oid == -1 )
{
ouid = 0;
pub = false;
}
else
if ( oid >= 0 )
{
object = pool->get(oid,true);
@ -74,17 +75,18 @@ bool Request::basic_authorization(int oid)
}
ouid = object->get_uid();
ogid = object->get_gid();
pub = object->isPublic();
object->unlock();
}
AuthRequest ar(uid);
AuthRequest ar(uid, group_ids);
ar.add_auth(auth_object, oid, auth_op, ouid, pub);
ar.add_auth(auth_object, oid, ogid, op, ouid, pub);
if (UserPool::authorize(ar) == -1)
{
if (UserPool::authorize(ar) == -1)
{
failure_response(AUTHORIZATION, authorization_error(ar.message));
return false;
@ -164,6 +166,8 @@ string Request::object_name(AuthRequest::Object ob)
return "virtual machine template";
case AuthRequest::GROUP:
return "group";
case AuthRequest::ACL:
return "ACL";
default:
return "-";
}

View File

@ -33,6 +33,7 @@
#include "RequestManagerHost.h"
#include "RequestManagerImage.h"
#include "RequestManagerUser.h"
#include "RequestManagerAcl.h"
#include <sys/signal.h>
#include <sys/socket.h>
@ -310,6 +311,11 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr image_chown(new ImageChown());
xmlrpc_c::methodPtr user_chown(new UserChown());
// ACL Methods
xmlrpc_c::methodPtr acl_addrule(new AclAddRule());
xmlrpc_c::methodPtr acl_delrule(new AclDelRule());
xmlrpc_c::methodPtr acl_info(new AclInfo());
/* VM related methods */
RequestManagerRegistry.addMethod("one.vm.deploy", vm_deploy);
RequestManagerRegistry.addMethod("one.vm.action", vm_action);
@ -383,6 +389,11 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.image.chown", image_chown);
RequestManagerRegistry.addMethod("one.imagepool.info", imagepool_info);
/* ACL related methods */
RequestManagerRegistry.addMethod("one.acl.addrule", acl_addrule);
RequestManagerRegistry.addMethod("one.acl.delrule", acl_delrule);
RequestManagerRegistry.addMethod("one.acl.info", acl_info);
};
/* -------------------------------------------------------------------------- */

123
src/rm/RequestManagerAcl.cc Normal file
View File

@ -0,0 +1,123 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 "RequestManagerAcl.h"
using namespace std;
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void AclAddRule::request_execute(xmlrpc_c::paramList const& paramList)
{
/*
xmlrpc-c version 1.07 can manage 64 bit numbers, but not all distros. ship
the latest version.
user = xmlrpc_c::value_i8(paramList.getI8(1));
resource = xmlrpc_c::value_i8(paramList.getI8(2));
rights = xmlrpc_c::value_i8(paramList.getI8(3));
*/
long long user;
long long resource;
long long rights;
istringstream iss;
iss.str( xmlrpc_c::value_string(paramList.getString(1)) );
iss >> hex >> user;
iss.clear();
iss.str( xmlrpc_c::value_string(paramList.getString(2)) );
iss >> hex >> resource;
iss.clear();
iss.str( xmlrpc_c::value_string(paramList.getString(3)) );
iss >> hex >> rights;
string error_msg;
if ( basic_authorization(-1) == false )
{
return;
}
int rc = aclm->add_rule(user, resource, rights, error_msg);
if ( rc < 0 )
{
failure_response(INTERNAL, request_error(error_msg, ""));
return;
}
success_response(rc);
return;
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void AclDelRule::request_execute(xmlrpc_c::paramList const& paramList)
{
int oid = xmlrpc_c::value_int(paramList.getInt(1));
string error_msg;
if ( basic_authorization(-1) == false )
{
return;
}
int rc = aclm->del_rule(oid, error_msg);
if ( rc < 0 )
{
failure_response(INTERNAL, request_error(error_msg, ""));
return;
}
success_response(oid);
return;
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void AclInfo::request_execute(xmlrpc_c::paramList const& paramList)
{
ostringstream oss;
int rc;
if ( basic_authorization(-1) == false )
{
return;
}
rc = aclm->dump(oss);
if ( rc != 0 )
{
failure_response(INTERNAL, request_error("Internal Error",""));
return;
}
success_response(oss.str());
return;
}
/* ------------------------------------------------------------------------- */

View File

@ -30,17 +30,17 @@ bool RequestManagerAllocate::allocate_authorization(Template * tmpl)
return true;
}
AuthRequest ar(uid);
AuthRequest ar(uid, group_ids);
if ( tmpl == 0 )
{
ar.add_auth(auth_object,-1,auth_op,uid,false);
ar.add_auth(auth_object,-1,-1,auth_op,uid,false);
}
else
{
string t64;
ar.add_auth(auth_object,tmpl->to_xml(t64),auth_op,uid,false);
ar.add_auth(auth_object,tmpl->to_xml(t64),-1,auth_op,uid,false);
}
if (UserPool::authorize(ar) == -1)
@ -62,12 +62,13 @@ bool VirtualMachineAllocate::allocate_authorization(Template * tmpl)
return true;
}
AuthRequest ar(uid);
AuthRequest ar(uid, group_ids);
string t64;
VirtualMachineTemplate * ttmpl = static_cast<VirtualMachineTemplate *>(tmpl);
ar.add_auth(auth_object,tmpl->to_xml(t64),auth_op,uid,false);
ar.add_auth(auth_object,tmpl->to_xml(t64),-1,auth_op,uid,false);
VirtualMachine::set_auth_request(uid, ar, ttmpl);
@ -132,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);
}
@ -150,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);
}
/* -------------------------------------------------------------------------- */
@ -164,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);
}
/* -------------------------------------------------------------------------- */
@ -179,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);
}
/* -------------------------------------------------------------------------- */
@ -212,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);
}
/* -------------------------------------------------------------------------- */

View File

@ -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;
}

View File

@ -27,49 +27,168 @@ const int RequestManagerPoolInfoFilter::MINE = -3;
const int RequestManagerPoolInfoFilter::MINE_GROUP = -1;
/* ------------------------------------------------------------------------- */
const int VirtualMachinePoolInfo::ALL_VM = -2;
const int VirtualMachinePoolInfo::NOT_DONE = -1;
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void RequestManagerPoolInfoFilter::request_execute(xmlrpc_c::paramList const& paramList)
{
int filter_flag = xmlrpc_c::value_int(paramList.getInt(1));
int start_id = xmlrpc_c::value_int(paramList.getInt(2));
int end_id = xmlrpc_c::value_int(paramList.getInt(3));
ostringstream oss, where_string;
set<int>::iterator it;
ostringstream oss;
bool empty = true;
ostringstream where_string;
ostringstream uid_filter;
ostringstream state_filter;
ostringstream id_filter;
string uid_str;
string state_str;
string id_str;
int rc;
AuthRequest::Operation request_op;
// ------------------------------------------
// User ID filter
// ------------------------------------------
if ( filter_flag < MINE )
{
failure_response(XML_RPC_API, request_error("Incorrect filter_flag",""));
failure_response(XML_RPC_API,request_error("Incorrect filter_flag",""));
return;
}
switch(filter_flag)
{
case MINE:
where_string << "UID=" << uid;
auth_op = AuthRequest::INFO_POOL_MINE;
uid_filter << "uid = " << uid;
request_op = AuthRequest::INFO_POOL_MINE;
break;
case ALL:
request_op = AuthRequest::INFO_POOL;
break;
case MINE_GROUP:
where_string << "UID=" << uid << " OR GID=" << gid;
auth_op = AuthRequest::INFO_POOL_MINE;
uid_filter << "uid = " << uid;
for ( it = group_ids.begin() ; it != group_ids.end(); it++ )
{
uid_filter << " OR gid = " << *it;
}
request_op = AuthRequest::INFO_POOL_MINE;
break;
default:
where_string << "UID=" << filter_flag;
uid_filter << "uid = " << filter_flag;
request_op = AuthRequest::INFO_POOL;
break;
}
if ( basic_authorization(-1) == false )
uid_str = uid_filter.str();
// ------------------------------------------
// Resource ID filter
// ------------------------------------------
if ( start_id != -1 )
{
id_filter << "oid >= " << start_id;
if ( end_id != -1 )
{
id_filter << " AND oid <= " << end_id;
}
}
id_str = id_filter.str();
// ------------ State filter for VM --------------
if ( auth_object == AuthRequest::VM )
{
int state = xmlrpc_c::value_int(paramList.getInt(4));
if (( state < MINE ) || ( state > VirtualMachine::FAILED ))
{
failure_response(XML_RPC_API,
request_error("Incorrect filter_flag, state",""));
return;
}
switch(state)
{
case VirtualMachinePoolInfo::ALL_VM:
break;
case VirtualMachinePoolInfo::NOT_DONE:
state_filter << "state <> " << VirtualMachine::DONE;
break;
default:
state_filter << "state = " << state;
break;
}
}
state_str = state_filter.str();
// ------------------------------------------
// Compound WHERE clause
// ------------------------------------------
if (!uid_str.empty())
{
where_string << "(" << uid_str << ")" ;
empty = false;
}
if (!id_str.empty())
{
if (!empty)
{
where_string << " AND ";
}
where_string << "(" << id_str << ")";
empty = false;
}
if (!state_str.empty())
{
if (!empty)
{
where_string << " AND ";
}
where_string << "(" << state_str << ")";
}
// ------------------------------------------
// Authorize & get the pool
// ------------------------------------------
if ( basic_authorization(-1, request_op) == false )
{
return;
}
// Call the template pool dump
rc = pool->dump(oss,where_string.str());
if ( rc != 0 )

View File

@ -25,7 +25,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
int id = xmlrpc_c::value_int(paramList.getInt(1));
string name = xmlrpc_c::value_string(paramList.getString(2));
int rc, ouid, vid;
int rc, ouid, ogid, vid;
Nebula& nd = Nebula::instance();
VirtualMachinePool* vmpool = nd.get_vmpool();
@ -46,6 +46,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
tmpl = rtmpl->clone_template();
ouid = rtmpl->get_uid();
ogid = rtmpl->get_gid();
rtmpl->unlock();
@ -54,9 +55,9 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
if ( uid != 0 )
{
AuthRequest ar(uid);
AuthRequest ar(uid, group_ids);
ar.add_auth(auth_object, id, auth_op, ouid, false);
ar.add_auth(auth_object, id, ogid, auth_op, ouid, false);
VirtualMachine::set_auth_request(uid, ar, tmpl);
@ -68,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 )
{

View File

@ -25,6 +25,7 @@ bool RequestManagerVirtualMachine::vm_authorization(int oid, int hid, ImageTempl
PoolObjectSQL * object;
int ouid;
int ogid;
if ( uid == 0 )
{
@ -40,16 +41,17 @@ bool RequestManagerVirtualMachine::vm_authorization(int oid, int hid, ImageTempl
}
ouid = object->get_uid();
ogid = object->get_gid();
object->unlock();
AuthRequest ar(uid);
AuthRequest ar(uid, group_ids);
ar.add_auth(auth_object, oid, auth_op, ouid, false);
ar.add_auth(auth_object, oid, ogid, auth_op, ouid, false);
if (hid != -1)
{
ar.add_auth(AuthRequest::HOST,hid,AuthRequest::USE,0,false);
ar.add_auth(AuthRequest::HOST,hid,-1,AuthRequest::USE,0,false);
}
else if (tmpl != 0)
{
@ -57,6 +59,7 @@ bool RequestManagerVirtualMachine::vm_authorization(int oid, int hid, ImageTempl
ar.add_auth(AuthRequest::IMAGE,
tmpl->to_xml(t64),
-1,
AuthRequest::CREATE,
uid,
false);
@ -395,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 )
{

View File

@ -38,36 +38,7 @@ source_files=[
'RequestManagerHost.cc',
'RequestManagerImage.cc',
'RequestManagerChown.cc',
# 'RequestManagerAction.cc',
# 'RequestManagerAllocate.cc',
# 'RequestManagerDeploy.cc',
# 'RequestManagerMigrate.cc',
# 'RequestManagerSaveDisk.cc',
# 'RequestManagerHostAllocate.cc',
# 'RequestManagerHostEnable.cc',
# 'RequestManagerImageAllocate.cc',
# 'RequestManagerImageUpdate.cc',
# 'RequestManagerImageRemoveAttribute.cc',
# 'RequestManagerImagePublish.cc',
# 'RequestManagerImagePersistent.cc',
# 'RequestManagerImageEnable.cc',
# 'RequestManagerClusterAdd.cc',
# 'RequestManagerClusterAllocate.cc',
# 'RequestManagerClusterRemove.cc',
# 'RequestManagerGroupAllocate.cc',
# 'RequestManagerVirtualNetworkAllocate.cc',
# 'RequestManagerVirtualNetworkInfo.cc',
# 'RequestManagerVirtualNetworkPublish.cc',
# 'RequestManagerVirtualNetworkAddLeases.cc',
# 'RequestManagerVirtualNetworkRemoveLeases.cc',
# 'RequestManagerUserAllocate.cc',
# 'RequestManagerUserChangePassword.cc',
# 'RequestManagerTemplateAllocate.cc',
# 'RequestManagerTemplateUpdate.cc',
# 'RequestManagerTemplateRemoveAttribute.cc',
# 'RequestManagerTemplatePublish.cc',
# 'RequestManagerChown.cc',
'RequestManagerAcl.cc',
]
# Build library

View File

@ -0,0 +1,83 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 ACL_XML_H_
#define ACL_XML_H_
#include "AclManager.h"
#include "Client.h"
using namespace std;
/**
* This class manages the ACL rules and the authorization engine
*/
class AclXML : public AclManager
{
public:
AclXML(Client * _client):AclManager(), client(_client){};
virtual ~AclXML(){};
/**
* Loads the ACL rule set from the DB
* @return 0 on success.
*/
int set_up();
private:
/* ---------------------------------------------------------------------- */
/* Re-implement DB public functions not used in scheduler */
/* ---------------------------------------------------------------------- */
int start()
{
return -1;
}
int add_rule(long long user,
long long resource,
long long rights,
string& error_str)
{
return -1;
};
int del_rule(int oid, string& error_str)
{
return -1;
};
int dump(ostringstream& oss)
{
return -1;
};
Client * client;
/**
* Loads the ACL rule set from its XML representation:
* as obtained by a dump call
*
* @param xml_str string with the XML document for the ACL
* @return 0 on success.
*/
int load_rules(const string& xml_str);
void flush_rules();
};
#endif /*ACL_XML_H*/

View File

@ -49,9 +49,9 @@ protected:
return get_nodes("/HOST_POOL/HOST[STATE<3]", content);
};
virtual void add_object(xmlNodePtr node);
void add_object(xmlNodePtr node);
virtual int load_info(xmlrpc_c::value &result);
int load_info(xmlrpc_c::value &result);
};
#endif /* HOST_POOL_XML_H_ */

View File

@ -53,7 +53,7 @@ public:
flush();
// -------------------------------------------------------------------------
// Load the ids (to get an updated list of hosts)
// Load the ids (to get an updated list of the pool)
// -------------------------------------------------------------------------
xmlrpc_c::value result;
@ -97,6 +97,8 @@ public:
add_object(nodes[i]);
}
free_nodes(nodes);
return 0;
};

View File

@ -18,10 +18,12 @@
#define SCHEDULER_H_
#include "Log.h"
#include "UserPoolXML.h"
#include "HostPoolXML.h"
#include "VirtualMachinePoolXML.h"
#include "SchedulerPolicy.h"
#include "ActionManager.h"
#include "AclXML.h"
using namespace std;
@ -48,6 +50,8 @@ protected:
int _machines_limit, int _dispatch_limit, int _host_dispatch_limit):
hpool(0),
vmpool(0),
upool(0),
acls(0),
timer(_timer),
url(_url),
machines_limit(_machines_limit),
@ -71,6 +75,16 @@ protected:
delete vmpool;
}
if ( upool != 0)
{
delete upool;
}
if ( acls != 0)
{
delete acls;
}
if ( client != 0)
{
delete client;
@ -83,6 +97,8 @@ protected:
HostPoolXML * hpool;
VirtualMachinePoolXML * vmpool;
UserPoolXML * upool;
AclXML * acls;
// ---------------------------------------------------------------
// Scheduler Policies

View File

@ -0,0 +1,57 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 USER_POOL_XML_H_
#define USER_POOL_XML_H_
#include "PoolXML.h"
#include "UserXML.h"
using namespace std;
class UserPoolXML : public PoolXML
{
public:
UserPoolXML(Client* client):PoolXML(client){};
int set_up();
/**
* Gets an object from the pool
* @param oid the object unique identifier
*
* @return a pointer to the object, 0 in case of failure
*/
UserXML * get(int oid) const
{
return static_cast<UserXML *>(PoolXML::get(oid));
};
protected:
int get_suitable_nodes(vector<xmlNodePtr>& content)
{
return get_nodes("/USER_POOL/USER[ENABLED=1]", content);
};
void add_object(xmlNodePtr node);
int load_info(xmlrpc_c::value &result);
};
#endif /* HOST_POOL_XML_H_ */

View File

@ -0,0 +1,63 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 USER_XML_H_
#define USER_XML_H_
#include "ObjectXML.h"
#include <set>
using namespace std;
class UserXML : public ObjectXML
{
public:
UserXML(const string &xml_doc):ObjectXML(xml_doc)
{
init_attributes();
};
UserXML(const xmlNodePtr node):ObjectXML(node)
{
init_attributes();
};
int get_uid()
{
return oid;
};
int get_gid()
{
return gid;
};
const set<int>& get_groups()
{
return group_ids;
};
private:
int oid;
int gid;
set<int> group_ids;
void init_attributes();
};
#endif /* USER_XML_H_ */

View File

@ -46,6 +46,11 @@ public:
return oid;
};
int get_uid() const
{
return uid;
};
/**
* Adds a new share to the map of suitable shares to start this VM
* @param hid of the selected host
@ -138,6 +143,8 @@ protected:
*/
int oid;
int uid;
int memory;
float cpu;

View File

@ -0,0 +1,114 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 "AclXML.h"
#include "ObjectXML.h"
#include <vector>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclXML::set_up()
{
xmlrpc_c::value result;
try
{
client->call(client->get_endpoint(), // serverUrl
"one.acl.info", // methodName
"s", // arguments format
&result, // resultP
client->get_oneauth().c_str());// argument
vector<xmlrpc_c::value> values =
xmlrpc_c::value_array(result).vectorValueValue();
bool success = xmlrpc_c::value_boolean(values[0]);
string message = xmlrpc_c::value_string(values[1]);
if( !success )
{
ostringstream oss;
oss << "ONE returned error while retrieving the acls:" << endl;
oss << message;
NebulaLog::log("ACL", Log::ERROR, oss);
return -1;
}
flush_rules();
load_rules(message);
return 0;
}
catch (exception const& e)
{
ostringstream oss;
oss << "Exception raised: " << e.what();
NebulaLog::log("ACL", Log::ERROR, oss);
return -1;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int AclXML::load_rules(const string& xml_str)
{
ObjectXML acl_xml(xml_str);
vector<xmlNodePtr> rules;
vector<xmlNodePtr>::iterator it;
acl_xml.get_nodes("/ACL_POOL/ACL",rules);
for (it = rules.begin(); it != rules.end() ; it++)
{
AclRule * rule = new AclRule(0,0,0,0);
int rc = rule->from_xml(*it);
if ( rc == 0 )
{
acl_rules.insert( make_pair(rule->get_user(), rule) );
acl_rules_oids.insert( make_pair(rule->get_oid(), rule) );
}
}
acl_xml.free_nodes(rules);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void AclXML::flush_rules()
{
multimap<long long, AclRule *>::iterator it;
for ( it = acl_rules.begin(); it != acl_rules.end(); it++ )
{
delete it->second;
}
acl_rules.clear();
acl_rules_oids.clear();
}

View File

@ -21,6 +21,9 @@ Import('sched_env')
lib_name='scheduler_pool'
source_files=[
'AclXML.cc',
'UserPoolXML.cc',
'UserXML.cc',
'HostPoolXML.cc',
'HostXML.cc',
'VirtualMachinePoolXML.cc',

View File

@ -0,0 +1,90 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 "UserPoolXML.h"
int UserPoolXML::set_up()
{
ostringstream oss;
int rc;
rc = PoolXML::set_up();
if ( rc == 0 )
{
oss.str("");
oss << "Users (enabled):";
map<int,ObjectXML*>::iterator it;
for (it=objects.begin();it!=objects.end();it++)
{
oss << " " << it->first;
}
NebulaLog::log("HOST",Log::DEBUG,oss);
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void UserPoolXML::add_object(xmlNodePtr node)
{
if ( node == 0 || node->children == 0 )
{
NebulaLog::log("USER",Log::ERROR,
"XML Node does not represent a valid User");
return;
}
UserXML* user = new UserXML(node);
objects.insert(pair<int,ObjectXML*>(user->get_uid(), user));
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int UserPoolXML::load_info(xmlrpc_c::value &result)
{
try
{
client->call(client->get_endpoint(), // serverUrl
"one.userpool.info", // methodName
"s", // arguments format
&result, // resultP
client->get_oneauth().c_str()); // argument
return 0;
}
catch (exception const& e)
{
ostringstream oss;
oss << "Exception raised: " << e.what();
NebulaLog::log("USER", Log::ERROR, oss);
return -1;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,74 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, 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 "UserXML.h"
#include <sstream>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void UserXML::init_attributes()
{
vector<xmlNodePtr> content;
oid = atoi(((*this)["/USER/ID"] )[0].c_str() );
gid = atoi(((*this)["/USER/GID"] )[0].c_str() );
get_nodes("/USER/GROUPS",content);
if (!content.empty())
{
xmlNodePtr cur_node = 0;
istringstream iss;
int id;
for (cur_node = content[0]->children;
cur_node != 0;
cur_node = cur_node->next)
{
if ((cur_node->type == XML_ELEMENT_NODE) &&
(cur_node->children != 0) &&
((cur_node->children->type == XML_TEXT_NODE ) ||
(cur_node->children->type == XML_CDATA_SECTION_NODE)))
{
iss.clear();
iss.str(reinterpret_cast<const char *>(cur_node->children->content));
iss >> dec >> id;
if ( iss.fail() )
{
//TODO Print a warning message
break;
}
else
{
group_ids.insert(id);
}
}
else
{
//TODO Print a warning message
break;
}
}
}
free_nodes(content);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -64,13 +64,15 @@ int VirtualMachinePoolXML::load_info(xmlrpc_c::value &result)
{
try
{
client->call(client->get_endpoint(), // serverUrl
"one.vmpool.info", // methodName
"sii", // arguments format
&result, // resultP
client->get_oneauth().c_str(), // auth string
-2, // VM from all users
1); // in pending state
client->call(client->get_endpoint(), // serverUrl
"one.vmpool.info", // methodName
"siiii", // arguments format
&result, // resultP
client->get_oneauth().c_str(), // auth string
-2, // VM from all users
-1, // start_id (none)
-1, // end_id (none)
1); // in pending state
return 0;
}
catch (exception const& e)

View File

@ -22,7 +22,8 @@ void VirtualMachineXML::init_attributes()
{
vector<string> result;
oid = atoi(((*this)["/VM/ID"] )[0].c_str() );
oid = atoi(((*this)["/VM/ID"] )[0].c_str());
uid = atoi(((*this)["/VM/UID"])[0].c_str());
result = ((*this)["/VM/TEMPLATE/MEMORY"]);
if (result.size() > 0)

View File

@ -32,6 +32,7 @@ sched_env.Prepend(LIBS=[
'scheduler_pool',
'nebula_log',
'scheduler_client',
'nebula_acl',
'nebula_xml',
'nebula_common',
'crypto',

View File

@ -121,6 +121,8 @@ void Scheduler::start()
hpool = new HostPoolXML(client);
vmpool = new VirtualMachinePoolXML(client, machines_limit);
upool = new UserPoolXML(client);
acls = new AclXML(client);
// -----------------------------------------------------------
// Load scheduler policies
@ -228,6 +230,28 @@ int Scheduler::set_up_pools()
return rc;
}
//--------------------------------------------------------------------------
//Cleans the cache and get the users
//--------------------------------------------------------------------------
rc = upool->set_up();
if ( rc != 0 )
{
return rc;
}
//--------------------------------------------------------------------------
//Cleans the cache and get the ACLs
//--------------------------------------------------------------------------
rc = acls->set_up();
if ( rc != 0 )
{
return rc;
}
//--------------------------------------------------------------------------
//Get the matching hosts for each VM
//--------------------------------------------------------------------------
@ -246,6 +270,7 @@ void Scheduler::match()
int vm_memory;
int vm_cpu;
int vm_disk;
int uid;
string reqs;
HostXML * host;
@ -254,6 +279,9 @@ void Scheduler::match()
char * error;
bool matched;
UserXML * user;
set<int> gids;
int rc;
map<int, ObjectXML*>::const_iterator vm_it;
@ -268,8 +296,9 @@ void Scheduler::match()
vm = static_cast<VirtualMachineXML*>(vm_it->second);
reqs = vm->get_requirements();
uid = vm->get_uid();
for (h_it=hosts.begin(); h_it != hosts.end(); h_it++)
for (h_it=hosts.begin(), matched=false; h_it != hosts.end(); h_it++)
{
host = static_cast<HostXML *>(h_it->second);
@ -298,12 +327,58 @@ void Scheduler::match()
{
matched = true;
}
if ( matched == false )
{
ostringstream oss;
oss << "Host " << host->get_hid() <<
" filtered out. It does not fullfil REQUIREMENTS.";
NebulaLog::log("SCHED",Log::DEBUG,oss);
continue;
}
// -----------------------------------------------------------------
// Check if user is authorized
// -----------------------------------------------------------------
user = upool->get(uid);
matched = false;
if ( user != 0 )
{
const set<int> groups = user->get_groups();
if ( uid == 0 || user->get_gid() == 0 )
{
matched = true;
}
else
{
matched = acls->authorize(uid,
groups,
AuthRequest::HOST,
host->get_hid(),
-1,
AuthRequest::USE);
}
}
else
{
continue;
}
if ( matched == false )
{
ostringstream oss;
oss << "Host " << host->get_hid() <<
" filtered out. User is not authorized to use it.";
NebulaLog::log("SCHED",Log::DEBUG,oss);
continue;
}
// -----------------------------------------------------------------
// Check host capacity
// -----------------------------------------------------------------
@ -319,6 +394,16 @@ void Scheduler::match()
vm->add_host(host->get_hid());
}
}
else
{
ostringstream oss;
oss << "Host " << host->get_hid() <<
" filtered out. It does not have enough capacity.";
NebulaLog::log("SCHED",Log::DEBUG,oss);
}
}
}
}

View File

@ -1,16 +1,19 @@
---
- plugins/dashboard-tab.js:
:ALL: true
:ALL: false
:user:
:group:
oneadmin: true
- plugins/hosts-tab.js:
:ALL: true
:ALL: false
:user:
:group:
oneadmin: true
- plugins/groups-tab.js:
:ALL: true
:ALL: false
:user:
:group:
oneadmin: true
- plugins/templates-tab.js:
:ALL: true
:user:
@ -28,6 +31,7 @@
:user:
:group:
- plugins/users-tab.js:
:ALL: true
:ALL: false
:user:
:group:
oneadmin: true

View File

@ -39,6 +39,8 @@ module OpenNebulaJSON
rc = case action_hash['perform']
when "passwd" then self.passwd(action_hash['params'])
when "chgrp" then self.chgrp(action_hash['params'])
when "addgroup" then self.addgroup(action_hash['params'])
when "delgroup" then self.delgroup(action_hash['params'])
else
error_msg = "#{action_hash['perform']} action not " <<
" available for this resource"
@ -52,7 +54,16 @@ module OpenNebulaJSON
end
def chgrp(params=Hash.new)
super(params['group_id'])
super(params['group_id'].to_i)
end
def addgroup(params=Hash.new)
super(params['group_id'].to_i)
end
def delgroup(params=Hash.new)
super(params['group_id'].to_i)
end
end
end

View File

@ -69,19 +69,28 @@ class SunstonePlugins
@installed_plugins.include? plugin
end
def authorized_plugins(user,group=nil)
def authorized_plugins(user, group)
auth_plugins = {"user-plugins"=>Array.new, "plugins"=>Array.new}
@plugins_conf.each do |plugin_conf|
plugin = plugin_conf.keys.first
perms = plugin_conf[plugin]
perms = plugin_conf[plugin]
if installed?(plugin)
p_path, p_name = plugin.split('/')
if perms[:user] and perms[:user][user]
auth_plugins[p_path] << p_name
elsif perms[:group] and perms[:group][group]
auth_plugins[p_path] << p_name
if perms[:user] and perms[:user].has_key? user
if perms[:user][user]
auth_plugins[p_path] << p_name
else
next
end
elsif perms[:group] and perms[:group].has_key? group
if perms[:group][group]
auth_plugins[p_path] << p_name
else
next
end
elsif perms[:ALL]
auth_plugins[p_path] << p_name
end

View File

@ -41,9 +41,13 @@ class SunstoneServer
return [500, false]
end
user_pass = user_pool["USER[NAME=\"#{user}\"]/PASSWORD"]
user_pass = user_pool["USER[NAME=\"#{user}\"]/PASSWORD"]
user_id = user_pool["USER[NAME=\"#{user}\"]/ID"]
user_gid = user_pool["USER[NAME=\"#{user}\"]/GID"]
user_gname = user_pool["USER[NAME=\"#{user}\"]/GNAME"]
if user_pass == sha1_pass
return [204, user_pool["USER[NAME=\"#{user}\"]/ID"]]
return [204, [user_id, user_gid, user_gname]]
else
return [401, nil]
end

View File

@ -151,7 +151,7 @@ var OpenNebula = {
{
return Error('Incorrect Pool');
}
var p_pool = [];
if (response[pool_name]) {
@ -227,7 +227,7 @@ var OpenNebula = {
var password = params.data.password;
var remember = params.remember;
var resource = OpenNebula.Auth.resource;
var resource = OpenNebula.Auth.resource;
var request = OpenNebula.Helper.request(resource,"login");
$.ajax({
@ -709,7 +709,7 @@ var OpenNebula = {
var callback_error = params.error;
var timeout = params.timeout || false;
var resource = OpenNebula.Network.resource;
var request = OpenNebula.Helper.request(resource,"list");
$.ajax({
@ -1257,7 +1257,7 @@ var OpenNebula = {
var callback_error = params.error;
var id = params.data.id;
var resource = OpenNebula.VM.resource;
var method = "suspend";
var action = OpenNebula.Helper.action(method);
var request = OpenNebula.Helper.request(resource,method, id);
@ -1331,7 +1331,7 @@ var OpenNebula = {
"type" : type
}
var resource = OpenNebula.VM.resource;
var action = OpenNebula.Helper.action(method,saveas_params)
var request = OpenNebula.Helper.request(resource,method, [id,disk_id, image_name, type]);
@ -1387,7 +1387,7 @@ var OpenNebula = {
}
});
},
"resubmit": function(params)
{
var callback = params.success;
@ -1419,7 +1419,7 @@ var OpenNebula = {
}
});
},
"startvnc" : function(params){
var callback = params.success;
var callback_error = params.error;
@ -1449,7 +1449,7 @@ var OpenNebula = {
}
});
},
"stopvnc" : function(params){
var callback = params.success;
var callback_error = params.error;
@ -1687,6 +1687,36 @@ var OpenNebula = {
});
},
"show" : function(params)
{
var callback = params.success;
var callback_error = params.error;
var id = params.data.id;
var resource = OpenNebula.User.resource;
var request = OpenNebula.Helper.request(resource,"show", id);
$.ajax({
url: "user/" + id,
type: "GET",
dataType: "json",
success: function(response)
{
if (callback)
{
callback(request, response);
}
},
error: function(response)
{
if (callback_error)
{
callback_error(request, OpenNebula.Error(response));
}
}
});
},
"delete": function(params)
{
var callback = params.success;
@ -1759,7 +1789,7 @@ var OpenNebula = {
var action = OpenNebula.Helper.action(method, {
"password" : passwd
});
var resource = OpenNebula.User.resource;
var request = OpenNebula.Helper.request(resource,method, passwd);
@ -1794,6 +1824,67 @@ var OpenNebula = {
var action = OpenNebula.Helper.action(method, {"group_id": gid});
var request = OpenNebula.Helper.request(OpenNebula.User.resource,method, [id, gid]);
$.ajax({
url: "user/" + id + "/action",
type: "POST",
data: JSON.stringify(action),
success: function()
{
if (callback)
{
callback(request);
}
},
error: function(response)
{
if (callback_error)
{
callback_error(request, OpenNebula.Error(response));
}
}
});
},
"addgroup" : function(params){
var callback = params.success;
var callback_error = params.error;
var id = params.data.id;
var gid = params.data.extra_param;
var method = "addgroup";
var action = OpenNebula.Helper.action(method, {"group_id": gid});
var request = OpenNebula.Helper.request(OpenNebula.User.resource,method, [id, gid]);
$.ajax({
url: "user/" + id + "/action",
type: "POST",
data: JSON.stringify(action),
success: function()
{
if (callback)
{
callback(request);
}
},
error: function(response)
{
if (callback_error)
{
callback_error(request, OpenNebula.Error(response));
}
}
});
},
"delgroup" : function(params){
var callback = params.success;
var callback_error = params.error;
var id = params.data.id;
var gid = params.data.extra_param;
var method = "delgroup";
var action = OpenNebula.Helper.action(method, {"group_id": gid});
var request = OpenNebula.Helper.request(OpenNebula.User.resource,method, [id, gid]);
$.ajax({
url: "user/" + id + "/action",
type: "POST",
@ -2012,7 +2103,7 @@ var OpenNebula = {
var method = "enable";
var action = OpenNebula.Helper.action(method);
var resource = OpenNebula.Image.resource;
var request = OpenNebula.Helper.request(resource,method, id);
@ -2141,7 +2232,7 @@ var OpenNebula = {
var method = "persistent";
var action = OpenNebula.Helper.action(method);
var resource = OpenNebula.Image.resource;
var request = OpenNebula.Helper.request(resource,method, id);
@ -2174,7 +2265,7 @@ var OpenNebula = {
var method = "nonpersistent";
var action = OpenNebula.Helper.action(method);
var resource = OpenNebula.Image.resource;
var request = OpenNebula.Helper.request(resource,method, id);
@ -2207,10 +2298,10 @@ var OpenNebula = {
OpenNebula.Helper.chgrp(params,OpenNebula.Image.resource,"image");
}
},
"Template" : {
"resource" : "VMTEMPLATE",
"create" : function(params)
{
var callback = params.success;
@ -2240,7 +2331,7 @@ var OpenNebula = {
}
}
});
},
"fetch_template" : function(params)
{
@ -2283,7 +2374,7 @@ var OpenNebula = {
var method = "update";
var action = OpenNebula.Helper.action(method, template_obj);
var resource = OpenNebula.Template.resource;
var resource = OpenNebula.Template.resource;
var request = OpenNebula.Helper.request(resource,method, [id, template_obj]);
$.ajax({
@ -2427,7 +2518,7 @@ var OpenNebula = {
callback_error(request, OpenNebula.Error(response));
}
}
});
});
},
"delete" : function(params)
{
@ -2455,7 +2546,7 @@ var OpenNebula = {
callback_error(request, OpenNebula.Error(response));
}
}
});
});
},
"chown" : function(params){

View File

@ -14,7 +14,7 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
var group_select="";
var groups_select="";
var group_list_json = {};
var dataTable_groups;
@ -28,8 +28,8 @@ var groups_tab_content =
<tr>\
<th class="check"><input type="checkbox" class="check_all" value="">All</input></th>\
<th>ID</th>\
<th>Owner</th>\
<th>Name</th>\
<th>Users</th>\
</tr>\
</thead>\
<tbody id="tbodygroups">\
@ -157,11 +157,23 @@ Sunstone.addMainTab('groups_tab',groups_tab);
function groupElementArray(group_json){
var group = group_json.GROUP;
var users_str="";
if (group.USERS.ID &&
group.USERS.ID.constructor == Array){
for (var i=0; i<group.USERS.ID.length; i++){
users_str+=getUserName(group.USERS.ID[i])+', ';
};
users_str=users_str.slice(0,-2);
} else if (group.USERS.ID) {
users_str=getUserName(group.USERS.ID);
};
return [
'<input type="checkbox" id="group_'+group.ID+'" name="selected_items" value="'+group.ID+'"/>',
group.ID,
getUserName(group.UID),
group.NAME ];
group.NAME,
users_str ];
}
function groupInfoListener(){
@ -176,7 +188,7 @@ function groupInfoListener(){
}
function updateGroupSelect(){
groups_select = makeSelectOptions(dataTable_groups,1,3,-1,"",-1);
groups_select = makeSelectOptions(dataTable_groups,1,2,-1,"",-1);
}
function updateGroupElement(request, group_json){

View File

@ -222,7 +222,7 @@ var host_actions = {
"Host.update_dialog" : {
type: "custom",
call: function() {
popUpTemplateUpdateDialog("Host",hosts_select);
popUpTemplateUpdateDialog("Host",hosts_select,getSelectedNodes(dataTable_hosts));
}
},

View File

@ -223,7 +223,7 @@ var image_actions = {
"Image.update_dialog" : {
type: "custom",
call: function() {
popUpTemplateUpdateDialog("Image",images_select);
popUpTemplateUpdateDialog("Image",images_select,getSelectedNodes(dataTable_images));
}
},
@ -442,8 +442,8 @@ function imageElementArray(image_json){
return [
'<input type="checkbox" id="image_'+image.ID+'" name="selected_items" value="'+image.ID+'"/>',
image.ID,
getUserName(image.UID),
getGroupName(image.GID),
image.UNAME,
image.GNAME,
image.NAME,
OpenNebula.Helper.image_type(image.TYPE),
pretty_time(image.REGTIME),
@ -530,6 +530,14 @@ function updateImageInfo(request,img){
<td class="key_td">Name</td>\
<td class="value_td">'+img_info.NAME+'</td>\
</tr>\
<tr>\
<td class="key_td">Owner</td>\
<td class="value_td">'+img_info.UNAME+'</td>\
</tr>\
<tr>\
<td class="key_td">Group</td>\
<td class="value_td">'+img_info.GNAME+'</td>\
</tr>\
<tr>\
<td class="key_td">Type</td>\
<td class="value_td">'+OpenNebula.Helper.image_type(img_info.TYPE)+'</td>\

View File

@ -591,7 +591,7 @@ var template_actions = {
"Template.update_dialog" : {
type: "custom",
call: function() {
popUpTemplateUpdateDialog("Template",templates_select);
popUpTemplateUpdateDialog("Template",templates_select,getSelectedNodes(dataTable_templates));
}
},
@ -768,8 +768,8 @@ function templateElementArray(template_json){
return [
'<input type="checkbox" id="template_'+template.ID+'" name="selected_items" value="'+template.ID+'"/>',
template.ID,
getUserName(template.UID),
getGroupName(template.GID),
template.UNAME,
template.GNAME,
template.NAME,
pretty_time(template.REGTIME),
parseInt(template.PUBLIC) ? "yes" : "no"
@ -852,6 +852,14 @@ function updateTemplateInfo(request,template){
<td class="key_td">Name</td>\
<td class="value_td">'+template_info.NAME+'</td>\
</tr>\
<tr>\
<td class="key_td">Owner</td>\
<td class="value_td">'+template_info.UNAME+'</td>\
</tr>\
<tr>\
<td class="key_td">Group</td>\
<td class="value_td">'+template_info.GNAME+'</td>\
</tr>\
<tr>\
<td class="key_td">Register time</td>\
<td class="value_td">'+pretty_time(template_info.REGTIME)+'</td>\

View File

@ -97,6 +97,46 @@ var user_actions = {
notify: false
},
"User.chgrp" : {
type: "multiple",
call: OpenNebula.User.chgrp,
callback : function(req){
Sunstone.runAction("User.show",req.request.data[0]);
},
elements : function() {return getSelectedNodes(dataTable_users);},
error: onError,
notify: true
},
"User.addgroup" : {
type: "multiple",
call: OpenNebula.User.addgroup,
callback : function(req){
Sunstone.runAction("User.show",req.request.data[0]);
},
elements : function() {return getSelectedNodes(dataTable_users);},
error: onError,
notify: true
},
"User.delgroup" : {
type: "multiple",
call: OpenNebula.User.delgroup,
callback : function(req){
Sunstone.runAction("User.show",req.request.data[0]);
},
elements : function() {return getSelectedNodes(dataTable_users);},
error: onError,
notify: true
},
"User.show" : {
type: "single",
call: OpenNebula.User.show,
callback: updateUserElement,
error: onError
},
"User.delete" : {
type: "multiple",
call: OpenNebula.User.delete,
@ -119,6 +159,27 @@ var user_buttons = {
text: "+ New",
condition: True
},
"User.chgrp" : {
type: "confirm_with_select",
text: "Change main group",
select: function(){ return groups_select; },
tip: "This will change the main group of the selected users. Select the new group:",
condition: True
},
"User.addgroup" : {
type: "confirm_with_select",
text: "Add to group",
select: function(){ return groups_select; },
tip: "Select the new group to add users:",
condition: True
},
"User.delgroup" : {
type: "confirm_with_select",
text: "Delete from group",
select: function(){ return groups_select; },
tip: "Select the group from which to delete users:",
condition: True
},
"User.delete" : {
type: "action",
text: "Delete",
@ -146,30 +207,38 @@ function userElementArray(user_json){
name = user.NAME;
}
var i = 1;
var groups_str=getGroupName(user.GID)+", ";
var groups_full_str=getGroupName(user.GID)+", ";
var group_field;
var groups_str="";
if (user.GROUPS.ID.constructor == Array){ //several groups
for (var i=0; i< user.GROUPS.ID.length; i++){
groups_str+=getGroupName(user.GROUPS.ID[i])+', ';
};
groups_str = groups_str.slice(0,-2);
} else { //one group
groups_str = getGroupName(user.GROUPS.ID);
};
if (user.GROUPS.ID){
$.each(user.GROUPS.ID,function() {
if (i<=5) {
groups_str+=getGroupName(this)+", ";
};
groups_full_str+=getGroupName(this)+", ";
i++;
});
if (i>0){
groups_str = groups_str.slice(0, -2);
groups_full_str = groups_str.slice(0, -2);
};
if (i>5){
groups_str+="...";
group_field = '<div class="shortened_info">'+groups_str+'</div><div class="full_info" style="display:none">'+groups_full_str+'</div>';
} else {
group_field=groups_str;
};
}
// var groups_full_str=getGroupName(user.GID)+", ";
// var group_field;
// if (user.GROUPS.ID){
// $.each(user.GROUPS.ID,function() {
// if (i<=5) {
// groups_str+=getGroupName(this)+", ";
// };
// groups_full_str+=getGroupName(this)+", ";
// i++;
// });
// if (i>0){
// groups_str = groups_str.slice(0, -2);
// groups_full_str = groups_str.slice(0, -2);
// };
// if (i>5){
// groups_str+="...";
// group_field = '<div class="shortened_info">'+groups_str+'</div><div class="full_info" style="display:none">'+groups_full_str+'</div>';
// } else {
// group_field=groups_str;
// };
// }
@ -177,7 +246,7 @@ function userElementArray(user_json){
'<input type="checkbox" id="user_'+user.ID+'" name="selected_items" value="'+user.ID+'"/>',
user.ID,
name,
group_field
groups_str
]
}

View File

@ -580,8 +580,8 @@ function vMachineElementArray(vm_json){
return [
'<input type="checkbox" id="vm_'+vm.ID+'" name="selected_items" value="'+vm.ID+'"/>',
vm.ID,
getUserName(vm.UID),
getGroupName(vm.GID),
vm.UNAME,
vm.GNAME,
vm.NAME,
state,
vm.CPU,
@ -659,6 +659,14 @@ function updateVMInfo(request,vm){
<td class="key_td">Name</td>\
<td class="value_td">'+vm_info.NAME+'</td>\
</tr>\
<tr>\
<td class="key_td">Owner</td>\
<td class="value_td">'+vm_info.UNAME+'</td>\
</tr>\
<tr>\
<td class="key_td">Group</td>\
<td class="value_td">'+vm_info.GNAME+'</td>\
</tr>\
<tr>\
<td class="key_td">State</td>\
<td class="value_td">'+OpenNebula.Helper.resource_state("vm",vm_info.STATE)+'</td>\

View File

@ -318,8 +318,8 @@ function vNetworkElementArray(vn_json){
return [
'<input type="checkbox" id="vnetwork_'+network.ID+'" name="selected_items" value="'+network.ID+'"/>',
network.ID,
getUserName(network.UID),
getGroupName(network.GID),
network.UNAME,
network.GNAME,
network.NAME,
parseInt(network.TYPE) ? "FIXED" : "RANGED",
network.BRIDGE,
@ -401,8 +401,12 @@ function updateVNetworkInfo(request,vn){
<td class="value_td">'+vn_info.ID+'</td>\
<tr>\
<tr>\
<td class="key_td">UID</td>\
<td class="value_td">'+vn_info.UID+'</td>\
<td class="key_td">Owner</td>\
<td class="value_td">'+vn_info.UNAME+'</td>\
</tr>\
<tr>\
<td class="key_td">Group</td>\
<td class="value_td">'+vn_info.GNAME+'</td>\
</tr>\
<tr>\
<td class="key_td">Public</td>\

Some files were not shown because too many files have changed in this diff Show More