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

feature #1099: Moved SQL filters to the corresponding pools

This commit is contained in:
Ruben S. Montero 2012-05-05 03:18:25 +02:00
parent 70d5c75d04
commit 7ad3ce1965
8 changed files with 290 additions and 209 deletions

View File

@ -62,12 +62,6 @@ public:
*/
string& to_xml(string& xml) const;
// ----------------------------------------
// DataBase implementation
// ----------------------------------------
static const char * table;
private:
friend class VirtualMachine;
friend class VirtualMachinePool;
@ -75,7 +69,8 @@ private:
// ----------------------------------------
// DataBase implementation variables
// ----------------------------------------
static const char * table;
static const char * db_names;
static const char * db_bootstrap;

View File

@ -154,19 +154,47 @@ public:
*/
virtual int dump(ostringstream& oss, const string& where) = 0;
/**
* Dumps the output of the custom sql query into an xml
*
* @param oss The output stream to dump the xml contents
* @param root_elem_name Name of the root xml element name
* @param sql_query The SQL query to execute
*
* @return 0 on success
*/
int custom_dump(ostringstream& oss,
const string& root_elem_name,
ostringstream& sql_query);
// -------------------------------------------------------------------------
// Function to generate dump filters
// -------------------------------------------------------------------------
/**
* Creates a filter for those objects (oids) or objects owned by a given
* group that an user can access based on the ACL rules
* @param uid the user id
* @param gid the group id
* @param auth_object object type
* @param all returns if the user can access all objects
* @param filter the resulting filter string
*/
static void acl_filter(int uid,
int gid,
PoolObjectSQL::ObjectType auth_object,
bool& all,
string& filter);
/**
* Creates a filter for the objects owned by a given user/group
* @param uid the user id
* @param gid the group id
* @param filter_flag query type (ALL, MINE, GROUP)
* @param all user can access all objects
* @param filter the resulting filter string
*/
static void usr_filter(int uid,
int gid,
int filter_flag,
bool all,
const string& acl_str,
string& filter);
/**
* Creates a filter for a given set of objects based on their id
* @param start_id first id
* @param end_id last id
* @param filter the resulting filter string
*/
static void oid_filter(int start_id,
int end_id,
string& filter);
protected:
/**
@ -195,8 +223,23 @@ protected:
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& elem_name,
const char * table, const string& where);
int dump(ostringstream& oss,
const string& elem_name,
const char * table,
const string& where);
/**
* Dumps the output of the custom sql query into an xml
*
* @param oss The output stream to dump the xml contents
* @param root_elem_name Name of the root xml element name
* @param sql_query The SQL query to execute
*
* @return 0 on success
*/
int dump(ostringstream& oss,
const string& root_elem_name,
ostringstream& sql_query);
/* ---------------------------------------------------------------------- */
/* Interface to access the lastOID assigned by the pool */

View File

