mirror of
https://github.com/OpenNebula/one.git
synced 2024-12-22 13:33:52 +03:00
feature #1611: Abstracts system properties and system DB management
This commit is contained in:
parent
e4a601dde8
commit
d6091c439e
@ -21,7 +21,7 @@
|
||||
#include "SqlDB.h"
|
||||
#include "ObjectSQL.h"
|
||||
|
||||
class DefaultQuotas : public Quotas, ObjectSQL
|
||||
class DefaultQuotas : public Quotas
|
||||
{
|
||||
public:
|
||||
DefaultQuotas(
|
||||
@ -48,95 +48,34 @@ public:
|
||||
* @param db pointer to the db
|
||||
* @return 0 on success
|
||||
*/
|
||||
int insert(SqlDB *db, string& error_str)
|
||||
{
|
||||
return insert_replace(db, false, error_str);
|
||||
};
|
||||
int insert();
|
||||
|
||||
/**
|
||||
* Writes/updates the quotas data fields in the database.
|
||||
* @param db pointer to the db
|
||||
* @return 0 on success
|
||||
*/
|
||||
int update(SqlDB *db)
|
||||
{
|
||||
string error_str;
|
||||
return insert_replace(db, true, error_str);
|
||||
};
|
||||
int update();
|
||||
|
||||
/**
|
||||
* Reads the Quotas from the database.
|
||||
* @param db pointer to the db
|
||||
* @return 0 on success
|
||||
*/
|
||||
int select(SqlDB *db);
|
||||
|
||||
/**
|
||||
* Bootstraps the database table(s) associated to the default quotas
|
||||
* @return 0 on success
|
||||
*/
|
||||
static int bootstrap(SqlDB * db)
|
||||
{
|
||||
ostringstream oss(DefaultQuotas::db_bootstrap);
|
||||
|
||||
return db->exec(oss);
|
||||
}
|
||||
int select();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Name for the default quota attribute
|
||||
*/
|
||||
const char * root_elem;
|
||||
|
||||
// *************************************************************************
|
||||
// DataBase implementation
|
||||
// *************************************************************************
|
||||
|
||||
static const char * db_names;
|
||||
|
||||
static const char * db_bootstrap;
|
||||
|
||||
static const char * table;
|
||||
|
||||
/**
|
||||
* Execute an INSERT or REPLACE Sql query.
|
||||
* @param db The SQL DB
|
||||
* @param replace Execute an INSERT or a REPLACE
|
||||
* @param error_str Returns the error reason, if any
|
||||
* @return 0 one success
|
||||
*/
|
||||
int insert_replace(SqlDB *db, bool replace, string& error_str);
|
||||
|
||||
/**
|
||||
* Callback function to unmarshall a PoolObjectSQL
|
||||
* @param num the number of columns read from the DB
|
||||
* @param names the column names
|
||||
* @param vaues the column values
|
||||
* @return 0 on success
|
||||
*/
|
||||
int select_cb(void *nil, int num, char **values, char **names)
|
||||
{
|
||||
if ( (!values[0]) || (num != 1) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return from_xml(values[0]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds quota object from an ObjectXML
|
||||
* @param xml The xml-formatted string
|
||||
* @return 0 on success
|
||||
*/
|
||||
int from_xml(const string& xml);
|
||||
|
||||
/**
|
||||
* Removes the Quotas from the database.
|
||||
* @param db pointer to the db
|
||||
* @return 0 on success
|
||||
*/
|
||||
int drop(SqlDB * db)
|
||||
{
|
||||
return -1; // Not supported
|
||||
};
|
||||
};
|
||||
|
||||
#endif /*DEFAULT_QUOTAS_H_*/
|
||||
|
100
include/Nebula.h
100
include/Nebula.h
@ -18,6 +18,7 @@
|
||||
#define NEBULA_H_
|
||||
|
||||
#include "SqlDB.h"
|
||||
#include "SystemDB.h"
|
||||
|
||||
#include "NebulaTemplate.h"
|
||||
|
||||
@ -46,7 +47,13 @@
|
||||
|
||||
#include "Callbackable.h"
|
||||
|
||||
class Nebula : public Callbackable
|
||||
|
||||
/**
|
||||
* This is the main class for the OpenNebula daemon oned. It stores references
|
||||
* to the main modules and data pools. It also includes functions to bootstrap
|
||||
* the system and start all its components.
|
||||
*/
|
||||
class Nebula
|
||||
{
|
||||
public:
|
||||
|
||||
@ -325,7 +332,7 @@ public:
|
||||
|
||||
if ( rc == 0 )
|
||||
{
|
||||
rc = default_user_quota.update(db);
|
||||
rc = default_user_quota.update();
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -343,12 +350,52 @@ public:
|
||||
|
||||
if ( rc == 0 )
|
||||
{
|
||||
rc = default_group_quota.update(db);
|
||||
rc = default_group_quota.update();
|
||||
}
|
||||
|
||||
return rc;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// System attributes
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Reads a System attribute from the DB
|
||||
* @param attr_name name of the attribute
|
||||
* @param cb Callback that will receive the attribute in XML
|
||||
* @return 0 on success
|
||||
*/
|
||||
int select_sys_attribute(const string& attr_name, string& attr_xml)
|
||||
{
|
||||
return system_db->select_sys_attribute(attr_name, attr_xml);
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes a system attribute in the database.
|
||||
* @param db pointer to the db
|
||||
* @return 0 on success
|
||||
*/
|
||||
int insert_sys_attribute(
|
||||
const string& attr_name,
|
||||
const string& xml_attr,
|
||||
string& error_str)
|
||||
{
|
||||
return system_db->insert_sys_attribute(attr_name, xml_attr, error_str);
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the system attribute in the database.
|
||||
* @param db pointer to the db
|
||||
* @return 0 on success
|
||||
*/
|
||||
int update_sys_attribute(
|
||||
const string& attr_name,
|
||||
const string& xml_attr,
|
||||
string& error_str)
|
||||
{
|
||||
return system_db->update_sys_attribute(attr_name, xml_attr, error_str);
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -366,9 +413,10 @@ private:
|
||||
"/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA",
|
||||
"/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA",
|
||||
"/DEFAULT_GROUP_QUOTAS/VM_QUOTA"),
|
||||
db(0),vmpool(0),hpool(0),vnpool(0),
|
||||
upool(0),ipool(0),gpool(0),tpool(0),dspool(0),clpool(0),docpool(0),
|
||||
lcm(0),vmm(0),im(0),tm(0),dm(0),rm(0),hm(0),authm(0),aclm(0),imagem(0)
|
||||
system_db(0), db(0), vmpool(0), hpool(0), vnpool(0),
|
||||
upool(0), ipool(0), gpool(0), tpool(0), dspool(0), clpool(0),
|
||||
docpool(0), lcm(0), vmm(0), im(0), tm(0), dm(0), rm(0), hm(0), authm(0),
|
||||
aclm(0), imagem(0)
|
||||
{
|
||||
const char * nl = getenv("ONE_LOCATION");
|
||||
|
||||
@ -514,6 +562,11 @@ private:
|
||||
{
|
||||
delete db;
|
||||
}
|
||||
|
||||
if ( system_db != 0 )
|
||||
{
|
||||
delete system_db;
|
||||
}
|
||||
};
|
||||
|
||||
Nebula& operator=(Nebula const&){return *this;};
|
||||
@ -539,7 +592,7 @@ private:
|
||||
// Configuration
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
OpenNebulaTemplate * nebula_configuration;
|
||||
OpenNebulaTemplate * nebula_configuration;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Default quotas
|
||||
@ -548,6 +601,11 @@ private:
|
||||
DefaultQuotas default_user_quota;
|
||||
DefaultQuotas default_group_quota;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// The system database
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
SystemDB * system_db;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Nebula Pools
|
||||
@ -585,34 +643,6 @@ private:
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
friend void nebula_signal_handler (int sig);
|
||||
|
||||
/**
|
||||
* Bootstraps the database control tables
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int bootstrap();
|
||||
|
||||
/**
|
||||
* Callback function for the check_db_version method. Stores the read
|
||||
* version in loaded_db_version
|
||||
* @param _loaded_db_version returned columns
|
||||
* @param num the number of columns read from the DB
|
||||
* @param names the column names
|
||||
* @param vaues the column values
|
||||
* @return 0 on success
|
||||
*/
|
||||
int select_cb(void *_loaded_db_version, int num, char **values,
|
||||
char **names);
|
||||
|
||||
/**
|
||||
* Reads the current DB version.
|
||||
*
|
||||
* @return 0 on success,
|
||||
* -1 if there is a version mismatch,
|
||||
* -2 if the DB needs a bootstrap
|
||||
*/
|
||||
int check_db_version();
|
||||
};
|
||||
|
||||
#endif /*NEBULA_H_*/
|
||||
|
147
include/SystemDB.h
Normal file
147
include/SystemDB.h
Normal file
@ -0,0 +1,147 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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 SYSTEM_DB_H_
|
||||
#define SYSTEM_DB_H_
|
||||
|
||||
#include "SqlDB.h"
|
||||
#include "Callbackable.h"
|
||||
|
||||
class Nebula;
|
||||
|
||||
/**
|
||||
* This class represents the OpenNebula core system data tables:
|
||||
* - pool_control
|
||||
* - db_versioning
|
||||
* - system attributes
|
||||
*/
|
||||
class SystemDB: public Callbackable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Reads a System attribute from the DB
|
||||
* @param attr_name name of the attribute
|
||||
* @param attr_xml the attribute in a XML document
|
||||
* @return 0 on success
|
||||
*/
|
||||
int select_sys_attribute(const string& attr_name, string& attr_zml);
|
||||
|
||||
/**
|
||||
* Writes a system attribute in the database.
|
||||
* @param db pointer to the db
|
||||
* @return 0 on success
|
||||
*/
|
||||
int insert_sys_attribute(
|
||||
const string& attr_name,
|
||||
const string& xml_attr,
|
||||
string& error_str)
|
||||
{
|
||||
return insert_replace(attr_name, xml_attr, false, error_str);
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the system attribute in the database.
|
||||
* @param db pointer to the db
|
||||
* @return 0 on success
|
||||
*/
|
||||
int update_sys_attribute(
|
||||
const string& attr_name,
|
||||
const string& xml_attr,
|
||||
string& error_str)
|
||||
{
|
||||
return insert_replace(attr_name, xml_attr, true, error_str);
|
||||
};
|
||||
|
||||
private:
|
||||
friend class Nebula; //Only for Nebula class
|
||||
|
||||
SystemDB(SqlDB *_db):db(_db){};
|
||||
|
||||
~SystemDB(){};
|
||||
|
||||
// Pool control table
|
||||
static const char * pc_names;
|
||||
|
||||
static const char * pc_bootstrap;
|
||||
|
||||
static const char * pc_table;
|
||||
|
||||
// DB versioning table
|
||||
static const char * ver_names;
|
||||
|
||||
static const char * ver_bootstrap;
|
||||
|
||||
static const char * ver_table;
|
||||
|
||||
// System attributes table
|
||||
static const char * sys_names;
|
||||
|
||||
static const char * sys_bootstrap;
|
||||
|
||||
static const char * sys_table;
|
||||
|
||||
// Pointer to the db database
|
||||
SqlDB *db;
|
||||
|
||||
/**
|
||||
* Execute an INSERT or REPLACE Sql query for a system attribute.
|
||||
* @param db The SQL DB
|
||||
* @param replace Execute an INSERT or a REPLACE
|
||||
* @param error_str Returns the error reason, if any
|
||||
* @return 0 one success
|
||||
*/
|
||||
int insert_replace(const string& attr_name,
|
||||
const string& xml_attr,
|
||||
bool replace,
|
||||
string& error_str);
|
||||
/**
|
||||
* Bootstraps the database control tables
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int bootstrap();
|
||||
|
||||
/**
|
||||
* Callback function for the check_db_version method. Stores the read
|
||||
* version in loaded_db_version
|
||||
* @param _loaded_db_version returned columns
|
||||
* @param num the number of columns read from the DB
|
||||
* @param names the column names
|
||||
* @param vaues the column values
|
||||
* @return 0 on success
|
||||
*/
|
||||
int select_cb(void *_loaded_db_version,
|
||||
int num,
|
||||
char **values,
|
||||
char **names);
|
||||
/**
|
||||
* Callback function for selecting system attributes
|
||||
*/
|
||||
int select_attr_cb(void *_attr_xml,
|
||||
int num,
|
||||
char **values,
|
||||
char **names);
|
||||
/**
|
||||
* Reads the current DB version.
|
||||
*
|
||||
* @return 0 on success,
|
||||
* -1 if there is a version mismatch,
|
||||
* -2 if the DB needs a bootstrap
|
||||
*/
|
||||
int check_db_version();
|
||||
};
|
||||
|
||||
#endif //SYSTEM_DB_H
|
@ -33,6 +33,238 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
// Pool control table
|
||||
const char * SystemDB::pc_table = "pool_control";
|
||||
const char * SystemDB::pc_names = "tablename, last_oid";
|
||||
|
||||
const char * SystemDB::pc_bootstrap = "CREATE TABLE pool_control "
|
||||
"(tablename VARCHAR(32) PRIMARY KEY, last_oid BIGINT UNSIGNED)";
|
||||
|
||||
|
||||
// DB versioning table
|
||||
const char * SystemDB::ver_table = "db_versioning";
|
||||
const char * SystemDB::ver_names = "oid, version, timestamp, comment";
|
||||
|
||||
const char * SystemDB::ver_bootstrap = "CREATE TABLE db_versioning "
|
||||
"(oid INTEGER PRIMARY KEY, version VARCHAR(256), timestamp INTEGER, "
|
||||
"comment VARCHAR(256))";
|
||||
|
||||
// System attributes table
|
||||
const char * SystemDB::sys_table = "system_attributes";
|
||||
const char * SystemDB::sys_names = "name, body";
|
||||
|
||||
const char * SystemDB::sys_bootstrap = "CREATE TABLE IF NOT EXISTS"
|
||||
" system_attributes (name VARCHAR(128) PRIMARY KEY, body TEXT)";
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::bootstrap()
|
||||
{
|
||||
int rc;
|
||||
ostringstream oss;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// pool control, tracks the last ID's assigned to objects
|
||||
// ------------------------------------------------------------------------
|
||||
oss.str(pc_bootstrap);
|
||||
rc = db->exec(oss);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// db versioning, version of OpenNebula. Insert this version number
|
||||
// ------------------------------------------------------------------------
|
||||
oss.str(ver_bootstrap);
|
||||
rc += db->exec(oss);
|
||||
|
||||
oss.str("");
|
||||
oss << "INSERT INTO " << ver_table << " (" << ver_names << ") "
|
||||
<< "VALUES (0, '" << Nebula::db_version() << "', " << time(0)
|
||||
<< ", '" << Nebula::version() << " daemon bootstrap')";
|
||||
|
||||
rc += db->exec(oss);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// system , version of OpenNebula. Insert this version number
|
||||
// ------------------------------------------------------------------------
|
||||
oss.str(sys_bootstrap);
|
||||
rc += db->exec(oss);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::select_cb(void *_loaded_db_version, int num, char **values,
|
||||
char **names)
|
||||
{
|
||||
istringstream iss;
|
||||
string * loaded_db_version;
|
||||
|
||||
loaded_db_version = static_cast<string *>(_loaded_db_version);
|
||||
|
||||
if ( (values[0]) && (num == 1) )
|
||||
{
|
||||
*loaded_db_version = values[0];
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::check_db_version()
|
||||
{
|
||||
int rc;
|
||||
ostringstream oss;
|
||||
|
||||
string loaded_db_version = "";
|
||||
|
||||
// Try to read latest version
|
||||
set_callback( static_cast<Callbackable::Callback>(&SystemDB::select_cb),
|
||||
static_cast<void *>(&loaded_db_version) );
|
||||
|
||||
oss << "SELECT version FROM " << ver_table
|
||||
<< " WHERE oid=(SELECT MAX(oid) FROM " << ver_table << ")";
|
||||
|
||||
db->exec(oss, this);
|
||||
|
||||
oss.str("");
|
||||
unset_callback();
|
||||
|
||||
if( loaded_db_version == "" )
|
||||
{
|
||||
// Table user_pool is present for all OpenNebula versions, and it
|
||||
// always contains at least the oneadmin user.
|
||||
oss << "SELECT MAX(oid) FROM user_pool";
|
||||
rc = db->exec(oss);
|
||||
|
||||
oss.str("");
|
||||
|
||||
if( rc != 0 ) // Database needs bootstrap
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
if( Nebula::db_version() != loaded_db_version )
|
||||
{
|
||||
oss << "Database version mismatch. "
|
||||
<< "Installed " << Nebula::version() << " uses DB version '"
|
||||
<< Nebula::db_version() << "', and existing DB version is '"
|
||||
<< loaded_db_version << "'.";
|
||||
|
||||
NebulaLog::log("ONE",Log::ERROR,oss);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::insert_replace(
|
||||
const string& attr_name,
|
||||
const string& xml_attr,
|
||||
bool replace,
|
||||
string& err)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
int rc;
|
||||
char * sql_xml;
|
||||
|
||||
sql_xml = db->escape_str(xml_attr.c_str());
|
||||
|
||||
if ( sql_xml == 0 )
|
||||
{
|
||||
goto error_body;
|
||||
}
|
||||
|
||||
if ( ObjectXML::validate_xml(sql_xml) != 0 )
|
||||
{
|
||||
goto error_xml;
|
||||
}
|
||||
|
||||
if ( replace )
|
||||
{
|
||||
oss << "REPLACE";
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << "INSERT";
|
||||
}
|
||||
|
||||
// Construct the SQL statement to Insert or Replace
|
||||
|
||||
oss <<" INTO "<< sys_table <<
|
||||
" ("<< sys_names <<") VALUES ("
|
||||
<< "'" << attr_name << "',"
|
||||
<< "'" << sql_xml << "')";
|
||||
|
||||
rc = db->exec(oss);
|
||||
|
||||
db->free_str(sql_xml);
|
||||
|
||||
return rc;
|
||||
|
||||
error_xml:
|
||||
db->free_str(sql_xml);
|
||||
|
||||
error_body:
|
||||
err = "Error inserting system attribute in DB.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::select_attr_cb(void * _xml_attr,
|
||||
int num,
|
||||
char ** values,
|
||||
char ** names)
|
||||
{
|
||||
istringstream iss;
|
||||
string * xml_attr;
|
||||
|
||||
xml_attr = static_cast<string *>(_xml_attr);
|
||||
|
||||
if ( (values[0]) && (num == 1) )
|
||||
{
|
||||
*xml_attr = values[0];
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::select_sys_attribute(const string& attr_name, string& attr_xml)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
int rc;
|
||||
|
||||
set_callback(static_cast<Callbackable::Callback>(&SystemDB::select_attr_cb),
|
||||
static_cast<void *>(&attr_xml) );
|
||||
|
||||
oss << "SELECT body FROM " << sys_table << " WHERE name = '"
|
||||
<< attr_name << "'";
|
||||
|
||||
rc = db->exec(oss, this);
|
||||
|
||||
unset_callback();
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
@ -219,8 +451,15 @@ void Nebula::start()
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Prepare the SystemDB and check versions
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
NebulaLog::log("ONE",Log::INFO,"Checking database version.");
|
||||
rc = check_db_version();
|
||||
|
||||
system_db = new SystemDB(db);
|
||||
|
||||
rc = system_db->check_db_version();
|
||||
|
||||
if( rc == -1 )
|
||||
{
|
||||
@ -245,14 +484,16 @@ void Nebula::start()
|
||||
rc += ClusterPool::bootstrap(db);
|
||||
rc += DocumentPool::bootstrap(db);
|
||||
|
||||
rc += DefaultQuotas::bootstrap(db);
|
||||
|
||||
// Create the versioning table only if bootstrap went well
|
||||
// Create the system tables only if bootstrap went well
|
||||
if ( rc == 0 )
|
||||
{
|
||||
rc += bootstrap();
|
||||
rc += system_db->bootstrap();
|
||||
}
|
||||
|
||||
// Insert default system attributes
|
||||
rc += default_user_quota.insert();
|
||||
rc += default_group_quota.insert();
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
throw runtime_error("Error bootstrapping database.");
|
||||
@ -343,8 +584,8 @@ void Nebula::start()
|
||||
|
||||
dspool = new DatastorePool(db);
|
||||
|
||||
default_user_quota.select(db);
|
||||
default_group_quota.select(db);
|
||||
default_user_quota.select();
|
||||
default_group_quota.select();
|
||||
}
|
||||
catch (exception&)
|
||||
{
|
||||
@ -679,103 +920,3 @@ void Nebula::start()
|
||||
NebulaLog::log("ONE", Log::INFO, "All modules finalized, exiting.\n");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int Nebula::bootstrap()
|
||||
{
|
||||
int rc;
|
||||
ostringstream oss;
|
||||
string error;
|
||||
|
||||
oss << "CREATE TABLE pool_control (tablename VARCHAR(32) PRIMARY KEY, "
|
||||
"last_oid BIGINT UNSIGNED)";
|
||||
|
||||
rc = db->exec(oss);
|
||||
|
||||
oss.str("");
|
||||
oss << "CREATE TABLE db_versioning (oid INTEGER PRIMARY KEY, "
|
||||
"version VARCHAR(256), timestamp INTEGER, comment VARCHAR(256))";
|
||||
|
||||
rc += db->exec(oss);
|
||||
|
||||
oss.str("");
|
||||
oss << "INSERT INTO db_versioning (oid, version, timestamp, comment) "
|
||||
<< "VALUES (0, '" << db_version() << "', " << time(0)
|
||||
<< ", '" << version() << " daemon bootstrap')";
|
||||
|
||||
rc += db->exec(oss);
|
||||
|
||||
rc += default_user_quota.insert(db, error);
|
||||
rc += default_group_quota.insert(db, error);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int Nebula::check_db_version()
|
||||
{
|
||||
int rc;
|
||||
ostringstream oss;
|
||||
|
||||
|
||||
string loaded_db_version = "";
|
||||
|
||||
// Try to read latest version
|
||||
set_callback( static_cast<Callbackable::Callback>(&Nebula::select_cb),
|
||||
static_cast<void *>(&loaded_db_version) );
|
||||
|
||||
oss << "SELECT version FROM db_versioning "
|
||||
<< "WHERE oid=(SELECT MAX(oid) FROM db_versioning)";
|
||||
|
||||
db->exec(oss, this);
|
||||
|
||||
oss.str("");
|
||||
unset_callback();
|
||||
|
||||
if( loaded_db_version == "" )
|
||||
{
|
||||
// Table user_pool is present for all OpenNebula versions, and it
|
||||
// always contains at least the oneadmin user.
|
||||
oss << "SELECT MAX(oid) FROM user_pool";
|
||||
rc = db->exec(oss);
|
||||
|
||||
oss.str("");
|
||||
|
||||
if( rc != 0 ) // Database needs bootstrap
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
if( db_version() != loaded_db_version )
|
||||
{
|
||||
oss << "Database version mismatch. "
|
||||
<< "Installed " << version() << " uses DB version '" << db_version()
|
||||
<< "', and existing DB version is '"
|
||||
<< loaded_db_version << "'.";
|
||||
|
||||
NebulaLog::log("ONE",Log::ERROR,oss);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Nebula::select_cb(void *_loaded_db_version, int num, char **values,
|
||||
char **names)
|
||||
{
|
||||
istringstream iss;
|
||||
string * loaded_db_version;
|
||||
|
||||
loaded_db_version = static_cast<string *>(_loaded_db_version);
|
||||
|
||||
if ( (values[0]) && (num == 1) )
|
||||
{
|
||||
*loaded_db_version = values[0];
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
@ -23,6 +23,7 @@ lib_name='nebula_core'
|
||||
|
||||
# Sources to generate the library
|
||||
source_files=[
|
||||
'SystemDB.cc',
|
||||
'Nebula.cc',
|
||||
'NebulaTemplate.cc',
|
||||
]
|
||||
|
252
src/nebula/SystemDB.cc
Normal file
252
src/nebula/SystemDB.cc
Normal file
@ -0,0 +1,252 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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 "Nebula.h"
|
||||
#include "SystemDB.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
// Pool control table
|
||||
const char * SystemDB::pc_table = "pool_control";
|
||||
const char * SystemDB::pc_names = "tablename, last_oid";
|
||||
|
||||
const char * SystemDB::pc_bootstrap = "CREATE TABLE pool_control "
|
||||
"(tablename VARCHAR(32) PRIMARY KEY, last_oid BIGINT UNSIGNED)";
|
||||
|
||||
|
||||
// DB versioning table
|
||||
const char * SystemDB::ver_table = "db_versioning";
|
||||
const char * SystemDB::ver_names = "oid, version, timestamp, comment";
|
||||
|
||||
const char * SystemDB::ver_bootstrap = "CREATE TABLE db_versioning "
|
||||
"(oid INTEGER PRIMARY KEY, version VARCHAR(256), timestamp INTEGER, "
|
||||
"comment VARCHAR(256))";
|
||||
|
||||
// System attributes table
|
||||
const char * SystemDB::sys_table = "system_attributes";
|
||||
const char * SystemDB::sys_names = "name, body";
|
||||
|
||||
const char * SystemDB::sys_bootstrap = "CREATE TABLE IF NOT EXISTS"
|
||||
" system_attributes (name VARCHAR(128) PRIMARY KEY, body TEXT)";
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::bootstrap()
|
||||
{
|
||||
int rc;
|
||||
ostringstream oss;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// pool control, tracks the last ID's assigned to objects
|
||||
// ------------------------------------------------------------------------
|
||||
oss.str(pc_bootstrap);
|
||||
rc = db->exec(oss);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// db versioning, version of OpenNebula. Insert this version number
|
||||
// ------------------------------------------------------------------------
|
||||
oss.str(ver_bootstrap);
|
||||
rc += db->exec(oss);
|
||||
|
||||
oss.str("");
|
||||
oss << "INSERT INTO " << ver_table << " (" << ver_names << ") "
|
||||
<< "VALUES (0, '" << Nebula::db_version() << "', " << time(0)
|
||||
<< ", '" << Nebula::version() << " daemon bootstrap')";
|
||||
|
||||
rc += db->exec(oss);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// system , version of OpenNebula. Insert this version number
|
||||
// ------------------------------------------------------------------------
|
||||
oss.str(sys_bootstrap);
|
||||
rc += db->exec(oss);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::select_cb(void *_loaded_db_version, int num, char **values,
|
||||
char **names)
|
||||
{
|
||||
istringstream iss;
|
||||
string * loaded_db_version;
|
||||
|
||||
loaded_db_version = static_cast<string *>(_loaded_db_version);
|
||||
|
||||
if ( (values[0]) && (num == 1) )
|
||||
{
|
||||
*loaded_db_version = values[0];
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::check_db_version()
|
||||
{
|
||||
int rc;
|
||||
ostringstream oss;
|
||||
|
||||
string loaded_db_version = "";
|
||||
|
||||
// Try to read latest version
|
||||
set_callback( static_cast<Callbackable::Callback>(&SystemDB::select_cb),
|
||||
static_cast<void *>(&loaded_db_version) );
|
||||
|
||||
oss << "SELECT version FROM " << ver_table
|
||||
<< " WHERE oid=(SELECT MAX(oid) FROM " << ver_table << ")";
|
||||
|
||||
db->exec(oss, this);
|
||||
|
||||
oss.str("");
|
||||
unset_callback();
|
||||
|
||||
if( loaded_db_version == "" )
|
||||
{
|
||||
// Table user_pool is present for all OpenNebula versions, and it
|
||||
// always contains at least the oneadmin user.
|
||||
oss << "SELECT MAX(oid) FROM user_pool";
|
||||
rc = db->exec(oss);
|
||||
|
||||
oss.str("");
|
||||
|
||||
if( rc != 0 ) // Database needs bootstrap
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
if( Nebula::db_version() != loaded_db_version )
|
||||
{
|
||||
oss << "Database version mismatch. "
|
||||
<< "Installed " << Nebula::version() << " uses DB version '"
|
||||
<< Nebula::db_version() << "', and existing DB version is '"
|
||||
<< loaded_db_version << "'.";
|
||||
|
||||
NebulaLog::log("ONE",Log::ERROR,oss);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::insert_replace(
|
||||
const string& attr_name,
|
||||
const string& xml_attr,
|
||||
bool replace,
|
||||
string& err)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
int rc;
|
||||
char * sql_xml;
|
||||
|
||||
sql_xml = db->escape_str(xml_attr.c_str());
|
||||
|
||||
if ( sql_xml == 0 )
|
||||
{
|
||||
goto error_body;
|
||||
}
|
||||
|
||||
if ( ObjectXML::validate_xml(sql_xml) != 0 )
|
||||
{
|
||||
goto error_xml;
|
||||
}
|
||||
|
||||
if ( replace )
|
||||
{
|
||||
oss << "REPLACE";
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << "INSERT";
|
||||
}
|
||||
|
||||
// Construct the SQL statement to Insert or Replace
|
||||
|
||||
oss <<" INTO "<< sys_table << " ("<< sys_names <<") VALUES ("
|
||||
<< "'" << attr_name << "'," << "'" << sql_xml << "')";
|
||||
|
||||
rc = db->exec(oss);
|
||||
|
||||
db->free_str(sql_xml);
|
||||
|
||||
return rc;
|
||||
|
||||
error_xml:
|
||||
db->free_str(sql_xml);
|
||||
|
||||
error_body:
|
||||
err = "Error inserting system attribute in DB.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::select_attr_cb(void * _xml_attr,
|
||||
int num,
|
||||
char ** values,
|
||||
char ** names)
|
||||
{
|
||||
istringstream iss;
|
||||
string * xml_attr;
|
||||
|
||||
xml_attr = static_cast<string *>(_xml_attr);
|
||||
|
||||
if ( (values[0]) && (num == 1) )
|
||||
{
|
||||
*xml_attr = values[0];
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int SystemDB::select_sys_attribute(const string& attr_name, string& attr_xml)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
int rc;
|
||||
|
||||
set_callback(static_cast<Callbackable::Callback>(&SystemDB::select_attr_cb),
|
||||
static_cast<void *>(&attr_xml) );
|
||||
|
||||
oss << "SELECT body FROM " << sys_table << " WHERE name = '"
|
||||
<< attr_name << "'";
|
||||
|
||||
rc = db->exec(oss, this);
|
||||
|
||||
unset_callback();
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -17,14 +17,7 @@
|
||||
#include "DefaultQuotas.h"
|
||||
#include "ObjectXML.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
const char * DefaultQuotas::table = "system_attributes";
|
||||
const char * DefaultQuotas::db_names = "name, body";
|
||||
|
||||
const char * DefaultQuotas::db_bootstrap = "CREATE TABLE IF NOT EXISTS"
|
||||
" system_attributes (name VARCHAR(128) PRIMARY KEY, body TEXT)";
|
||||
#include "Nebula.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -61,84 +54,39 @@ int DefaultQuotas::from_xml(const string& xml)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int DefaultQuotas::select(SqlDB *db)
|
||||
int DefaultQuotas::select()
|
||||
{
|
||||
ostringstream oss;
|
||||
string xml_body;
|
||||
Nebula& nd = Nebula::instance();
|
||||
|
||||
int rc;
|
||||
|
||||
set_callback(
|
||||
static_cast<Callbackable::Callback>(&DefaultQuotas::select_cb));
|
||||
|
||||
oss << "SELECT body FROM " << table << " WHERE name = '" << root_elem << "'";
|
||||
|
||||
rc = db->exec(oss, this);
|
||||
|
||||
unset_callback();
|
||||
|
||||
if (rc != 0)
|
||||
if ( nd.select_sys_attribute(root_elem, xml_body) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return from_xml(xml_body);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int DefaultQuotas::insert_replace(SqlDB *db, bool replace, string& error_str)
|
||||
int DefaultQuotas::insert()
|
||||
{
|
||||
ostringstream oss;
|
||||
string xml_body;
|
||||
string error;
|
||||
Nebula& nd = Nebula::instance();
|
||||
|
||||
int rc;
|
||||
string xml_body;
|
||||
|
||||
char * sql_xml;
|
||||
|
||||
sql_xml = db->escape_str(to_xml(xml_body).c_str());
|
||||
|
||||
if ( sql_xml == 0 )
|
||||
{
|
||||
goto error_body;
|
||||
}
|
||||
|
||||
if ( ObjectXML::validate_xml(sql_xml) != 0 )
|
||||
{
|
||||
goto error_xml;
|
||||
}
|
||||
|
||||
if ( replace )
|
||||
{
|
||||
oss << "REPLACE";
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << "INSERT";
|
||||
}
|
||||
|
||||
// Construct the SQL statement to Insert or Replace
|
||||
|
||||
oss <<" INTO "<<table <<" ("<< db_names <<") VALUES ("
|
||||
<< "'" << root_elem << "',"
|
||||
<< "'" << sql_xml << "')";
|
||||
|
||||
rc = db->exec(oss);
|
||||
|
||||
db->free_str(sql_xml);
|
||||
|
||||
return rc;
|
||||
|
||||
error_xml:
|
||||
db->free_str(sql_xml);
|
||||
|
||||
error_str = "Error transforming the Quotas to XML.";
|
||||
return -1;
|
||||
|
||||
error_body:
|
||||
error_str = "Error inserting Quotas in DB.";
|
||||
return -1;
|
||||
return nd.insert_sys_attribute(root_elem, to_xml(xml_body), error);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int DefaultQuotas::update()
|
||||
{
|
||||
string xml_body;
|
||||
string error;
|
||||
Nebula& nd = Nebula::instance();
|
||||
|
||||
return nd.update_sys_attribute(root_elem, to_xml(xml_body), error);
|
||||
}
|
||||
|
@ -120,12 +120,12 @@ int Quota::set(vector<Attribute*> * new_quotas, string& error)
|
||||
if (update_limits(tq, iq) != 0)
|
||||
{
|
||||
goto error_limits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup_quota(id);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
error_limits:
|
||||
@ -141,16 +141,16 @@ error_limits:
|
||||
|
||||
delete quota_str;
|
||||
}
|
||||
|
||||
|
||||
error = oss.str();
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool Quota::check_quota(const string& qid,
|
||||
bool Quota::check_quota(const string& qid,
|
||||
map<string, float>& usage_req,
|
||||
Quotas& default_quotas,
|
||||
string& error)
|
||||
@ -184,7 +184,7 @@ bool Quota::check_quota(const string& qid,
|
||||
if ( q == 0 )
|
||||
{
|
||||
map<string, string> values;
|
||||
|
||||
|
||||
for (int i=0; i < num_metrics; i++)
|
||||
{
|
||||
string metrics_used = metrics[i];
|
||||
@ -211,7 +211,7 @@ bool Quota::check_quota(const string& qid,
|
||||
for (int i=0; i < num_metrics; i++)
|
||||
{
|
||||
string metrics_used = metrics[i];
|
||||
|
||||
|
||||
metrics_used += "_USED";
|
||||
|
||||
it = usage_req.find(metrics[i]);
|
||||
@ -245,7 +245,7 @@ bool Quota::check_quota(const string& qid,
|
||||
oss << "limit of " << limit << " reached for " << metrics[i]
|
||||
<< " quota in " << template_name;
|
||||
|
||||
if ( !qid.empty() )
|
||||
if ( !qid.empty() )
|
||||
{
|
||||
oss << " with ID: " << qid;
|
||||
}
|
||||
@ -262,7 +262,7 @@ bool Quota::check_quota(const string& qid,
|
||||
for (int i=0; i < num_metrics; i++)
|
||||
{
|
||||
string metrics_used = metrics[i];
|
||||
|
||||
|
||||
metrics_used += "_USED";
|
||||
|
||||
it = usage_req.find(metrics[i]);
|
||||
@ -294,12 +294,12 @@ void Quota::del_quota(const string& qid, map<string, float>& usage_req)
|
||||
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]);
|
||||
@ -323,8 +323,7 @@ void Quota::cleanup_quota(const string& qid)
|
||||
VectorAttribute * q;
|
||||
map<string, Attribute *>::iterator q_it;
|
||||
|
||||
float usage, usage_tmp, limit_tmp, implicit_limit;
|
||||
bool default_limit;
|
||||
float usage, limit, implicit_limit;
|
||||
|
||||
if ( get_quota(qid, &q, q_it) == -1)
|
||||
{
|
||||
@ -345,28 +344,24 @@ void Quota::cleanup_quota(const string& qid)
|
||||
implicit_limit = -1;
|
||||
}
|
||||
|
||||
default_limit = true;
|
||||
usage = 0;
|
||||
|
||||
for (int i=0; i < num_metrics; i++)
|
||||
{
|
||||
string metrics_used = metrics[i];
|
||||
|
||||
metrics_used += "_USED";
|
||||
|
||||
q->vector_value(metrics[i], limit_tmp);
|
||||
q->vector_value(metrics_used.c_str(), usage_tmp);
|
||||
q->vector_value(metrics[i], limit);
|
||||
q->vector_value(metrics_used.c_str(), usage);
|
||||
|
||||
default_limit = (default_limit && limit_tmp == implicit_limit );
|
||||
usage += usage_tmp;
|
||||
if ( usage != 0 || limit != implicit_limit )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( usage == 0 && default_limit )
|
||||
{
|
||||
delete static_cast<Attribute *>(q_it->second);
|
||||
delete static_cast<Attribute *>(q_it->second);
|
||||
|
||||
attributes.erase(q_it);
|
||||
}
|
||||
attributes.erase(q_it);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -395,7 +390,7 @@ int Quota::update_limits(
|
||||
quota->replace(metrics[i], limit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -412,7 +407,7 @@ VectorAttribute * Quota::new_quota(VectorAttribute * va)
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user