mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-07 17:17:41 +03:00
Merge remote branch 'origin/master' into feature-1223
This commit is contained in:
commit
17635e19c3
@ -18,6 +18,7 @@
|
||||
#define ACL_MANAGER_H_
|
||||
|
||||
#include "AuthManager.h"
|
||||
#include "AuthRequest.h"
|
||||
#include "PoolObjectSQL.h"
|
||||
#include "AclRule.h"
|
||||
|
||||
|
@ -239,7 +239,10 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the string value
|
||||
* @param name of the attribute
|
||||
*
|
||||
* @return the value of the attribute if found, empty otherwise
|
||||
*/
|
||||
string vector_value(const char *name) const;
|
||||
|
||||
@ -251,7 +254,18 @@ public:
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int vector_value(const char *name, int & value) const;
|
||||
int vector_value(const char *name, int& value) const;
|
||||
|
||||
/**
|
||||
* Returns the integer value
|
||||
*
|
||||
* @param name Name of the attribute
|
||||
* @param value Integer value, if an error ocurred the string returned is
|
||||
* empty and value set to -1;
|
||||
*
|
||||
* @return the value in string form on success, "" otherwise
|
||||
*/
|
||||
string vector_value_str(const char *name, int& value) const;
|
||||
|
||||
/**
|
||||
* Marshall the attribute in a single string. The string MUST be freed
|
||||
@ -290,7 +304,19 @@ public:
|
||||
* Replace the value of the given vector attribute
|
||||
*/
|
||||
void replace(const string& name, const string& value);
|
||||
|
||||
|
||||
/**
|
||||
* Replace the value of the given vector attribute
|
||||
*/
|
||||
void replace(const string& name, int value)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << value;
|
||||
|
||||
replace(name, oss.str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute type
|
||||
*/
|
||||
|
@ -21,11 +21,8 @@
|
||||
|
||||
#include "MadManager.h"
|
||||
#include "ActionManager.h"
|
||||
#include "SSLTools.h"
|
||||
|
||||
#include "AuthManagerDriver.h"
|
||||
#include "PoolObjectSQL.h"
|
||||
#include "PoolObjectAuth.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -43,16 +40,11 @@ class AuthManager : public MadManager, public ActionListener
|
||||
public:
|
||||
|
||||
AuthManager(
|
||||
time_t timer,
|
||||
time_t __time_out,
|
||||
vector<const Attribute*>& _mads):
|
||||
time_t timer,
|
||||
vector<const Attribute*>& _mads):
|
||||
MadManager(_mads), timer_period(timer)
|
||||
{
|
||||
_time_out = __time_out;
|
||||
|
||||
am.addListener(this);
|
||||
|
||||
pthread_mutex_init(&mutex,0);
|
||||
};
|
||||
|
||||
~AuthManager(){};
|
||||
@ -99,32 +91,6 @@ public:
|
||||
return authm_thread;
|
||||
};
|
||||
|
||||
/**
|
||||
* Notify the result of an auth request
|
||||
*/
|
||||
void notify_request(int auth_id, bool result, const string& message);
|
||||
|
||||
/**
|
||||
* Discards a pending request. Call this before freeing not notified or
|
||||
* timeout requests.
|
||||
*/
|
||||
void discard_request(int auth_id)
|
||||
{
|
||||
lock();
|
||||
|
||||
auth_requests.erase(auth_id);
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets default timeout for Auth requests
|
||||
*/
|
||||
static time_t time_out()
|
||||
{
|
||||
return _time_out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there is an authorization driver enabled
|
||||
*
|
||||
@ -146,21 +112,6 @@ private:
|
||||
*/
|
||||
ActionManager am;
|
||||
|
||||
/**
|
||||
* List of pending requests
|
||||
*/
|
||||
map<int, AuthRequest *> auth_requests;
|
||||
|
||||
/**
|
||||
* Mutex to access the auth_requests
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
/**
|
||||
* Default timeout for Auth requests
|
||||
*/
|
||||
static time_t _time_out;
|
||||
|
||||
/**
|
||||
* Timer for the Manager (periocally triggers timer action)
|
||||
*/
|
||||
@ -230,287 +181,6 @@ private:
|
||||
* This function authorizes a user request
|
||||
*/
|
||||
void authorize_action(AuthRequest * ar);
|
||||
|
||||
/**
|
||||
* This function is periodically executed to check time_outs on requests
|
||||
*/
|
||||
void timer_action();
|
||||
|
||||
/**
|
||||
* Function to lock the pool
|
||||
*/
|
||||
void lock()
|
||||
{
|
||||
pthread_mutex_lock(&mutex);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to unlock the pool
|
||||
*/
|
||||
void unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a new request to the Request map
|
||||
* @param ar pointer to the AuthRequest
|
||||
* @return the id for the request
|
||||
*/
|
||||
int add_request(AuthRequest *ar);
|
||||
|
||||
/**
|
||||
* Gets request from the Request map
|
||||
* @param id for the request
|
||||
* @return pointer to the AuthRequest
|
||||
*/
|
||||
AuthRequest * get_request(int id);
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The AuthRequest class is used to pass an Authorization or Authentication
|
||||
* request to the AuthManager. The result of the request will be stored
|
||||
* in the result and message attributes of this class.
|
||||
*/
|
||||
class AuthRequest : public ActionListener
|
||||
{
|
||||
public:
|
||||
AuthRequest(int _uid, int _gid):
|
||||
result(false),
|
||||
timeout(false),
|
||||
uid(_uid),
|
||||
gid(_gid),
|
||||
time_out(0),
|
||||
self_authorize(true)
|
||||
{
|
||||
am.addListener(this);
|
||||
};
|
||||
|
||||
~AuthRequest(){};
|
||||
|
||||
/**
|
||||
* Authorization Request Type
|
||||
*/
|
||||
enum Operation
|
||||
{
|
||||
USE = 0x1LL, /**< Auth. to use an object */
|
||||
MANAGE = 0x2LL, /**< Auth. to perform management actions */
|
||||
ADMIN = 0x4LL, /**< Auth. to perform administrative actions */
|
||||
CREATE = 0x8LL /**< Auth. to create an object */
|
||||
};
|
||||
|
||||
static string operation_to_str(Operation op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case USE: return "USE";
|
||||
case MANAGE: return "MANAGE";
|
||||
case ADMIN: return "ADMIN";
|
||||
case CREATE: return "CREATE";
|
||||
default: return "";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the challenge to authenticate an user
|
||||
* @param challenge a driver specific authentication challenge
|
||||
*/
|
||||
void add_authenticate(const string &_driver,
|
||||
const string &_username,
|
||||
const string &_password,
|
||||
const string &_session)
|
||||
{
|
||||
username = _username;
|
||||
password = _password;
|
||||
session = _session;
|
||||
|
||||
driver = _driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a CREATE authorization request.
|
||||
*
|
||||
* OBJECT:<-1|OBJECT_TMPL_XML64>:CREATE:UID:AUTH
|
||||
*
|
||||
* @param type of the object to be created
|
||||
* @param template (base64 encoded) of the new object
|
||||
*/
|
||||
void add_create_auth(PoolObjectSQL::ObjectType type, const string& txml_64)
|
||||
{
|
||||
PoolObjectAuth perms; //oid & gid set to -1
|
||||
|
||||
perms.uid = uid;
|
||||
perms.obj_type = type;
|
||||
|
||||
add_auth(AuthRequest::CREATE, perms, txml_64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new authorization item to this request
|
||||
*
|
||||
* OBJECT:OBJECT_ID:ACTION:OWNER:AUTH
|
||||
*
|
||||
* @param op the operation to be authorized
|
||||
* @param ob_perms object's permission attributes
|
||||
*/
|
||||
void add_auth(Operation op,
|
||||
const PoolObjectAuth& ob_perms)
|
||||
{
|
||||
add_auth(op, ob_perms, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the authorization requests in a single string
|
||||
* @return a space separated list of auth requests, or an empty string if
|
||||
* no auth requests were added
|
||||
*/
|
||||
string get_auths()
|
||||
{
|
||||
ostringstream oss;
|
||||
unsigned int i;
|
||||
|
||||
if ( auths.empty() )
|
||||
{
|
||||
return string();
|
||||
}
|
||||
|
||||
for (i=0; i<auths.size()-1; i++)
|
||||
{
|
||||
oss << auths[i] << " ";
|
||||
}
|
||||
|
||||
oss << auths[i];
|
||||
|
||||
return oss.str();
|
||||
};
|
||||
|
||||
/**
|
||||
* Notify client that we have an answer for the request
|
||||
*/
|
||||
void notify()
|
||||
{
|
||||
am.trigger(ActionListener::ACTION_FINALIZE,0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Wait for the AuthRequest to be completed
|
||||
*/
|
||||
void wait()
|
||||
{
|
||||
time_out = time(0) + AuthManager::time_out();
|
||||
|
||||
am.loop(0,0);
|
||||
};
|
||||
|
||||
bool core_authorize()
|
||||
{
|
||||
return ( uid == 0 || self_authorize );
|
||||
}
|
||||
|
||||
bool core_authenticate()
|
||||
{
|
||||
string sha1_session = SSLTools::sha1_digest(session);
|
||||
|
||||
return (password == sha1_session);
|
||||
}
|
||||
|
||||
/**
|
||||
* The result of the request, true if authorized or authenticated
|
||||
*/
|
||||
bool result;
|
||||
|
||||
/**
|
||||
* Error message for negative results
|
||||
*/
|
||||
string message;
|
||||
|
||||
/**
|
||||
* Time out
|
||||
*/
|
||||
bool timeout;
|
||||
|
||||
/**
|
||||
* Identification of this request
|
||||
*/
|
||||
int id;
|
||||
|
||||
private:
|
||||
|
||||
friend class AuthManager;
|
||||
|
||||
/**
|
||||
* The ActionManager that will be notify when the request is ready.
|
||||
*/
|
||||
ActionManager am;
|
||||
|
||||
/**
|
||||
* The user id for this request
|
||||
*/
|
||||
int uid;
|
||||
|
||||
/**
|
||||
* The user group ID
|
||||
*/
|
||||
int gid;
|
||||
|
||||
/**
|
||||
* Timeout for this request
|
||||
*/
|
||||
time_t time_out;
|
||||
|
||||
/**
|
||||
* Username to authenticate the user
|
||||
*/
|
||||
string username;
|
||||
|
||||
/**
|
||||
* User password to authenticate the user
|
||||
*/
|
||||
string password;
|
||||
|
||||
/**
|
||||
* Authentication token as sent in the XML-RPC call (user:session)
|
||||
*/
|
||||
string session;
|
||||
|
||||
/**
|
||||
* Authentication driver to be used with this request
|
||||
*/
|
||||
string driver;
|
||||
|
||||
/**
|
||||
* A list of authorization requests
|
||||
*/
|
||||
vector<string> auths;
|
||||
|
||||
/**
|
||||
* Plain authorization for the request
|
||||
*/
|
||||
bool self_authorize;
|
||||
|
||||
/**
|
||||
* No actions defined for the Auth request, just FINALIZE when done
|
||||
*/
|
||||
void do_action(const string &name, void *args){};
|
||||
|
||||
/**
|
||||
* Adds a new authorization item to this request, with a template for
|
||||
* a new object
|
||||
*
|
||||
* OBJECT:<OBJECT_ID|OBJECT_TMPL_XML64>:ACTION:OWNER:AUTH
|
||||
*
|
||||
* @param op the operation to be authorized
|
||||
* @param ob_perms object's permission attributes
|
||||
* @param ob_template new object's template. If it is empty,
|
||||
* it will be ignored
|
||||
*/
|
||||
void add_auth(Operation op,
|
||||
const PoolObjectAuth& ob_perms,
|
||||
string ob_template);
|
||||
};
|
||||
|
||||
#endif /*AUTH_MANAGER_H*/
|
||||
|
211
include/AuthRequest.h
Normal file
211
include/AuthRequest.h
Normal file
@ -0,0 +1,211 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 AUTH_REQUEST_H_
|
||||
#define AUTH_REQUEST_H_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "ActionManager.h"
|
||||
#include "PoolObjectAuth.h"
|
||||
#include "SSLTools.h"
|
||||
#include "AuthManager.h"
|
||||
|
||||
#include "SyncRequest.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* The AuthRequest class is used to pass an Authorization or Authentication
|
||||
* request to the AuthManager. The result of the request will be stored
|
||||
* in the result and message attributes of this class.
|
||||
*/
|
||||
class AuthRequest : public SyncRequest
|
||||
{
|
||||
public:
|
||||
AuthRequest(int _uid, int _gid): uid(_uid),gid(_gid),self_authorize(true){};
|
||||
|
||||
~AuthRequest(){};
|
||||
|
||||
/**
|
||||
* Authorization Request Type
|
||||
*/
|
||||
enum Operation
|
||||
{
|
||||
USE = 0x1LL, /**< Auth. to use an object */
|
||||
MANAGE = 0x2LL, /**< Auth. to perform management actions */
|
||||
ADMIN = 0x4LL, /**< Auth. to perform administrative actions */
|
||||
CREATE = 0x8LL /**< Auth. to create an object */
|
||||
};
|
||||
|
||||
static string operation_to_str(Operation op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case USE: return "USE";
|
||||
case MANAGE: return "MANAGE";
|
||||
case ADMIN: return "ADMIN";
|
||||
case CREATE: return "CREATE";
|
||||
default: return "";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the challenge to authenticate an user
|
||||
* @param challenge a driver specific authentication challenge
|
||||
*/
|
||||
void add_authenticate(const string &_driver,
|
||||
const string &_username,
|
||||
const string &_password,
|
||||
const string &_session)
|
||||
{
|
||||
username = _username;
|
||||
password = _password;
|
||||
session = _session;
|
||||
|
||||
driver = _driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a CREATE authorization request.
|
||||
*
|
||||
* OBJECT:<-1|OBJECT_TMPL_XML64>:CREATE:UID:AUTH
|
||||
*
|
||||
* @param type of the object to be created
|
||||
* @param template (base64 encoded) of the new object
|
||||
*/
|
||||
void add_create_auth(PoolObjectSQL::ObjectType type, const string& txml_64)
|
||||
{
|
||||
PoolObjectAuth perms; //oid & gid set to -1
|
||||
|
||||
perms.uid = uid;
|
||||
perms.obj_type = type;
|
||||
|
||||
add_auth(AuthRequest::CREATE, perms, txml_64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new authorization item to this request
|
||||
*
|
||||
* OBJECT:OBJECT_ID:ACTION:OWNER:AUTH
|
||||
*
|
||||
* @param op the operation to be authorized
|
||||
* @param ob_perms object's permission attributes
|
||||
*/
|
||||
void add_auth(Operation op,
|
||||
const PoolObjectAuth& ob_perms)
|
||||
{
|
||||
add_auth(op, ob_perms, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the authorization requests in a single string
|
||||
* @return a space separated list of auth requests, or an empty string if
|
||||
* no auth requests were added
|
||||
*/
|
||||
string get_auths()
|
||||
{
|
||||
ostringstream oss;
|
||||
unsigned int i;
|
||||
|
||||
if ( auths.empty() )
|
||||
{
|
||||
return string();
|
||||
}
|
||||
|
||||
for (i=0; i<auths.size()-1; i++)
|
||||
{
|
||||
oss << auths[i] << " ";
|
||||
}
|
||||
|
||||
oss << auths[i];
|
||||
|
||||
return oss.str();
|
||||
};
|
||||
|
||||
bool core_authorize()
|
||||
{
|
||||
return ( uid == 0 || self_authorize );
|
||||
}
|
||||
|
||||
bool core_authenticate()
|
||||
{
|
||||
string sha1_session = SSLTools::sha1_digest(session);
|
||||
|
||||
return (password == sha1_session);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend class AuthManager;
|
||||
|
||||
/**
|
||||
* The user id for this request
|
||||
*/
|
||||
int uid;
|
||||
|
||||
/**
|
||||
* The user group ID
|
||||
*/
|
||||
int gid;
|
||||
|
||||
/**
|
||||
* Username to authenticate the user
|
||||
*/
|
||||
string username;
|
||||
|
||||
/**
|
||||
* User password to authenticate the user
|
||||
*/
|
||||
string password;
|
||||
|
||||
/**
|
||||
* Authentication token as sent in the XML-RPC call (user:session)
|
||||
*/
|
||||
string session;
|
||||
|
||||
/**
|
||||
* Authentication driver to be used with this request
|
||||
*/
|
||||
string driver;
|
||||
|
||||
/**
|
||||
* A list of authorization requests
|
||||
*/
|
||||
vector<string> auths;
|
||||
|
||||
/**
|
||||
* Plain authorization for the request
|
||||
*/
|
||||
bool self_authorize;
|
||||
|
||||
/**
|
||||
* Adds a new authorization item to this request, with a template for
|
||||
* a new object
|
||||
*
|
||||
* OBJECT:<OBJECT_ID|OBJECT_TMPL_XML64>:ACTION:OWNER:AUTH
|
||||
*
|
||||
* @param op the operation to be authorized
|
||||
* @param ob_perms object's permission attributes
|
||||
* @param ob_template new object's template. If it is empty,
|
||||
* it will be ignored
|
||||
*/
|
||||
void add_auth(Operation op,
|
||||
const PoolObjectAuth& ob_perms,
|
||||
string ob_template);
|
||||
};
|
||||
|
||||
#endif
|
@ -20,6 +20,7 @@
|
||||
#include "PoolSQL.h"
|
||||
#include "ObjectCollection.h"
|
||||
#include "User.h"
|
||||
#include "Quotas.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -65,6 +66,11 @@ public:
|
||||
return del_collection_id(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Object quotas, provides set and check interface
|
||||
*/
|
||||
Quotas quota;
|
||||
|
||||
private:
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -79,7 +85,11 @@ private:
|
||||
|
||||
Group(int id, const string& name):
|
||||
PoolObjectSQL(id,GROUP,name,-1,-1,"","",table),
|
||||
ObjectCollection("USERS")
|
||||
ObjectCollection("USERS"),
|
||||
quota("/GROUP/DATASTORE_QUOTA",
|
||||
"/GROUP/NETWORK_QUOTA",
|
||||
"/GROUP/IMAGE_QUOTA",
|
||||
"/GROUP/VM_QUOTA")
|
||||
{
|
||||
// Allow users in this group to see it
|
||||
group_u = 1;
|
||||
|
@ -55,6 +55,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the string representation of an ImageType
|
||||
* @param ob the type
|
||||
* @return the string
|
||||
*/
|
||||
static ImageType str_to_type(string& str_type);
|
||||
|
||||
/**
|
||||
* Type of Disks (used by the VMM_MAD). Values: BLOCK, CDROM or
|
||||
* FILE
|
||||
|
@ -26,6 +26,7 @@ using namespace std;
|
||||
extern "C" void * image_action_loop(void *arg);
|
||||
|
||||
class Image;
|
||||
class Template;
|
||||
|
||||
class ImageManager : public MadManager, public ActionListener
|
||||
{
|
||||
@ -125,6 +126,18 @@ public:
|
||||
*/
|
||||
int delete_image(int iid, const string& ds_data);
|
||||
|
||||
/**
|
||||
* Gets the size of an image by calling the STAT action of the associated
|
||||
* datastore driver.
|
||||
*
|
||||
* @param img_tmpl the template for the image
|
||||
* @param ds_tmpl the template for the datastore
|
||||
* @oaram result with a string representation of the size or if an error
|
||||
* occurred describing the error.
|
||||
* @result 0 on success
|
||||
*/
|
||||
int stat_image(Template* img_tmpl, const string& ds_tmpl, string& res);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Generic name for the Image driver
|
||||
|
@ -71,27 +71,26 @@ private:
|
||||
//Template driver_conf;
|
||||
|
||||
/**
|
||||
* Sends a copy request to the MAD
|
||||
* Sends a copy request to the MAD.
|
||||
* @param oid the image id.
|
||||
* @param drv_msg xml data for the mad operation.
|
||||
*/
|
||||
void cp(int oid, const string& drv_msg) const;
|
||||
|
||||
/**
|
||||
* Sends a move request to the MAD: "MV IMAGE_ID SRC_PATH DST_PATH"
|
||||
* @param oid the image id.
|
||||
* @param destination is a driver specific location or "-" if not
|
||||
* initialized
|
||||
* @param size_mb of the image to be created
|
||||
* Sends a stat request to the MAD.
|
||||
* @param oid the id of the stat request
|
||||
* @param drv_msg xml data for the mad operation.
|
||||
*/
|
||||
void mv(int oid, const string& source, const string& destination) const;
|
||||
void stat(int oid, const string& drv_msg) const;
|
||||
|
||||
/**
|
||||
* Sends a make filesystem request to the MAD: "MKFS IMAGE_ID PATH SIZE_MB"
|
||||
* Sends a make filesystem request to the MAD.
|
||||
* @param oid the image id.
|
||||
* @param drv_msg xml data for the mad operation.
|
||||
*/
|
||||
void mkfs(int oid, const string& drv_msg) const;
|
||||
|
||||
/**
|
||||
* Sends a delete request to the MAD: "DELETE IMAGE_ID PATH"
|
||||
* @param oid the image id.
|
||||
|
@ -30,6 +30,8 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
class SyncRequest;
|
||||
|
||||
extern "C" void * mad_manager_listener(void * _mm);
|
||||
|
||||
/**
|
||||
@ -54,7 +56,12 @@ public:
|
||||
* sudo application.
|
||||
*/
|
||||
virtual void load_mads(int uid) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Notify the result of an auth request
|
||||
*/
|
||||
void notify_request(int id, bool result, const string& message);
|
||||
|
||||
protected:
|
||||
|
||||
MadManager(vector<const Attribute *>& _mads);
|
||||
@ -93,7 +100,28 @@ protected:
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int add(Mad *mad);
|
||||
|
||||
|
||||
/**
|
||||
* This function can be periodically executed to check time_outs on
|
||||
* request. It will fail requests with an expired timeout and will notify
|
||||
* the clients.
|
||||
*/
|
||||
void check_time_outs_action();
|
||||
|
||||
/**
|
||||
* Add a new request to the Request map
|
||||
* @param ar pointer to the request
|
||||
* @return the id for the request
|
||||
*/
|
||||
void add_request(SyncRequest *ar);
|
||||
|
||||
/**
|
||||
* Gets request from the Request map
|
||||
* @param id for the request
|
||||
* @return pointer to the Request
|
||||
*/
|
||||
SyncRequest * get_request(int id);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Function to lock the Manager
|
||||
@ -155,11 +183,16 @@ private:
|
||||
* can be free upon listener thread cancellation.
|
||||
*/
|
||||
ostringstream buffer;
|
||||
|
||||
/**
|
||||
* List of pending requests
|
||||
*/
|
||||
map<int, SyncRequest *> sync_requests;
|
||||
|
||||
/**
|
||||
* Listener thread implementation.
|
||||
*/
|
||||
void listener();
|
||||
void listener();
|
||||
};
|
||||
|
||||
#endif /*MAD_MANAGER_H_*/
|
||||
|
175
include/Quota.h
Normal file
175
include/Quota.h
Normal file
@ -0,0 +1,175 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 QUOTA_H_
|
||||
#define QUOTA_H_
|
||||
|
||||
#include "Template.h"
|
||||
|
||||
/**
|
||||
* Base class for resource quotas, it provides basic storage and management of
|
||||
* the quotas. Each resource MUST inherit from it to implement check and
|
||||
* update methods. Quotas are stored in a template form, each class store the
|
||||
* limits and usage in a resource specific format.
|
||||
*/
|
||||
class Quota: public Template
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Set the quotas. If the quota previously exists its limit is updated.
|
||||
* @param quota_str the quota template in ASCII or XML formats
|
||||
* @param error describe the error in case of error
|
||||
* @return 0 on success -1 otherwise
|
||||
*/
|
||||
int set(vector<Attribute*> * quotas, string& error);
|
||||
|
||||
/**
|
||||
* Check if the resource allocation will exceed the quota limits. If not
|
||||
* the usage counters are updated
|
||||
* @param tmpl template for the resource
|
||||
* @param error string
|
||||
* @return true if the operation can be performed
|
||||
*/
|
||||
virtual bool check(Template* tmpl, string& error) = 0;
|
||||
|
||||
/**
|
||||
* Decrement usage counters when deallocating image
|
||||
* @param tmpl template for the resource
|
||||
*/
|
||||
virtual void del(Template* tmpl) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name that identifies the quota in a template
|
||||
*/
|
||||
const char * get_quota_name()
|
||||
{
|
||||
return template_name;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
Quota(const char * quota_name,
|
||||
const char * _template_name,
|
||||
const char ** _metrics,
|
||||
int _num_metrics)
|
||||
: Template(false, '=', quota_name),
|
||||
template_name(_template_name),
|
||||
metrics(_metrics),
|
||||
num_metrics(_num_metrics){};
|
||||
|
||||
virtual ~Quota(){};
|
||||
|
||||
/**
|
||||
* Generic Quota Names
|
||||
*
|
||||
* template_name = [
|
||||
* ID = "ID to identify the resource",
|
||||
* metrics[0] = "Limit for the first metric"
|
||||
* metrics[0]_USED = "Usage for metric"
|
||||
* ]
|
||||
*
|
||||
* ID & counter fields are optional
|
||||
*/
|
||||
|
||||
/**
|
||||
* Name of the quota used in the templates
|
||||
*/
|
||||
const char * template_name;
|
||||
|
||||
/**
|
||||
* The name of the quota metrics
|
||||
*/
|
||||
const char ** metrics;
|
||||
|
||||
/**
|
||||
* Length
|
||||
*/
|
||||
int num_metrics;
|
||||
|
||||
/**
|
||||
* Check a given quota for an usage request and update counters if the
|
||||
* request does not exceed quota limits
|
||||
* @param qid id that identifies the quota, to be used by get_quota
|
||||
* @param usage_req usage for each metric
|
||||
* @return true if the request does not exceed current limits
|
||||
*/
|
||||
bool check_quota(const string& qid,
|
||||
map<string, int>& usage_req,
|
||||
string& error);
|
||||
|
||||
/**
|
||||
* Reduce usage from a given quota based on the current consumption
|
||||
* @param qid id that identifies the quota, to be used by get_quota
|
||||
* @param usage_req usage for each metric
|
||||
*/
|
||||
void del_quota(const string& qid,
|
||||
map<string, int>& usage_req);
|
||||
|
||||
/**
|
||||
* Gets a quota identified by its ID.
|
||||
* @param id of the quota
|
||||
* @return a pointer to the quota or 0 if not found
|
||||
*/
|
||||
virtual int get_quota(const string& id, VectorAttribute **va);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Creates an empty quota based on the given attribute. The attribute va
|
||||
* contains the limits for the quota.
|
||||
* @param va limits for the new quota if 0 limits will be 0
|
||||
* @return a new attribute representing the quota
|
||||
*/
|
||||
VectorAttribute * new_quota(VectorAttribute* va);
|
||||
|
||||
/**
|
||||
* Adds a new quota, it also updates an internal index for fast accessing
|
||||
* the quotas
|
||||
* @param quota is the new quota, allocated in the HEAP
|
||||
*/
|
||||
void add(VectorAttribute * nq)
|
||||
{
|
||||
attributes.insert(make_pair(nq->name(), nq));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a given value to the current quota (vector)
|
||||
* @param attr the quota;
|
||||
* @param va_name name of the quota in the vector attribute
|
||||
* @param num value to add to the current quota;
|
||||
*/
|
||||
void add_to_quota(VectorAttribute * attr, const string& va_name, int num);
|
||||
|
||||
/**
|
||||
* Sets new limit values for the quota
|
||||
* @param quota to be updated
|
||||
* @param va attribute with the new limits
|
||||
* @return 0 on success or -1 if wrong limits
|
||||
*/
|
||||
int update_limits(VectorAttribute* quota, const VectorAttribute* va);
|
||||
|
||||
/**
|
||||
* Extract the limits for the defined quota metrics from a given attribute
|
||||
* @param va the attribute with the limits
|
||||
* @param limits stores the known limits
|
||||
* @return 0 on success
|
||||
*/
|
||||
int get_limits(const VectorAttribute * va, map<string, string>& limits);
|
||||
};
|
||||
|
||||
#endif /*QUOTA_H_*/
|
68
include/QuotaDatastore.h
Normal file
68
include/QuotaDatastore.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 QUOTA_DATASTORE_H_
|
||||
#define QUOTA_DATASTORE_H_
|
||||
|
||||
#include "Quota.h"
|
||||
|
||||
/**
|
||||
* DataStore Quotas, defined as:
|
||||
* DATASTORE = [
|
||||
* ID = <ID of the datastore>
|
||||
* IMAGES = <Max. number of images allowed in the datastore>
|
||||
* SIZE = <Max. number of MB used in the datastore>
|
||||
* IMAGES_USED = Current number of images in the datastore
|
||||
* SIZE_USED = Current storage capacity un the datastore
|
||||
* ]
|
||||
*
|
||||
* 0 = unlimited, default if missing
|
||||
*/
|
||||
|
||||
class QuotaDatastore : public Quota
|
||||
{
|
||||
public:
|
||||
|
||||
QuotaDatastore():Quota("DATASTORE_QUOTA",
|
||||
"DATASTORE",
|
||||
DS_METRICS,
|
||||
NUM_DS_METRICS)
|
||||
{};
|
||||
|
||||
~QuotaDatastore(){};
|
||||
|
||||
/**
|
||||
* Check if the resource allocation will exceed the quota limits. If not
|
||||
* the usage counters are updated
|
||||
* @param tmpl template for the resource
|
||||
* @param error string
|
||||
* @return true if the operation can be performed
|
||||
*/
|
||||
bool check(Template* tmpl, string& error);
|
||||
|
||||
/**
|
||||
* Decrement usage counters when deallocating image
|
||||
* @param tmpl template for the resource
|
||||
*/
|
||||
void del(Template* tmpl);
|
||||
|
||||
protected:
|
||||
static const char * DS_METRICS[];
|
||||
|
||||
static const int NUM_DS_METRICS;
|
||||
};
|
||||
|
||||
#endif /*QUOTA_DATASTORE_H_*/
|
66
include/QuotaImage.h
Normal file
66
include/QuotaImage.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 QUOTA_IMAGE_H_
|
||||
#define QUOTA_IMAGE_H_
|
||||
|
||||
#include "Quota.h"
|
||||
|
||||
/**
|
||||
* Image Quotas, defined as:
|
||||
* IMAGE = [
|
||||
* ID = <ID of the image>
|
||||
* RVMS = <Max. number times the image can be instantiated>
|
||||
* RVMS _USED = Current number of VMs using the image
|
||||
* ]
|
||||
*
|
||||
* 0 = unlimited, default if missing
|
||||
*/
|
||||
|
||||
class QuotaImage : public Quota
|
||||
{
|
||||
public:
|
||||
|
||||
QuotaImage():Quota("IMAGE_QUOTA",
|
||||
"IMAGE",
|
||||
IMAGE_METRICS,
|
||||
NUM_IMAGE_METRICS)
|
||||
{};
|
||||
|
||||
~QuotaImage(){};
|
||||
|
||||
/**
|
||||
* Check if the resource allocation will exceed the quota limits. If not
|
||||
* the usage counters are updated
|
||||
* @param tmpl template for the resource
|
||||
* @param error string
|
||||
* @return true if the operation can be performed
|
||||
*/
|
||||
bool check(Template* tmpl, string& error);
|
||||
|
||||
/**
|
||||
* Decrement usage counters when deallocating image
|
||||
* @param tmpl template for the resource
|
||||
*/
|
||||
void del(Template* tmpl);
|
||||
|
||||
protected:
|
||||
static const char * IMAGE_METRICS[];
|
||||
|
||||
static const int NUM_IMAGE_METRICS;
|
||||
};
|
||||
|
||||
#endif /*QUOTA_IMAGE_H_*/
|
66
include/QuotaNetwork.h
Normal file
66
include/QuotaNetwork.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 QUOTA_NETWORK_H_
|
||||
#define QUOTA_NETWORK_H_
|
||||
|
||||
#include "Quota.h"
|
||||
|
||||
/**
|
||||
* DataStore Quotas, defined as:
|
||||
* NETWORK = [
|
||||
* ID = <ID of the datastore>
|
||||
* LEASES = <Max. number of IPs that can be leased from net>
|
||||
* LEASES_USED = Current number of IPs
|
||||
* ]
|
||||
*
|
||||
* 0 = unlimited, default if missing
|
||||
*/
|
||||
|
||||
class QuotaNetwork : public Quota
|
||||
{
|
||||
public:
|
||||
|
||||
QuotaNetwork():Quota("NETWORK_QUOTA",
|
||||
"NETWORK",
|
||||
NET_METRICS,
|
||||
NUM_NET_METRICS)
|
||||
{};
|
||||
|
||||
~QuotaNetwork(){};
|
||||
|
||||
/**
|
||||
* Check if the resource allocation will exceed the quota limits. If not
|
||||
* the usage counters are updated
|
||||
* @param tmpl template for the resource
|
||||
* @param error string
|
||||
* @return true if the operation can be performed
|
||||
*/
|
||||
bool check(Template* tmpl, string& error);
|
||||
|
||||
/**
|
||||
* Decrement usage counters when deallocating image
|
||||
* @param tmpl template for the resource
|
||||
*/
|
||||
void del(Template* tmpl);
|
||||
|
||||
protected:
|
||||
static const char * NET_METRICS[];
|
||||
|
||||
static const int NUM_NET_METRICS;
|
||||
};
|
||||
|
||||
#endif /*QUOTA_NETWORK_H_*/
|
76
include/QuotaVirtualMachine.h
Normal file
76
include/QuotaVirtualMachine.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 QUOTA_VIRTUALMACHINE_H_
|
||||
#define QUOTA_VIRTUALMACHINE_H_
|
||||
|
||||
#include "Quota.h"
|
||||
|
||||
/**
|
||||
* VM Quotas, defined as:
|
||||
* VM = [
|
||||
* VMS = <Max. number of VMs>
|
||||
* MEMORY = <Max. number of MB requested by VMs>
|
||||
* CPU = <Max. number of CPU units requested by VMs>
|
||||
* VMS_USED = Current number of VMs
|
||||
* MEMORY_USED = Overall Memory requested
|
||||
* CPU_USED = Overall CPU requested
|
||||
* ]
|
||||
*
|
||||
* 0 = unlimited, default if missing
|
||||
*/
|
||||
|
||||
class QuotaVirtualMachine : public Quota
|
||||
{
|
||||
public:
|
||||
|
||||
QuotaVirtualMachine():Quota("VM_QUOTA",
|
||||
"VM",
|
||||
VM_METRICS,
|
||||
NUM_VM_METRICS)
|
||||
{};
|
||||
|
||||
~QuotaVirtualMachine(){};
|
||||
|
||||
/**
|
||||
* Check if the resource allocation will exceed the quota limits. If not
|
||||
* the usage counters are updated
|
||||
* @param tmpl template for the resource
|
||||
* @param error string
|
||||
* @return true if the operation can be performed
|
||||
*/
|
||||
bool check(Template* tmpl, string& error);
|
||||
|
||||
/**
|
||||
* Decrement usage counters when deallocating image
|
||||
* @param tmpl template for the resource
|
||||
*/
|
||||
void del(Template* tmpl);
|
||||
|
||||
/**
|
||||
* Gets a quota, overrides base to not to use ID.
|
||||
* @param id of the quota
|
||||
* @return a pointer to the quota or 0 if not found
|
||||
*/
|
||||
int get_quota(const string& id, VectorAttribute **va);
|
||||
|
||||
protected:
|
||||
static const char * VM_METRICS[];
|
||||
|
||||
static const int NUM_VM_METRICS;
|
||||
};
|
||||
|
||||
#endif /*QUOTA_VIRTUALMACHINE_H_*/
|
284
include/Quotas.h
Normal file
284
include/Quotas.h
Normal file
@ -0,0 +1,284 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 QUOTAS_H_
|
||||
#define QUOTAS_H_
|
||||
|
||||
#include "QuotaDatastore.h"
|
||||
#include "QuotaNetwork.h"
|
||||
#include "QuotaVirtualMachine.h"
|
||||
#include "QuotaImage.h"
|
||||
|
||||
class Quotas
|
||||
{
|
||||
public:
|
||||
Quotas(const char * _ds_xpath,
|
||||
const char * _net_xpath,
|
||||
const char * _img_xpath,
|
||||
const char * _vm_xpath):
|
||||
ds_xpath(_ds_xpath),
|
||||
net_xpath(_net_xpath),
|
||||
img_xpath(_img_xpath),
|
||||
vm_xpath(_vm_xpath)
|
||||
{};
|
||||
|
||||
virtual ~Quotas(){};
|
||||
|
||||
/**
|
||||
* Set the quotas
|
||||
* @param tmpl contains the user quota limits
|
||||
* @param error describes error when setting the quotas
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int set(Template *tmpl, string& error)
|
||||
{
|
||||
vector<Attribute *> vquotas;
|
||||
|
||||
if ( tmpl->get(datastore_quota.get_quota_name(), vquotas) > 0 )
|
||||
{
|
||||
if ( datastore_quota.set(&vquotas, error) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
vquotas.clear();
|
||||
}
|
||||
|
||||
if ( tmpl->get(network_quota.get_quota_name(), vquotas) > 0 )
|
||||
{
|
||||
if ( network_quota.set(&vquotas, error) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
vquotas.clear();
|
||||
}
|
||||
|
||||
if ( tmpl->get(image_quota.get_quota_name(), vquotas) > 0 )
|
||||
{
|
||||
if ( image_quota.set(&vquotas, error) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
vquotas.clear();
|
||||
}
|
||||
|
||||
if ( tmpl->get(vm_quota.get_quota_name(), vquotas) > 0 )
|
||||
{
|
||||
if ( vm_quota.set(&vquotas, error) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
vquotas.clear();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Datastore quotas, it updates usage counters if quotas are not
|
||||
* exceeded.
|
||||
* @param tmpl template for the image
|
||||
* @param reason string describing the error
|
||||
* @return true if image can be allocated, false otherwise
|
||||
*/
|
||||
bool ds_check(Template * tmpl, string& reason)
|
||||
{
|
||||
return datastore_quota.check(tmpl, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete usage from quota counters.
|
||||
* @param tmpl template for the image, with usage
|
||||
*/
|
||||
void ds_del(Template * tmpl)
|
||||
{
|
||||
return datastore_quota.del(tmpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Virtual Machine quotas (network, image and compute), it updates
|
||||
* usage counters if quotas are not exceeded.
|
||||
* @param tmpl template for the VirtualMachine
|
||||
* @param error_str string describing the error
|
||||
* @return true if VM can be allocated, false otherwise
|
||||
*/
|
||||
bool vm_check(Template * tmpl, string& error_str)
|
||||
{
|
||||
|
||||
if ( network_quota.check(tmpl, error_str) == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( vm_quota.check(tmpl, error_str) == false )
|
||||
{
|
||||
network_quota.del(tmpl);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( image_quota.check(tmpl, error_str) == false )
|
||||
{
|
||||
network_quota.del(tmpl);
|
||||
vm_quota.del(tmpl);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete VM related usage (network, image and compute) from quota counters.
|
||||
* @param tmpl template for the image, with usage
|
||||
*/
|
||||
void vm_del(Template * tmpl)
|
||||
{
|
||||
network_quota.del(tmpl);
|
||||
vm_quota.del(tmpl);
|
||||
image_quota.del(tmpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of the quotas in XML format
|
||||
* @param xml the string to store the XML
|
||||
* @return the same xml string to use it in << compounds
|
||||
*/
|
||||
string& to_xml(string& xml) const
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
string ds_quota_xml;
|
||||
string net_quota_xml;
|
||||
string vm_quota_xml;
|
||||
string image_quota_xml;
|
||||
|
||||
oss << datastore_quota.to_xml(ds_quota_xml)
|
||||
<< network_quota.to_xml(net_quota_xml)
|
||||
<< vm_quota.to_xml(vm_quota_xml)
|
||||
<< image_quota.to_xml(image_quota_xml);
|
||||
|
||||
xml = oss.str();
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds quota object from an ObjectXML
|
||||
* @param object_xml pointer to the ObjectXML
|
||||
* @return 0 if success
|
||||
*/
|
||||
int from_xml(ObjectXML * object_xml)
|
||||
{
|
||||
vector<xmlNodePtr> content;
|
||||
int rc = 0;
|
||||
|
||||
object_xml->get_nodes(ds_xpath, content);
|
||||
|
||||
if (!content.empty())
|
||||
{
|
||||
rc += datastore_quota.from_xml_node(content[0]);
|
||||
}
|
||||
|
||||
object_xml->free_nodes(content);
|
||||
content.clear();
|
||||
|
||||
object_xml->get_nodes(net_xpath, content);
|
||||
|
||||
if (!content.empty())
|
||||
{
|
||||
rc += network_quota.from_xml_node(content[0]);
|
||||
}
|
||||
|
||||
object_xml->free_nodes(content);
|
||||
content.clear();
|
||||
|
||||
object_xml->get_nodes(vm_xpath, content);
|
||||
|
||||
if (!content.empty())
|
||||
{
|
||||
rc += vm_quota.from_xml_node(content[0]);
|
||||
}
|
||||
|
||||
object_xml->free_nodes(content);
|
||||
content.clear();
|
||||
|
||||
object_xml->get_nodes(img_xpath, content);
|
||||
|
||||
if (!content.empty())
|
||||
{
|
||||
rc += image_quota.from_xml_node(content[0]);
|
||||
}
|
||||
|
||||
object_xml->free_nodes(content);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------------
|
||||
// Usage Counters and Quotas
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Datastore Quotas
|
||||
*/
|
||||
QuotaDatastore datastore_quota;
|
||||
|
||||
/**
|
||||
* Network Quotas
|
||||
*/
|
||||
QuotaNetwork network_quota;
|
||||
|
||||
/**
|
||||
* Image Quotas
|
||||
*/
|
||||
QuotaImage image_quota;
|
||||
|
||||
/**
|
||||
* Virtual Machine Quotas
|
||||
*/
|
||||
QuotaVirtualMachine vm_quota;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// XPaths
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Path for the datastore quota object
|
||||
*/
|
||||
const char * ds_xpath;
|
||||
|
||||
/**
|
||||
* Path for the network quota object
|
||||
*/
|
||||
const char * net_xpath;
|
||||
|
||||
/**
|
||||
* Path for the image quota object
|
||||
*/
|
||||
const char * img_xpath;
|
||||
|
||||
/**
|
||||
* Path for the vm quota object
|
||||
*/
|
||||
const char * vm_xpath;
|
||||
|
||||
};
|
||||
|
||||
#endif /*QUOTABLE_H_*/
|
@ -21,7 +21,7 @@
|
||||
#include <xmlrpc-c/registry.hpp>
|
||||
|
||||
#include "RequestManager.h"
|
||||
#include "AuthManager.h"
|
||||
#include "AuthRequest.h"
|
||||
#include "PoolObjectSQL.h"
|
||||
|
||||
using namespace std;
|
||||
@ -75,6 +75,32 @@ protected:
|
||||
string session; /**< Session from ONE XML-RPC API */
|
||||
|
||||
xmlrpc_c::value * retval; /**< Return value from libxmlrpc-c */
|
||||
|
||||
RequestAttributes(){};
|
||||
|
||||
RequestAttributes(const RequestAttributes& ra)
|
||||
{
|
||||
uid = ra.uid;
|
||||
gid = ra.gid;
|
||||
|
||||
uname = ra.uname;
|
||||
gname = ra.gname;
|
||||
|
||||
session = ra.session;
|
||||
retval = ra.retval;
|
||||
};
|
||||
|
||||
RequestAttributes(int _uid, int _gid, const RequestAttributes& ra)
|
||||
{
|
||||
uid = _uid;
|
||||
gid = _gid;
|
||||
|
||||
uname = "";
|
||||
gname = "";
|
||||
|
||||
session = ra.session;
|
||||
retval = ra.retval;
|
||||
};
|
||||
};
|
||||
|
||||
/* -------- Static (shared among request of the same method) -------- */
|
||||
@ -130,7 +156,54 @@ protected:
|
||||
*/
|
||||
bool basic_authorization(int oid, AuthRequest::Operation op,
|
||||
RequestAttributes& att);
|
||||
|
||||
|
||||
/**
|
||||
* Performs a basic quota check for this request using the uid/gid and
|
||||
* object type from the request. Usage counters are updated for the
|
||||
* user/group.
|
||||
* @param tmpl describing the object
|
||||
* @param att the specific request attributes
|
||||
*
|
||||
* @return true if the user is authorized.
|
||||
*/
|
||||
bool quota_authorization(Template * tmpl, RequestAttributes& att)
|
||||
{
|
||||
return quota_authorization(tmpl, auth_object, att);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a basic quota check for this request using the uid/gid
|
||||
* from the request. Usage counters are updated for the user/group.
|
||||
* @param tmpl describing the object
|
||||
* @param object type of the object
|
||||
* @param att the specific request attributes
|
||||
*
|
||||
* @return true if the user is authorized.
|
||||
*/
|
||||
bool quota_authorization(Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att);
|
||||
/**
|
||||
* Performs rollback on usage counters for a previous quota check operation
|
||||
* for the request.
|
||||
* @param tmpl describing the object
|
||||
* @param att the specific request attributes
|
||||
*/
|
||||
void quota_rollback(Template * tmpl, RequestAttributes& att)
|
||||
{
|
||||
quota_rollback(tmpl, auth_object, att);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs rollback on usage counters for a previous quota check operation
|
||||
* for the request.
|
||||
* @param tmpl describing the object
|
||||
* @param att the specific request attributes
|
||||
*/
|
||||
void quota_rollback(Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att);
|
||||
|
||||
/**
|
||||
* Actual Execution method for the request. Must be implemented by the
|
||||
* XML-RPC requests
|
||||
@ -239,6 +312,27 @@ protected:
|
||||
RequestAttributes& att,
|
||||
PoolObjectAuth& perms,
|
||||
string& name);
|
||||
private:
|
||||
|
||||
/* ------------- Functions to manage user and group quotas -------------- */
|
||||
|
||||
bool user_quota_authorization(Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att,
|
||||
string& error_str);
|
||||
|
||||
bool group_quota_authorization(Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att,
|
||||
string& error_str);
|
||||
|
||||
void user_quota_rollback(Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att);
|
||||
|
||||
void group_quota_rollback(Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att);
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -52,6 +52,11 @@ protected:
|
||||
|
||||
virtual void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att);
|
||||
|
||||
PoolObjectSQL * get_and_quota(int oid,
|
||||
int new_uid,
|
||||
int new_gid,
|
||||
RequestAttributes& att);
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
72
include/RequestManagerGroup.h
Normal file
72
include/RequestManagerGroup.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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_GROUP_H
|
||||
#define REQUEST_MANAGER_GROUP_H
|
||||
|
||||
#include "Request.h"
|
||||
#include "Nebula.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class RequestManagerGroup: public Request
|
||||
{
|
||||
protected:
|
||||
RequestManagerGroup(const string& method_name,
|
||||
const string& help,
|
||||
const string& params)
|
||||
:Request(method_name,params,help)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_gpool();
|
||||
|
||||
auth_object = PoolObjectSQL::GROUP;
|
||||
};
|
||||
|
||||
virtual ~RequestManagerGroup(){};
|
||||
|
||||
virtual void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att) = 0;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class GroupSetQuota : public RequestManagerGroup
|
||||
{
|
||||
public:
|
||||
GroupSetQuota():
|
||||
RequestManagerGroup("GroupSetQuota",
|
||||
"Sets group quota limits",
|
||||
"A:sis")
|
||||
{
|
||||
auth_op = AuthRequest::ADMIN;
|
||||
};
|
||||
|
||||
~GroupSetQuota(){};
|
||||
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att);
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#endif
|
@ -97,6 +97,27 @@ public:
|
||||
string& err);
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class UserSetQuota : public RequestManagerUser
|
||||
{
|
||||
public:
|
||||
UserSetQuota():
|
||||
RequestManagerUser("UserSetQuota",
|
||||
"Sets user quota limits",
|
||||
"A:sis")
|
||||
{
|
||||
auth_op = AuthRequest::ADMIN;
|
||||
};
|
||||
|
||||
~UserSetQuota(){};
|
||||
|
||||
int user_action(int user_id,
|
||||
xmlrpc_c::paramList const& _paramList,
|
||||
string& err);
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
101
include/SyncRequest.h
Normal file
101
include/SyncRequest.h
Normal file
@ -0,0 +1,101 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 SYNC_REQUEST_H_
|
||||
#define SYNC_REQUEST_H_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "ActionManager.h"
|
||||
|
||||
/**
|
||||
* Base class to implement synchronous operation in the MadManagers. This class
|
||||
* cannot be directly instantiated.
|
||||
*/
|
||||
class SyncRequest: public ActionListener
|
||||
{
|
||||
public:
|
||||
SyncRequest():
|
||||
result(false),
|
||||
message(""),
|
||||
timeout(false),
|
||||
id(-1),
|
||||
time_out(0)
|
||||
{
|
||||
am.addListener(this);
|
||||
};
|
||||
|
||||
virtual ~SyncRequest(){};
|
||||
|
||||
/**
|
||||
* The result of the request, true if the operation succeeded
|
||||
*/
|
||||
bool result;
|
||||
|
||||
/**
|
||||
* Error message for negative results
|
||||
*/
|
||||
string message;
|
||||
|
||||
/**
|
||||
* Time out, true if the request ended because of a time out
|
||||
*/
|
||||
bool timeout;
|
||||
|
||||
/**
|
||||
* Identification of this request
|
||||
*/
|
||||
int id;
|
||||
|
||||
/**
|
||||
* Notify client that we have an answer for the request
|
||||
*/
|
||||
void notify()
|
||||
{
|
||||
am.trigger(ActionListener::ACTION_FINALIZE,0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Wait for the AuthRequest to be completed
|
||||
*/
|
||||
void wait()
|
||||
{
|
||||
time_out = time(0) + 90;//Requests will expire in 1.5 minutes
|
||||
|
||||
am.loop(0,0);
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
friend class MadManager;
|
||||
|
||||
/**
|
||||
* Time in seconds when this request will expire
|
||||
*/
|
||||
time_t time_out;
|
||||
|
||||
/**
|
||||
* The ActionManager that will be notify when the request is ready.
|
||||
*/
|
||||
ActionManager am;
|
||||
|
||||
/**
|
||||
* No actions defined for the request, just FINALIZE when done
|
||||
*/
|
||||
void do_action(const string &name, void *args){};
|
||||
};
|
||||
|
||||
#endif /*SYNC_REQUEST_H_*/
|
@ -134,6 +134,30 @@ public:
|
||||
*/
|
||||
virtual void set(Attribute * attr);
|
||||
|
||||
/**
|
||||
* Adds a new single attribute to the template.
|
||||
* @param name of the attribute
|
||||
* @param value of the attribute
|
||||
*/
|
||||
void add(const string& name, const string& value)
|
||||
{
|
||||
set(new SingleAttribute(name, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new single attribute to the template.
|
||||
* @param name of the attribute
|
||||
* @param value of the attribute
|
||||
*/
|
||||
void add(const string& name, int value)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << value;
|
||||
|
||||
set(new SingleAttribute(name, oss.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an attribute from the template. The attributes are returned. The
|
||||
* attributes MUST be freed by the calling funtion
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "PoolSQL.h"
|
||||
#include "UserTemplate.h"
|
||||
#include "Quotas.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -166,7 +167,12 @@ public:
|
||||
{
|
||||
return new UserTemplate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Object quotas, provides set and check interface
|
||||
*/
|
||||
Quotas quota;
|
||||
|
||||
private:
|
||||
// -------------------------------------------------------------------------
|
||||
// Friends
|
||||
@ -289,6 +295,10 @@ protected:
|
||||
const string& _auth_driver,
|
||||
bool _enabled):
|
||||
PoolObjectSQL(id,USER,_uname,-1,_gid,"",_gname,table),
|
||||
quota("/USER/DATASTORE_QUOTA",
|
||||
"/USER/NETWORK_QUOTA",
|
||||
"/USER/IMAGE_QUOTA",
|
||||
"/USER/VM_QUOTA"),
|
||||
password(_password),
|
||||
auth_driver(_auth_driver),
|
||||
enabled(_enabled),
|
||||
|
@ -131,7 +131,8 @@ public:
|
||||
string& uname,
|
||||
string& gname);
|
||||
/**
|
||||
* Returns whether there is a user with given username/password or not
|
||||
* Returns whether the operations described in a authorization request are
|
||||
* authorized ot not.
|
||||
* @param ar, an Authorization Request
|
||||
* @return -1 if authz failed, 0 otherwise
|
||||
*/
|
||||
|
@ -569,6 +569,17 @@ public:
|
||||
return new VirtualMachineTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the VirtualMachineTemplate
|
||||
* @return A copy of the VirtualMachineTemplate
|
||||
*/
|
||||
VirtualMachineTemplate * clone_template() const
|
||||
{
|
||||
return new VirtualMachineTemplate(
|
||||
*(static_cast<VirtualMachineTemplate *>(obj_template)));
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// States
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -76,6 +76,26 @@ public:
|
||||
return static_cast<VirtualMachine *>(PoolSQL::get(oid,lock));
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to get a VM from the pool, string version for VM ID
|
||||
*/
|
||||
VirtualMachine * get(
|
||||
const string& oid_s,
|
||||
bool lock)
|
||||
{
|
||||
istringstream iss(oid_s);
|
||||
int oid;
|
||||
|
||||
iss >> oid;
|
||||
|
||||
if ( iss.fail() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return static_cast<VirtualMachine *>(PoolSQL::get(oid,lock));
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to get the IDs of running VMs
|
||||
* @param oids a vector that contains the IDs
|
||||
|
13
install.sh
13
install.sh
@ -245,7 +245,6 @@ VAR_DIRS="$VAR_LOCATION/remotes \
|
||||
$VAR_LOCATION/remotes/auth/ldap \
|
||||
$VAR_LOCATION/remotes/auth/server_x509 \
|
||||
$VAR_LOCATION/remotes/auth/server_cipher \
|
||||
$VAR_LOCATION/remotes/auth/quota \
|
||||
$VAR_LOCATION/remotes/auth/dummy"
|
||||
|
||||
SUNSTONE_DIRS="$SUNSTONE_LOCATION/models \
|
||||
@ -392,7 +391,6 @@ INSTALL_FILES=(
|
||||
AUTH_SERVER_CIPHER_FILES:$VAR_LOCATION/remotes/auth/server_cipher
|
||||
AUTH_DUMMY_FILES:$VAR_LOCATION/remotes/auth/dummy
|
||||
AUTH_PLAIN_FILES:$VAR_LOCATION/remotes/auth/plain
|
||||
AUTH_QUOTA_FILES:$VAR_LOCATION/remotes/auth/quota
|
||||
VMM_EXEC_KVM_SCRIPTS:$VAR_LOCATION/remotes/vmm/kvm
|
||||
VMM_EXEC_XEN_SCRIPTS:$VAR_LOCATION/remotes/vmm/xen
|
||||
VMM_EXEC_VMWARE_SCRIPTS:$VAR_LOCATION/remotes/vmm/vmware
|
||||
@ -589,7 +587,6 @@ BIN_FILES="src/nebula/oned \
|
||||
src/cli/onecluster \
|
||||
src/onedb/onedb \
|
||||
src/onedb/onezonedb/onezonedb \
|
||||
src/authm_mad/remotes/quota/onequota \
|
||||
src/mad/utils/tty_expect \
|
||||
share/scripts/one"
|
||||
|
||||
@ -616,7 +613,6 @@ RUBY_LIB_FILES="src/mad/ruby/ActionManager.rb \
|
||||
src/mad/ruby/Ganglia.rb \
|
||||
src/oca/ruby/OpenNebula.rb \
|
||||
src/authm_mad/remotes/ssh/ssh_auth.rb \
|
||||
src/authm_mad/remotes/quota/quota.rb \
|
||||
src/authm_mad/remotes/server_x509/server_x509_auth.rb \
|
||||
src/authm_mad/remotes/server_cipher/server_cipher_auth.rb \
|
||||
src/authm_mad/remotes/ldap/ldap_auth.rb \
|
||||
@ -747,8 +743,6 @@ AUTH_DUMMY_FILES="src/authm_mad/remotes/dummy/authenticate"
|
||||
|
||||
AUTH_PLAIN_FILES="src/authm_mad/remotes/plain/authenticate"
|
||||
|
||||
AUTH_QUOTA_FILES="src/authm_mad/remotes/quota/authorize"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Virtual Network Manager drivers to be installed under $REMOTES_LOCATION/vnm
|
||||
#-------------------------------------------------------------------------------
|
||||
@ -869,23 +863,28 @@ DATASTORE_DRIVER_COMMON_SCRIPTS="src/datastore_mad/remotes/xpath.rb \
|
||||
|
||||
DATASTORE_DRIVER_DUMMY_SCRIPTS="src/datastore_mad/remotes/dummy/cp \
|
||||
src/datastore_mad/remotes/dummy/mkfs \
|
||||
src/datastore_mad/remotes/dummy/stat \
|
||||
src/datastore_mad/remotes/dummy/rm"
|
||||
|
||||
DATASTORE_DRIVER_FS_SCRIPTS="src/datastore_mad/remotes/fs/cp \
|
||||
src/datastore_mad/remotes/fs/mkfs \
|
||||
src/datastore_mad/remotes/fs/stat \
|
||||
src/datastore_mad/remotes/fs/rm"
|
||||
|
||||
DATASTORE_DRIVER_VMWARE_SCRIPTS="src/datastore_mad/remotes/vmware/cp \
|
||||
src/datastore_mad/remotes/vmware/mkfs \
|
||||
src/datastore_mad/remotes/vmware/stat \
|
||||
src/datastore_mad/remotes/vmware/rm"
|
||||
|
||||
DATASTORE_DRIVER_ISCSI_SCRIPTS="src/datastore_mad/remotes/iscsi/cp \
|
||||
src/datastore_mad/remotes/iscsi/mkfs \
|
||||
src/datastore_mad/remotes/iscsi/stat \
|
||||
src/datastore_mad/remotes/iscsi/rm \
|
||||
src/datastore_mad/remotes/iscsi/iscsi.conf"
|
||||
|
||||
DATASTORE_DRIVER_LVM_SCRIPTS="src/datastore_mad/remotes/lvm/cp \
|
||||
src/datastore_mad/remotes/lvm/mkfs \
|
||||
src/datastore_mad/remotes/lvm/stat \
|
||||
src/datastore_mad/remotes/lvm/rm \
|
||||
src/datastore_mad/remotes/lvm/lvm.conf"
|
||||
|
||||
@ -952,7 +951,6 @@ HM_ETC_FILES="src/hm_mad/hmrc"
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
AUTH_ETC_FILES="src/authm_mad/remotes/server_x509/server_x509_auth.conf \
|
||||
src/authm_mad/remotes/quota/quota.conf \
|
||||
src/authm_mad/remotes/ldap/ldap_auth.conf \
|
||||
src/authm_mad/remotes/x509/x509_auth.conf"
|
||||
|
||||
@ -1124,6 +1122,7 @@ ONE_CLI_LIB_FILES="src/cli/one_helper/onegroup_helper.rb \
|
||||
src/cli/one_helper/onehost_helper.rb \
|
||||
src/cli/one_helper/oneimage_helper.rb \
|
||||
src/cli/one_helper/onetemplate_helper.rb \
|
||||
src/cli/one_helper/onequota_helper.rb \
|
||||
src/cli/one_helper/oneuser_helper.rb \
|
||||
src/cli/one_helper/onevm_helper.rb \
|
||||
src/cli/one_helper/onevnet_helper.rb \
|
||||
|
@ -13,6 +13,63 @@
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="DATASTORE_QUOTA" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:element name="DATASTORE" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string"/>
|
||||
<xs:element name="IMAGES" type="xs:string"/>
|
||||
<xs:element name="IMAGES_USED" type="xs:string"/>
|
||||
<xs:element name="SIZE" type="xs:string"/>
|
||||
<xs:element name="SIZE_USED" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="VM_QUOTA" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:element name="VM" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="VMS" type="xs:string"/>
|
||||
<xs:element name="VMS_USED" type="xs:string"/>
|
||||
<xs:element name="MEMORY" type="xs:string"/>
|
||||
<xs:element name="MEMORY_USED" type="xs:string"/>
|
||||
<xs:element name="CPU" type="xs:string"/>
|
||||
<xs:element name="CPU_USED" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="NETWORK_QUOTA" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:element name="NETWORK" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string"/>
|
||||
<xs:element name="LEASES" type="xs:string"/>
|
||||
<xs:element name="LEASES_USED" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="IMAGE_QUOTA" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:element name="IMAGE" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string"/>
|
||||
<xs:element name="RVMS" type="xs:string"/>
|
||||
<xs:element name="RVMS_USED" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
@ -12,6 +12,63 @@
|
||||
<xs:element name="AUTH_DRIVER" type="xs:string"/>
|
||||
<xs:element name="ENABLED" type="xs:integer"/>
|
||||
<xs:element name="TEMPLATE" type="xs:anyType"/>
|
||||
<xs:element name="DATASTORE_QUOTA" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:element name="DATASTORE" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string"/>
|
||||
<xs:element name="IMAGES" type="xs:string"/>
|
||||
<xs:element name="IMAGES_USED" type="xs:string"/>
|
||||
<xs:element name="SIZE" type="xs:string"/>
|
||||
<xs:element name="SIZE_USED" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="VM_QUOTA" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:element name="VM" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="VMS" type="xs:string"/>
|
||||
<xs:element name="VMS_USED" type="xs:string"/>
|
||||
<xs:element name="MEMORY" type="xs:string"/>
|
||||
<xs:element name="MEMORY_USED" type="xs:string"/>
|
||||
<xs:element name="CPU" type="xs:string"/>
|
||||
<xs:element name="CPU_USED" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="NETWORK_QUOTA" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:element name="NETWORK" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string"/>
|
||||
<xs:element name="LEASES" type="xs:string"/>
|
||||
<xs:element name="LEASES_USED" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="IMAGE_QUOTA" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:element name="IMAGE" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string"/>
|
||||
<xs:element name="RVMS" type="xs:string"/>
|
||||
<xs:element name="RVMS_USED" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
@ -419,22 +419,20 @@ HM_MAD = [
|
||||
# valid. During this time, the driver is not used. Use 0 to disable session
|
||||
# caching
|
||||
#
|
||||
# ENABLE_OTHER_PERMISSIONS: Whether or not to enable the permissions for
|
||||
# 'other'. Users in the oneadmin group will still be able to change
|
||||
# these permissions. Values: YES or NO
|
||||
# ENABLE_OTHER_PERMISSIONS: Whether or not users can set the permissions for
|
||||
# 'other', so publishing or sharing resources with others. Users in the oneadmin
|
||||
# group will still be able to change these permissions. Values: YES or NO.
|
||||
#*******************************************************************************
|
||||
|
||||
AUTH_MAD = [
|
||||
executable = "one_auth_mad",
|
||||
authn = "ssh,x509,ldap,server_cipher,server_x509"
|
||||
# , authz = "quota"
|
||||
]
|
||||
|
||||
SESSION_EXPIRATION_TIME = 900
|
||||
|
||||
#ENABLE_OTHER_PERMISSIONS = "YES"
|
||||
|
||||
|
||||
#*******************************************************************************
|
||||
# Restricted Attributes Configuration
|
||||
#*******************************************************************************
|
||||
|
@ -15,7 +15,7 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "AclRule.h"
|
||||
#include "AuthManager.h"
|
||||
#include "AuthRequest.h"
|
||||
#include "PoolObjectSQL.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -15,6 +15,7 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "AuthManager.h"
|
||||
#include "AuthRequest.h"
|
||||
#include "NebulaLog.h"
|
||||
#include "SSLTools.h"
|
||||
#include "PoolObjectAuth.h"
|
||||
@ -23,8 +24,6 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
time_t AuthManager::_time_out;
|
||||
|
||||
const char * AuthManager::auth_driver_name = "auth_exe";
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -125,7 +124,7 @@ extern "C" void * authm_action_loop(void *arg)
|
||||
|
||||
NebulaLog::log("AuM",Log::INFO,"Authorization Manager started.");
|
||||
|
||||
authm->am.loop(authm->timer_period,0);
|
||||
authm->am.loop(authm->timer_period, 0);
|
||||
|
||||
NebulaLog::log("AuM",Log::INFO,"Authorization Manager stopped.");
|
||||
|
||||
@ -203,7 +202,7 @@ void AuthManager::do_action(const string &action, void * arg)
|
||||
}
|
||||
else if (action == ACTION_TIMER)
|
||||
{
|
||||
timer_action();
|
||||
check_time_outs_action();
|
||||
}
|
||||
else if (action == ACTION_FINALIZE)
|
||||
{
|
||||
@ -242,13 +241,12 @@ void AuthManager::authenticate_action(AuthRequest * ar)
|
||||
// Queue the request
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
ar->id = add_request(ar);
|
||||
add_request(ar);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Make the request to the driver
|
||||
// ---- --------------------------------------------------------------------
|
||||
|
||||
|
||||
authm_md->authenticate(ar->id,
|
||||
ar->uid,
|
||||
ar->driver,
|
||||
@ -287,7 +285,7 @@ void AuthManager::authorize_action(AuthRequest * ar)
|
||||
// Queue the request
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
ar->id = add_request(ar);
|
||||
add_request(ar);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Make the request to the driver
|
||||
@ -312,116 +310,6 @@ error:
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void AuthManager::timer_action()
|
||||
{
|
||||
map<int,AuthRequest *>::iterator it;
|
||||
|
||||
time_t the_time = time(0);
|
||||
|
||||
lock();
|
||||
|
||||
it = auth_requests.begin();
|
||||
|
||||
while ( it !=auth_requests.end())
|
||||
{
|
||||
if ((it->second->time_out != 0) && (the_time > it->second->time_out))
|
||||
{
|
||||
AuthRequest * ar = it->second;
|
||||
auth_requests.erase(it++);
|
||||
|
||||
ar->result = false;
|
||||
ar->timeout = true;
|
||||
ar->message = "Auth request timeout";
|
||||
|
||||
ar->notify();
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int AuthManager::add_request(AuthRequest *ar)
|
||||
{
|
||||
static int auth_id = 0;
|
||||
int id;
|
||||
|
||||
lock();
|
||||
|
||||
id = auth_id++;
|
||||
|
||||
auth_requests.insert(auth_requests.end(),make_pair(id,ar));
|
||||
|
||||
unlock();
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
AuthRequest * AuthManager::get_request(int id)
|
||||
{
|
||||
AuthRequest * ar = 0;
|
||||
map<int,AuthRequest *>::iterator it;
|
||||
ostringstream oss;
|
||||
|
||||
lock();
|
||||
|
||||
it=auth_requests.find(id);
|
||||
|
||||
if ( it != auth_requests.end())
|
||||
{
|
||||
ar = it->second;
|
||||
|
||||
auth_requests.erase(it);
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void AuthManager::notify_request(int auth_id,bool result,const string& message)
|
||||
{
|
||||
|
||||
AuthRequest * ar;
|
||||
|
||||
ar = get_request(auth_id);
|
||||
|
||||
if ( ar == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ar->result = result;
|
||||
|
||||
if ( message != "-" )
|
||||
{
|
||||
if ( !ar->message.empty() )
|
||||
{
|
||||
ar->message.append("; ");
|
||||
}
|
||||
|
||||
ar->message.append(message);
|
||||
}
|
||||
|
||||
ar->notify();
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* MAD Loading */
|
||||
/* ************************************************************************** */
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
|
||||
t->get("AUTH_MAD", am_mads);
|
||||
|
||||
return new AuthManager(1,3,am_mads);
|
||||
return new AuthManager(1,am_mads);
|
||||
};
|
||||
};
|
||||
|
||||
@ -144,7 +144,7 @@ public:
|
||||
/* ********************************************************************* */
|
||||
/* ********************************************************************* */
|
||||
|
||||
//This test needs a driver that takes more than 3 secs to AUTHENTICATE
|
||||
//This test needs a driver that takes more than 90 secs to AUTHENTICATE
|
||||
void timeout()
|
||||
{
|
||||
AuthRequest ar(2, 2);
|
||||
@ -157,8 +157,6 @@ public:
|
||||
|
||||
CPPUNIT_ASSERT(ar.result==false);
|
||||
CPPUNIT_ASSERT(ar.timeout==true);
|
||||
|
||||
am->discard_request(ar.id);
|
||||
}
|
||||
|
||||
void authenticate()
|
||||
|
@ -45,4 +45,6 @@ env.Prepend(LIBS=[
|
||||
'crypto'
|
||||
])
|
||||
|
||||
env.Program('test','AuthManagerTest.cc')
|
||||
nt = env.Object('NebulaTemplate.o','../../nebula/NebulaTemplate.cc')
|
||||
|
||||
env.Program('test',[nt,'AuthManagerTest.cc'])
|
||||
|
@ -36,7 +36,7 @@ do
|
||||
"AUTHENTICATE")
|
||||
date 1>&2 >> mad.log
|
||||
if [ "$ARG4" = "timeout" ] ; then
|
||||
sleep 4
|
||||
sleep 95
|
||||
fi
|
||||
date 1>&2 >> mad.log
|
||||
|
||||
|
@ -1,189 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2012, 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 'cli_helper'
|
||||
require 'one_helper'
|
||||
require 'quota'
|
||||
|
||||
require 'pp'
|
||||
|
||||
QUOTA_KEYS = Quota::DB_QUOTA_SCHEMA.keys
|
||||
|
||||
def show_table(values, usage=nil)
|
||||
size = usage ? 12 : 8
|
||||
|
||||
values.sort!{|v1, v2| v1[:UID]<=>v2[:UID] }
|
||||
|
||||
table=CLIHelper::ShowTable.new(nil, self) do
|
||||
column :UID, "ONE identifier for the User", :size=>4 do |d|
|
||||
d[:UID]
|
||||
end
|
||||
|
||||
QUOTA_KEYS.each { |key|
|
||||
column key, "#{key} quota", :size=>size do |d|
|
||||
if usage
|
||||
"#{usage[key].to_i}/#{d[key].to_i}"
|
||||
else
|
||||
"#{d[key].to_i}"
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
default :UID, *QUOTA_KEYS
|
||||
end
|
||||
|
||||
table.show(values)
|
||||
end
|
||||
|
||||
cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
usage "`onequota` <command> [<args>] [<options>]"
|
||||
version OpenNebulaHelper::ONE_VERSION
|
||||
|
||||
quota = Quota.new
|
||||
|
||||
########################################################################
|
||||
# Global Options
|
||||
########################################################################
|
||||
set :option, CommandParser::OPTIONS
|
||||
|
||||
########################################################################
|
||||
# Argument Formats
|
||||
########################################################################
|
||||
quota_list_desc = <<-EOT.unindent
|
||||
List of quota keys, comma separated.
|
||||
Available quotas: #{QUOTA_KEYS.join(', ')}
|
||||
EOT
|
||||
|
||||
set :format, :quota_list, quota_list_desc do |arg|
|
||||
arg_list = arg.split(',')
|
||||
|
||||
rc = nil
|
||||
arg_list.collect! do |elem|
|
||||
sym = elem.upcase.to_sym
|
||||
if !QUOTA_KEYS.include?(sym)
|
||||
rc = -1, "#{elem} is not a valid quota"
|
||||
break
|
||||
end
|
||||
sym
|
||||
end
|
||||
|
||||
rc ? rc : [0, arg_list]
|
||||
end
|
||||
|
||||
set :format, :value_list, "List of quota values, comma separated." do |arg|
|
||||
arg_list = arg.split(',')
|
||||
arg_list.map! {|a| a.to_i }
|
||||
[0, arg_list]
|
||||
end
|
||||
|
||||
set :format, :userid, OpenNebulaHelper.rname_to_id_desc("USER") do |arg|
|
||||
OpenNebulaHelper.rname_to_id(arg, "USER")
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Commands
|
||||
########################################################################
|
||||
set_desc = <<-EOT.unindent
|
||||
Set a quota for a given user.
|
||||
Examples:
|
||||
onequota set 3 cpu 12
|
||||
onequota set 4 cpu,memory,storage 8,4096,10000
|
||||
EOT
|
||||
|
||||
command :set, set_desc, :userid, :quota_list, :value_list do
|
||||
user_id, keys, values = args
|
||||
|
||||
if keys.length != values.length
|
||||
exit_with_code -1, "The number of keys and values does not match"
|
||||
end
|
||||
|
||||
values_hash = Hash.new
|
||||
keys.each_with_index { |k,i|
|
||||
values_hash[k] = values[i]
|
||||
}
|
||||
|
||||
quota.set_quota(user_id, values_hash)
|
||||
exit_with_code 0
|
||||
end
|
||||
|
||||
########################################################################
|
||||
unset_desc = <<-EOT.unindent
|
||||
Unset a quota for a given user.
|
||||
Examples:
|
||||
onequota unset 3 cpu
|
||||
onequota unset 4 cpu,memory,storage
|
||||
EOT
|
||||
|
||||
command :unset, unset_desc, :userid, :quota_list do
|
||||
user_id, keys = args
|
||||
|
||||
values_hash = Hash.new
|
||||
keys.each_with_index { |k,i|
|
||||
values_hash[k] = 0
|
||||
}
|
||||
|
||||
quota.set_quota(user_id, values_hash)
|
||||
exit_with_code 0
|
||||
end
|
||||
|
||||
########################################################################
|
||||
delete_desc = "Delete the defined quotas for the given user"
|
||||
|
||||
command :delete, delete_desc, :userid do
|
||||
quota.delete_quota(args[0])
|
||||
exit_with_code 0
|
||||
end
|
||||
|
||||
########################################################################
|
||||
show_desc = "Show the user's quota and usage. (usage/quota)"
|
||||
|
||||
FORCE={
|
||||
:name => "force",
|
||||
:short => "-f",
|
||||
:large => "--force",
|
||||
:description => "Force the usage calculation instead of using the cache"
|
||||
}
|
||||
|
||||
command :show, show_desc, :userid, :options=>[FORCE] do
|
||||
user_usage = quota.get_usage(args[0],nil,options[:force])
|
||||
user_quota = quota.get_quota(args[0])
|
||||
|
||||
show_table([user_quota], user_usage)
|
||||
exit_with_code 0
|
||||
end
|
||||
|
||||
########################################################################
|
||||
list_desc = "List the defined quotas for all the users"
|
||||
|
||||
command :list, list_desc do
|
||||
show_table(quota.get_quota)
|
||||
exit_with_code 0
|
||||
end
|
||||
end
|
@ -1,374 +0,0 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2012, 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 'sequel'
|
||||
require 'base64'
|
||||
require 'yaml'
|
||||
require 'uri'
|
||||
require 'net/http'
|
||||
|
||||
class Quota
|
||||
###########################################################################
|
||||
# Constants with paths to relevant files and defaults
|
||||
###########################################################################
|
||||
ONE_LOCATION=ENV["ONE_LOCATION"]
|
||||
|
||||
if !ONE_LOCATION
|
||||
VAR_LOCATION = "/var/lib/one"
|
||||
ETC_LOCATION = "/etc/one"
|
||||
else
|
||||
VAR_LOCATION = ONE_LOCATION + "/var"
|
||||
ETC_LOCATION = ONE_LOCATION + "/etc"
|
||||
end
|
||||
|
||||
CONF_FILE = ETC_LOCATION + "/auth/quota.conf"
|
||||
|
||||
CONF = {
|
||||
:db => "sqlite://#{VAR_LOCATION}/onequota.db",
|
||||
:defaults => {
|
||||
:CPU => nil,
|
||||
:MEMORY => nil,
|
||||
:NUM_VMS => nil,
|
||||
:STORAGE => nil
|
||||
}
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
# Schema for the USAGE and QUOTA tables
|
||||
###########################################################################
|
||||
DB_QUOTA_SCHEMA = {
|
||||
:CPU => Float,
|
||||
:MEMORY => Integer,
|
||||
:NUM_VMS => Integer,
|
||||
:STORAGE => Integer
|
||||
}
|
||||
|
||||
QUOTA_TABLE = :quotas
|
||||
USAGE_TABLE = :usage
|
||||
|
||||
###########################################################################
|
||||
# Usage params to calculate each quota
|
||||
###########################################################################
|
||||
VM_USAGE = {
|
||||
:CPU => {
|
||||
:proc_info => lambda {|template| template['CPU']},
|
||||
:xpath => 'TEMPLATE/CPU'
|
||||
},
|
||||
:MEMORY => {
|
||||
:proc_info => lambda {|template| template['MEMORY']},
|
||||
:xpath => 'TEMPLATE/MEMORY'
|
||||
},
|
||||
:NUM_VMS => {
|
||||
:proc_info => lambda {|template| 1 },
|
||||
:xpath => 'ID',
|
||||
:count => true
|
||||
}
|
||||
}
|
||||
|
||||
IMAGE_USAGE = {
|
||||
:STORAGE => {
|
||||
:proc_info => lambda {|template|
|
||||
if template['TYPE'] == 'DATABLOCK'
|
||||
template['SIZE'].to_i
|
||||
elsif template['PATH']
|
||||
uri = URI.parse(template['PATH'])
|
||||
size = if uri.scheme.nil?
|
||||
File.size(template['PATH'])
|
||||
else
|
||||
Net::HTTP.start(uri.host,uri.port) { |http|
|
||||
http.head(uri.path)
|
||||
}.content_length
|
||||
end
|
||||
(size.to_f / 2**20).round
|
||||
elsif template['SAVED_VM_ID']
|
||||
vm_id = template['SAVED_VM_ID'].to_i
|
||||
disk_id = template['SAVED_DISK_ID'].to_i
|
||||
|
||||
client = OpenNebula::Client.new
|
||||
vm = OpenNebula::VirtualMachine.new_with_id(vm_id, client)
|
||||
vm.info
|
||||
|
||||
im_id = vm["DISK[DISK_ID=#{disk_id}]/IMAGE_ID"].to_i
|
||||
|
||||
im = OpenNebula::Image.new_with_id(im_id, client)
|
||||
im.info
|
||||
|
||||
im['SIZE'].to_i
|
||||
else
|
||||
0
|
||||
end
|
||||
},
|
||||
:xpath => 'SIZE'
|
||||
}
|
||||
}
|
||||
|
||||
RESOURCES = ["VM", "IMAGE"]
|
||||
|
||||
###########################################################################
|
||||
# DB handling
|
||||
###########################################################################
|
||||
def initialize
|
||||
conf = YAML.load_file(CONF_FILE)
|
||||
@conf=CONF.merge(conf) {|key,h1,h2|
|
||||
if h1.instance_of?(Hash) && h2.instance_of?(Hash)
|
||||
h1.merge(h2)
|
||||
else
|
||||
if h2
|
||||
h2
|
||||
else
|
||||
h1
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
@client = OpenNebula::Client.new
|
||||
|
||||
@db=Sequel.connect(@conf[:db])
|
||||
|
||||
create_table(QUOTA_TABLE)
|
||||
create_table(USAGE_TABLE)
|
||||
end
|
||||
|
||||
# Creates database quota table if it does not exist
|
||||
def create_table(table)
|
||||
@db.create_table?(table) do
|
||||
Integer :UID
|
||||
|
||||
DB_QUOTA_SCHEMA.each { |key,value|
|
||||
column key, value
|
||||
}
|
||||
|
||||
primary_key :UID
|
||||
index :UID
|
||||
end
|
||||
end
|
||||
|
||||
# Adds new user limits
|
||||
def set(table, uid, quota={})
|
||||
data=quota.delete_if{|key,value| !DB_QUOTA_SCHEMA.keys.include?(key)}
|
||||
|
||||
quotas=@db[table].filter(:UID => uid)
|
||||
|
||||
if quotas.first
|
||||
quotas.update(data)
|
||||
else
|
||||
@db[table].insert(data.merge!(:UID => uid))
|
||||
end
|
||||
end
|
||||
|
||||
# Gets user limits
|
||||
def get(table, uid=nil)
|
||||
if uid
|
||||
@db[table].filter(:UID => uid).first
|
||||
else
|
||||
@db[table].all
|
||||
end
|
||||
end
|
||||
|
||||
# Delete user limits
|
||||
def delete(table, uid)
|
||||
quotas=@db[table].filter(:UID => uid)
|
||||
|
||||
if quotas.first
|
||||
quotas.delete
|
||||
end
|
||||
end
|
||||
|
||||
###########################################################################
|
||||
# Quota Client
|
||||
###########################################################################
|
||||
def set_quota(uid, quota={})
|
||||
set(QUOTA_TABLE, uid, quota)
|
||||
end
|
||||
|
||||
# Retrieves quota information for a given user
|
||||
#
|
||||
# @param [Integer, nil] uid the user id from which get the quota
|
||||
# information, if nil will retrieve the quotas for all users.
|
||||
# @return [Hash] Hash containing the quota information and the user id
|
||||
#
|
||||
# {
|
||||
# :uid => 4,
|
||||
# :cpu => 8,
|
||||
# :memory => 8064,
|
||||
# :num_vms => 4,
|
||||
# :storage => 1240019
|
||||
# }
|
||||
def get_quota(uid=nil)
|
||||
limit = get(QUOTA_TABLE, uid)
|
||||
limit ? limit : @conf[:defaults].merge!(:UID => uid)
|
||||
end
|
||||
|
||||
def delete_quota(uid)
|
||||
delete(QUOTA_TABLE, uid)
|
||||
end
|
||||
|
||||
###########################################################################
|
||||
# Authorization
|
||||
###########################################################################
|
||||
def authorize(user_id, request)
|
||||
obj, template_or_id, op, owner, acl_eval = request.split(':')
|
||||
|
||||
if acl_eval.to_i == 0
|
||||
return "ACL evaluation denied"
|
||||
end
|
||||
|
||||
# Check if this op needs to check the quota
|
||||
return false unless with_quota?(obj, op)
|
||||
|
||||
template = ""
|
||||
|
||||
if ( obj == "TEMPLATE" )
|
||||
obj = "VM"
|
||||
|
||||
vm_template = OpenNebula::Template.new_with_id(template_or_id, @client)
|
||||
vm_template.info
|
||||
|
||||
vm_template.each("TEMPLATE") { |xml_elem|
|
||||
template = xml_elem.to_xml
|
||||
}
|
||||
else
|
||||
template = Base64::decode64(template_or_id)
|
||||
end
|
||||
|
||||
check_quotas(user_id.to_i, obj, template)
|
||||
end
|
||||
|
||||
def check_quotas(user_id, obj, template)
|
||||
info = get_resources(obj, template)
|
||||
total = get_usage(user_id, obj, true)
|
||||
quota = get_quota(user_id)
|
||||
|
||||
msg = ""
|
||||
separator = ""
|
||||
info.each { |qname, quota_requested|
|
||||
unless quota[qname] || quota[qname]==0
|
||||
next
|
||||
end
|
||||
|
||||
type = DB_QUOTA_SCHEMA[qname].name.to_sym
|
||||
|
||||
used = send(type, total[qname])
|
||||
request = send(type, quota_requested)
|
||||
limit = send(type, quota[qname])
|
||||
spent = used + request
|
||||
|
||||
if spent > limit
|
||||
msg << separator
|
||||
msg << " #{qname.to_s.upcase} quota exceeded "
|
||||
msg << "(Quota: #{limit}, "
|
||||
msg << "Used: #{used}, "
|
||||
msg << "Requested: #{request})"
|
||||
|
||||
separator = ";"
|
||||
end
|
||||
}
|
||||
|
||||
if msg==""
|
||||
return false
|
||||
else
|
||||
return msg.strip
|
||||
end
|
||||
end
|
||||
|
||||
def with_quota?(obj, op)
|
||||
return (obj == "VM" && op == "CREATE") ||
|
||||
(obj == "IMAGE" && op == "CREATE") ||
|
||||
(obj == "TEMPLATE" && op == "USE")
|
||||
end
|
||||
|
||||
###########################################################################
|
||||
# Usage
|
||||
###########################################################################
|
||||
# Retrieves usage information for a given user
|
||||
#
|
||||
# @param [Integer] uid the user id from which get the usage information.
|
||||
# @param ["VM", "IMAGE"] resource kind of resource. If nil will return
|
||||
# the usage for all kinds of resources
|
||||
# @param [true, false] force If true will force the usage calculation
|
||||
# instead of retrieving it from the cache
|
||||
# @return [Hash] Hash containing the usage information and the user id
|
||||
#
|
||||
# {
|
||||
# :uid => 4,
|
||||
# :cpu => 8,
|
||||
# :memory => 8064,
|
||||
# :num_vms => 4,
|
||||
# :storage => 1240019
|
||||
# }
|
||||
def get_usage(user_id, resource=nil, force=false)
|
||||
if force
|
||||
if RESOURCES.include?(resource)
|
||||
resources = [resource]
|
||||
else
|
||||
resources = RESOURCES
|
||||
end
|
||||
|
||||
usage = Hash.new
|
||||
|
||||
resources.each{ |res|
|
||||
pool = get_pool(res, user_id)
|
||||
base_xpath = "/#{res}_POOL/#{resource}"
|
||||
Quota.const_get("#{res}_USAGE".to_sym).each { |key, params|
|
||||
usage[key] ||= 0
|
||||
pool.each_xpath("#{base_xpath}/#{params[:xpath]}") { |elem|
|
||||
if elem
|
||||
if params[:count]
|
||||
usage[key] += 1
|
||||
else
|
||||
usage[key] += send(DB_QUOTA_SCHEMA[key].name.to_sym, elem)
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
set(USAGE_TABLE, user_id, usage) unless usage.empty?
|
||||
usage.merge!(:UID => user_id)
|
||||
}
|
||||
else
|
||||
usage = get(USAGE_TABLE, user_id)
|
||||
usage ||= {:UID => user_id}
|
||||
end
|
||||
|
||||
usage
|
||||
end
|
||||
|
||||
# Retrieve the useful information of the template for the specified
|
||||
# kind of resource
|
||||
def get_resources(resource, xml_template)
|
||||
template = OpenNebula::XMLElement.new
|
||||
template.initialize_xml(xml_template, 'TEMPLATE')
|
||||
|
||||
info = Hash.new
|
||||
|
||||
self.class.const_get("#{resource}_USAGE").each { |key, params|
|
||||
info[key] = params[:proc_info].call(template).to_i
|
||||
}
|
||||
|
||||
info
|
||||
end
|
||||
|
||||
# Returns a an Array than contains the elements of the resource Pool
|
||||
def get_pool(resource, user_id)
|
||||
pool = case resource
|
||||
when "VM" then OpenNebula::VirtualMachinePool.new(@client, user_id)
|
||||
when "IMAGE" then OpenNebula::ImagePool.new(@client, user_id)
|
||||
end
|
||||
|
||||
rc = pool.info
|
||||
return pool
|
||||
end
|
||||
end
|
@ -1,26 +0,0 @@
|
||||
<IMAGE_POOL>
|
||||
<% images.each do |id,image| %>
|
||||
<IMAGE>
|
||||
<ID><%= id %></ID>
|
||||
<UID><%= image[:uid] ? image[:uid] : 0 %></UID>
|
||||
<GID><%= image[:gid] ? image[:gid] : 0 %></GID>
|
||||
<UNAME><%= image[:uname] ? image[:uname] : 'oneadmin' %></UNAME>
|
||||
<GNAME><%= image[:gname] ? image[:gname] : 'oneadmin' %></GNAME>
|
||||
<NAME><%= image[:name] ? image[:name] : 'ttylinux' %></NAME>
|
||||
<TYPE><%= image[:type] ? image[:type] : 0 %></TYPE>
|
||||
<PUBLIC><%= image[:pub] ? image[:pub] : 0 %></PUBLIC>
|
||||
<PERSISTENT><%= image[:persistent] ? image[:persistent] : 0 %></PERSISTENT>
|
||||
<REGTIME>1314875019</REGTIME>
|
||||
<SOURCE><%= image[:source] ? image[:source] : '/etc/hosts' %></SOURCE>
|
||||
<STATE><%= image[:state] ? image[:state] : 1 %></STATE>
|
||||
<SIZE><%= image[:size] ? image[:size] : 100 %></SIZE>
|
||||
<RUNNING_VMS>0</RUNNING_VMS>
|
||||
<TEMPLATE>
|
||||
<DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX>
|
||||
<NAME><![CDATA[PEPE]]></NAME>
|
||||
<PATH><![CDATA[/etc/hosts]]></PATH>
|
||||
<TYPE><![CDATA[OS]]></TYPE>
|
||||
</TEMPLATE>
|
||||
</IMAGE>
|
||||
<% end %>
|
||||
</IMAGE_POOL>
|
46
src/authm_mad/remotes/quota/test/fixtures/vm.xml
vendored
46
src/authm_mad/remotes/quota/test/fixtures/vm.xml
vendored
@ -1,46 +0,0 @@
|
||||
<VM>
|
||||
<ID><%= id %></ID>
|
||||
<UID><%= vm[:uid] ? vm[:uid] : 0 %></UID>
|
||||
<GID><%= vm[:gid] ? vm[:gid] : 0 %></GID>
|
||||
<NAME><%= vm[:name] ? vm[:uid] : 'pepe' %></NAME>
|
||||
<LAST_POLL><%= vm[:last_poll] ? vm[:last_poll] : '1309275256' %></LAST_POLL>
|
||||
<STATE><%= vm[:state] ? vm[:state] : 3 %></STATE>
|
||||
<LCM_STATE>3</LCM_STATE>
|
||||
<STIME>1309275252</STIME>
|
||||
<ETIME>0</ETIME>
|
||||
<DEPLOY_ID>dummy</DEPLOY_ID>
|
||||
<MEMORY><%= vm[:memory] ? vm[:memory] : 128 %></MEMORY>
|
||||
<CPU><%= vm[:cpu] ? vm[:cpu] : 1 %></CPU>
|
||||
<NET_TX><%= vm[:net_tx] ? vm[:net_tx] : 0 %></NET_TX>
|
||||
<NET_RX><%= vm[:net_rx] ? vm[:net_rx] : 0 %></NET_RX>
|
||||
<TEMPLATE>
|
||||
<CPU><![CDATA[1]]></CPU>
|
||||
<MEMORY><![CDATA[1024]]></MEMORY>
|
||||
<NAME><![CDATA[PEPEPE]]></NAME>
|
||||
<VCPU><![CDATA[1]]></VCPU>
|
||||
<VMID><![CDATA[4]]></VMID>
|
||||
</TEMPLATE>
|
||||
<% if history = vm[:history] %>
|
||||
<HISTORY_RECORDS>
|
||||
<% history.each do |h| %>
|
||||
<HISTORY>
|
||||
<SEQ><%= h[:seq] ? h[:seq] : 0 %></SEQ>
|
||||
<HOSTNAME><%= h[:hostname] ? h[:hostname] : "kvxen" %></HOSTNAME>
|
||||
<VM_DIR>/Users/dmolina/trabajo/acctmoni/install/var/</VM_DIR>
|
||||
<HID><%= h[:hid] ? h[:hid] : 0 %></HID>
|
||||
<STIME>1309275256</STIME>
|
||||
<ETIME>0</ETIME>
|
||||
<VMMMAD>vmm_dummy</VMMMAD>
|
||||
<TMMAD>tm_dummy</TMMAD>
|
||||
<PSTIME><%= h[:pstime] ? h[:pstime] : 0 %></PSTIME>
|
||||
<PETIME><%= h[:petime] ? h[:petime] : 0 %></PETIME>
|
||||
<RSTIME><%= h[:rstime] ? h[:rstime] : 0 %></RSTIME>
|
||||
<RETIME><%= h[:retime] ? h[:retime] : 0 %></RETIME>
|
||||
<ESTIME><%= h[:estime] ? h[:estime] : 0 %></ESTIME>
|
||||
<EETIME><%= h[:eetime] ? h[:eetime] : 0 %></EETIME>
|
||||
<REASON><%= h[:reason] ? h[:reason] : 0 %></REASON>
|
||||
</HISTORY>
|
||||
<% end %>
|
||||
</HISTORY_RECORDS>
|
||||
<% end %>
|
||||
</VM>
|
@ -1,49 +0,0 @@
|
||||
<VM_POOL>
|
||||
<% vms.each do |id,vm| %>
|
||||
<VM>
|
||||
<ID><%= id %></ID>
|
||||
<UID><%= vm[:uid] ? vm[:uid] : 0 %></UID>
|
||||
<GID><%= vm[:gid] ? vm[:gid] : 0 %></GID>
|
||||
<NAME><%= vm[:name] ? vm[:uid] : 'pepe' %></NAME>
|
||||
<LAST_POLL><%= vm[:last_poll] ? vm[:last_poll] : '1309275256' %></LAST_POLL>
|
||||
<STATE><%= vm[:state] ? vm[:state] : 3 %></STATE>
|
||||
<LCM_STATE>3</LCM_STATE>
|
||||
<STIME>1309275252</STIME>
|
||||
<ETIME>0</ETIME>
|
||||
<DEPLOY_ID>dummy</DEPLOY_ID>
|
||||
<MEMORY><%= vm[:memory] ? vm[:memory] : 128 %></MEMORY>
|
||||
<CPU><%= vm[:cpu] ? vm[:cpu] : 1 %></CPU>
|
||||
<NET_TX><%= vm[:net_tx] ? vm[:net_tx] : 0 %></NET_TX>
|
||||
<NET_RX><%= vm[:net_rx] ? vm[:net_rx] : 0 %></NET_RX>
|
||||
<TEMPLATE>
|
||||
<CPU><![CDATA[<%= vm[:cpu] ? vm[:cpu] : 1 %>]]></CPU>
|
||||
<MEMORY><![CDATA[<%= vm[:memory] ? vm[:memory] : 128 %>]]></MEMORY>
|
||||
<NAME><![CDATA[PEPEPE]]></NAME>
|
||||
<VCPU><![CDATA[1]]></VCPU>
|
||||
<VMID><![CDATA[4]]></VMID>
|
||||
</TEMPLATE>
|
||||
<% if history = vm[:history] %>
|
||||
<HISTORY_RECORDS>
|
||||
<% h = history.last %>
|
||||
<HISTORY>
|
||||
<SEQ><%= h[:seq] ? h[:seq] : 0 %></SEQ>
|
||||
<HOSTNAME><%= h[:hostname] ? h[:hostname] : "kvxen" %></HOSTNAME>
|
||||
<VM_DIR>/Users/dmolina/trabajo/acctmoni/install/var/</VM_DIR>
|
||||
<HID><%= h[:hid] ? h[:hid] : 0 %></HID>
|
||||
<STIME>1309275256</STIME>
|
||||
<ETIME>0</ETIME>
|
||||
<VMMMAD>vmm_dummy</VMMMAD>
|
||||
<TMMAD>tm_dummy</TMMAD>
|
||||
<PSTIME><%= h[:pstime] ? h[:pstime] : 0 %></PSTIME>
|
||||
<PETIME><%= h[:petime] ? h[:petime] : 0 %></PETIME>
|
||||
<RSTIME><%= h[:rstime] ? h[:rstime] : 0 %></RSTIME>
|
||||
<RETIME><%= h[:retime] ? h[:retime] : 0 %></RETIME>
|
||||
<ESTIME><%= h[:estime] ? h[:estime] : 0 %></ESTIME>
|
||||
<EETIME><%= h[:eetime] ? h[:eetime] : 0 %></EETIME>
|
||||
<REASON><%= h[:reason] ? h[:reason] : 0 %></REASON>
|
||||
</HISTORY>
|
||||
</HISTORY_RECORDS>
|
||||
<% end %>
|
||||
</VM>
|
||||
<% end %>
|
||||
</VM_POOL>
|
@ -1,53 +0,0 @@
|
||||
require 'erb'
|
||||
|
||||
FPATH = "./fixtures/"
|
||||
|
||||
class MockClient
|
||||
def initialize
|
||||
@vms = Hash.new
|
||||
@done_vms = Hash.new
|
||||
|
||||
@images = Hash.new
|
||||
end
|
||||
|
||||
|
||||
def call(action, *args)
|
||||
xmlrpc_action = "one."+action
|
||||
|
||||
case xmlrpc_action
|
||||
when "one.vm.info"
|
||||
id = args[0]
|
||||
vm = @vms[id]
|
||||
return ERB.new(File.read(FPATH+'vm.xml')).result(binding)
|
||||
when "one.vmpool.info"
|
||||
case args[3]
|
||||
when -1
|
||||
vms = @vms
|
||||
return ERB.new(File.read(FPATH+'vmpool.xml')).result(binding)
|
||||
when 6 then
|
||||
vms = @done_vms
|
||||
return ERB.new(File.read(FPATH+'vmpool.xml')).result(binding)
|
||||
end
|
||||
when "one.imagepool.info"
|
||||
images = @images
|
||||
return ERB.new(File.read(FPATH+'imagepool.xml')).result(binding)
|
||||
end
|
||||
end
|
||||
|
||||
def add_vm(id, values)
|
||||
if values[:state] == 6
|
||||
@done_vms[id] = values.clone
|
||||
else
|
||||
@vms[id] = values.clone
|
||||
end
|
||||
end
|
||||
|
||||
def delete_vm(id)
|
||||
@vms.delete(id)
|
||||
@vms_done.delete(id)
|
||||
end
|
||||
|
||||
def add_image(id, values)
|
||||
@images[id] = values
|
||||
end
|
||||
end
|
@ -1,31 +0,0 @@
|
||||
|
||||
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
|
||||
|
||||
$: << './helper'
|
||||
$: << '.'
|
||||
$: << '..'
|
||||
|
||||
require 'mock_client'
|
||||
require 'OpenNebula'
|
||||
require 'quota'
|
||||
|
||||
class Quota
|
||||
def set_client(client)
|
||||
@client = client
|
||||
end
|
||||
|
||||
def rm_and_set_testdb
|
||||
`rm -f /tmp/onequota_test.db`
|
||||
@db=Sequel.connect("sqlite:///tmp/onequota_test.db")
|
||||
|
||||
create_table(QUOTA_TABLE)
|
||||
create_table(USAGE_TABLE)
|
||||
end
|
||||
end
|
@ -1,343 +0,0 @@
|
||||
$: << '.'
|
||||
|
||||
require 'helper/test_helper'
|
||||
|
||||
describe "Quota testing" do
|
||||
before(:all) do
|
||||
@mock_client = MockClient.new
|
||||
|
||||
@quota = Quota.new
|
||||
@quota.set_client(@mock_client)
|
||||
@quota.rm_and_set_testdb
|
||||
|
||||
@uid1 = 0
|
||||
@quota1 = {
|
||||
:CPU => 2.4,
|
||||
:MEMORY => 1024,
|
||||
:NUM_VMS => 4,
|
||||
:STORAGE => 10000
|
||||
}
|
||||
|
||||
@uid2 = 1
|
||||
@quota2 = {
|
||||
:CPU => 1.2,
|
||||
:MEMORY => 512,
|
||||
:NUM_VMS => 2,
|
||||
:STORAGE => 5000
|
||||
}
|
||||
|
||||
# Generate VM ACL request
|
||||
vm_template = <<-EOT
|
||||
<TEMPLATE>
|
||||
<CPU>2</CPU>
|
||||
<MEMORY>128</MEMORY>
|
||||
</TEMPLATE>
|
||||
EOT
|
||||
|
||||
vm_base64 = Base64::encode64(vm_template)
|
||||
@acl_vm_create = "VM:#{vm_base64}:CREATE:0:1:1"
|
||||
|
||||
# Generate IMAGE ACL request
|
||||
image_template = <<-EOT
|
||||
<TEMPLATE>
|
||||
<PATH>/etc/hosts</PATH>
|
||||
</TEMPLATE>
|
||||
EOT
|
||||
|
||||
image_base64 = Base64::encode64(image_template)
|
||||
@acl_image_create = "IMAGE:#{image_base64}:CREATE:0:1:1"
|
||||
|
||||
# Generate TEMPLATE ACL request
|
||||
temp_template = <<-EOT
|
||||
<TEMPLATE>
|
||||
<CPU>2</CPU>
|
||||
<MEMORY>128</MEMORY>
|
||||
</TEMPLATE>
|
||||
EOT
|
||||
|
||||
temp_base64 = Base64::encode64(temp_template)
|
||||
@acl_template_instantiate = "TEMPLATE:#{temp_base64}:INSTANTIATE:0:1:1"
|
||||
end
|
||||
|
||||
it "should check default quotas" do
|
||||
quota1 = @quota.get_quota(@uid1)
|
||||
quota1[:UID].should eql(0)
|
||||
quota1[:NUM_VMS].should eql(nil)
|
||||
quota1[:CPU].should eql(nil)
|
||||
quota1[:MEMORY].should eql(nil)
|
||||
quota1[:STORAGE].should eql(nil)
|
||||
end
|
||||
|
||||
it "should check default usage cache" do
|
||||
usage1cache = @quota.get_usage(@uid1)
|
||||
usage1cache[:UID].should eql(0)
|
||||
usage1cache[:NUM_VMS].should eql(nil)
|
||||
usage1cache[:CPU].should eql(nil)
|
||||
usage1cache[:MEMORY].should eql(nil)
|
||||
usage1cache[:STORAGE].should eql(nil)
|
||||
end
|
||||
|
||||
it "should check default cache (force)" do
|
||||
usage1force = @quota.get_usage(@uid1, nil, true)
|
||||
usage1force[:UID].should eql(0)
|
||||
usage1force[:NUM_VMS].should eql(0)
|
||||
usage1force[:CPU].should eql(0)
|
||||
usage1force[:MEMORY].should eql(0)
|
||||
usage1force[:STORAGE].should eql(0)
|
||||
end
|
||||
|
||||
it "should authorize the user because there is no quota defined" do
|
||||
@quota.authorize(@uid1, @acl_vm_create).should eql(false)
|
||||
@quota.authorize(@uid1, @acl_image_create).should eql(false)
|
||||
@quota.authorize(@uid1, @acl_template_instantiate).should eql(false)
|
||||
end
|
||||
|
||||
it "should add a new VM" do
|
||||
values = {
|
||||
:CPU => 2,
|
||||
:MEMORY => 128,
|
||||
:UID => 2,
|
||||
:GID => 4,
|
||||
}
|
||||
|
||||
@mock_client.add_vm(0, values)
|
||||
end
|
||||
|
||||
it "should check the usage cache is not updated" do
|
||||
usage1cache = @quota.get_usage(@uid1)
|
||||
usage1cache[:UID].should eql(0)
|
||||
usage1cache[:NUM_VMS].should eql(0)
|
||||
usage1cache[:CPU].should eql(0.0)
|
||||
usage1cache[:MEMORY].should eql(0)
|
||||
usage1cache[:STORAGE].should eql(0)
|
||||
end
|
||||
|
||||
it "should check the cache (force)" do
|
||||
usage1force = @quota.get_usage(@uid1, nil, true)
|
||||
usage1force[:UID].should eql(0)
|
||||
usage1force[:NUM_VMS].should eql(1)
|
||||
usage1force[:CPU].should eql(2.0)
|
||||
usage1force[:MEMORY].should eql(128)
|
||||
usage1force[:STORAGE].should eql(0)
|
||||
end
|
||||
|
||||
it "should check the usage cache is updated and contains the last usage" do
|
||||
usage1cache = @quota.get_usage(@uid1)
|
||||
usage1cache[:UID].should eql(0)
|
||||
usage1cache[:NUM_VMS].should eql(1)
|
||||
usage1cache[:CPU].should eql(2.0)
|
||||
usage1cache[:MEMORY].should eql(128)
|
||||
usage1cache[:STORAGE].should eql(0)
|
||||
end
|
||||
|
||||
it "should add a new Image" do
|
||||
values = {
|
||||
:UID => 2,
|
||||
:GID => 4,
|
||||
:SIZE => 1000
|
||||
}
|
||||
|
||||
@mock_client.add_image(0, values)
|
||||
end
|
||||
|
||||
it "should check the usage cache is not updated" do
|
||||
usage1cache = @quota.get_usage(@uid1)
|
||||
usage1cache[:UID].should eql(0)
|
||||
usage1cache[:NUM_VMS].should eql(1)
|
||||
usage1cache[:CPU].should eql(2.0)
|
||||
usage1cache[:MEMORY].should eql(128)
|
||||
usage1cache[:STORAGE].should eql(0)
|
||||
end
|
||||
|
||||
it "should check the cache (force)" do
|
||||
usage1force = @quota.get_usage(@uid1, nil, true)
|
||||
usage1force[:UID].should eql(0)
|
||||
usage1force[:NUM_VMS].should eql(1)
|
||||
usage1force[:CPU].should eql(2.0)
|
||||
usage1force[:MEMORY].should eql(128)
|
||||
usage1force[:STORAGE].should eql(1000)
|
||||
end
|
||||
|
||||
it "should check the usage cache is updated and contains the last usage" do
|
||||
usage1cache = @quota.get_usage(@uid1)
|
||||
usage1cache[:UID].should eql(0)
|
||||
usage1cache[:NUM_VMS].should eql(1)
|
||||
usage1cache[:CPU].should eql(2.0)
|
||||
usage1cache[:MEMORY].should eql(128)
|
||||
usage1cache[:STORAGE].should eql(1000)
|
||||
end
|
||||
|
||||
it "should add a second VM" do
|
||||
values = {
|
||||
:CPU => 2,
|
||||
:MEMORY => 128,
|
||||
:UID => 2,
|
||||
:GID => 4,
|
||||
}
|
||||
|
||||
@mock_client.add_vm(1, values)
|
||||
end
|
||||
|
||||
it "should check the usage cache is not updated" do
|
||||
usage1cache = @quota.get_usage(@uid1)
|
||||
usage1cache[:UID].should eql(0)
|
||||
usage1cache[:NUM_VMS].should eql(1)
|
||||
usage1cache[:CPU].should eql(2.0)
|
||||
usage1cache[:MEMORY].should eql(128)
|
||||
usage1cache[:STORAGE].should eql(1000)
|
||||
end
|
||||
|
||||
it "should check the cache (force)" do
|
||||
usage1force = @quota.get_usage(@uid1, nil, true)
|
||||
usage1force[:UID].should eql(0)
|
||||
usage1force[:NUM_VMS].should eql(1*2)
|
||||
usage1force[:CPU].should eql(2.0*2)
|
||||
usage1force[:MEMORY].should eql(128*2)
|
||||
usage1force[:STORAGE].should eql(1000)
|
||||
end
|
||||
|
||||
it "should check the usage cache is updated and contains the last usage" do
|
||||
usage1cache = @quota.get_usage(@uid1)
|
||||
usage1cache[:UID].should eql(0)
|
||||
usage1cache[:NUM_VMS].should eql(1*2)
|
||||
usage1cache[:CPU].should eql(2.0*2)
|
||||
usage1cache[:MEMORY].should eql(128*2)
|
||||
usage1cache[:STORAGE].should eql(1000)
|
||||
end
|
||||
|
||||
it "should add a second Image" do
|
||||
values = {
|
||||
:UID => 2,
|
||||
:GID => 4,
|
||||
:SIZE => 1000
|
||||
}
|
||||
|
||||
@mock_client.add_image(1, values)
|
||||
end
|
||||
|
||||
it "should check the usage cache is not updated" do
|
||||
usage1cache = @quota.get_usage(@uid1)
|
||||
usage1cache[:UID].should eql(0)
|
||||
usage1cache[:NUM_VMS].should eql(1*2)
|
||||
usage1cache[:CPU].should eql(2.0*2)
|
||||
usage1cache[:MEMORY].should eql(128*2)
|
||||
usage1cache[:STORAGE].should eql(1000)
|
||||
end
|
||||
|
||||
it "should check the cache (force)" do
|
||||
usage1force = @quota.get_usage(@uid1, nil, true)
|
||||
usage1force[:UID].should eql(0)
|
||||
usage1force[:NUM_VMS].should eql(1*2)
|
||||
usage1force[:CPU].should eql(2.0*2)
|
||||
usage1force[:MEMORY].should eql(128*2)
|
||||
usage1force[:STORAGE].should eql(1000*2)
|
||||
end
|
||||
|
||||
it "should check the usage cache is updated and contains the last usage" do
|
||||
usage1cache = @quota.get_usage(@uid1)
|
||||
usage1cache[:UID].should eql(0)
|
||||
usage1cache[:NUM_VMS].should eql(1*2)
|
||||
usage1cache[:CPU].should eql(2.0*2)
|
||||
usage1cache[:MEMORY].should eql(128*2)
|
||||
usage1cache[:STORAGE].should eql(1000*2)
|
||||
end
|
||||
|
||||
it "should add a new quota and check it" do
|
||||
@quota.set_quota(@uid1, @quota1)
|
||||
|
||||
quota = @quota.get_quota(@uid1)
|
||||
@quota1.each{ |key,value|
|
||||
quota[key].should eql(value)
|
||||
}
|
||||
end
|
||||
|
||||
it "should not authorize the user because the vm quota is spent" do
|
||||
err_msg = "CPU quota exceeded (Quota: 2.4, Used: 4.0, Requested: 2.0)"
|
||||
@quota.authorize(@uid1, @acl_vm_create).should eql(err_msg)
|
||||
@quota.authorize(@uid1, @acl_template_instantiate).should eql(err_msg)
|
||||
|
||||
@quota.authorize(@uid1, @acl_image_create).should eql(false)
|
||||
end
|
||||
|
||||
it "should add a new quota for another user and check it" do
|
||||
@quota.set_quota(@uid2, @quota2)
|
||||
|
||||
quota = @quota.get_quota(@uid2)
|
||||
@quota2.each{ |key,value|
|
||||
quota[key].should eql(value)
|
||||
}
|
||||
end
|
||||
|
||||
it "should list all the defined quotas" do
|
||||
quotas = @quota.get_quota
|
||||
quotas.each { |quota|
|
||||
if quota[:UID] == @uid1
|
||||
@quota1.each{ |key,value|
|
||||
quota[key].should eql(value)
|
||||
}
|
||||
elsif quota[:UID] == @uid2
|
||||
@quota2.each{ |key,value|
|
||||
quota[key].should eql(value)
|
||||
}
|
||||
end
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
it "should update the first user quota and check it" do
|
||||
new_quota = Hash.new
|
||||
@quota1.each { |key,value|
|
||||
new_quota[key] = value*3
|
||||
}
|
||||
|
||||
@quota.set_quota(@uid1, new_quota)
|
||||
|
||||
quota = @quota.get_quota(@uid1)
|
||||
new_quota.each{ |key,value|
|
||||
quota[key] == value
|
||||
}
|
||||
end
|
||||
|
||||
it "should authorize the user because the quota is not spent" do
|
||||
@quota.authorize(@uid1, @acl_vm_create).should eql(false)
|
||||
@quota.authorize(@uid1, @acl_image_create).should eql(false)
|
||||
@quota.authorize(@uid1, @acl_template_instantiate).should eql(false)
|
||||
end
|
||||
|
||||
it "should update the first user quota and check it" do
|
||||
new_quota = {
|
||||
:STORAGE => 0
|
||||
}
|
||||
|
||||
@quota.set_quota(@uid1, new_quota)
|
||||
|
||||
quota = @quota.get_quota(@uid1)
|
||||
|
||||
quota[:STORAGE].should eql(new_quota[:STORAGE])
|
||||
end
|
||||
|
||||
it "should not authorize the user because the image quota is spent" do
|
||||
@quota.authorize(@uid1, @acl_vm_create).should eql(false)
|
||||
@quota.authorize(@uid1, @acl_template_instantiate).should eql(false)
|
||||
|
||||
err_msg = "STORAGE quota exceeded (Quota: 0, Used: 2000, Requested: 271)"
|
||||
@quota.authorize(@uid1, @acl_image_create).should eql(err_msg)
|
||||
end
|
||||
|
||||
it "should delete the quota and check it" do
|
||||
@quota.delete_quota(@uid1)
|
||||
|
||||
quota1 = @quota.get_quota(@uid1)
|
||||
quota1[:UID].should eql(0)
|
||||
quota1[:NUM_VMS].should eql(nil)
|
||||
quota1[:CPU].should eql(nil)
|
||||
quota1[:MEMORY].should eql(nil)
|
||||
quota1[:STORAGE].should eql(nil)
|
||||
end
|
||||
|
||||
it "should authorize the user because the quota was deleted" do
|
||||
@quota.authorize(@uid1, @acl_vm_create).should eql(false)
|
||||
@quota.authorize(@uid1, @acl_image_create).should eql(false)
|
||||
@quota.authorize(@uid1, @acl_template_instantiate).should eql(false)
|
||||
end
|
||||
end
|
@ -8,7 +8,21 @@
|
||||
:size: 15
|
||||
:left: true
|
||||
|
||||
:VMS:
|
||||
:desc: Number of VMS
|
||||
:size: 8
|
||||
|
||||
:MEMORY:
|
||||
:desc: Total memory allocated to user VMs
|
||||
:size: 8
|
||||
|
||||
:CPU:
|
||||
:desc: Total CPU allocated to user VMs
|
||||
:size: 8
|
||||
|
||||
:default:
|
||||
- :ID
|
||||
- :NAME
|
||||
|
||||
- :VMS
|
||||
- :MEMORY
|
||||
- :CPU
|
||||
|
@ -18,6 +18,18 @@
|
||||
:size: 8
|
||||
:left: true
|
||||
|
||||
:VMS:
|
||||
:desc: Number of VMS
|
||||
:size: 8
|
||||
|
||||
:MEMORY:
|
||||
:desc: Total memory allocated to user VMs
|
||||
:size: 8
|
||||
|
||||
:CPU:
|
||||
:desc: Total CPU allocated to user VMs
|
||||
:size: 8
|
||||
|
||||
:PASSWORD:
|
||||
:desc: Password of the User
|
||||
:size: 50
|
||||
@ -27,4 +39,7 @@
|
||||
- :GROUP
|
||||
- :NAME
|
||||
- :AUTH
|
||||
- :PASSWORD
|
||||
- :VMS
|
||||
- :MEMORY
|
||||
- :CPU
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'one_helper'
|
||||
require 'one_helper/onequota_helper'
|
||||
|
||||
class OneGroupHelper < OpenNebulaHelper::OneHelper
|
||||
def self.rname
|
||||
@ -56,7 +57,31 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
|
||||
d["NAME"]
|
||||
end
|
||||
|
||||
default :ID, :NAME
|
||||
column :VMS, "Total number of VMS", :size=>8 do |d|
|
||||
if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
|
||||
d['VM_QUOTA']['VM']['VMS']
|
||||
else
|
||||
"-"
|
||||
end
|
||||
end
|
||||
|
||||
column :MEMORY, "Total memory allocated to group VMs", :size=>8 do |d|
|
||||
if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
|
||||
d['VM_QUOTA']['VM']['MEMORY_USED']
|
||||
else
|
||||
"-"
|
||||
end
|
||||
end
|
||||
|
||||
column :CPU, "Total CPU allocated to group VMs", :size=>8 do |d|
|
||||
if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
|
||||
d['VM_QUOTA']['VM']['CPU_USED']
|
||||
else
|
||||
"-"
|
||||
end
|
||||
end
|
||||
|
||||
default :ID, :NAME, :VMS, :MEMORY, :CPU
|
||||
end
|
||||
|
||||
table
|
||||
@ -92,5 +117,9 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
|
||||
group.user_ids.each do |uid|
|
||||
puts "%-15s" % [uid]
|
||||
end
|
||||
|
||||
group_hash = group.to_hash
|
||||
|
||||
OneQuotaHelper.format_quota(group_hash['GROUP'])
|
||||
end
|
||||
end
|
||||
|
209
src/cli/one_helper/onequota_helper.rb
Normal file
209
src/cli/one_helper/onequota_helper.rb
Normal file
@ -0,0 +1,209 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2012, 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 'cli_helper'
|
||||
|
||||
class OneQuotaHelper
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Tables to format user quotas
|
||||
#---------------------------------------------------------------------------
|
||||
TABLE_DS = CLIHelper::ShowTable.new(nil, self) do
|
||||
column :"DATASTORE ID", "", :left, :size=>12 do |d|
|
||||
d["ID"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"IMAGES (used)", "", :right, :size=>14 do |d|
|
||||
d["IMAGES_USED"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"IMAGES (limit)", "", :right, :size=>14 do |d|
|
||||
d["IMAGES"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"SIZE (used)", "", :right, :size=>14 do |d|
|
||||
d["SIZE_USED"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"SIZE (limit)", "", :right, :size=>14 do |d|
|
||||
d["SIZE"] if !d.nil?
|
||||
end
|
||||
end
|
||||
|
||||
TABLE_NET = CLIHelper::ShowTable.new(nil, self) do
|
||||
column :"NETWORK ID", "", :left, :size=>12 do |d|
|
||||
d["ID"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"LEASES (used)", "", :right, :size=>14 do |d|
|
||||
d["LEASES_USED"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"LEASES (limit)", "", :right, :size=>14 do |d|
|
||||
d["LEASES"] if !d.nil?
|
||||
end
|
||||
end
|
||||
|
||||
TABLE_VM = CLIHelper::ShowTable.new(nil, self) do
|
||||
column :"VMS", "", :left, :size=>12 do |d|
|
||||
d["VMS"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"MEMORY (used)", "", :right, :size=>14 do |d|
|
||||
d["MEMORY_USED"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"MEMORY (limit)", "", :right, :size=>14 do |d|
|
||||
d["MEMORY"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"CPU (used)", "", :right, :size=>14 do |d|
|
||||
d["CPU_USED"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"CPU (limit)", "", :right, :size=>14 do |d|
|
||||
d["CPU"] if !d.nil?
|
||||
end
|
||||
end
|
||||
|
||||
TABLE_IMG = CLIHelper::ShowTable.new(nil, self) do
|
||||
column :"IMAGE ID", "", :left, :size=>12 do |d|
|
||||
d["ID"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"RVMS (used)", "", :right, :size=>14 do |d|
|
||||
d["RVMS_USED"] if !d.nil?
|
||||
end
|
||||
|
||||
column :"RVMS (limit)", "", :right, :size=>14 do |d|
|
||||
d["RVMS"] if !d.nil?
|
||||
end
|
||||
end
|
||||
|
||||
HELP_QUOTA = <<-EOT.unindent
|
||||
#-----------------------------------------------------------------------
|
||||
# Supported quota limits:
|
||||
#
|
||||
# DATASTORE = [
|
||||
# ID = <ID of the datastore>
|
||||
# IMAGES = <Max. number of images in the datastore>
|
||||
# SIZE = <Max. storage capacity (Mb) used in the datastore>
|
||||
# ]
|
||||
#
|
||||
# VM = [
|
||||
# VMS = <Max. number of VMs>
|
||||
# MEMORY = <Max. allocated memory (Mb)>
|
||||
# CPU = <Max. allocated CPU>
|
||||
# ]
|
||||
#
|
||||
# NETWORK = [
|
||||
# ID = <ID of the network>
|
||||
# LEASES = <Max. number of IP leases from the network>
|
||||
# ]
|
||||
#
|
||||
# IMAGE = [
|
||||
# ID = <ID of the image>
|
||||
# RVMS = <Max. number of VMs using the image>
|
||||
# ]
|
||||
#
|
||||
# In any quota 0 means unlimited. The usage counters "*_USED" are
|
||||
# shown for information purposes and will NOT be modified.
|
||||
#-----------------------------------------------------------------------
|
||||
EOT
|
||||
|
||||
# Edits the quota template of a resource
|
||||
# @param resource [PoolElement] to get the current info from
|
||||
# @param path [String] path to the new contents. If nil a editor will be
|
||||
# used
|
||||
# @return [String] contents of the new quotas
|
||||
def self.set_quota(resource, path)
|
||||
str = ""
|
||||
|
||||
if path.nil?
|
||||
require 'tempfile'
|
||||
|
||||
tmp = Tempfile.new('one-cli')
|
||||
path = tmp.path
|
||||
|
||||
rc = resource.info
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
puts rc.message
|
||||
exit -1
|
||||
end
|
||||
|
||||
tmp << HELP_QUOTA
|
||||
tmp << resource.template_like_str("DATASTORE_QUOTA") << "\n"
|
||||
tmp << resource.template_like_str("VM_QUOTA") << "\n"
|
||||
tmp << resource.template_like_str("NETWORK_QUOTA") << "\n"
|
||||
tmp << resource.template_like_str("IMAGE_QUOTA") << "\n"
|
||||
|
||||
tmp.close
|
||||
|
||||
editor_path = ENV["EDITOR"] ? ENV["EDITOR"] : EDITOR_PATH
|
||||
system("#{editor_path} #{path}")
|
||||
|
||||
unless $?.exitstatus == 0
|
||||
puts "Editor not defined"
|
||||
exit -1
|
||||
end
|
||||
|
||||
str = File.read(path)
|
||||
|
||||
File.unlink(path)
|
||||
else
|
||||
str = File.read(path)
|
||||
end
|
||||
|
||||
str
|
||||
end
|
||||
|
||||
# Outputs formated quota information to stdout
|
||||
# @param qh [Hash] with the quotas for a given resource
|
||||
#
|
||||
def self.format_quota(qh)
|
||||
str_h1="%-80s"
|
||||
|
||||
puts
|
||||
|
||||
CLIHelper.print_header(str_h1 % "RESOURCE USAGE & QUOTAS",false)
|
||||
|
||||
puts
|
||||
|
||||
ds_quotas = [qh['DATASTORE_QUOTA']['DATASTORE']].flatten
|
||||
if !ds_quotas[0].nil?
|
||||
TABLE_DS.show(ds_quotas, {})
|
||||
puts
|
||||
end
|
||||
|
||||
vm_quotas = [qh['VM_QUOTA']['VM']].flatten
|
||||
if !vm_quotas[0].nil?
|
||||
TABLE_VM.show(vm_quotas, {})
|
||||
puts
|
||||
end
|
||||
|
||||
net_quotas = [qh['NETWORK_QUOTA']['NETWORK']].flatten
|
||||
if !net_quotas[0].nil?
|
||||
TABLE_NET.show(net_quotas, {})
|
||||
puts
|
||||
end
|
||||
|
||||
image_quotas = [qh['IMAGE_QUOTA']['IMAGE']].flatten
|
||||
if !image_quotas[0].nil?
|
||||
TABLE_IMG.show(image_quotas, {})
|
||||
end
|
||||
end
|
||||
end
|
@ -15,6 +15,7 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'one_helper'
|
||||
require 'one_helper/onequota_helper'
|
||||
|
||||
class OneUserHelper < OpenNebulaHelper::OneHelper
|
||||
def self.rname
|
||||
@ -163,11 +164,35 @@ class OneUserHelper < OpenNebulaHelper::OneHelper
|
||||
d["AUTH_DRIVER"]
|
||||
end
|
||||
|
||||
column :VMS, "Number of VMS", :size=>8 do |d|
|
||||
if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
|
||||
d['VM_QUOTA']['VM']['VMS']
|
||||
else
|
||||
"-"
|
||||
end
|
||||
end
|
||||
|
||||
column :MEMORY, "Total memory allocated to user VMs", :size=>8 do |d|
|
||||
if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
|
||||
d['VM_QUOTA']['VM']['MEMORY_USED']
|
||||
else
|
||||
"-"
|
||||
end
|
||||
end
|
||||
|
||||
column :CPU, "Total CPU allocated to user VMs", :size=>8 do |d|
|
||||
if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
|
||||
d['VM_QUOTA']['VM']['CPU_USED']
|
||||
else
|
||||
"-"
|
||||
end
|
||||
end
|
||||
|
||||
column :PASSWORD, "Password of the User", :size=>50 do |d|
|
||||
d['PASSWORD']
|
||||
end
|
||||
|
||||
default :ID, :GROUP, :NAME, :AUTH, :PASSWORD
|
||||
default :ID, :GROUP, :NAME, :AUTH, :VMS, :MEMORY, :CPU
|
||||
end
|
||||
|
||||
table
|
||||
@ -207,5 +232,9 @@ class OneUserHelper < OpenNebulaHelper::OneHelper
|
||||
|
||||
CLIHelper.print_header(str_h1 % "USER TEMPLATE",false)
|
||||
puts user.template_str
|
||||
|
||||
user_hash = user.to_hash
|
||||
|
||||
OneQuotaHelper.format_quota(user_hash['USER'])
|
||||
end
|
||||
end
|
||||
|
@ -97,4 +97,20 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
helper.show_resource(group,options)
|
||||
end
|
||||
|
||||
quota_desc = <<-EOT.unindent
|
||||
Set the quota limits for the group. If a path is not provided the editor
|
||||
will be launched to modify the current quotas.
|
||||
EOT
|
||||
|
||||
command :quota, quota_desc, :groupid, [:file, nil] do
|
||||
helper.perform_action(args[0], options, "modified") do |group|
|
||||
str = OneQuotaHelper.set_quota(group, args[1])
|
||||
rc = group.set_quota(str)
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
puts rc.message
|
||||
exit -1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -29,6 +29,7 @@ $: << RUBY_LIB_LOCATION+"/cli"
|
||||
|
||||
require 'command_parser'
|
||||
require 'one_helper/oneuser_helper'
|
||||
require 'one_helper/onequota_helper'
|
||||
|
||||
require 'uri'
|
||||
|
||||
@ -196,6 +197,26 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
end
|
||||
end
|
||||
|
||||
quota_desc = <<-EOT.unindent
|
||||
Set the quota limits for the user. If a path is not provided the editor
|
||||
will be launched to modify the current quotas.
|
||||
EOT
|
||||
|
||||
command :quota, quota_desc, :userid, [:file, nil] do
|
||||
helper = OneUserHelper.new
|
||||
|
||||
helper.perform_action(args[0], options, "modified") do |user|
|
||||
str = OneQuotaHelper.set_quota(user, args[1])
|
||||
rc = user.set_quota(str)
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
puts rc.message
|
||||
exit -1
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
login_desc = <<-EOT.unindent
|
||||
Creates the Login token for authentication
|
||||
Examples:
|
||||
@ -237,7 +258,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
|
||||
command :delete, delete_desc, [:range, :userid_list] do
|
||||
helper = OneUserHelper.new
|
||||
helper.perform_actions(args[0],options,"deleted") do |user|
|
||||
helper.perform_actions(args[0], options, "deleted") do |user|
|
||||
user.delete
|
||||
end
|
||||
end
|
||||
|
@ -225,3 +225,39 @@ int VectorAttribute::vector_value(const char *name, int & value) const
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
string VectorAttribute::vector_value_str(const char *name, int& value) const
|
||||
{
|
||||
map<string,string>::const_iterator it;
|
||||
|
||||
it = attribute_value.find(name);
|
||||
|
||||
if ( it == attribute_value.end() )
|
||||
{
|
||||
value = -1;
|
||||
return "";
|
||||
}
|
||||
|
||||
if ( it->second.empty() )
|
||||
{
|
||||
value = -1;
|
||||
return "";
|
||||
}
|
||||
|
||||
istringstream iss(it->second);
|
||||
iss >> value;
|
||||
|
||||
if (iss.fail() || !iss.eof())
|
||||
{
|
||||
value = -1;
|
||||
return "";
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -44,11 +44,11 @@ class DatastoreDriver < OpenNebulaDriver
|
||||
|
||||
# Image Driver Protocol constants
|
||||
ACTION = {
|
||||
:mv => "MV",
|
||||
:cp => "CP",
|
||||
:rm => "RM",
|
||||
:mkfs => "MKFS",
|
||||
:log => "LOG"
|
||||
:log => "LOG",
|
||||
:stat => "STAT"
|
||||
}
|
||||
|
||||
# Register default actions for the protocol
|
||||
@ -58,7 +58,7 @@ class DatastoreDriver < OpenNebulaDriver
|
||||
:threaded => true,
|
||||
:retries => 0,
|
||||
:local_actions => {
|
||||
ACTION[:mv] => nil,
|
||||
ACTION[:stat] => nil,
|
||||
ACTION[:cp] => nil,
|
||||
ACTION[:rm] => nil,
|
||||
ACTION[:mkfs] => nil
|
||||
@ -77,19 +77,15 @@ class DatastoreDriver < OpenNebulaDriver
|
||||
@types = ds_type
|
||||
end
|
||||
|
||||
# register_action(ACTION[:mv].to_sym, method("mv"))
|
||||
register_action(ACTION[:cp].to_sym, method("cp"))
|
||||
register_action(ACTION[:rm].to_sym, method("rm"))
|
||||
register_action(ACTION[:cp].to_sym, method("cp"))
|
||||
register_action(ACTION[:rm].to_sym, method("rm"))
|
||||
register_action(ACTION[:mkfs].to_sym, method("mkfs"))
|
||||
register_action(ACTION[:stat].to_sym, method("stat"))
|
||||
end
|
||||
|
||||
############################################################################
|
||||
# Image Manager Protocol Actions (generic implementation)
|
||||
############################################################################
|
||||
# TODO: Integrate this with TM
|
||||
# def mv(id, ds, src, dst)
|
||||
# do_image_action(id, ds, :mv, "'#{src}' '#{dst}' '#{id}'")
|
||||
# end
|
||||
|
||||
def cp(id, drv_message)
|
||||
ds = get_ds_type(drv_message)
|
||||
@ -106,6 +102,11 @@ class DatastoreDriver < OpenNebulaDriver
|
||||
do_image_action(id, ds, :mkfs, "#{drv_message} #{id}")
|
||||
end
|
||||
|
||||
def stat(id, drv_message)
|
||||
ds = get_ds_type(drv_message)
|
||||
do_image_action(id, ds, :stat, "#{drv_message} #{id}")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def is_available?(ds, id, action)
|
||||
@ -130,8 +131,6 @@ class DatastoreDriver < OpenNebulaDriver
|
||||
|
||||
result, info = get_info_from_execution(rc)
|
||||
|
||||
|
||||
PP.pp([ACTION[action], result, id, info],STDERR)
|
||||
send_message(ACTION[action], result, id, info)
|
||||
end
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env ruby
|
||||
#!/bin/bash
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
|
||||
@ -16,54 +16,44 @@
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
ONE_LOCATION=ENV["ONE_LOCATION"]
|
||||
###############################################################################
|
||||
# This script is used to copy a VM image (SRC) to the image repository as DST
|
||||
# Several SRC types are supported
|
||||
###############################################################################
|
||||
|
||||
if !ONE_LOCATION
|
||||
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
|
||||
ETC_LOCATION="/etc/one/"
|
||||
# -------- Set up the environment to source common tools & conf ------------
|
||||
|
||||
if [ -z "${ONE_LOCATION}" ]; then
|
||||
LIB_LOCATION=/usr/lib/one
|
||||
else
|
||||
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
|
||||
ETC_LOCATION=ONE_LOCATION+"/etc/"
|
||||
end
|
||||
LIB_LOCATION=$ONE_LOCATION/lib
|
||||
fi
|
||||
|
||||
$: << RUBY_LIB_LOCATION
|
||||
. $LIB_LOCATION/sh/scripts_common.sh
|
||||
|
||||
require 'scripts_common'
|
||||
require 'OpenNebula'
|
||||
require 'quota'
|
||||
DRIVER_PATH=$(dirname $0)
|
||||
source ${DRIVER_PATH}/../libfs.sh
|
||||
|
||||
user_id = ARGV.shift
|
||||
# -------- Get cp and datastore arguments from OpenNebula core ------------
|
||||
|
||||
overall_evalutation = ARGV.pop
|
||||
exit -1 if overall_evalutation.to_i == 0
|
||||
DRV_ACTION=$1
|
||||
ID=$2
|
||||
|
||||
quota = Quota.new
|
||||
XPATH="${DRIVER_PATH}/../xpath.rb -b $DRV_ACTION"
|
||||
|
||||
#q = {
|
||||
# :cpu => 10,
|
||||
# :memory => 2048,
|
||||
# :storage => 100000,
|
||||
# :num_vms => 5
|
||||
#}
|
||||
#
|
||||
#quota.set(1, q)
|
||||
#OpenNebula.log_debug("quotas: #{quota.get(1)}")
|
||||
unset i XPATH_ELEMENTS
|
||||
|
||||
ARGV.each {|request|
|
||||
obj, template_or_id, op, owner, acl_eval = request.split(':')
|
||||
while IFS= read -r -d '' element; do
|
||||
XPATH_ELEMENTS[i++]="$element"
|
||||
done < <($XPATH /DS_DRIVER_ACTION_DATA/IMAGE/PATH)
|
||||
|
||||
if ( obj == "TEMPLATE" && op == "USE" && ARGV.size == 1 )
|
||||
rc = false
|
||||
else
|
||||
rc = quota.authorize(user_id, request)
|
||||
end
|
||||
|
||||
if rc
|
||||
OpenNebula.error_message rc
|
||||
exit -1
|
||||
end
|
||||
}
|
||||
SRC="${XPATH_ELEMENTS[0]}"
|
||||
|
||||
#OpenNebula.log_debug("AUTHORIZE ARGS: #{ARGV.join(' ')}")
|
||||
SIZE=`fs_size $SRC`
|
||||
|
||||
exit 0
|
||||
if [ "$SIZE" = "0" ]; then
|
||||
log_error "Cannot determine size for $SRC"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
echo "$SIZE"
|
@ -16,4 +16,4 @@
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
echo "dummy_path 1024"
|
||||
echo "dummy_path"
|
||||
|
@ -16,4 +16,4 @@
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
echo "dummy_path 1024"
|
||||
echo "dummy_path"
|
||||
|
16
src/authm_mad/remotes/quota/quota.conf → src/datastore_mad/remotes/dummy/stat
Normal file → Executable file
16
src/authm_mad/remotes/quota/quota.conf → src/datastore_mad/remotes/dummy/stat
Normal file → Executable file
@ -1,3 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
|
||||
# #
|
||||
@ -14,16 +16,4 @@
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
# Database URI
|
||||
#:db: sqlite:///var/one/onequota.db
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Default quotas, these apply to all users. Leave empty to disable quota for
|
||||
# a given metric.
|
||||
#-------------------------------------------------------------------------------
|
||||
:defaults:
|
||||
:CPU:
|
||||
:MEMORY:
|
||||
:NUM_VMS:
|
||||
:STORAGE:
|
||||
|
||||
echo "1024"
|
@ -84,8 +84,4 @@ http://*)
|
||||
;;
|
||||
esac
|
||||
|
||||
# ---------------- Get the size of the image ------------
|
||||
|
||||
SIZE=`fs_du $DST`
|
||||
|
||||
echo "$DST $SIZE"
|
||||
echo "$DST"
|
||||
|
@ -68,7 +68,7 @@ DST=`generate_image_path`
|
||||
# ------------ Image to save_as disk, no need to create a FS ------------
|
||||
|
||||
if [ "$FSTYPE" = "save_as" ]; then
|
||||
echo "$DST $SIZE"
|
||||
echo "$DST"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@ -81,4 +81,4 @@ exec_and_log "$DD if=/dev/zero of=$DST bs=1 count=1 seek=${SIZE}M" \
|
||||
exec_and_log "$MKFS_CMD" \
|
||||
"Unable to create filesystem $FSTYPE in $DST"
|
||||
|
||||
echo "$DST $SIZE"
|
||||
echo "$DST"
|
||||
|
1
src/datastore_mad/remotes/fs/stat
Symbolic link
1
src/datastore_mad/remotes/fs/stat
Symbolic link
@ -0,0 +1 @@
|
||||
../common/stat
|
@ -54,8 +54,8 @@ done < <($XPATH /DS_DRIVER_ACTION_DATA/DATASTORE/BASE_PATH \
|
||||
/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VG_NAME \
|
||||
/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/BASE_IQN \
|
||||
/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/BASE_TID \
|
||||
/DS_DRIVER_ACTION_DATA/IMAGE/PATH)
|
||||
|
||||
/DS_DRIVER_ACTION_DATA/IMAGE/PATH \
|
||||
/DS_DRIVER_ACTION_DATA/IMAGE/SIZE)
|
||||
|
||||
BASE_PATH="${XPATH_ELEMENTS[0]}"
|
||||
RESTRICTED_DIRS="${XPATH_ELEMENTS[1]}"
|
||||
@ -66,10 +66,10 @@ VG_NAME="${XPATH_ELEMENTS[5]:-$VG_NAME}"
|
||||
BASE_IQN="${XPATH_ELEMENTS[6]:-$BASE_IQN}"
|
||||
BASE_TID="${XPATH_ELEMENTS[7]:-$BASE_TID}"
|
||||
SRC="${XPATH_ELEMENTS[8]}"
|
||||
SIZE="${XPATH_ELEMENTS[9]}"
|
||||
|
||||
set_up_datastore "$BASE_PATH" "$RESTRICTED_DIRS" "$SAFE_DIRS" "$UMASK"
|
||||
|
||||
SIZE=`fs_du $SRC`
|
||||
LV_NAME="lv-one-${ID}"
|
||||
IQN="$BASE_IQN:$DST_HOST.$VG_NAME.$LV_NAME"
|
||||
DEV="/dev/$VG_NAME/$LV_NAME"
|
||||
@ -110,4 +110,4 @@ ssh_exec_and_log "$DST_HOST" "$REGISTER_CMD" "Error registering $DST_HOST:$DEV"
|
||||
exec_and_log "eval $DUMP | $SSH $DST_HOST $SUDO $DD of=$DEV bs=64k" \
|
||||
"Error dumping $SRC to $DST_HOST:$DEV"
|
||||
|
||||
echo "$IQN $SIZE"
|
||||
echo "$IQN"
|
||||
|
@ -90,7 +90,7 @@ EOF
|
||||
# ------------ Image to save_as disk, no need to create a FS ------------
|
||||
|
||||
if [ "$FSTYPE" = "save_as" ]; then
|
||||
echo "$DST $SIZE"
|
||||
echo "$DST"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@ -99,4 +99,4 @@ fi
|
||||
ssh_exec_and_log "$DST_HOST" "$REGISTER_CMD" \
|
||||
"Error registering $DST_HOST:$DEV"
|
||||
|
||||
echo "$IQN $SIZE"
|
||||
echo "$IQN"
|
||||
|
1
src/datastore_mad/remotes/iscsi/stat
Symbolic link
1
src/datastore_mad/remotes/iscsi/stat
Symbolic link
@ -0,0 +1 @@
|
||||
../common/stat
|
@ -88,14 +88,23 @@ EOF
|
||||
# @param $1 - Path to the image
|
||||
# @return size of the image in Mb
|
||||
#-------------------------------------------------------------------------------
|
||||
function fs_du {
|
||||
if [ -d "$1" ]; then
|
||||
SIZE=`du -sb "$1" | cut -f1`
|
||||
function fs_size {
|
||||
|
||||
case $1 in
|
||||
http://*)
|
||||
SIZE=`curl --head $1 2>/dev/null | grep Length | cut -d: -f`
|
||||
error=$?
|
||||
else
|
||||
SIZE=`stat -c %s "$1"`
|
||||
error=$?
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if [ -d "$1" ]; then
|
||||
SIZE=`du -sb "$1" | cut -f1`
|
||||
error=$?
|
||||
else
|
||||
SIZE=`stat -c %s "$1"`
|
||||
error=$?
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $error -ne 0 ]; then
|
||||
SIZE=0
|
||||
@ -106,22 +115,6 @@ function fs_du {
|
||||
echo "$SIZE"
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Computes the size of an image
|
||||
# @param $1 - Path to the image
|
||||
# @return size of the image in Mb
|
||||
#-------------------------------------------------------------------------------
|
||||
function qemu_size {
|
||||
DISK="$1"
|
||||
|
||||
SIZE=`$QEMU_IMG info $DISK|grep "^virtual size:"|\
|
||||
sed 's/^.*(\([0-9]\+\) bytes.*$/\1/g'`
|
||||
|
||||
SIZE=$((($SIZE+1048575)/1048576))
|
||||
|
||||
echo "$SIZE"
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Checks if a path is safe for copying the image from
|
||||
# @param $1 - Path to the image
|
||||
|
@ -52,7 +52,8 @@ done < <($XPATH /DS_DRIVER_ACTION_DATA/DATASTORE/BASE_PATH \
|
||||
/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/UMASK \
|
||||
/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/HOST \
|
||||
/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VG_NAME \
|
||||
/DS_DRIVER_ACTION_DATA/IMAGE/PATH)
|
||||
/DS_DRIVER_ACTION_DATA/IMAGE/PATH \
|
||||
/DS_DRIVER_ACTION_DATA/IMAGE/SIZE)
|
||||
|
||||
BASE_PATH="${XPATH_ELEMENTS[0]}"
|
||||
RESTRICTED_DIRS="${XPATH_ELEMENTS[1]}"
|
||||
@ -61,11 +62,10 @@ UMASK="${XPATH_ELEMENTS[3]}"
|
||||
DST_HOST="${XPATH_ELEMENTS[4]:-$HOST}"
|
||||
VG_NAME="${XPATH_ELEMENTS[5]:-$VG_NAME}"
|
||||
SRC="${XPATH_ELEMENTS[6]}"
|
||||
SIZE="${XPATH_ELEMENTS[7]}"
|
||||
|
||||
set_up_datastore "$BASE_PATH" "$RESTRICTED_DIRS" "$SAFE_DIRS" "$UMASK"
|
||||
|
||||
SIZE=`fs_du $SRC`
|
||||
|
||||
LV_NAME="lv-one-${ID}"
|
||||
LVM_SOURCE="$DST_HOST:$VG_NAME.$LV_NAME"
|
||||
DEV="/dev/$VG_NAME/$LV_NAME"
|
||||
@ -101,4 +101,4 @@ ssh_exec_and_log "$DST_HOST" "$REGISTER_CMD" "Error registering $DST_HOST:$DEV"
|
||||
exec_and_log "eval $DUMP | $SSH $DST_HOST $SUDO $DD of=$DEV bs=64k" \
|
||||
"Error dumping $SRC to $DST_HOST:$DEV"
|
||||
|
||||
echo "$LVM_SOURCE $SIZE"
|
||||
echo "$LVM_SOURCE"
|
||||
|
@ -62,7 +62,7 @@ UMASK="${XPATH_ELEMENTS[3]}"
|
||||
DST_HOST="${XPATH_ELEMENTS[4]:-$HOST}"
|
||||
VG_NAME="${XPATH_ELEMENTS[5]:-$VG_NAME}"
|
||||
FSTYPE="${XPATH_ELEMENTS[6]}"
|
||||
SIZE="${XPATH_ELEMENTS[7]:-0}"
|
||||
SIZE="${XPATH_ELEMENTS[7]}"
|
||||
|
||||
set_up_datastore "$BASE_PATH" "$RESTRICTED_DIRS" "$SAFE_DIRS" "$UMASK"
|
||||
|
||||
@ -80,7 +80,7 @@ EOF
|
||||
# ------------ Image to save_as disk, no need to create a FS ------------
|
||||
|
||||
if [ "$FSTYPE" = "save_as" ]; then
|
||||
echo "$LVM_SOURCE $SIZE"
|
||||
echo "$LVM_SOURCE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@ -89,4 +89,4 @@ fi
|
||||
ssh_exec_and_log "$DST_HOST" "$REGISTER_CMD" \
|
||||
"Error registering $DST_HOST:$DEV"
|
||||
|
||||
echo "$LVM_SOURCE $SIZE"
|
||||
echo "$LVM_SOURCE"
|
||||
|
1
src/datastore_mad/remotes/lvm/stat
Symbolic link
1
src/datastore_mad/remotes/lvm/stat
Symbolic link
@ -0,0 +1 @@
|
||||
../common/stat
|
@ -87,8 +87,4 @@ case $SRC in
|
||||
;;
|
||||
esac
|
||||
|
||||
# ---------------- Get the size of the image ------------
|
||||
|
||||
SIZE=`fs_du $DST`
|
||||
|
||||
echo "$DST $SIZE"
|
||||
echo "$DST"
|
||||
|
@ -67,7 +67,7 @@ DST=`generate_image_path`
|
||||
# ------------ Image to save_as disk, no need to create a FS ------------
|
||||
|
||||
if [ "$FSTYPE" = "save_as" ]; then
|
||||
echo "$DST $SIZE"
|
||||
echo "$DST"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@ -91,8 +91,4 @@ exec_and_log "$QEMU_IMG convert -O $IMAGE_FORMAT $DISK_TMP $DISK" \
|
||||
exec_and_log "rm -f $DISK_TMP" \
|
||||
"Unable to remove temporary disk $DISK_TMP"
|
||||
|
||||
# ---------------- Get the size of the image ------------
|
||||
|
||||
SIZE=`qemu_size $DISK`
|
||||
|
||||
echo "$DST $SIZE"
|
||||
echo "$DST"
|
||||
|
1
src/datastore_mad/remotes/vmware/stat
Symbolic link
1
src/datastore_mad/remotes/vmware/stat
Symbolic link
@ -0,0 +1 @@
|
||||
../common/stat
|
@ -683,7 +683,15 @@ int DispatchManager::finalize(
|
||||
int vid)
|
||||
{
|
||||
VirtualMachine * vm;
|
||||
ostringstream oss;
|
||||
ostringstream oss;
|
||||
Template * tmpl;
|
||||
|
||||
User * user;
|
||||
Group * group;
|
||||
|
||||
int uid;
|
||||
int gid;
|
||||
|
||||
VirtualMachine::VmState state;
|
||||
|
||||
vm = vmpool->get(vid,true);
|
||||
@ -701,6 +709,8 @@ int DispatchManager::finalize(
|
||||
Nebula& nd = Nebula::instance();
|
||||
TransferManager * tm = nd.get_tm();
|
||||
LifeCycleManager * lcm = nd.get_lcm();
|
||||
UserPool * upool = nd.get_upool();
|
||||
GroupPool * gpool = nd.get_gpool();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
@ -722,17 +732,55 @@ int DispatchManager::finalize(
|
||||
vmpool->update(vm);
|
||||
|
||||
vm->log("DiM", Log::INFO, "New VM state is DONE.");
|
||||
|
||||
uid = vm->get_uid();
|
||||
gid = vm->get_gid();
|
||||
tmpl = vm->clone_template();
|
||||
|
||||
vm->unlock();
|
||||
|
||||
if ( uid != UserPool::ONEADMIN_ID )
|
||||
{
|
||||
|
||||
user = upool->get(uid, true);
|
||||
|
||||
if ( user != 0 )
|
||||
{
|
||||
user->quota.vm_del(tmpl);
|
||||
|
||||
upool->update(user);
|
||||
|
||||
user->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
if ( gid != GroupPool::ONEADMIN_ID )
|
||||
{
|
||||
group = gpool->get(gid, true);
|
||||
|
||||
if ( group != 0 )
|
||||
{
|
||||
group->quota.vm_del(tmpl);
|
||||
|
||||
gpool->update(group);
|
||||
|
||||
group->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
delete tmpl;
|
||||
break;
|
||||
|
||||
case VirtualMachine::ACTIVE:
|
||||
lcm->trigger(LifeCycleManager::DELETE,vid);
|
||||
vm->unlock();
|
||||
break;
|
||||
|
||||
case VirtualMachine::DONE:
|
||||
vm->unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
vm->unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "DispatchManager.h"
|
||||
#include "NebulaLog.h"
|
||||
|
||||
#include "Nebula.h"
|
||||
|
||||
void DispatchManager::suspend_success_action(int vid)
|
||||
{
|
||||
VirtualMachine * vm;
|
||||
@ -97,11 +99,22 @@ void DispatchManager::stop_success_action(int vid)
|
||||
|
||||
void DispatchManager::done_action(int vid)
|
||||
{
|
||||
VirtualMachine * vm;
|
||||
VirtualMachine * vm;
|
||||
Template * tmpl;
|
||||
|
||||
int uid;
|
||||
int gid;
|
||||
|
||||
VirtualMachine::LcmState lcm_state;
|
||||
VirtualMachine::VmState dm_state;
|
||||
|
||||
Nebula& nd = Nebula::instance();
|
||||
UserPool * upool = nd.get_upool();
|
||||
GroupPool* gpool = nd.get_gpool();
|
||||
|
||||
User * user;
|
||||
Group * group;
|
||||
|
||||
vm = vmpool->get(vid,true);
|
||||
|
||||
if ( vm == 0 )
|
||||
@ -130,6 +143,44 @@ void DispatchManager::done_action(int vid)
|
||||
vm->release_network_leases();
|
||||
|
||||
vm->release_disk_images();
|
||||
|
||||
uid = vm->get_uid();
|
||||
gid = vm->get_gid();
|
||||
tmpl = vm->clone_template();
|
||||
|
||||
vm->unlock();
|
||||
|
||||
/* ---------------- Update Group & User quota counters -------------- */
|
||||
|
||||
if ( uid != UserPool::ONEADMIN_ID )
|
||||
{
|
||||
user = upool->get(uid, true);
|
||||
|
||||
if ( user != 0 )
|
||||
{
|
||||
user->quota.vm_del(tmpl);
|
||||
|
||||
upool->update(user);
|
||||
|
||||
user->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
if ( gid != GroupPool::ONEADMIN_ID )
|
||||
{
|
||||
group = gpool->get(gid, true);
|
||||
|
||||
if ( group != 0 )
|
||||
{
|
||||
group->quota.vm_del(tmpl);
|
||||
|
||||
gpool->update(group);
|
||||
|
||||
group->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
delete tmpl;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -137,10 +188,10 @@ void DispatchManager::done_action(int vid)
|
||||
|
||||
oss << "done action received but VM " << vid << " not in ACTIVE state";
|
||||
NebulaLog::log("DiM",Log::ERROR,oss);
|
||||
|
||||
vm->unlock();
|
||||
}
|
||||
|
||||
vm->unlock();
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -130,14 +130,18 @@ string& Group::to_xml(string& xml) const
|
||||
{
|
||||
ostringstream oss;
|
||||
string collection_xml;
|
||||
string quota_xml;
|
||||
|
||||
ObjectCollection::to_xml(collection_xml);
|
||||
|
||||
quota.to_xml(quota_xml);
|
||||
|
||||
oss <<
|
||||
"<GROUP>" <<
|
||||
"<ID>" << oid << "</ID>" <<
|
||||
"<NAME>" << name << "</NAME>" <<
|
||||
collection_xml <<
|
||||
quota_xml <<
|
||||
"</GROUP>";
|
||||
|
||||
xml = oss.str();
|
||||
@ -179,6 +183,8 @@ int Group::from_xml(const string& xml)
|
||||
|
||||
ObjectXML::free_nodes(content);
|
||||
|
||||
rc += quota.from_xml(this);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
return -1;
|
||||
|
@ -97,7 +97,9 @@ int Image::insert(SqlDB *db, string& error_str)
|
||||
string dev_prefix;
|
||||
string source_attr;
|
||||
string saved_id;
|
||||
string size_attr;
|
||||
|
||||
istringstream iss;
|
||||
ostringstream oss;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
@ -141,6 +143,13 @@ int Image::insert(SqlDB *db, string& error_str)
|
||||
obj_template->set(dev_att);
|
||||
}
|
||||
|
||||
// ------------ SIZE --------------------
|
||||
|
||||
erase_template_attribute("SIZE", size_attr);
|
||||
|
||||
iss.str(size_attr);
|
||||
iss >> size_mb;
|
||||
|
||||
// ------------ PATH & SOURCE --------------------
|
||||
|
||||
erase_template_attribute("PATH", path);
|
||||
@ -150,26 +159,13 @@ int Image::insert(SqlDB *db, string& error_str)
|
||||
{
|
||||
if ( source.empty() && path.empty() )
|
||||
{
|
||||
string size_attr;
|
||||
istringstream iss;
|
||||
|
||||
erase_template_attribute("SIZE", size_attr);
|
||||
erase_template_attribute("FSTYPE", fs_type);
|
||||
|
||||
// DATABLOCK image needs SIZE and FSTYPE
|
||||
if (type != DATABLOCK || size_attr.empty() || fs_type.empty())
|
||||
// DATABLOCK image needs FSTYPE
|
||||
if (type != DATABLOCK || fs_type.empty())
|
||||
{
|
||||
goto error_no_path;
|
||||
}
|
||||
|
||||
iss.str(size_attr);
|
||||
|
||||
iss >> size_mb;
|
||||
|
||||
if (iss.fail() == true)
|
||||
{
|
||||
goto error_size_format;
|
||||
}
|
||||
}
|
||||
else if ( !source.empty() && !path.empty() )
|
||||
{
|
||||
@ -178,20 +174,7 @@ int Image::insert(SqlDB *db, string& error_str)
|
||||
}
|
||||
else
|
||||
{
|
||||
string size_attr;
|
||||
istringstream iss;
|
||||
|
||||
fs_type = "save_as";
|
||||
erase_template_attribute("SIZE", size_attr);
|
||||
|
||||
iss.str(size_attr);
|
||||
|
||||
iss >> size_mb;
|
||||
|
||||
if (iss.fail() == true)
|
||||
{
|
||||
goto error_size_format;
|
||||
}
|
||||
}
|
||||
|
||||
state = LOCKED; //LOCKED till the ImageManager copies it to the Repository
|
||||
@ -220,10 +203,6 @@ error_no_path:
|
||||
}
|
||||
goto error_common;
|
||||
|
||||
error_size_format:
|
||||
error_str = "Wrong number in SIZE.";
|
||||
goto error_common;
|
||||
|
||||
error_path_and_source:
|
||||
error_str = "Template malformed, PATH and SOURCE are mutually exclusive.";
|
||||
goto error_common;
|
||||
@ -464,7 +443,7 @@ int Image::disk_attribute( VectorAttribute * disk,
|
||||
|
||||
get_template_attribute("DEV_PREFIX", dev_prefix);
|
||||
|
||||
if (dev_prefix.empty())//Removed from image template, get it again from defaults
|
||||
if (dev_prefix.empty())//Removed from image template, get it again
|
||||
{
|
||||
dev_prefix = ImagePool::default_dev_prefix();
|
||||
}
|
||||
@ -561,3 +540,30 @@ int Image::set_type(string& _type)
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
Image::ImageType Image::str_to_type(string& str_type)
|
||||
{
|
||||
Image::ImageType it = OS;
|
||||
|
||||
if (str_type.empty())
|
||||
{
|
||||
str_type = ImagePool::default_type();
|
||||
}
|
||||
|
||||
TO_UPPER(str_type);
|
||||
|
||||
if ( str_type == "OS" )
|
||||
{
|
||||
it = OS;
|
||||
}
|
||||
else if ( str_type == "CDROM" )
|
||||
{
|
||||
it = CDROM;
|
||||
}
|
||||
else if ( str_type == "DATABLOCK" )
|
||||
{
|
||||
it = DATABLOCK;
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
@ -126,4 +126,3 @@ void ImageManager::do_action(const string &action, void * arg)
|
||||
NebulaLog::log("ImM", Log::ERROR, oss);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,10 @@
|
||||
#include "NebulaLog.h"
|
||||
#include "ImagePool.h"
|
||||
#include "SSLTools.h"
|
||||
#include "SyncRequest.h"
|
||||
#include "Template.h"
|
||||
#include "Nebula.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -259,10 +263,23 @@ int ImageManager::enable_image(int iid, bool to_enable)
|
||||
|
||||
int ImageManager::delete_image(int iid, const string& ds_data)
|
||||
{
|
||||
Image * img;
|
||||
string source;
|
||||
string img_tmpl;
|
||||
string * drv_msg;
|
||||
Image * img;
|
||||
|
||||
string source;
|
||||
string img_tmpl;
|
||||
string * drv_msg;
|
||||
|
||||
int size;
|
||||
int ds_id;
|
||||
|
||||
int uid;
|
||||
int gid;
|
||||
Group* group;
|
||||
User * user;
|
||||
|
||||
Nebula& nd = Nebula::instance();
|
||||
UserPool * upool = nd.get_upool();
|
||||
GroupPool* gpool = nd.get_gpool();
|
||||
|
||||
img = ipool->get(iid,true);
|
||||
|
||||
@ -303,7 +320,11 @@ int ImageManager::delete_image(int iid, const string& ds_data)
|
||||
|
||||
drv_msg = format_message(img->to_xml(img_tmpl), ds_data);
|
||||
source = img->get_source();
|
||||
|
||||
size = img->get_size();
|
||||
ds_id = img->get_ds_id();
|
||||
uid = img->get_uid();
|
||||
gid = img->get_gid();
|
||||
|
||||
if (source.empty())
|
||||
{
|
||||
string err_str;
|
||||
@ -326,6 +347,41 @@ int ImageManager::delete_image(int iid, const string& ds_data)
|
||||
|
||||
delete drv_msg;
|
||||
|
||||
/* -------------------- Update Group & User quota counters -------------- */
|
||||
|
||||
Template img_usage;
|
||||
|
||||
img_usage.add("DATASTORE", ds_id);
|
||||
img_usage.add("SIZE", size);
|
||||
|
||||
if ( uid != UserPool::ONEADMIN_ID )
|
||||
{
|
||||
user = upool->get(uid, true);
|
||||
|
||||
if ( user != 0 )
|
||||
{
|
||||
user->quota.ds_del(&img_usage);
|
||||
|
||||
upool->update(user);
|
||||
|
||||
user->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
if ( gid != GroupPool::ONEADMIN_ID )
|
||||
{
|
||||
group = gpool->get(gid, true);
|
||||
|
||||
if ( group != 0 )
|
||||
{
|
||||
group->quota.ds_del(&img_usage);
|
||||
|
||||
gpool->update(group);
|
||||
|
||||
group->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -395,6 +451,80 @@ int ImageManager::register_image(int iid, const string& ds_data)
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ImageManager::stat_image(Template* img_tmpl,
|
||||
const string& ds_data,
|
||||
string& res)
|
||||
{
|
||||
const ImageManagerDriver* imd = get();
|
||||
|
||||
string* drv_msg;
|
||||
string type_att;
|
||||
|
||||
ostringstream img_data;
|
||||
|
||||
SyncRequest sr;
|
||||
|
||||
int rc = 0;
|
||||
|
||||
img_tmpl->get("TYPE", type_att);
|
||||
|
||||
switch (Image::str_to_type(type_att))
|
||||
{
|
||||
case Image::OS:
|
||||
case Image::CDROM:
|
||||
img_tmpl->get("SOURCE", res);
|
||||
|
||||
if (!res.empty())
|
||||
{
|
||||
res = "0";
|
||||
return 0;
|
||||
}
|
||||
|
||||
img_tmpl->get("PATH", res);
|
||||
|
||||
if (res.empty())
|
||||
{
|
||||
res = "Either PATH or SOURCE are required for " + type_att;
|
||||
return -1;
|
||||
}
|
||||
|
||||
img_data << "<IMAGE><PATH>" << res << "</PATH></IMAGE>";
|
||||
break;
|
||||
|
||||
case Image::DATABLOCK:
|
||||
img_tmpl->get("SIZE", res);
|
||||
|
||||
if (res.empty())
|
||||
{
|
||||
res = "SIZE attribute is mandatory for DATABLOCK.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
add_request(&sr);
|
||||
|
||||
drv_msg = format_message(img_data.str(), ds_data);
|
||||
|
||||
imd->stat(sr.id, *drv_msg);
|
||||
|
||||
sr.wait();
|
||||
|
||||
delete drv_msg;
|
||||
|
||||
res = sr.message;
|
||||
|
||||
if ( sr.result != true )
|
||||
{
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -38,13 +38,12 @@ void ImageManagerDriver::cp(int oid,
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ImageManagerDriver::mv(int oid,
|
||||
const string& source,
|
||||
const string& destination) const
|
||||
void ImageManagerDriver::stat(int oid,
|
||||
const string& drv_msg) const
|
||||
{
|
||||
ostringstream os;
|
||||
|
||||
os << "MV " << oid << " " << source << " " << destination << endl;
|
||||
os << "STAT " << oid << " " << drv_msg << endl;
|
||||
|
||||
write(os);
|
||||
}
|
||||
@ -79,26 +78,329 @@ void ImageManagerDriver::rm(int oid, const string& drv_msg) const
|
||||
/* MAD Interface */
|
||||
/* ************************************************************************** */
|
||||
|
||||
static void stat_action(istringstream& is, int id, const string& result)
|
||||
{
|
||||
string size_mb;
|
||||
string info;
|
||||
|
||||
Nebula& nd = Nebula::instance();
|
||||
ImageManager * im = nd.get_imagem();
|
||||
|
||||
if ( result == "SUCCESS" )
|
||||
{
|
||||
if ( is.good() )
|
||||
{
|
||||
is >> size_mb >> ws;
|
||||
}
|
||||
|
||||
if ( is.fail() )
|
||||
{
|
||||
im->notify_request(id, false, "Cannot get size from STAT");
|
||||
}
|
||||
|
||||
im->notify_request(id, true, size_mb);
|
||||
}
|
||||
else
|
||||
{
|
||||
getline(is,info);
|
||||
|
||||
im->notify_request(id, false, info);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void cp_action(istringstream& is,
|
||||
ImagePool* ipool,
|
||||
int id,
|
||||
const string& result)
|
||||
{
|
||||
string source;
|
||||
string info;
|
||||
|
||||
Image * image;
|
||||
|
||||
ostringstream oss;
|
||||
|
||||
image = ipool->get(id,true);
|
||||
|
||||
if ( image == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( result == "FAILURE" )
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ( is.good() )
|
||||
{
|
||||
is >> source >> ws;
|
||||
}
|
||||
|
||||
if ( is.fail() )
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
image->set_source(source);
|
||||
|
||||
image->set_state(Image::READY);
|
||||
|
||||
ipool->update(image);
|
||||
|
||||
image->unlock();
|
||||
|
||||
NebulaLog::log("ImM", Log::INFO, "Image copied and ready to use.");
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
oss << "Error copying image in the repository";
|
||||
|
||||
getline(is, info);
|
||||
|
||||
if (!info.empty() && (info[0] != '-'))
|
||||
{
|
||||
oss << ": " << info;
|
||||
}
|
||||
|
||||
NebulaLog::log("ImM", Log::ERROR, oss);
|
||||
|
||||
image->set_template_error_message(oss.str());
|
||||
image->set_state(Image::ERROR);
|
||||
|
||||
ipool->update(image);
|
||||
|
||||
image->unlock();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void mkfs_action(istringstream& is,
|
||||
ImagePool* ipool,
|
||||
int id,
|
||||
const string& result)
|
||||
{
|
||||
string source;
|
||||
Image * image;
|
||||
bool is_saving;
|
||||
|
||||
string disk_id;
|
||||
string vm_id;
|
||||
string info;
|
||||
int rc;
|
||||
|
||||
VirtualMachine * vm;
|
||||
ostringstream oss;
|
||||
|
||||
Nebula& nd = Nebula::instance();
|
||||
VirtualMachinePool * vmpool = nd.get_vmpool();
|
||||
|
||||
image = ipool->get(id, true);
|
||||
|
||||
if ( image == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( result == "FAILURE" )
|
||||
{
|
||||
goto error_img;
|
||||
}
|
||||
|
||||
if ( is.good() )
|
||||
{
|
||||
is >> source >> ws;
|
||||
}
|
||||
|
||||
if ( is.fail() )
|
||||
{
|
||||
goto error_img;
|
||||
}
|
||||
|
||||
is_saving = image->isSaving();
|
||||
|
||||
image->set_source(source);
|
||||
|
||||
if (is_saving)
|
||||
{
|
||||
image->get_template_attribute("SAVED_DISK_ID", disk_id);
|
||||
image->get_template_attribute("SAVED_VM_ID", vm_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
image->set_state(Image::READY);
|
||||
|
||||
NebulaLog::log("ImM", Log::INFO, "Image created and ready to use");
|
||||
}
|
||||
|
||||
ipool->update(image);
|
||||
|
||||
image->unlock();
|
||||
|
||||
if ( ! is_saving )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* ---------------- Set up information for the Saved Image -------------- */
|
||||
|
||||
vm = vmpool->get(vm_id, true);
|
||||
|
||||
if ( vm == 0 )
|
||||
{
|
||||
goto error_save_get;
|
||||
}
|
||||
|
||||
rc = vm->save_disk(disk_id, source, id);
|
||||
|
||||
if ( rc == -1 )
|
||||
{
|
||||
goto error_save_state;
|
||||
}
|
||||
|
||||
vmpool->update(vm);
|
||||
|
||||
vm->unlock();
|
||||
|
||||
return;
|
||||
|
||||
error_img:
|
||||
oss << "Error creating datablock";
|
||||
goto error;
|
||||
|
||||
error_save_get:
|
||||
oss << "Image created for SAVE_AS, but the associated VM does not exist.";
|
||||
goto error_save;
|
||||
|
||||
error_save_state:
|
||||
vm->unlock();
|
||||
oss << "Image created for SAVE_AS, but VM is no longer running";
|
||||
|
||||
error_save:
|
||||
image = ipool->get(id, true);
|
||||
|
||||
if ( image == 0 )
|
||||
{
|
||||
NebulaLog::log("ImM", Log::ERROR, oss);
|
||||
return;
|
||||
}
|
||||
|
||||
error:
|
||||
getline(is,info);
|
||||
|
||||
if (!info.empty() && (info[0] != '-'))
|
||||
{
|
||||
oss << ": " << info;
|
||||
}
|
||||
|
||||
NebulaLog::log("ImM", Log::ERROR, oss);
|
||||
|
||||
image->set_template_error_message(oss.str());
|
||||
image->set_state(Image::ERROR);
|
||||
|
||||
ipool->update(image);
|
||||
|
||||
image->unlock();
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void rm_action(istringstream& is,
|
||||
ImagePool* ipool,
|
||||
int id,
|
||||
const string& result)
|
||||
{
|
||||
int rc;
|
||||
string tmp_error;
|
||||
string source;
|
||||
string info;
|
||||
Image * image;
|
||||
|
||||
ostringstream oss;
|
||||
|
||||
image = ipool->get(id, true);
|
||||
|
||||
if ( image == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
source = image->get_source();
|
||||
|
||||
rc = ipool->drop(image, tmp_error);
|
||||
|
||||
image->unlock();
|
||||
|
||||
if ( result == "FAILURE" )
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
else if ( rc < 0 )
|
||||
{
|
||||
goto error_drop;
|
||||
}
|
||||
|
||||
NebulaLog::log("ImM", Log::INFO, "Image successfully removed.");
|
||||
|
||||
return;
|
||||
|
||||
error_drop:
|
||||
oss << "Error removing image from DB: " << tmp_error
|
||||
<< ". Remove image source " << source << " to completely delete image.";
|
||||
|
||||
NebulaLog::log("ImM", Log::ERROR, oss);
|
||||
return;
|
||||
|
||||
error:
|
||||
oss << "Error removing image from datastore. Manually remove image source "
|
||||
<< source << " to completely delete the image";
|
||||
|
||||
getline(is,info);
|
||||
|
||||
if (!info.empty() && (info[0] != '-'))
|
||||
{
|
||||
oss << ": " << info;
|
||||
}
|
||||
|
||||
NebulaLog::log("ImM", Log::ERROR, oss);
|
||||
|
||||
image->set_template_error_message(oss.str());
|
||||
image->set_state(Image::ERROR);
|
||||
|
||||
ipool->update(image);
|
||||
|
||||
image->unlock();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ImageManagerDriver::protocol(
|
||||
string& message)
|
||||
{
|
||||
istringstream is(message);
|
||||
ostringstream os;
|
||||
ostringstream oss;
|
||||
|
||||
string action;
|
||||
string result;
|
||||
string action;
|
||||
string result;
|
||||
string source;
|
||||
string info;
|
||||
int id;
|
||||
|
||||
oss << "Message received: " << message;
|
||||
NebulaLog::log("ImG", Log::DEBUG, oss);
|
||||
|
||||
int id;
|
||||
Image * image;
|
||||
string source;
|
||||
unsigned int size_mb;
|
||||
// --------------------- Parse the driver message --------------------------
|
||||
|
||||
string info;
|
||||
|
||||
os << "Message received: " << message;
|
||||
NebulaLog::log("ImG", Log::DEBUG, os);
|
||||
|
||||
// Parse the driver message
|
||||
if ( is.good() )
|
||||
is >> action >> ws;
|
||||
else
|
||||
@ -117,8 +419,6 @@ void ImageManagerDriver::protocol(
|
||||
{
|
||||
if ( action == "LOG" )
|
||||
{
|
||||
string info;
|
||||
|
||||
is.clear();
|
||||
getline(is,info);
|
||||
|
||||
@ -131,145 +431,21 @@ void ImageManagerDriver::protocol(
|
||||
else
|
||||
return;
|
||||
|
||||
// Parse driver message for CP, MV and MKFS
|
||||
// <CP|MV|MKFS> SUCESS IMAGE_ID SOURCE SIZE
|
||||
if ( (result == "SUCCESS") && (action != "RM") )
|
||||
if ( action == "STAT" )
|
||||
{
|
||||
if ( is.good() )
|
||||
{
|
||||
is >> source >> ws;
|
||||
}
|
||||
|
||||
if ( is.good() )
|
||||
{
|
||||
is >> size_mb >> ws;
|
||||
}
|
||||
|
||||
if ( is.fail() )
|
||||
{
|
||||
result = "FAILURE";
|
||||
}
|
||||
stat_action(is, id, result);
|
||||
}
|
||||
|
||||
|
||||
// Get the image from the pool
|
||||
image = ipool->get(id,true);
|
||||
|
||||
if ( image == 0 )
|
||||
else if ( action == "CP" )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Driver Actions
|
||||
if ( action == "CP" )
|
||||
{
|
||||
if ( result == "SUCCESS" )
|
||||
{
|
||||
image->set_source(source);
|
||||
image->set_size(size_mb);
|
||||
|
||||
image->set_state(Image::READY);
|
||||
|
||||
ipool->update(image);
|
||||
|
||||
NebulaLog::log("ImM", Log::INFO, "Image copied and ready to use.");
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error_cp;
|
||||
}
|
||||
cp_action(is, ipool, id, result);
|
||||
}
|
||||
else if ( action == "MKFS" )
|
||||
{
|
||||
if ( result == "SUCCESS" )
|
||||
{
|
||||
bool is_saving = image->isSaving();
|
||||
|
||||
string disk_id;
|
||||
string vm_id;
|
||||
int rc;
|
||||
|
||||
image->set_source(source);
|
||||
|
||||
if (is_saving)
|
||||
{
|
||||
image->get_template_attribute("SAVED_DISK_ID",disk_id);
|
||||
image->get_template_attribute("SAVED_VM_ID", vm_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
image->set_size(size_mb);
|
||||
|
||||
image->set_state(Image::READY);
|
||||
|
||||
NebulaLog::log("ImM", Log::INFO,
|
||||
"Image created and ready to use");
|
||||
}
|
||||
|
||||
ipool->update(image);
|
||||
|
||||
image->unlock();
|
||||
|
||||
if (is_saving)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
|
||||
VirtualMachinePool * vmpool = nd.get_vmpool();
|
||||
|
||||
VirtualMachine * vm;
|
||||
istringstream iss(vm_id);
|
||||
|
||||
int vm_id_i;
|
||||
|
||||
iss >> vm_id_i;
|
||||
|
||||
vm = vmpool->get(vm_id_i, true);
|
||||
|
||||
if ( vm == 0 )
|
||||
{
|
||||
goto error_save_no_vm;
|
||||
}
|
||||
|
||||
rc = vm->save_disk(disk_id, source, id);
|
||||
|
||||
if ( rc == -1 )
|
||||
{
|
||||
vm->unlock();
|
||||
goto error_save_state_vm;
|
||||
}
|
||||
|
||||
vmpool->update(vm);
|
||||
|
||||
vm->unlock();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error_mkfs;
|
||||
}
|
||||
mkfs_action(is, ipool, id, result);
|
||||
}
|
||||
else if ( action == "RM" )
|
||||
{
|
||||
int rc;
|
||||
string tmp_error;
|
||||
|
||||
rc = ipool->drop(image, tmp_error);
|
||||
|
||||
if ( rc < 0 )
|
||||
{
|
||||
NebulaLog::log("ImM",Log::ERROR,"Image could not be removed from DB");
|
||||
}
|
||||
|
||||
if ( result == "SUCCESS" )
|
||||
{
|
||||
NebulaLog::log("ImM",Log::INFO,"Image successfully removed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error_rm;
|
||||
}
|
||||
rm_action(is, ipool, id, result);
|
||||
}
|
||||
else if (action == "LOG")
|
||||
{
|
||||
@ -277,72 +453,6 @@ void ImageManagerDriver::protocol(
|
||||
NebulaLog::log("ImM", log_type(result[0]), info.c_str());
|
||||
}
|
||||
|
||||
image->unlock();
|
||||
|
||||
return;
|
||||
|
||||
error_cp:
|
||||
os.str("");
|
||||
os << "Error copying image in the repository";
|
||||
goto error_common;
|
||||
|
||||
error_mkfs:
|
||||
os.str("");
|
||||
os << "Error creating datablock";
|
||||
goto error_common;
|
||||
|
||||
error_rm:
|
||||
os.str("");
|
||||
os << "Error removing image from repository. Remove file " << image->get_source()
|
||||
<< " to completely delete image.";
|
||||
|
||||
image->unlock();
|
||||
|
||||
getline(is,info);
|
||||
|
||||
if (!info.empty() && (info[0] != '-'))
|
||||
{
|
||||
os << ": " << info;
|
||||
}
|
||||
|
||||
NebulaLog::log("ImM", Log::ERROR, os);
|
||||
return;
|
||||
|
||||
error_save_no_vm:
|
||||
os.str("");
|
||||
os << "Image created for SAVE_AS, but the associated VM does not exist.";
|
||||
|
||||
goto error_save_common;
|
||||
|
||||
error_save_state_vm:
|
||||
os.str("");
|
||||
os << "Image created for SAVE_AS, but VM is no longer running";
|
||||
|
||||
goto error_save_common;
|
||||
|
||||
error_save_common:
|
||||
image = ipool->get(id, true);
|
||||
|
||||
if (image == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
error_common:
|
||||
getline(is,info);
|
||||
|
||||
if (!info.empty() && (info[0] != '-'))
|
||||
{
|
||||
os << ": " << info;
|
||||
image->set_template_error_message(os.str());
|
||||
}
|
||||
|
||||
NebulaLog::log("ImM", Log::ERROR, os);
|
||||
|
||||
image->set_state(Image::ERROR);
|
||||
ipool->update(image);
|
||||
|
||||
image->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -349,6 +349,11 @@ void ImagePool::authorize_disk(VectorAttribute * disk,int uid, AuthRequest * ar)
|
||||
}
|
||||
|
||||
img = get(source , uiid, true);
|
||||
|
||||
if ( img != 0 )
|
||||
{
|
||||
disk->replace("IMAGE_ID", img->get_oid());
|
||||
}
|
||||
}
|
||||
else if (!(source = disk->vector_value("IMAGE_ID")).empty())
|
||||
{
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "MadManager.h"
|
||||
#include "SyncRequest.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -336,3 +337,110 @@ void MadManager::listener()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void MadManager::check_time_outs_action()
|
||||
{
|
||||
map<int, SyncRequest *>::iterator it;
|
||||
|
||||
time_t the_time = time(0);
|
||||
|
||||
lock();
|
||||
|
||||
it = sync_requests.begin();
|
||||
|
||||
while ( it != sync_requests.end())
|
||||
{
|
||||
if ((it->second->time_out != 0) && (the_time > it->second->time_out))
|
||||
{
|
||||
SyncRequest * ar = it->second;
|
||||
sync_requests.erase(it++);
|
||||
|
||||
ar->result = false;
|
||||
ar->timeout = true;
|
||||
ar->message = "Request timeout";
|
||||
|
||||
ar->notify();
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void MadManager::add_request(SyncRequest *ar)
|
||||
{
|
||||
static int request_id = 0;
|
||||
|
||||
lock();
|
||||
|
||||
ar->id = request_id++;
|
||||
|
||||
sync_requests.insert(sync_requests.end(),make_pair(ar->id,ar));
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
SyncRequest * MadManager::get_request(int id)
|
||||
{
|
||||
SyncRequest * ar = 0;
|
||||
map<int,SyncRequest *>::iterator it;
|
||||
ostringstream oss;
|
||||
|
||||
lock();
|
||||
|
||||
it = sync_requests.find(id);
|
||||
|
||||
if ( it != sync_requests.end())
|
||||
{
|
||||
ar = it->second;
|
||||
|
||||
sync_requests.erase(it);
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void MadManager::notify_request(int id, bool result, const string& message)
|
||||
{
|
||||
|
||||
SyncRequest * ar;
|
||||
|
||||
ar = get_request(id);
|
||||
|
||||
if ( ar == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ar->result = result;
|
||||
|
||||
if ( message != "-" )
|
||||
{
|
||||
if ( !ar->message.empty() )
|
||||
{
|
||||
ar->message.append("; ");
|
||||
}
|
||||
|
||||
ar->message.append(message);
|
||||
}
|
||||
|
||||
ar->notify();
|
||||
}
|
||||
|
@ -512,8 +512,7 @@ void Nebula::start()
|
||||
|
||||
if (!auth_mads.empty())
|
||||
{
|
||||
//Defaults 60s to timeout auth requests
|
||||
authm = new AuthManager(timer_period,60,auth_mads);
|
||||
authm = new AuthManager(timer_period, auth_mads);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -23,11 +23,11 @@ module OpenNebula
|
||||
# Constants and Class Methods
|
||||
#######################################################################
|
||||
|
||||
|
||||
GROUP_METHODS = {
|
||||
:info => "group.info",
|
||||
:allocate => "group.allocate",
|
||||
:delete => "group.delete"
|
||||
:info => "group.info",
|
||||
:allocate => "group.allocate",
|
||||
:delete => "group.delete",
|
||||
:quota => "group.quota"
|
||||
}
|
||||
|
||||
# Flag for requesting connected user's group info
|
||||
@ -120,6 +120,20 @@ module OpenNebula
|
||||
super(GROUP_METHODS[:delete])
|
||||
end
|
||||
|
||||
# Sets the group quota limits
|
||||
# @param quota [String] a template (XML or txt) with the new quota limits
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def set_quota(quota)
|
||||
return Error.new('ID not defined') if !@pe_id
|
||||
|
||||
rc = @client.call(GROUP_METHODS[:quota],@pe_id, quota)
|
||||
rc = nil if !OpenNebula.is_error?(rc)
|
||||
|
||||
return rc
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Helpers to get information
|
||||
# ---------------------------------------------------------------------
|
||||
|
@ -30,7 +30,8 @@ module OpenNebula
|
||||
:passwd => "user.passwd",
|
||||
:chgrp => "user.chgrp",
|
||||
:update => "user.update",
|
||||
:chauth => "user.chauth"
|
||||
:chauth => "user.chauth",
|
||||
:quota => "user.quota"
|
||||
}
|
||||
|
||||
SELF = -1
|
||||
@ -144,6 +145,20 @@ module OpenNebula
|
||||
return rc
|
||||
end
|
||||
|
||||
# Sets the user quota limits
|
||||
# @param quota [String] a template (XML or txt) with the new quota limits
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def set_quota(quota)
|
||||
return Error.new('ID not defined') if !@pe_id
|
||||
|
||||
rc = @client.call(USER_METHODS[:quota],@pe_id, quota)
|
||||
rc = nil if !OpenNebula.is_error?(rc)
|
||||
|
||||
return rc
|
||||
end
|
||||
|
||||
#######################################################################
|
||||
# Helpers to get User information
|
||||
#######################################################################
|
||||
|
@ -1,9 +1,52 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$1" != "sqlite" -a "$1" != "mysql" -a "$1" != "postgres" ]; then
|
||||
echo "$0: The first command needs to be one of {sqlite, mysql}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
usage()
|
||||
{
|
||||
cat << EOF
|
||||
usage: $0 options
|
||||
|
||||
This script upgrades oZones DB from 3.4 to 3.6
|
||||
|
||||
OPTIONS:
|
||||
-h Show this message
|
||||
-t DB type, can be "mysql" or "sqlite". Compulsory
|
||||
-s Server address (for mysql only, "localhost" if not defined)
|
||||
-u User name (for mysql only, compulsory)
|
||||
-p User password (for mysql only, compulsory)
|
||||
-l DB path (for sqlite only, compulsory)
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
while getopts “t:u:p:s:l:h” OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
h)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
t)
|
||||
TYPE=$OPTARG
|
||||
;;
|
||||
s)
|
||||
SERVER=$OPTARG
|
||||
;;
|
||||
u)
|
||||
USERNAME=$OPTARG
|
||||
;;
|
||||
p)
|
||||
PASSWD=$OPTARG
|
||||
;;
|
||||
l)
|
||||
DB_PATH=$OPTARG
|
||||
;;
|
||||
?)
|
||||
usage
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
MIGRATE_CMDS=$(cat <<EOF
|
||||
drop table zones;
|
||||
@ -20,33 +63,31 @@ drop table o_zones_vdcs;
|
||||
EOF
|
||||
)
|
||||
|
||||
if [ "$1" == "sqlite" ]; then
|
||||
if [ ! -f $2 ]; then
|
||||
echo "$0: A valid sqlite DB file needs to be provided as second argument"
|
||||
if [ $TYPE == "sqlite" ]; then
|
||||
if [ -z "$DB_PATH" -o ! -f "$DB_PATH" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sqlite3 $2 < <(echo $MIGRATE_CMDS)
|
||||
sqlite3 $DB_PATH < <(echo $MIGRATE_CMDS)
|
||||
RC=$?
|
||||
fi
|
||||
|
||||
if [ "$1" == "mysql" ]; then
|
||||
if [ -z $2 -a -z $3 ]; then
|
||||
echo "$0: A valid username and password for mysql server needs to be provided"
|
||||
echo "Usage: $0 username password <mysql_server_location>"
|
||||
echo " where <mysql_server_location> is optional and defaults to localhost"
|
||||
if [ $TYPE == "mysql" ]; then
|
||||
if [ -z $USERNAME -a -z $PASSWD ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $4 ]; then
|
||||
MYSQL_SERVER="localhost"
|
||||
else
|
||||
MYSQL_SERVER=$4
|
||||
if [ -z $SERVER ]; then
|
||||
SERVER="localhost"
|
||||
fi
|
||||
|
||||
mysql -u $2 --password=$3 -h $MYSQL_SERVER ozones < <(echo $MIGRATE_CMDS)
|
||||
mysql -u $USERNAME --password=$PASSWD -h $SERVER ozones < <(echo $MIGRATE_CMDS)
|
||||
RC=$?
|
||||
fi
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "There was an error during migration"
|
||||
else
|
||||
echo "Migration successful"
|
||||
|
@ -15,7 +15,7 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "PoolObjectAuth.h"
|
||||
#include "AuthManager.h"
|
||||
#include "AuthRequest.h"
|
||||
#include "AclRule.h"
|
||||
|
||||
void PoolObjectAuth::get_acl_rules(AclRule& owner_rule,
|
||||
|
@ -112,6 +112,246 @@ bool Request::basic_authorization(int oid,
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool Request::user_quota_authorization (Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att,
|
||||
string& error_str)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
UserPool * upool = nd.get_upool();
|
||||
User * user;
|
||||
|
||||
bool rc = false;
|
||||
|
||||
user = upool->get(att.uid, true);
|
||||
|
||||
if ( user == 0 )
|
||||
{
|
||||
error_str = "User not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (object)
|
||||
{
|
||||
case PoolObjectSQL::IMAGE:
|
||||
rc = user->quota.ds_check(tmpl, error_str);
|
||||
break;
|
||||
|
||||
case PoolObjectSQL::VM:
|
||||
case PoolObjectSQL::TEMPLATE:
|
||||
rc = user->quota.vm_check(tmpl, error_str);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc == true)
|
||||
{
|
||||
upool->update(user);
|
||||
}
|
||||
|
||||
user->unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool Request::group_quota_authorization (Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att,
|
||||
string& error_str)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
GroupPool * gpool = nd.get_gpool();
|
||||
Group * group;
|
||||
|
||||
bool rc = false;
|
||||
|
||||
group = gpool->get(att.gid, true);
|
||||
|
||||
if ( group == 0 )
|
||||
{
|
||||
error_str = "Group not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (object)
|
||||
{
|
||||
case PoolObjectSQL::IMAGE:
|
||||
rc = group->quota.ds_check(tmpl, error_str);
|
||||
break;
|
||||
|
||||
case PoolObjectSQL::VM:
|
||||
case PoolObjectSQL::TEMPLATE:
|
||||
rc = group->quota.vm_check(tmpl, error_str);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc == true)
|
||||
{
|
||||
gpool->update(group);
|
||||
}
|
||||
|
||||
group->unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void Request::user_quota_rollback(Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
UserPool * upool = nd.get_upool();
|
||||
|
||||
User * user;
|
||||
|
||||
user = upool->get(att.uid, true);
|
||||
|
||||
if ( user == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (object)
|
||||
{
|
||||
case PoolObjectSQL::IMAGE:
|
||||
user->quota.ds_del(tmpl);
|
||||
break;
|
||||
|
||||
case PoolObjectSQL::VM:
|
||||
case PoolObjectSQL::TEMPLATE:
|
||||
user->quota.vm_del(tmpl);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
upool->update(user);
|
||||
|
||||
user->unlock();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void Request::group_quota_rollback(Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
GroupPool * gpool = nd.get_gpool();
|
||||
|
||||
Group * group;
|
||||
|
||||
group = gpool->get(att.gid, true);
|
||||
|
||||
if ( group == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (object)
|
||||
{
|
||||
case PoolObjectSQL::IMAGE:
|
||||
group->quota.ds_del(tmpl);
|
||||
break;
|
||||
|
||||
case PoolObjectSQL::VM:
|
||||
case PoolObjectSQL::TEMPLATE:
|
||||
group->quota.vm_del(tmpl);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gpool->update(group);
|
||||
|
||||
group->unlock();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool Request::quota_authorization(Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
string error_str;
|
||||
|
||||
if (object != PoolObjectSQL::IMAGE &&
|
||||
object != PoolObjectSQL::VM &&
|
||||
object != PoolObjectSQL::TEMPLATE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// uid/gid == -1 means do not update user/group
|
||||
if ( att.uid != UserPool::ONEADMIN_ID && att.uid != -1)
|
||||
{
|
||||
if ( user_quota_authorization(tmpl, object, att, error_str) == false )
|
||||
{
|
||||
failure_response(AUTHORIZATION,
|
||||
authorization_error(error_str, att),
|
||||
att);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( att.gid != GroupPool::ONEADMIN_ID && att.gid != -1)
|
||||
{
|
||||
if ( group_quota_authorization(tmpl, object, att, error_str) == false )
|
||||
{
|
||||
user_quota_rollback(tmpl, object, att);
|
||||
|
||||
failure_response(AUTHORIZATION,
|
||||
authorization_error(error_str, att),
|
||||
att);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void Request::quota_rollback(Template * tmpl,
|
||||
PoolObjectSQL::ObjectType object,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
if (object != PoolObjectSQL::IMAGE &&
|
||||
object != PoolObjectSQL::VM &&
|
||||
object != PoolObjectSQL::TEMPLATE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// uid/gid == -1 means do not update user/group
|
||||
if ( att.uid != UserPool::ONEADMIN_ID && att.uid != -1 )
|
||||
{
|
||||
user_quota_rollback(tmpl, object, att);
|
||||
}
|
||||
|
||||
if ( att.gid != GroupPool::ONEADMIN_ID && att.gid != -1 )
|
||||
{
|
||||
group_quota_rollback(tmpl, object, att);;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void Request::failure_response(ErrorCode ec, const string& str_val,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "RequestManagerUser.h"
|
||||
#include "RequestManagerAcl.h"
|
||||
#include "RequestManagerCluster.h"
|
||||
#include "RequestManagerGroup.h"
|
||||
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
@ -233,6 +234,10 @@ void RequestManager::register_xml_methods()
|
||||
// User Methods
|
||||
xmlrpc_c::methodPtr user_change_password(new UserChangePassword());
|
||||
xmlrpc_c::methodPtr user_change_auth(new UserChangeAuth());
|
||||
xmlrpc_c::methodPtr user_set_quota(new UserSetQuota());
|
||||
|
||||
// Group Methods
|
||||
xmlrpc_c::methodPtr group_set_quota(new GroupSetQuota());
|
||||
|
||||
// VMTemplate Methods
|
||||
xmlrpc_c::methodPtr template_instantiate(new VMTemplateInstantiate());
|
||||
@ -384,6 +389,7 @@ void RequestManager::register_xml_methods()
|
||||
RequestManagerRegistry.addMethod("one.group.allocate", group_allocate);
|
||||
RequestManagerRegistry.addMethod("one.group.delete", group_delete);
|
||||
RequestManagerRegistry.addMethod("one.group.info", group_info);
|
||||
RequestManagerRegistry.addMethod("one.group.quota", group_set_quota);
|
||||
|
||||
RequestManagerRegistry.addMethod("one.grouppool.info", grouppool_info);
|
||||
|
||||
@ -409,6 +415,7 @@ void RequestManager::register_xml_methods()
|
||||
RequestManagerRegistry.addMethod("one.user.passwd", user_change_password);
|
||||
RequestManagerRegistry.addMethod("one.user.chgrp", user_chown);
|
||||
RequestManagerRegistry.addMethod("one.user.chauth", user_change_auth);
|
||||
RequestManagerRegistry.addMethod("one.user.quota", user_set_quota);
|
||||
|
||||
RequestManagerRegistry.addMethod("one.userpool.info", userpool_info);
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "RequestManagerAllocate.h"
|
||||
#include "NebulaLog.h"
|
||||
|
||||
#include "Nebula.h"
|
||||
#include "PoolObjectSQL.h"
|
||||
@ -80,7 +79,7 @@ bool VirtualMachineAllocate::allocate_authorization(
|
||||
|
||||
VirtualMachineTemplate * ttmpl = static_cast<VirtualMachineTemplate *>(tmpl);
|
||||
|
||||
// Check template for restricted attributes
|
||||
// ------------ Check template for restricted attributes -------------------
|
||||
|
||||
if ( att.uid != 0 && att.gid != GroupPool::ONEADMIN_ID )
|
||||
{
|
||||
@ -98,6 +97,8 @@ bool VirtualMachineAllocate::allocate_authorization(
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ Authorize VM create operation ------------------------
|
||||
|
||||
ar.add_create_auth(auth_object, tmpl->to_xml(t64));
|
||||
|
||||
VirtualMachine::set_auth_request(att.uid, ar, ttmpl);
|
||||
@ -111,6 +112,13 @@ bool VirtualMachineAllocate::allocate_authorization(
|
||||
return false;
|
||||
}
|
||||
|
||||
// -------------------------- Check Quotas ----------------------------
|
||||
|
||||
if ( quota_authorization(tmpl, att) == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -266,8 +274,17 @@ int VirtualMachineAllocate::pool_allocate(xmlrpc_c::paramList const& paramList,
|
||||
VirtualMachineTemplate * ttmpl= static_cast<VirtualMachineTemplate *>(tmpl);
|
||||
VirtualMachinePool * vmpool = static_cast<VirtualMachinePool *>(pool);
|
||||
|
||||
return vmpool->allocate(att.uid, att.gid, att.uname, att.gname, ttmpl, &id,
|
||||
error_str, false);
|
||||
Template tmpl_back(*tmpl);
|
||||
|
||||
int rc = vmpool->allocate(att.uid, att.gid, att.uname, att.gname, ttmpl, &id,
|
||||
error_str, false);
|
||||
|
||||
if ( rc < 0 )
|
||||
{
|
||||
quota_rollback(&tmpl_back, att);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -297,8 +314,14 @@ void ImageAllocate::request_execute(xmlrpc_c::paramList const& params,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
string error_str;
|
||||
string size_str;
|
||||
|
||||
int size_mb;
|
||||
istringstream iss;
|
||||
|
||||
string ds_name;
|
||||
string ds_data;
|
||||
|
||||
int rc, id;
|
||||
|
||||
PoolObjectAuth ds_perms;
|
||||
@ -309,9 +332,12 @@ void ImageAllocate::request_execute(xmlrpc_c::paramList const& params,
|
||||
Nebula& nd = Nebula::instance();
|
||||
|
||||
DatastorePool * dspool = nd.get_dspool();
|
||||
ImagePool * ipool = static_cast<ImagePool *>(pool);
|
||||
|
||||
ImagePool * ipool = static_cast<ImagePool *>(pool);
|
||||
ImageManager * imagem = nd.get_imagem();
|
||||
|
||||
ImageTemplate * tmpl = new ImageTemplate;
|
||||
Template img_usage;
|
||||
|
||||
Datastore * ds;
|
||||
Image::DiskType ds_disk_type;
|
||||
|
||||
@ -359,13 +385,45 @@ void ImageAllocate::request_execute(xmlrpc_c::paramList const& params,
|
||||
|
||||
ds->unlock();
|
||||
|
||||
// --------------- Get the SIZE for the Image, (DS driver) -----------------
|
||||
|
||||
rc = imagem->stat_image(tmpl, ds_data, size_str);
|
||||
|
||||
if ( rc == -1 )
|
||||
{
|
||||
failure_response(INTERNAL,
|
||||
request_error("Cannot determine Image SIZE", size_str),
|
||||
att);
|
||||
delete tmpl;
|
||||
return;
|
||||
}
|
||||
|
||||
iss.str(size_str);
|
||||
iss >> size_mb;
|
||||
|
||||
if ( iss.fail() )
|
||||
{
|
||||
failure_response(INTERNAL,
|
||||
request_error("Cannot parse SIZE", size_str),
|
||||
att);
|
||||
delete tmpl;
|
||||
return;
|
||||
}
|
||||
|
||||
tmpl->erase("SIZE");
|
||||
tmpl->add("SIZE", size_str);
|
||||
|
||||
// ------------- Set authorization request for non-oneadmin's --------------
|
||||
|
||||
img_usage.add("DATASTORE", ds_id);
|
||||
img_usage.add("SIZE", size_str);
|
||||
|
||||
if ( att.uid != 0 )
|
||||
{
|
||||
AuthRequest ar(att.uid, att.gid);
|
||||
string tmpl_str = "";
|
||||
string tmpl_str;
|
||||
|
||||
// ------------------ Check permissions and ACLs ----------------------
|
||||
tmpl->to_xml(tmpl_str);
|
||||
|
||||
ar.add_create_auth(auth_object, tmpl_str); // CREATE IMAGE
|
||||
@ -381,6 +439,14 @@ void ImageAllocate::request_execute(xmlrpc_c::paramList const& params,
|
||||
delete tmpl;
|
||||
return;
|
||||
}
|
||||
|
||||
// -------------------------- Check Quotas ----------------------------
|
||||
|
||||
if ( quota_authorization(&img_usage, att) == false )
|
||||
{
|
||||
delete tmpl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ipool->allocate(att.uid,
|
||||
@ -396,6 +462,8 @@ void ImageAllocate::request_execute(xmlrpc_c::paramList const& params,
|
||||
error_str);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
quota_rollback(&img_usage, att);
|
||||
|
||||
failure_response(INTERNAL, allocate_error(error_str), att);
|
||||
return;
|
||||
}
|
||||
@ -455,9 +523,6 @@ int HostAllocate::pool_allocate(
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -23,6 +23,94 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
PoolObjectSQL * RequestManagerChown::get_and_quota(
|
||||
int oid,
|
||||
int new_uid,
|
||||
int new_gid,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
Template * tmpl;
|
||||
|
||||
int old_uid;
|
||||
int old_gid;
|
||||
|
||||
PoolObjectSQL * object;
|
||||
|
||||
object = pool->get(oid,true);
|
||||
|
||||
if ( object == 0 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(auth_object), oid),
|
||||
att);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( auth_object == PoolObjectSQL::VM )
|
||||
{
|
||||
tmpl = (static_cast<VirtualMachine*>(object))->clone_template();
|
||||
}
|
||||
else
|
||||
{
|
||||
Image * img = static_cast<Image *>(object);
|
||||
tmpl = new Template;
|
||||
|
||||
tmpl->add("DATASTORE", img->get_ds_id());
|
||||
tmpl->add("SIZE", img->get_size());
|
||||
}
|
||||
|
||||
if ( new_uid == -1 )
|
||||
{
|
||||
old_uid = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
old_uid = object->get_uid();
|
||||
}
|
||||
|
||||
if ( new_gid == -1 )
|
||||
{
|
||||
old_gid = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
old_gid = object->get_gid();
|
||||
}
|
||||
|
||||
object->unlock();
|
||||
|
||||
RequestAttributes att_new(new_uid, new_gid, att);
|
||||
RequestAttributes att_old(old_uid, old_gid, att);
|
||||
|
||||
if ( quota_authorization(tmpl, att_new) == false )
|
||||
{
|
||||
delete tmpl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
quota_rollback(tmpl, att_old);
|
||||
|
||||
object = pool->get(oid,true);
|
||||
|
||||
if ( object == 0 )
|
||||
{
|
||||
quota_rollback(tmpl, att_new);
|
||||
|
||||
quota_authorization(tmpl, att_old);
|
||||
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(auth_object), oid),
|
||||
att);
|
||||
}
|
||||
|
||||
delete tmpl;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void RequestManagerChown::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
@ -102,13 +190,27 @@ void RequestManagerChown::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
}
|
||||
}
|
||||
|
||||
// ------------- Update the object ---------------------
|
||||
// --------------- Update the object and check quotas ----------------------
|
||||
|
||||
object = pool->get(oid,true);
|
||||
if ( auth_object == PoolObjectSQL::VM ||
|
||||
auth_object == PoolObjectSQL::IMAGE )
|
||||
{
|
||||
object = get_and_quota(oid, noid, ngid, att);
|
||||
}
|
||||
else
|
||||
{
|
||||
object = pool->get(oid,true);
|
||||
|
||||
if ( object == 0 )
|
||||
{
|
||||
failure_response(NO_EXISTS,get_error(object_name(auth_object),oid),att);
|
||||
if ( object == 0 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(auth_object), oid),
|
||||
att);
|
||||
}
|
||||
}
|
||||
|
||||
if ( object == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@ -118,7 +220,6 @@ void RequestManagerChown::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
old_uid = object->get_uid();
|
||||
|
||||
object->set_user(noid,nuname);
|
||||
|
||||
}
|
||||
|
||||
if ( ngid != -1 )
|
||||
|
83
src/rm/RequestManagerGroup.cc
Normal file
83
src/rm/RequestManagerGroup.cc
Normal file
@ -0,0 +1,83 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 "RequestManagerGroup.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void GroupSetQuota::
|
||||
request_execute(xmlrpc_c::paramList const& paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int id = xmlrpc_c::value_int(paramList.getInt(1));
|
||||
string quota_str = xmlrpc_c::value_string(paramList.getString(2));
|
||||
|
||||
Group * group;
|
||||
string error_str;
|
||||
|
||||
Template quota_tmpl;
|
||||
int rc;
|
||||
|
||||
if ( id == GroupPool::ONEADMIN_ID )
|
||||
{
|
||||
failure_response(ACTION,
|
||||
request_error("Cannot set quotas for oneadmin group",""),
|
||||
att);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( basic_authorization(id, att) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rc = quota_tmpl.parse_str_or_xml(quota_str, error_str);
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
failure_response(ACTION, request_error(error_str,""), att);
|
||||
return;
|
||||
}
|
||||
|
||||
group = static_cast<Group *>(pool->get(id,true));
|
||||
|
||||
if ( group == 0 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(auth_object),id),
|
||||
att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
group->quota.set("a_tmpl, error_str);
|
||||
|
||||
pool->update(group);
|
||||
|
||||
group->unlock();
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
failure_response(ACTION, request_error(error_str,""), att);
|
||||
}
|
||||
else
|
||||
{
|
||||
success_response(id, att);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
@ -44,7 +44,7 @@ void RequestManagerUser::
|
||||
|
||||
if ( user_action(id,paramList,error_str) < 0 )
|
||||
{
|
||||
failure_response(INTERNAL, request_error(error_str,""), att);
|
||||
failure_response(ACTION, request_error(error_str,""), att);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -133,6 +133,45 @@ int UserChangeAuth::user_action(int user_id,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int UserSetQuota::user_action(int user_id,
|
||||
xmlrpc_c::paramList const& paramList,
|
||||
string& error_str)
|
||||
{
|
||||
|
||||
string quota_str = xmlrpc_c::value_string(paramList.getString(2));
|
||||
Template quota_tmpl;
|
||||
|
||||
int rc;
|
||||
User * user;
|
||||
|
||||
if ( user_id == UserPool::ONEADMIN_ID )
|
||||
{
|
||||
error_str = "Cannot set quotas for oneadmin user";
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = quota_tmpl.parse_str_or_xml(quota_str, error_str);
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
user = static_cast<User *>(pool->get(user_id,true));
|
||||
|
||||
if ( user == 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = user->quota.set("a_tmpl, error_str);
|
||||
|
||||
pool->update(user);
|
||||
|
||||
user->unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -98,8 +98,16 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
|
||||
delete tmpl;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( quota_authorization(tmpl, att) == false )
|
||||
{
|
||||
delete tmpl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Template tmpl_back(*tmpl);
|
||||
|
||||
rc = vmpool->allocate(att.uid, att.gid, att.uname, att.gname, tmpl, &vid,
|
||||
error_str, false);
|
||||
|
||||
@ -109,6 +117,8 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
|
||||
allocate_error(PoolObjectSQL::VM,error_str),
|
||||
att);
|
||||
|
||||
quota_rollback(&tmpl_back, att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -518,33 +518,32 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
|
||||
// -------------------------------------------------------------------------
|
||||
// Create a template for the new Image
|
||||
// -------------------------------------------------------------------------
|
||||
ImageTemplate * itemplate;
|
||||
ostringstream oss;
|
||||
ImageTemplate * itemplate = new ImageTemplate;
|
||||
Template img_usage;
|
||||
|
||||
oss << "NAME = \"" << img_name << "\"" << endl;
|
||||
oss << "SIZE = " << size << endl;
|
||||
itemplate->add("NAME", img_name);
|
||||
itemplate->add("SIZE", size);
|
||||
|
||||
oss << "SAVED_IMAGE_ID = " << iid_orig << endl;
|
||||
oss << "SAVED_DISK_ID = " << disk_id << endl;
|
||||
oss << "SAVED_VM_ID = " << id << endl;
|
||||
itemplate->add("SAVED_IMAGE_ID",iid_orig);
|
||||
itemplate->add("SAVED_DISK_ID",disk_id);
|
||||
itemplate->add("SAVED_VM_ID", id);
|
||||
|
||||
if ( img_type.empty() )
|
||||
{
|
||||
oss << "TYPE = " << Image::type_to_str(type) << endl;
|
||||
itemplate->add("TYPE", Image::type_to_str(type));
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << "TYPE = " << img_type << endl;
|
||||
itemplate->add("TYPE", img_type);
|
||||
}
|
||||
|
||||
itemplate = new ImageTemplate;
|
||||
|
||||
itemplate->parse_str_or_xml(oss.str(), error_str);
|
||||
|
||||
itemplate->set_saving();
|
||||
|
||||
img_usage.add("SIZE", size);
|
||||
img_usage.add("DATASTORE", ds_id);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Authorize the operation
|
||||
// Authorize the operation & check quotas
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
if ( vm_authorization(id, itemplate, att, 0, &ds_perms, auth_op) == false )
|
||||
@ -553,6 +552,12 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
|
||||
return;
|
||||
}
|
||||
|
||||
if ( quota_authorization(&img_usage, PoolObjectSQL::IMAGE, att) == false )
|
||||
{
|
||||
delete itemplate;
|
||||
return;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Create the image
|
||||
// -------------------------------------------------------------------------
|
||||
@ -570,6 +575,8 @@ void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramLis
|
||||
error_str);
|
||||
if (rc < 0)
|
||||
{
|
||||
quota_rollback(&img_usage, PoolObjectSQL::IMAGE, att);
|
||||
|
||||
failure_response(INTERNAL,
|
||||
allocate_error(PoolObjectSQL::IMAGE, error_str), att);
|
||||
return;
|
||||
|
@ -33,6 +33,7 @@ source_files=[
|
||||
'RequestManagerVMTemplate.cc',
|
||||
'RequestManagerUpdateTemplate.cc',
|
||||
'RequestManagerUser.cc',
|
||||
'RequestManagerGroup.cc',
|
||||
'RequestManagerHost.cc',
|
||||
'RequestManagerImage.cc',
|
||||
'RequestManagerChown.cc',
|
||||
|
361
src/um/Quota.cc
Normal file
361
src/um/Quota.cc
Normal file
@ -0,0 +1,361 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 "Quota.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int Quota::get_quota(const string& id, VectorAttribute ** va)
|
||||
{
|
||||
map<string, Attribute *>::iterator it;
|
||||
VectorAttribute * q;
|
||||
|
||||
istringstream iss(id);
|
||||
int id_i;
|
||||
|
||||
*va = 0;
|
||||
|
||||
if ( id.empty() )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
iss >> id_i;
|
||||
|
||||
if (iss.fail() || !iss.eof())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for ( it = attributes.begin(); it != attributes.end(); it++)
|
||||
{
|
||||
q = static_cast<VectorAttribute *>(it->second);
|
||||
|
||||
if (q->vector_value("ID") == id)
|
||||
{
|
||||
*va = q;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void Quota::add_to_quota(VectorAttribute * attr, const string& va_name, int num)
|
||||
{
|
||||
istringstream iss;
|
||||
ostringstream oss;
|
||||
float total;
|
||||
|
||||
iss.str(attr->vector_value(va_name.c_str()));
|
||||
|
||||
iss >> total;
|
||||
|
||||
total += num;
|
||||
|
||||
oss << total;
|
||||
|
||||
attr->replace(va_name, oss.str());
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int Quota::set(vector<Attribute*> * new_quotas, string& error)
|
||||
{
|
||||
vector<Attribute *>::iterator it;
|
||||
|
||||
VectorAttribute * iq;
|
||||
VectorAttribute * tq;
|
||||
string id;
|
||||
|
||||
for ( it = new_quotas->begin(); it != new_quotas->end(); it++)
|
||||
{
|
||||
iq = dynamic_cast<VectorAttribute *>(*it);
|
||||
|
||||
if ( iq == 0 )
|
||||
{
|
||||
goto error_limits;
|
||||
}
|
||||
|
||||
id = iq->vector_value("ID");
|
||||
|
||||
if ( get_quota(id, &tq) == -1 )
|
||||
{
|
||||
goto error_limits;
|
||||
}
|
||||
|
||||
if ( tq == 0 )
|
||||
{
|
||||
VectorAttribute * nq;
|
||||
|
||||
if ((nq = new_quota(iq)) == 0)
|
||||
{
|
||||
goto error_limits;
|
||||
}
|
||||
|
||||
add(nq);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (update_limits(tq, iq) != 0)
|
||||
{
|
||||
goto error_limits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_limits:
|
||||
ostringstream oss;
|
||||
|
||||
oss << "Negative limits or bad format in quota " << template_name;
|
||||
|
||||
if ( iq != 0 )
|
||||
{
|
||||
string * quota_str = iq->marshall(",");
|
||||
|
||||
oss << " = [ " << *quota_str << " ]";
|
||||
|
||||
delete quota_str;
|
||||
}
|
||||
|
||||
error = oss.str();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool Quota::check_quota(const string& qid,
|
||||
map<string, int>& usage_req,
|
||||
string& error)
|
||||
{
|
||||
VectorAttribute * q;
|
||||
map<string, int>::iterator it;
|
||||
|
||||
bool check;
|
||||
int limit;
|
||||
int usage;
|
||||
|
||||
if ( get_quota(qid, &q) == -1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Quota does not exist, create a new one
|
||||
// -------------------------------------------------------------------------
|
||||
if ( q == 0 )
|
||||
{
|
||||
map<string, string> values;
|
||||
|
||||
for (int i=0; i < num_metrics; i++)
|
||||
{
|
||||
ostringstream usage_req_str;
|
||||
string metrics_used = metrics[i];
|
||||
|
||||
metrics_used += "_USED";
|
||||
|
||||
it = usage_req.find(metrics[i]);
|
||||
|
||||
if (it == usage_req.end())
|
||||
{
|
||||
usage_req_str << "0";
|
||||
}
|
||||
else
|
||||
{
|
||||
usage_req_str << it->second;
|
||||
}
|
||||
|
||||
values.insert(make_pair(metrics[i], "0"));
|
||||
values.insert(make_pair(metrics_used, usage_req_str.str()));
|
||||
}
|
||||
|
||||
if (!qid.empty())
|
||||
{
|
||||
values.insert(make_pair("ID", qid));
|
||||
}
|
||||
|
||||
add(new VectorAttribute(template_name, values));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Check the quotas for each usage request
|
||||
// -------------------------------------------------------------------------
|
||||
for (int i=0; i < num_metrics; i++)
|
||||
{
|
||||
string metrics_used = metrics[i];
|
||||
|
||||
metrics_used += "_USED";
|
||||
|
||||
it = usage_req.find(metrics[i]);
|
||||
|
||||
if (it == usage_req.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
q->vector_value(metrics[i], limit);
|
||||
q->vector_value(metrics_used.c_str(), usage);
|
||||
|
||||
check = ( limit == 0 ) || ( ( usage + it->second ) <= limit );
|
||||
|
||||
if ( !check )
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "Limit of " << limit << " reached for " << metrics[i]
|
||||
<< " quota in " << template_name;
|
||||
|
||||
if ( !qid.empty() )
|
||||
{
|
||||
oss << " with ID: " << qid;
|
||||
}
|
||||
|
||||
error = oss.str();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Add resource usage to quotas
|
||||
// -------------------------------------------------------------------------
|
||||
for (int i=0; i < num_metrics; i++)
|
||||
{
|
||||
string metrics_used = metrics[i];
|
||||
|
||||
metrics_used += "_USED";
|
||||
|
||||
it = usage_req.find(metrics[i]);
|
||||
|
||||
if (it == usage_req.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
add_to_quota(q, metrics_used, it->second);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void Quota::del_quota(const string& qid, map<string, int>& usage_req)
|
||||
{
|
||||
VectorAttribute * q;
|
||||
map<string, int>::iterator it;
|
||||
|
||||
if ( get_quota(qid, &q) == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( q == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0; i < num_metrics; i++)
|
||||
{
|
||||
string metrics_used = metrics[i];
|
||||
|
||||
metrics_used += "_USED";
|
||||
|
||||
it = usage_req.find(metrics[i]);
|
||||
|
||||
if (it == usage_req.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
add_to_quota(q, metrics_used, -it->second);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int Quota::update_limits(VectorAttribute * quota, const VectorAttribute * va)
|
||||
{
|
||||
string limit;
|
||||
int limit_i;
|
||||
|
||||
for (int i=0; i < num_metrics; i++)
|
||||
{
|
||||
limit = va->vector_value_str(metrics[i], limit_i);
|
||||
|
||||
if ( limit_i < 0 ) //No quota, NaN or negative
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
quota->replace(metrics[i], limit);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
VectorAttribute * Quota::new_quota(VectorAttribute * va)
|
||||
{
|
||||
map<string,string> limits;
|
||||
|
||||
string limit;
|
||||
int limit_i;
|
||||
|
||||
for (int i=0; i < num_metrics; i++)
|
||||
{
|
||||
string metrics_used = metrics[i];
|
||||
|
||||
metrics_used += "_USED";
|
||||
|
||||
limit = va->vector_value_str(metrics[i], limit_i);
|
||||
|
||||
if ( limit_i < 0 ) //No quota, NaN or negative
|
||||
{
|
||||
limit = "0";
|
||||
}
|
||||
|
||||
limits.insert(make_pair(metrics[i], limit));
|
||||
limits.insert(make_pair(metrics_used, "0"));
|
||||
}
|
||||
|
||||
string id = va->vector_value("ID");
|
||||
|
||||
if ( !id.empty() )
|
||||
{
|
||||
limits.insert(make_pair("ID", id));
|
||||
}
|
||||
|
||||
return new VectorAttribute(template_name,limits);
|
||||
}
|
||||
|
85
src/um/QuotaDatastore.cc
Normal file
85
src/um/QuotaDatastore.cc
Normal file
@ -0,0 +1,85 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 "QuotaDatastore.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
const char * QuotaDatastore::DS_METRICS[] = {"SIZE", "IMAGES"};
|
||||
|
||||
const int QuotaDatastore::NUM_DS_METRICS = 2;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool QuotaDatastore::check(Template * tmpl, string& error)
|
||||
{
|
||||
map<string, int> ds_request;
|
||||
|
||||
string ds_id;
|
||||
int size;
|
||||
|
||||
tmpl->get("DATASTORE", ds_id);
|
||||
|
||||
if ( ds_id.empty() )
|
||||
{
|
||||
error = "Datastore not defined for image";
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( tmpl->get("SIZE", size) == false )
|
||||
{
|
||||
error = "Size not defined for image";
|
||||
return false;
|
||||
}
|
||||
|
||||
ds_request.insert(make_pair("IMAGES",1));
|
||||
ds_request.insert(make_pair("SIZE", size));
|
||||
|
||||
return check_quota(ds_id, ds_request, error);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void QuotaDatastore::del(Template * tmpl)
|
||||
{
|
||||
map<string, int> ds_request;
|
||||
|
||||
string ds_id;
|
||||
int size;
|
||||
|
||||
tmpl->get("DATASTORE", ds_id);
|
||||
|
||||
if ( ds_id.empty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( tmpl->get("SIZE", size) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ds_request.insert(make_pair("IMAGES",1));
|
||||
ds_request.insert(make_pair("SIZE", size));
|
||||
|
||||
del_quota(ds_id, ds_request);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
97
src/um/QuotaImage.cc
Normal file
97
src/um/QuotaImage.cc
Normal file
@ -0,0 +1,97 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 "QuotaImage.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
const char * QuotaImage::IMAGE_METRICS[] = {"RVMS"};
|
||||
|
||||
const int QuotaImage::NUM_IMAGE_METRICS = 1;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool QuotaImage::check(Template * tmpl, string& error)
|
||||
{
|
||||
vector<Attribute*> disks;
|
||||
VectorAttribute * disk;
|
||||
|
||||
string image_id;
|
||||
int num;
|
||||
|
||||
map<string, int> image_request;
|
||||
|
||||
image_request.insert(make_pair("RVMS",1));
|
||||
|
||||
num = tmpl->get("DISK", disks);
|
||||
|
||||
for (int i = 0 ; i < num ; i++)
|
||||
{
|
||||
disk = dynamic_cast<VectorAttribute *>(disks[i]);
|
||||
|
||||
if ( disk == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
image_id = disk->vector_value("IMAGE_ID");
|
||||
|
||||
if ( !check_quota(image_id, image_request, error) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void QuotaImage::del(Template * tmpl)
|
||||
{
|
||||
|
||||
vector<Attribute*> disks;
|
||||
VectorAttribute * disk;
|
||||
|
||||
string image_id;
|
||||
int num;
|
||||
|
||||
map<string, int> image_request;
|
||||
|
||||
image_request.insert(make_pair("RVMS",1));
|
||||
|
||||
num = tmpl->get("DISK", disks);
|
||||
|
||||
for (int i = 0 ; i < num ; i++)
|
||||
{
|
||||
disk = dynamic_cast<VectorAttribute *>(disks[i]);
|
||||
|
||||
if ( disk == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
image_id = disk->vector_value("IMAGE_ID");
|
||||
|
||||
del_quota(image_id, image_request);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
97
src/um/QuotaNetwork.cc
Normal file
97
src/um/QuotaNetwork.cc
Normal file
@ -0,0 +1,97 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 "QuotaNetwork.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
const char * QuotaNetwork::NET_METRICS[] = {"LEASES"};
|
||||
|
||||
const int QuotaNetwork::NUM_NET_METRICS = 1;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool QuotaNetwork::check(Template * tmpl, string& error)
|
||||
{
|
||||
vector<Attribute*> nics;
|
||||
VectorAttribute * nic;
|
||||
|
||||
string net_id;
|
||||
int num;
|
||||
|
||||
map<string, int> net_request;
|
||||
|
||||
net_request.insert(make_pair("LEASES",1));
|
||||
|
||||
num = tmpl->get("NIC", nics);
|
||||
|
||||
for (int i = 0 ; i < num ; i++)
|
||||
{
|
||||
nic = dynamic_cast<VectorAttribute *>(nics[i]);
|
||||
|
||||
if ( nic == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
net_id = nic->vector_value("NETWORK_ID");
|
||||
|
||||
if ( !check_quota(net_id, net_request, error) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void QuotaNetwork::del(Template * tmpl)
|
||||
{
|
||||
|
||||
vector<Attribute*> nics;
|
||||
VectorAttribute * nic;
|
||||
|
||||
string net_id;
|
||||
int num;
|
||||
|
||||
map<string, int> net_request;
|
||||
|
||||
net_request.insert(make_pair("LEASES",1));
|
||||
|
||||
num = tmpl->get("NIC", nics);
|
||||
|
||||
for (int i = 0 ; i < num ; i++)
|
||||
{
|
||||
nic = dynamic_cast<VectorAttribute *>(nics[i]);
|
||||
|
||||
if ( nic == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
net_id = nic->vector_value("NETWORK_ID");
|
||||
|
||||
del_quota(net_id, net_request);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
105
src/um/QuotaVirtualMachine.cc
Normal file
105
src/um/QuotaVirtualMachine.cc
Normal file
@ -0,0 +1,105 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2012, 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 "QuotaVirtualMachine.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
const char * QuotaVirtualMachine::VM_METRICS[] = {"VMS", "CPU", "MEMORY"};
|
||||
|
||||
const int QuotaVirtualMachine::NUM_VM_METRICS = 3;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int QuotaVirtualMachine::get_quota(const string& id, VectorAttribute **va)
|
||||
{
|
||||
vector<Attribute*> values;
|
||||
int num;
|
||||
|
||||
*va = 0;
|
||||
|
||||
num = get(template_name, values);
|
||||
|
||||
if ( num == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*va = dynamic_cast<VectorAttribute *>(values[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool QuotaVirtualMachine::check(Template * tmpl, string& error)
|
||||
{
|
||||
map<string, int> vm_request;
|
||||
|
||||
int memory;
|
||||
int cpu;
|
||||
|
||||
if ( tmpl->get("MEMORY", memory) == false )
|
||||
{
|
||||
error = "MEMORY not defined for VM";
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( tmpl->get("CPU", cpu) == false )
|
||||
{
|
||||
error = "CPU not defined for VM";
|
||||
return false;
|
||||
}
|
||||
|
||||
vm_request.insert(make_pair("VMS",1));
|
||||
vm_request.insert(make_pair("MEMORY", memory));
|
||||
vm_request.insert(make_pair("CPU", cpu));
|
||||
|
||||
return check_quota("", vm_request, error);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void QuotaVirtualMachine::del(Template * tmpl)
|
||||
{
|
||||
map<string, int> vm_request;
|
||||
|
||||
int memory;
|
||||
int cpu;
|
||||
|
||||
if ( tmpl->get("MEMORY", memory) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( tmpl->get("CPU", cpu) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vm_request.insert(make_pair("VMS",1));
|
||||
vm_request.insert(make_pair("MEMORY", memory));
|
||||
vm_request.insert(make_pair("CPU", cpu));
|
||||
|
||||
del_quota("", vm_request);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
@ -23,7 +23,12 @@ lib_name='nebula_um'
|
||||
# Sources to generate the library
|
||||
source_files=[
|
||||
'User.cc',
|
||||
'UserPool.cc'
|
||||
'UserPool.cc',
|
||||
'Quota.cc',
|
||||
'QuotaDatastore.cc',
|
||||
'QuotaNetwork.cc',
|
||||
'QuotaVirtualMachine.cc',
|
||||
'QuotaImage.cc'
|
||||
]
|
||||
|
||||
# Build library
|
||||
|
@ -136,8 +136,10 @@ error_common:
|
||||
|
||||
string& User::to_xml(string& xml) const
|
||||
{
|
||||
ostringstream oss;
|
||||
string template_xml;
|
||||
ostringstream oss;
|
||||
|
||||
string template_xml;
|
||||
string quota_xml;
|
||||
|
||||
int enabled_int = enabled?1:0;
|
||||
|
||||
@ -151,6 +153,7 @@ string& User::to_xml(string& xml) const
|
||||
"<AUTH_DRIVER>" << auth_driver <<"</AUTH_DRIVER>"<<
|
||||
"<ENABLED>" << enabled_int <<"</ENABLED>" <<
|
||||
obj_template->to_xml(template_xml) <<
|
||||
quota.to_xml(quota_xml) <<
|
||||
"</USER>";
|
||||
|
||||
xml = oss.str();
|
||||
@ -194,6 +197,8 @@ int User::from_xml(const string& xml)
|
||||
rc += obj_template->from_xml_node(content[0]);
|
||||
|
||||
ObjectXML::free_nodes(content);
|
||||
|
||||
rc += quota.from_xml(this);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
|
@ -762,4 +762,3 @@ int UserPool::authorize(AuthRequest& ar)
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -212,8 +212,8 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
|
||||
int rc;
|
||||
string name;
|
||||
|
||||
string value;
|
||||
ostringstream oss;
|
||||
string value;
|
||||
ostringstream oss;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Set a name if the VM has not got one and VM_ID
|
||||
@ -241,6 +241,24 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
|
||||
|
||||
this->name = name;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Check for CPU and MEMORY attributes
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
get_template_attribute("MEMORY", value);
|
||||
|
||||
if ( value.empty())
|
||||
{
|
||||
goto error_no_memory;
|
||||
}
|
||||
|
||||
get_template_attribute("CPU", value);
|
||||
|
||||
if ( value.empty())
|
||||
{
|
||||
goto error_no_cpu;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Get network leases
|
||||
// ------------------------------------------------------------------------
|
||||
@ -321,9 +339,16 @@ error_leases_rollback:
|
||||
release_network_leases();
|
||||
goto error_common;
|
||||
|
||||
error_no_cpu:
|
||||
error_str = "CPU attribute missing.";
|
||||
goto error_common;
|
||||
|
||||
error_no_memory:
|
||||
error_str = "MEMORY attribute missing.";
|
||||
goto error_common;
|
||||
|
||||
error_name_length:
|
||||
oss << "NAME is too long; max length is 128 chars.";
|
||||
error_str = oss.str();
|
||||
error_str = "NAME is too long; max length is 128 chars.";
|
||||
goto error_common;
|
||||
|
||||
error_common:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user