@ -29,6 +29,16 @@ using namespace std;
class RequestManagerPoolInfoFilter: public Request
{
public:
/** Specify all objects the user has right to USE (-2) */
static const int ALL;
/** Specify user's objects in the pool (-3) */
static const int MINE;
/** Specify user's + group objects (-1) */
static const int MINE_GROUP;
protected:
RequestManagerPoolInfoFilter(const string& method_name,
const string& help,
@ -40,30 +50,18 @@ protected:
/* -------------------------------------------------------------------- */
/** Specify all objects the user has right to USE (-2) */
static const int ALL;
/** Specify user's objects in the pool (-3) */
static const int MINE;
/** Specify user's + group objects (-1) */
static const int MINE_GROUP;
/* -------------------------------------------------------------------- */
virtual void request_execute(
xmlrpc_c::paramList const& paramList, RequestAttributes& att);
/* -------------------------------------------------------------------- */
void generate_where_string(
RequestAttributes& att,
int filter_flag,
int start_id,
int end_id,
const string& and_clause,
const string& or_clause,
ostringstream& where_string);
void where_filter(RequestAttributes& att,
int filter_flag,
int start_id,
int end_id,
const string& and_clause,
const string& or_clause,
string& where_string);
/* -------------------------------------------------------------------- */

View File

@ -710,13 +710,6 @@ public:
static void set_auth_request(int uid,
AuthRequest& ar,
VirtualMachineTemplate *tmpl);
// ------------------------------------------------------------------------
// DataBase implementation (Public)
// ------------------------------------------------------------------------
static const char * table;
private:
// -------------------------------------------------------------------------
@ -952,6 +945,8 @@ protected:
// *************************************************************************
// DataBase implementation
// *************************************************************************
static const char * table;
static const char * db_names;

View File

@ -145,6 +145,18 @@ public:
return PoolSQL::dump(oss, "VM_POOL", VirtualMachine::table, where);
};
/**
* Dumps the VM accounting information in XML format. A filter can be also
* added to the query as well as a time frame.
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
*
* @return 0 on success
*/
int dump_acct(ostringstream& oss,
const string& where,
int time_start,
int time_end);
private:
/**
* Factory method to produce VM objects

View File

@ -21,6 +21,7 @@
#include <algorithm>
#include "PoolSQL.h"
#include "RequestManagerPoolInfoFilter.h"
#include <errno.h>
@ -490,22 +491,22 @@ int PoolSQL::dump(ostringstream& oss,
cmd << " ORDER BY oid";
return custom_dump(oss, elem_name, cmd);
return dump(oss, elem_name, cmd);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int PoolSQL::custom_dump(ostringstream& oss,
const string& root_elem_name,
ostringstream& sql_query)
int PoolSQL::dump(ostringstream& oss,
const string& root_elem_name,
ostringstream& sql_query)
{
int rc;
oss << "<" << root_elem_name << ">";
set_callback(static_cast<Callbackable::Callback>(&PoolSQL::dump_cb),
static_cast<void *>(&oss));
static_cast<void *>(&oss));
rc = db->exec(sql_query, this);
@ -557,3 +558,120 @@ int PoolSQL::search(
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void PoolSQL::acl_filter(int uid,
int gid,
PoolObjectSQL::ObjectType auth_object,
bool& all,
string& filter)
{
filter.clear();
if ( uid == 0 || gid == 0 )
{
all = true;
return;
}
Nebula& nd = Nebula::instance();
AclManager* aclm = nd.get_aclm();
ostringstream acl_filter;
vector<int>::iterator it;
vector<int> oids;
vector<int> gids;
aclm->reverse_search(uid,
gid,
auth_object,
AuthRequest::USE,
all,
oids,
gids);
for ( it = oids.begin(); it < oids.end(); it++ )
{
acl_filter << " OR oid = " << *it;
}
for ( it = gids.begin(); it < gids.end(); it++ )
{
acl_filter << " OR gid = " << *it;
}
filter = acl_filter.str();
}
/* -------------------------------------------------------------------------- */
void PoolSQL::usr_filter(int uid,
int gid,
int filter_flag,
bool all,
const string& acl_str,
string& filter)
{
ostringstream uid_filter;
if ( filter_flag == RequestManagerPoolInfoFilter::MINE )
{
uid_filter << "uid = " << uid;
}
else if ( filter_flag == RequestManagerPoolInfoFilter::MINE_GROUP )
{
uid_filter << " uid = " << uid
<< " OR ( gid = " << gid << " AND group_u = 1 )";
}
else if ( filter_flag == RequestManagerPoolInfoFilter::ALL )
{
if (!all)
{
uid_filter << " uid = " << uid
<< " OR ( gid = " << gid << " AND group_u = 1 )"
<< " OR other_u = 1"
<< acl_str;
}
}
else
{
uid_filter << "uid = " << filter_flag;
if ( filter_flag != uid && !all )
{
uid_filter << " AND ("
<< " ( gid = " << gid << " AND group_u = 1)"
<< " OR other_u = 1"
<< acl_str
<< ")";
}
}
filter = uid_filter.str();
}
/* -------------------------------------------------------------------------- */
void PoolSQL::oid_filter(int start_id,
int end_id,
string& filter)
{
ostringstream idfilter;
if ( start_id != -1 )
{
idfilter << "oid >= " << start_id;
if ( end_id != -1 )
{
idfilter << " AND oid <= " << end_id;
}
}
filter = idfilter.str();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -100,8 +100,7 @@ void VirtualMachinePoolAccounting::request_execute(
int time_end = xmlrpc_c::value_int(paramList.getInt(3));
ostringstream oss;
ostringstream cmd;
ostringstream vmpool_where;
string where;
int rc;
if ( filter_flag < MINE )
@ -112,39 +111,12 @@ void VirtualMachinePoolAccounting::request_execute(
return;
}
cmd << "SELECT " << History::table << ".body FROM " << History::table
<< " INNER JOIN " << VirtualMachine::table
<< " WHERE vid=oid";
generate_where_string(att, filter_flag, -1, -1,
"", "", vmpool_where);
if ( !vmpool_where.str().empty() ) //TODO: better empty check?
{
cmd << " AND " << vmpool_where;
}
if ( time_start != -1 || time_end != -1 )
{
if ( time_start != -1 )
{
cmd << " AND (etime > " << time_start << " OR etime = 0)";
}
if ( time_end != -1 )
{
cmd << " AND stime < " << time_end;
}
}
cmd << " GROUP BY vid,seq";
// ------------------------------------------
// Dump the history records
// ------------------------------------------
rc = pool->custom_dump(oss, "HISTORY_RECORDS", cmd);
where_filter(att, filter_flag, -1, -1, "", "", where);
rc = (static_cast<VirtualMachinePool *>(pool))->dump_acct(oss,
where,
time_start,
time_end);
if ( rc != 0 )
{
failure_response(INTERNAL,request_error("Internal Error",""), att);
@ -209,126 +181,38 @@ void ClusterPoolInfo::request_execute(
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void RequestManagerPoolInfoFilter::generate_where_string(
void RequestManagerPoolInfoFilter::where_filter(
RequestAttributes& att,
int filter_flag,
int start_id,
int end_id,
const string& and_clause,
const string& or_clause,
ostringstream& where_string)
string& filter_str)
{
bool empty = true;
bool empty = true;
bool all;
ostringstream uid_filter;
ostringstream id_filter;
string uid_str;
string acl_str;
string id_str;
string uid_str;
string oid_str;
Nebula& nd = Nebula::instance();
AclManager* aclm = nd.get_aclm();
bool all;
vector<int> oids;
vector<int> gids;
ostringstream filter;
PoolSQL::acl_filter(att.uid, att.gid, auth_object, all, acl_str);
PoolSQL::usr_filter(att.uid, att.gid, filter_flag, all, acl_str, uid_str);
PoolSQL::oid_filter(start_id, end_id, oid_str);
// -------------------------------------------------------------------------
// User ID filter
// -------------------------------------------------------------------------
// Compound WHERE clause
// WHERE ( id_str ) AND ( uid_str ) AND ( and_clause ) OR ( or_clause )
// -------------------------------------------------------------------------
if ( att.uid == 0 || att.gid == 0 )
if (!oid_str.empty())
{
all = true;
}
else
{
ostringstream acl_filter;
vector<int>::iterator it;
aclm->reverse_search(att.uid,
att.gid,
auth_object,
AuthRequest::USE,
all,
oids,
gids);
for ( it = oids.begin(); it < oids.end(); it++ )
{
acl_filter << " OR oid = " << *it;
}
for ( it = gids.begin(); it < gids.end(); it++ )
{
acl_filter << " OR gid = " << *it;
}
acl_str = acl_filter.str();
}
switch ( filter_flag )
{
case MINE:
uid_filter << "uid = " << att.uid;
break;
case MINE_GROUP:
uid_filter << " uid = " << att.uid
<< " OR ( gid = " << att.gid << " AND group_u = 1 )";
break;
case ALL:
if (!all)
{
uid_filter << " uid = " << att.uid
<< " OR ( gid = " << att.gid << " AND group_u = 1 )"
<< " OR other_u = 1"
<< acl_str;
}
break;
default:
uid_filter << "uid = " << filter_flag;
if ( filter_flag != att.uid && !all )
{
uid_filter << " AND ("
<< " ( gid = " << att.gid << " AND group_u = 1)"
<< " OR other_u = 1"
<< acl_str
<< ")";
}
break;
}
uid_str = uid_filter.str();
// ------------------------------------------
// Resource ID filter
// ------------------------------------------
if ( start_id != -1 )
{
id_filter << "oid >= " << start_id;
if ( end_id != -1 )
{
id_filter << " AND oid <= " << end_id;
}
}
id_str = id_filter.str();
// ------------------------------------------
// Compound WHERE clause
// ------------------------------------------
// WHERE ( id_str ) AND ( uid_str ) AND ( and_clause ) OR ( or_clause )
if (!id_str.empty())
{
where_string << "(" << id_str << ")" ;
filter << "(" << oid_str << ")" ;
empty = false;
}
@ -336,10 +220,10 @@ void RequestManagerPoolInfoFilter::generate_where_string(
{
if (!empty)
{
where_string << " AND ";
filter << " AND ";
}
where_string << "(" << uid_str << ")";
filter << "(" << uid_str << ")";
empty = false;
}
@ -347,10 +231,10 @@ void RequestManagerPoolInfoFilter::generate_where_string(
{
if (!empty)
{
where_string << " AND ";
filter << " AND ";
}
where_string << "(" << and_clause << ")";
filter << "(" << and_clause << ")";
empty = false;
}
@ -358,15 +242,17 @@ void RequestManagerPoolInfoFilter::generate_where_string(
{
if (!empty)
{
where_string << " OR ";
filter << " OR ";
}
where_string << "(" << or_clause << ")";
filter << "(" << or_clause << ")";
}
filter_str = filter.str();
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManagerPoolInfoFilter::dump(
RequestAttributes& att,
@ -377,7 +263,7 @@ void RequestManagerPoolInfoFilter::dump(
const string& or_clause)
{
ostringstream oss;
ostringstream where_string;
string where_string;
int rc;
if ( filter_flag < MINE )
@ -388,14 +274,15 @@ void RequestManagerPoolInfoFilter::dump(
return;
}
generate_where_string(att, filter_flag, start_id, end_id,
and_clause, or_clause, where_string);
where_filter(att,
filter_flag,
start_id,
end_id,
and_clause,
or_clause,
where_string);
// ------------------------------------------
// Get the pool
// ------------------------------------------
rc = pool->dump(oss, where_string.str());
rc = pool->dump(oss, where_string);
if ( rc != 0 )
{
@ -407,4 +294,3 @@ void RequestManagerPoolInfoFilter::dump(
return;
}

View File

@ -266,3 +266,37 @@ int VirtualMachinePool::get_pending(
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachinePool::dump_acct(ostringstream& oss,
const string& where,
int time_start,
int time_end)
{
ostringstream cmd;
cmd << "SELECT " << History::table << ".body FROM " << History::table
<< " INNER JOIN " << VirtualMachine::table
<< " WHERE vid=oid";
if ( !where.empty() )
{
cmd << " AND " << where;
}
if ( time_start != -1 || time_end != -1 )
{
if ( time_start != -1 )
{
cmd << " AND (etime > " << time_start << " OR etime = 0)";
}
if ( time_end != -1 )
{
cmd << " AND stime < " << time_end;
}
}
cmd << " GROUP BY vid,seq";
return PoolSQL::dump(oss, "HISTORY_RECORDS", cmd);
};