diff --git a/SConstruct b/SConstruct index 8029757457..917346a2fe 100644 --- a/SConstruct +++ b/SConstruct @@ -39,6 +39,8 @@ main_env.Append(CPPPATH=[ # Library dirs main_env.Append(LIBPATH=[ cwd+'/src/common', + cwd+'/src/log', + cwd+'/src/sql', cwd+'/src/host', cwd+'/src/mad', cwd+'/src/nebula', @@ -70,11 +72,27 @@ main_env.Append(LDFLAGS=["-g"]) ####################### # SQLITE -sqlite_dir=ARGUMENTS.get('sqlite', 'none') +sqlite_dir=ARGUMENTS.get('sqlite_dir', 'none') if sqlite_dir!='none': main_env.Append(LIBPATH=[sqlite_dir+"/lib"]) main_env.Append(CPPPATH=[sqlite_dir+"/include"]) +sqlite=ARGUMENTS.get('sqlite', 'yes') +if sqlite=='yes': + main_env.Append(sqlite='yes') + main_env.Append(CPPFLAGS=["-DSQLITE_DB"]) +else: + main_env.Append(sqlite='no') + +# MySQL +mysql=ARGUMENTS.get('mysql', 'no') +if mysql=='yes': + main_env.Append(mysql='yes') + main_env.Append(CPPFLAGS=["-DMYSQL_DB"]) +else: + main_env.Append(mysql='no') + + # xmlrpc xmlrpc_dir=ARGUMENTS.get('xmlrpc', 'none') if xmlrpc_dir!='none': @@ -92,6 +110,10 @@ if not main_env.GetOption('clean'): try: main_env.ParseConfig('share/scons/get_xmlrpc_config server') main_env.ParseConfig('share/scons/get_xmlrpc_config client') + + if mysql=='yes': + main_env.ParseConfig('mysql_config --cflags --libs') + except Exception, e: print "" print "Error searching for xmlrpc-c libraries. Please check this"+\ @@ -118,7 +140,8 @@ else: # SCONS scripts to build build_scripts=[ - 'src/client/SConstruct', + 'src/sql/SConstruct', + 'src/log/SConstruct', 'src/common/SConstruct', 'src/template/SConstruct', 'src/host/SConstruct', diff --git a/include/Attribute.h b/include/Attribute.h index 0cec75e889..d7de38672e 100644 --- a/include/Attribute.h +++ b/include/Attribute.h @@ -143,8 +143,8 @@ public: { string * xml = new string; - *xml = "<" + name() + ">" + attribute_value - + ""; + *xml = "<" + name() + ">"; return xml; } diff --git a/include/Callbackable.h b/include/Callbackable.h new file mode 100644 index 0000000000..58501c455b --- /dev/null +++ b/include/Callbackable.h @@ -0,0 +1,83 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 CALLBACKABLE_H_ +#define CALLBACKABLE_H_ + +using namespace std; + +/** + * ObjectSQL class. Provides a SQL backend interface, it should be implemented + * by persistent objects. + */ +class Callbackable +{ +public: + + Callbackable():cb(0),arg(0){}; + + virtual ~Callbackable(){}; + + /** + * Datatype for call back pointers + */ + typedef int (Callbackable::*Callback)(void *, int, char ** ,char **); + + /** + * Set the callback function and custom arguments to be executed by the + * next SQL command + * @param ptr to the callback function + * @param arg custom arguments for the callback function + */ + void set_callback(Callback _cb, void * _arg = 0) + { + cb = _cb; + arg = _arg; + }; + + /** + * Test if the CallBack is set for the object. + * @return true if the callback is set + */ + bool isCallBackSet() + { + return (cb != 0); + }; + + /** + * Set the callback function and custom arguments to be executed by the + * next SQL command + * @param ptr to the callback function + * @param arg custom arguments for the callback function + */ + int do_callback(int num, char **values, char **names) + { + return (this->*cb)(arg, num, values, names); + }; + +private: + /** + * SQL callback to be executed for each row result of an SQL statement + */ + Callback cb; + + /** + * Custom arguments for the callback + */ + void * arg; +}; + +#endif /*CALLBACKABLE_H_*/ diff --git a/include/FixedLeases.h b/include/FixedLeases.h index cb5f6e2ec4..3816a0f8b5 100644 --- a/include/FixedLeases.h +++ b/include/FixedLeases.h @@ -22,31 +22,31 @@ using namespace std; /** - * The FixedLeases class represents a pool of fixed IP-MAC leases. A lease can + * The FixedLeases class represents a pool of fixed IP-MAC leases. A lease can * be either a IP (the MAC is then PREFIX:IP) or the IP and MAC addresses. The * pool is read from a template file, each lease is in the form: * LEASE = [ IP = "", MAC = ""] - */ + */ class FixedLeases : public Leases { public: - /** - * Create a FixedLeases from template - */ - FixedLeases(SqliteDB * db, - int _oid, - unsigned int _mac_prefix, - vector& vector_leases); - /** - * Create a plain FixedLeases, you can populate the lease pool using - * select() - */ - FixedLeases(SqliteDB * db, - int _oid, - unsigned int _mac_prefix): - Leases(db,_oid,0), - mac_prefix(_mac_prefix), - current(leases.begin()){}; + /** + * Create a FixedLeases from template + */ + FixedLeases(SqlDB * db, + int _oid, + unsigned int _mac_prefix, + vector& vector_leases); + /** + * Create a plain FixedLeases, you can populate the lease pool using + * select() + */ + FixedLeases(SqlDB * db, + int _oid, + unsigned int _mac_prefix): + Leases(db,_oid,0), + mac_prefix(_mac_prefix), + current(leases.begin()){}; ~FixedLeases(){}; @@ -58,7 +58,7 @@ public: * @return 0 if success */ int get(int vid, string& ip, string& mac); - + /** * Ask for a specific lease in the network * @param vid identifier of the VM getting this lease @@ -76,32 +76,32 @@ public: { del(ip); } - + /** * Loads the leases from the DB. */ - int select(SqliteDB * db) + int select(SqlDB * db) { - //Read the leases from the DB - int rc = Leases::select(db); - //Update the size - size = leases.size(); - - return rc; + //Read the leases from the DB + int rc = Leases::select(db); + //Update the size + size = leases.size(); + + return rc; } private: - - /** - * The default MAC prefix for the OpenNebula cluster - */ - unsigned int mac_prefix; - - /** - * Current lease pointer - */ - map::iterator current; - + + /** + * The default MAC prefix for the OpenNebula cluster + */ + unsigned int mac_prefix; + + /** + * Current lease pointer + */ + map::iterator current; + /** * Add a lease, from the Lease interface * @param ip ip of the lease @@ -110,7 +110,7 @@ private: * @return 0 if success */ int add(const string& ip, const string& mac, int vid, bool used=true); - + /** * Remove a lease, from the Lease interface * @param db pointer to DB diff --git a/include/History.h b/include/History.h index 5c42205dcb..61c0638e88 100644 --- a/include/History.h +++ b/include/History.h @@ -17,17 +17,10 @@ #ifndef HISTORY_H_ #define HISTORY_H_ -#include #include "ObjectSQL.h" using namespace std; -extern "C" int history_select_cb ( - void * _history, - int num, - char ** values, - char ** names); - /** * The History class, it represents an execution record of a Virtual Machine. */ @@ -37,23 +30,23 @@ class History:public ObjectSQL public: enum MigrationReason { - NONE, /** < Normal termination in host */ - ERROR, /** < The VM was migrated because of an error */ + NONE, /** < Normal termination in host */ + ERROR, /** < The VM was migrated because of an error */ STOP_RESUME,/** < The VM was migrated because of a stop/resume request*/ - USER, /** < The VM was migrated because of an explicit request */ - CANCEL /** < The VM was migrated because of an explicit cancel */ + USER, /** < The VM was migrated because of an explicit request */ + CANCEL /** < The VM was migrated because of an explicit cancel */ }; History(int oid, int _seq = -1); History( - int oid, - int seq, - int hid, - string& hostname, - string& vm_dir, - string& vmm, - string& tm); + int oid, + int seq, + int hid, + string& hostname, + string& vm_dir, + string& vmm, + string& tm); ~History(){}; @@ -77,9 +70,10 @@ public: * @return a reference to the generated string */ string& to_xml(string& xml) const; - + private: friend class VirtualMachine; + friend class VirtualMachinePool; // ---------------------------------------- // DataBase implementation variables @@ -166,52 +160,50 @@ private: string checkpoint_file; string rdeployment_file; - friend int history_select_cb ( - void * _history, - int num, - char ** values, - char ** names); - /** * Writes the history record in the DB * @param db pointer to the database. * @return 0 on success. */ - int insert(SqliteDB * db); + int insert(SqlDB * db); /** * Reads the history record from the DB * @param db pointer to the database. * @return 0 on success. */ - int select(SqliteDB * db); - - /** - * Removes the all history records from the DB - * @param db pointer to the database. - * @return 0 on success. - - */ - int drop(SqliteDB * db); - + int select(SqlDB * db); + /** * Updates the history record * @param db pointer to the database. * @return 0 on success. */ - int update(SqliteDB * db) - { - return insert(db); - } + int update(SqlDB * db); /** - * Function to unmarshall a history object + * Removes the all history records from the DB + * @param db pointer to the database. + * @return 0 on success. + */ + int drop(SqlDB * db); + + /** + * Execute an INSERT or REPLACE Sql query. + * @param db The SQL DB + * @param replace Execute an INSERT or a REPLACE + * @return 0 on success + */ + int insert_replace(SqlDB *db, bool replace); + + /** + * Callback function to unmarshall a history object (History::select) * @param num the number of columns read from the DB * @para names the column names * @para vaues the column values * @return 0 on success */ - int unmarshall(int num, char **names, char ** values); + int select_cb(void *nil, int num, char **values, char **names); /** * Function to unmarshall a History object into an output stream with XML @@ -222,10 +214,7 @@ private: * @param vaues the column values * @return 0 on success */ - static int unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values); + static int dump(ostringstream& oss, int num, char **names, char **values); }; -#endif /*HISTORY_H_*/ +#endif /*HISTORY_H_*/ \ No newline at end of file diff --git a/include/Host.h b/include/Host.h index 5507cbbb4b..be471e8336 100644 --- a/include/Host.h +++ b/include/Host.h @@ -1,18 +1,18 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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. */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* Copyright 2002-2010, 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 HOST_H_ #define HOST_H_ @@ -23,32 +23,20 @@ using namespace std; -extern "C" int host_select_cb (void * _host, - int num, - char ** values, - char ** names); - -extern "C" int host_dump_cb (void * _oss, - int num, - char ** values, - char ** names); -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - /** - * The Host class. It represents a Host... + * The Host class. */ class Host : public PoolObjectSQL { public: - - // ------------------------------------------------------------------------ + + // ---------------------------------------------------------------------- // Host States - // ------------------------------------------------------------------------ + // ---------------------------------------------------------------------- enum HostState { - INIT = 0, /**< Initial state for enabled hosts. */ + INIT = 0, /**< Initial state for enabled hosts. */ MONITORING = 1, /**< The host is being monitored. */ MONITORED = 2, /**< The host has been successfully monitored. */ ERROR = 3, /**< An error ocurrer while monitoring the host. */ @@ -63,14 +51,14 @@ public: /** * Function to print the Host object into a string in plain text * @param str the resulting string - * @return a reference to the generated string + * @return a reference to the generated string */ string& to_str(string& str) const; /** * Function to print the Host object into a string in XML format * @param xml the resulting XML string - * @return a reference to the generated string + * @return a reference to the generated string */ string& to_xml(string& xml) const; @@ -91,7 +79,7 @@ public: { return state != DISABLED; } - + /** * Updates the Host's last_monitored time stamp. * @param success if the monitored action was successfully performed @@ -99,7 +87,7 @@ public: void touch(bool success) { last_monitored = time(0); - + if ( state != DISABLED) //Don't change the state is host is disabled { if (success == true) @@ -112,25 +100,25 @@ public: } } }; - + /** - * Disables the current host, it will not be monitored nor used by the + * Disables the current host, it will not be monitored nor used by the * scheduler - */ + */ void disable() { state = DISABLED; }; /** - * Enables the current host, it will be monitored and could be used by + * Enables the current host, it will be monitored and could be used by * the scheduler - */ + */ void enable() { state = INIT; }; - + /** * Returns host host_name * @return host_name Host's hostname @@ -139,7 +127,7 @@ public: { return hostname; }; - + /** Update host counters and update the whole host on the DB * @param parse_str string with values to be parsed * @return 0 on success @@ -147,7 +135,8 @@ public: int update_info(string &parse_str); /** - * + * Retrives host state + * @return HostState code number */ HostState get_state() const { @@ -155,39 +144,44 @@ public: }; /** - * + * Retrives VMM mad name + * @return string vmm mad name */ const string& get_vmm_mad() const { return vmm_mad_name; }; - + /** - * + * Retrives TM mad name + * @return string tm mad name */ const string& get_tm_mad() const { return tm_mad_name; }; - + /** - * + * Retrives IM mad name + * @return string im mad name */ const string& get_im_mad() const { return im_mad_name; }; - + /** - * + * Sets host state + * @param HostState state that applies to this host */ void set_state(HostState state) { this->state = state; }; - + /** - * + * Retrives last time the host was monitored + * @return time_t last monitored time */ time_t get_last_monitored() const { @@ -196,7 +190,7 @@ public: // ------------------------------------------------------------------------ // Template - // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ /** * Gets the values of a template attribute @@ -205,7 +199,7 @@ public: * @return the number of values */ int get_template_attribute( - string& name, + string& name, vector& values) const { return host_template.get(name,values); @@ -224,61 +218,37 @@ public: string str=name; return host_template.get(str,values); }; - + /** * Gets a string based host attribute * @param name of the attribute - * @param value of the attribute (a string), will be "" if not defined + * @param value of the attribute (a string), will be "" if not defined */ void get_template_attribute( - const char * name, + const char * name, string& value) const { string str=name; - host_template.get(str,value); - } - + host_template.get(str,value); + } + /** * Gets a string based host attribute * @param name of the attribute - * @param value of the attribute (an int), will be 0 if not defined + * @param value of the attribute (an int), will be 0 if not defined */ void get_template_attribute( - const char * name, + const char * name, int& value) const { string str=name; - host_template.get(str,value); + host_template.get(str,value); } - // --------------------------------------------------------- - // Lex & bison parser for requirements and rank expressions - // --------------------------------------------------------- - - /** - * Evaluates a requirement expression on the given host. - * @param requirements string - * @param result true if the host matches the requirements - * @param errmsg string describing the error, must be freed by the - * calling function - * @return 0 on success - */ - int match(const string& requirements, bool& result, char **errmsg); - - /** - * Evaluates a rank expression on the given host. - * @param rank string - * @param result of the rank evaluation - * @param errmsg string describing the error, must be freed by the - * calling function - * @return 0 on success - */ - int rank(const string& rank, int& result, char **errmsg); - // ------------------------------------------------------------------------ // Share functions - // ------------------------------------------------------------------------ - + // ------------------------------------------------------------------------ + /** * * @@ -349,7 +319,7 @@ public: } /** - * Adds a new VM to the given share by icrementing the cpu,mem and disk + * Adds a new VM to the given share by icrementing the cpu,mem and disk * counters * @param cpu needed by the VM (percentage) * @param mem needed by the VM (in Kb) @@ -360,9 +330,9 @@ public: { host_share.add(cpu,mem,disk); }; - + /** - * Deletes a new VM from the given share by decrementing the cpu,mem and + * Deletes a new VM from the given share by decrementing the cpu,mem and * disk counters * @param cpu useded by the VM (percentage) * @param mem used by the VM (in Kb) @@ -370,8 +340,8 @@ public: * @return 0 on success */ void del_capacity(int cpu, int mem, int disk) - { - host_share.del(cpu,mem,disk); + { + host_share.del(cpu,mem,disk); }; /** @@ -385,22 +355,15 @@ public: { return host_share.test(cpu,mem,disk); } - + private: + // ------------------------------------------------------------------------- // Friends // ------------------------------------------------------------------------- - friend class HostPool; - - friend int host_select_cb (void * _host, - int num, - char ** values, - char ** names); - friend int host_dump_cb (void * _oss, - int num, - char ** values, - char ** names); + friend class HostPool; + // ------------------------------------------------------------------------- // Host Description // ------------------------------------------------------------------------- @@ -411,32 +374,32 @@ private: * The state of the Host */ HostState state; - + /** * Name of the IM driver used to monitor this host - */ + */ string im_mad_name; - + /** * Name of the VM driver used to execute VMs in this host - */ + */ string vmm_mad_name; - + /** * Name of the TM driver used to transfer file to and from this host - */ + */ string tm_mad_name; - + /** * If Host State = MONITORED last time it got fully monitored or 1 Jan 1970 * Host State = MONITORING last time it got a signal to be monitored - */ + */ time_t last_monitored; // ------------------------------------------------------------------------- // Host Attributes // ------------------------------------------------------------------------- - + /** * The Host template, holds the Host attributes. */ @@ -447,54 +410,43 @@ private: */ HostShare host_share; - // ------------------------------------------------------------------------- - // Lex & bison - // ------------------------------------------------------------------------- - - /** - * Mutex to perform just one flex-bison parsing at a time - */ - static pthread_mutex_t lex_mutex; - // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* /** - * Function to unmarshall a Host object - * @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 unmarshall(int num, char **names, char ** values); + * Execute an INSERT or REPLACE Sql query. + * @param db The SQL DB + * @param replace Execute an INSERT or a REPLACE + * @return 0 one success + */ + int insert_replace(SqlDB *db, bool replace); /** - * Function to unmarshall a Host object in to an output stream in XML - * @param oss the output stream + * Callback function to unmarshall a Host object (Host::select) * @param num the number of columns read from the DB * @param names the column names * @param vaues the column values * @return 0 on success */ - static int unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values); + int select_cb(void *nil, int num, char **values, char **names); + /** * Bootstraps the database table(s) associated to the Host */ - static void bootstrap(SqliteDB * db) - { - db->exec(Host::db_bootstrap); - - db->exec(HostShare::db_bootstrap); - - db->exec(HostTemplate::db_bootstrap); + static void bootstrap(SqlDB * db) + { + ostringstream oss_host(Host::db_bootstrap); + ostringstream oss_share(HostShare::db_bootstrap); + ostringstream oss_templ(HostTemplate::db_bootstrap); + + db->exec(oss_host); + db->exec(oss_share); + db->exec(oss_templ); }; protected: - + // ************************************************************************* // Constructor // ************************************************************************* @@ -502,23 +454,23 @@ protected: Host(int id=-1, string _hostname="", string _im_mad_name="", - string _vmm_mad_name="", + string _vmm_mad_name="", string _tm_mad_name=""); virtual ~Host(); - + // ************************************************************************* // DataBase implementation // ************************************************************************* - + enum ColNames { - OID = 0, - HOST_NAME = 1, - STATE = 2, - IM_MAD = 3, - VM_MAD = 4, - TM_MAD = 5, + OID = 0, + HOST_NAME = 1, + STATE = 2, + IM_MAD = 3, + VM_MAD = 4, + TM_MAD = 5, LAST_MON_TIME = 6, LIMIT = 7 }; @@ -526,7 +478,7 @@ protected: static const char * db_names; static const char * db_bootstrap; - + static const char * table; /** @@ -534,38 +486,38 @@ protected: * @param db pointer to the db * @return 0 on success */ - virtual int select(SqliteDB *db); + virtual int select(SqlDB *db); /** * Writes the Host and its associated HostShares in the database. * @param db pointer to the db * @return 0 on success */ - virtual int insert(SqliteDB *db); + virtual int insert(SqlDB *db); /** * Writes/updates the Hosts data fields in the database. * @param db pointer to the db * @return 0 on success */ - virtual int update(SqliteDB *db); - + virtual int update(SqlDB *db); + /** * Drops host from the database * @param db pointer to the db * @return 0 on success */ - virtual int drop(SqliteDB *db); + virtual int drop(SqlDB *db); /** - * Dumps the contect of a set of Host objects in the given stream - * using XML format - * @param db pointer to the db + * Function to output a Host object in to an stream in XML format * @param oss the output stream - * @param where string to filter the VirtualMachine objects + * @param num the number of columns read from the DB + * @param names the column names + * @param vaues the column values * @return 0 on success */ - static int dump(SqliteDB * db, ostringstream& oss, const string& where); + static int dump(ostringstream& oss, int num, char **values, char **names); }; #endif /*HOST_H_*/ diff --git a/include/HostPool.h b/include/HostPool.h index 0bd48f03a6..e655463cb0 100644 --- a/include/HostPool.h +++ b/include/HostPool.h @@ -30,26 +30,26 @@ using namespace std; /** - * The Host Pool class. ... + * The Host Pool class. */ class HostPool : public PoolSQL { public: - HostPool(SqliteDB * db):PoolSQL(db,Host::table){}; + HostPool(SqlDB * db):PoolSQL(db,Host::table){}; ~HostPool(){}; /** * Function to allocate a new Host object * @param oid the id assigned to the Host - * @return 0 on success + * @return the oid assigned to the object or -1 in case of failure */ int allocate ( int * oid, string hostname, - string im_mad_name, - string vmm_mad_name, + string im_mad_name, + string vmm_mad_name, string tm_mad_name); /** @@ -65,33 +65,24 @@ public: { return static_cast(PoolSQL::get(oid,lock)); }; - - /** Update a particular Host + + /** Update a particular Host * @param host pointer to Host * @return 0 on success */ int update(Host * host) { - return host->update(db); - }; - - - /** Drops a host from the DB, the host mutex MUST BE locked - * @param host pointer to Host - */ - int drop(Host * host) - { - return host->drop(db); + return host->update(db); }; /** * Bootstraps the database table(s) associated to the Host pool */ - static void bootstrap(SqliteDB *_db) + static void bootstrap(SqlDB *_db) { Host::bootstrap(_db); }; - + /** * Get the 10 least monitored hosts * @param discovered hosts, map to store the retrieved hosts hids and @@ -109,36 +100,37 @@ public: */ void add_capacity(int oid,int cpu, int mem, int disk) { - Host * host = get(oid, true); - - if ( host != 0 ) - { - host->add_capacity(cpu, mem, disk); - - update(host); - - host->unlock(); - } + Host * host = get(oid, true); + + if ( host != 0 ) + { + host->add_capacity(cpu, mem, disk); + + update(host); + + host->unlock(); + } }; + /** * De-Allocates a given capacity to the host * @param oid the id of the host to allocate the capacity * @param cpu amount of CPU * @param mem amount of main memory * @param disk amount of disk - */ + */ void del_capacity(int oid,int cpu, int mem, int disk) { - Host * host = get(oid, true); - - if ( host != 0 ) - { - host->del_capacity(cpu, mem, disk); - - update(host); - - host->unlock(); - } + Host * host = get(oid, true); + + if ( host != 0 ) + { + host->del_capacity(cpu, mem, disk); + + update(host); + + host->unlock(); + } }; /** @@ -149,19 +141,8 @@ public: * * @return 0 on success */ - int dump(ostringstream& oss, const string& where) - { - int rc; + int dump(ostringstream& oss, const string& where); - oss << ""; - - rc = Host::dump(db,oss,where); - - oss << ""; - - return rc; - } - private: /** * Factory method to produce Host objects @@ -172,6 +153,25 @@ private: return new Host; }; + /** + * Callback function to get the IDs of the hosts to be monitored + * (Host::discover) + * @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 discover_cb(void * _map, int num, char **values, char **names); + + /** + * Callback function to get output the host pool in XML format + * (Host::dump) + * @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 dump_cb(void * _oss, int num, char **values, char **names); }; -#endif /*HOST_POOL_H_*/ +#endif /*HOST_POOL_H_*/ \ No newline at end of file diff --git a/include/HostShare.h b/include/HostShare.h index 55c455b99c..419d487a56 100644 --- a/include/HostShare.h +++ b/include/HostShare.h @@ -1,40 +1,35 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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. */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* Copyright 2002-2010, 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 HOST_SHARE_H_ #define HOST_SHARE_H_ -#include "SqliteDB.h" +#include "SqlDB.h" #include "ObjectSQL.h" #include using namespace std; -extern "C" int host_share_select_cb (void * _hs, - int num, - char ** values, - char ** names); - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ /** * The HostShare class. It represents a logical partition of a host... */ -class HostShare : public ObjectSQL +class HostShare : public ObjectSQL { public: @@ -57,7 +52,7 @@ public: cpu_usage += cpu; mem_usage += mem; disk_usage += disk; - + running_vms++; } @@ -72,17 +67,17 @@ public: cpu_usage -= cpu; mem_usage -= mem; disk_usage -= disk; - - running_vms--; + + running_vms--; } - + /** - * Check if this share can host a VM. + * Check if this share can host a VM. * @param cpu requested by the VM * @param mem requested by the VM * @param disk requested by the VM - * - * @return true if the share can host the VM or it is the only one + * + * @return true if the share can host the VM or it is the only one * configured */ bool test(int cpu, int mem, int disk) const @@ -90,8 +85,8 @@ public: return (((max_cpu - cpu_usage ) >= cpu) && ((max_mem - mem_usage ) >= mem) && ((max_disk - disk_usage) >= disk)); - } - + } + /** * Function to write a HostShare to an output stream */ @@ -112,15 +107,15 @@ public: * @return a reference to the generated string */ string& to_xml(string& xml) const; - + private: int hsid; /**< HostShare identifier */ - + int disk_usage; /**< Disk allocated to VMs (in Mb). */ int mem_usage; /**< Memory allocated to VMs (in Mb) */ int cpu_usage; /**< CPU allocated to VMs (in percentage) */ - + int max_disk; /**< Total disk capacity (in Mb) */ int max_mem; /**< Total memory capacity (in Mb) */ int max_cpu; /**< Total cpu capacity (in percentage) */ @@ -134,19 +129,14 @@ private: int used_cpu; /**< Used cpu from the IM monitor */ int running_vms; /**< Number of running VMs in this Host */ - + // ---------------------------------------- // Friends // ---------------------------------------- friend class Host; - - friend int host_share_select_cb ( - void * _hostshare, - int num, - char ** values, - char ** names); - + friend class HostPool; + // ---------------------------------------- // DataBase implementation variables // ---------------------------------------- @@ -171,7 +161,7 @@ private: }; static const char * table; - + static const char * db_names; static const char * db_bootstrap; @@ -179,43 +169,51 @@ private: // ---------------------------------------- // Database methods // ---------------------------------------- - + /** * Reads the HostShare (identified with its HSID) from the database. * @param db pointer to the db * @return 0 on success */ - int select(SqliteDB * db); + int select(SqlDB * db); /** * Writes the HostShare in the database. * @param db pointer to the db * @return 0 on success */ - int insert(SqliteDB * db); + int insert(SqlDB * db); /** * Writes/updates the HostShare data fields in the database. * @param db pointer to the db * @return 0 on success */ - int update(SqliteDB * db); - + int update(SqlDB * db); + /** * Drops hostshare from the database * @param db pointer to the db * @return 0 on success */ - int drop(SqliteDB * db); - + int drop(SqlDB * db); + /** - * Function to unmarshall a HostShare object + * Execute an INSERT or REPLACE Sql query. + * @param db The SQL DB + * @param replace Execute an INSERT or a REPLACE + * @return 0 one success + */ + int insert_replace(SqlDB *db, bool replace); + + /** + * Callback function to unmarshall a HostShare object (HostShare::select) * @param num the number of columns read from the DB * @para names the column names * @para vaues the column values * @return 0 on success */ - int unmarshall(int num, char **names, char ** values); + int select_cb(void * nil, int num, char **values, char **names); /** * Function to unmarshall a HostShare object in to an output stream in XML @@ -225,10 +223,8 @@ private: * @param vaues the column values * @return 0 on success */ - static int unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values); + static int dump(ostringstream& oss, int num, char **values, char **names); + }; diff --git a/include/Leases.h b/include/Leases.h index 9e50d571c0..2b5418b4e9 100644 --- a/include/Leases.h +++ b/include/Leases.h @@ -17,7 +17,6 @@ #ifndef LEASES_H_ #define LEASES_H_ -#include #include "ObjectSQL.h" #include "Attribute.h" @@ -27,12 +26,6 @@ using namespace std; -extern "C" int leases_select_cb ( - void * _lease, - int num, - char ** values, - char ** names); - /** * The Leases class represents all the IP and MAC addresses (lease) that can * be asigned (or are asigned) in a Virtual Network @@ -46,13 +39,13 @@ public: * @param _oid the virtual network unique identifier * @param _size the max number of leases */ - Leases(SqliteDB * _db, int _oid, unsigned long _size): + Leases(SqlDB * _db, int _oid, unsigned long _size): oid(_oid), size(_size), db(_db){}; - + virtual ~Leases() { map::iterator it; - + for(it=leases.begin();it!=leases.end();it++) { delete it->second; @@ -78,7 +71,7 @@ public: * @return 0 if success */ virtual int set(int vid, const string& ip, string& mac) = 0; - + /** * Release an used lease, which becomes unused * @param ip of the lease in use @@ -122,31 +115,31 @@ protected: }; ~Lease(){}; - + /** * Converts this lease's IP and MAC to string * @param ip ip of the lease in string * @param mac mac of the lease in string */ void to_string(string& _ip, string& _mac) const; - + /** * Conversion from string IP to unsigned int IP * @return 0 if success */ static int ip_to_number(const string& ip, unsigned int& i_ip); - + /** * Conversion from unsigned int IP to string IP */ static void ip_to_string(const unsigned int i_ip, string& ip); - + /** * Conversion from string MAC to unsigned int[] MAC * @return 0 if success */ static int mac_to_number(const string& mac, unsigned int i_mac[]); - + /** * Conversion from string IP to unsigned int IP */ @@ -161,7 +154,7 @@ protected: * Function to print the Lease object into a string in * plain text * @param str the resulting string - * @return a reference to the generated string + * @return a reference to the generated string */ string& to_str(string& str) const; @@ -169,10 +162,10 @@ protected: * Function to print the Lease object into a string in * XML format * @param xml the resulting XML string - * @return a reference to the generated string + * @return a reference to the generated string */ string& to_xml(string& xml) const; - + /** * Constants to access the array storing the MAC address */ @@ -181,19 +174,19 @@ protected: SUFFIX = 0,/**< Lower significant 4 bytes */ PREFIX = 1 /**< Higher significant 2 bytes */ }; - + unsigned int ip; - + unsigned int mac [2]; - + int vid; - + bool used; }; friend class VirtualNetwork; + friend class VirtualNetworkPool; - // ------------------------------------------------------------------------- // Leases fields // ------------------------------------------------------------------------- @@ -201,12 +194,12 @@ protected: * Leases indentifier. Connects it to a Virtual Network */ int oid; - + /** * Number of possible leases (free + asigned) */ unsigned int size; - + /** * Hash of leases, indexed by lease.ip */ @@ -218,7 +211,7 @@ protected: /** * Pointer to the DataBase */ - SqliteDB * db; + SqlDB * db; enum ColNames { @@ -240,29 +233,30 @@ protected: // ------------------------------------------------------------------------- // Leases methods // ------------------------------------------------------------------------- + /** * Check if the passed ip corresponds with a given lease * @param ip of the lease to be checked * @return true if the ip was already assigned */ - bool check(const string& ip); - - bool check(unsigned int ip); + bool check(const string& ip); + + bool check(unsigned int ip); + + /** + * Reads the leases from the DB, and updates the lease hash table + * @param db pointer to the database. + * @return 0 on success. + */ + virtual int select(SqlDB * db); - /** - * Reads the leases from the DB, and updates the lease hash table - * @param db pointer to the database. - * @return 0 on success. - */ - virtual int select(SqliteDB * db); - friend ostream& operator<<(ostream& os, Lease& _lease); /** * Function to print the Leases object into a string in * plain text * @param str the resulting string - * @return a reference to the generated string + * @return a reference to the generated string */ string& to_str(string& str) const; @@ -270,34 +264,27 @@ protected: * Function to print the Leases object into a string in * XML format * @param xml the resulting XML string - * @return a reference to the generated string + * @return a reference to the generated string */ string& to_xml(string& xml) const; private: - - friend int leases_select_cb ( - void * _leases, - int num, - char ** values, - char ** names); - /** - * Function to unmarshall a leases object + * Callback function to unmarshall a Lease object (Lease::select) * @param num the number of columns read from the DB * @para names the column names * @para vaues the column values * @return 0 on success */ - int unmarshall(int num, char **names, char ** values); - + int select_cb(void *nil, int num, char **values, char **names); + /** * This method should not be called, leases are added/removed/updated * through add/del interface * @param db pointer to the database. * @return 0 on success. */ - int insert(SqliteDB * db); + int insert(SqlDB * db); /** * Leases are added/removed/updated through add/del interface @@ -305,7 +292,7 @@ private: * @param db pointer to the database. * @return 0 on success. */ - int drop(SqliteDB * db); + int drop(SqlDB * db); /** * This method should not be called, leases are added/removed/updated @@ -313,7 +300,7 @@ private: * @param db pointer to the database. * @return 0 on success. */ - int update(SqliteDB * db); + int update(SqlDB * db); }; #endif /*LEASES_H_*/ diff --git a/include/Log.h b/include/Log.h index 83f11c1f8b..d64eb79640 100644 --- a/include/Log.h +++ b/include/Log.h @@ -22,6 +22,10 @@ using namespace std; +/** + * The Logger class is an interface used by OpenNebula components to log + * messages + */ class Log { public: @@ -29,39 +33,108 @@ public: ERROR = 0, WARNING = 1, INFO = 2, - DEBUG = 3 + DEBUG = 3, + DDEBUG = 4, + DDDEBUG = 5 }; - typedef void (*LogFunction)( - const char *, - const MessageType, - const ostringstream&, - const char *, - const MessageType); - - Log(const string& file_name, - const MessageType level = WARNING, - ios_base::openmode mode = ios_base::app); + static const char error_names[]; + + Log(const MessageType _level = WARNING):log_level(_level){}; + + virtual ~Log(){}; + + // ------------------------------------------------------------------------- + // Logger interface + // ------------------------------------------------------------------------- + + virtual void log( + const char * module, + const MessageType type, + const char * message) = 0; + +protected: + /** + * Minimum log level for the messages + */ + MessageType log_level; +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +/** + * Log messages to a log file + */ +class FileLog : public Log +{ +public: + FileLog(const string& file_name, + const MessageType level = WARNING, + ios_base::openmode mode = ios_base::app); + + virtual ~FileLog(); + + virtual void log( + const char * module, + const MessageType type, + const char * message); + +private: + char * log_file; +}; + +/** + * Log messages to a log file + */ +class FileLogTS : public FileLog +{ +public: + FileLogTS(const string& file_name, + const MessageType level = WARNING, + ios_base::openmode mode = ios_base::app) + :FileLog(file_name,level,mode) + { + pthread_mutex_init(&log_mutex,0); + } + + ~FileLogTS() + { + pthread_mutex_destroy(&log_mutex); + } - ~Log(); - void log( const char * module, const MessageType type, - const ostringstream& message); + const char * message) + { + pthread_mutex_lock(&log_mutex); + FileLog::log(module,type,message); + pthread_mutex_unlock(&log_mutex); + } + +private: + pthread_mutex_t log_mutex; +}; + + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +/** + * + */ +class CerrLog : public Log +{ +public: + CerrLog(const MessageType level = WARNING):Log(level){}; + + ~CerrLog(){}; void log( const char * module, const MessageType type, const char * message); - -private: - - static const char error_names[]; - - MessageType log_level; - - char * log_file; }; #endif /* _LOG_H_ */ diff --git a/include/MySqlDB.h b/include/MySqlDB.h new file mode 100644 index 0000000000..71d9097345 --- /dev/null +++ b/include/MySqlDB.h @@ -0,0 +1,129 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 MYSQL_DB_H_ +#define MYSQL_DB_H_ + +#include +#include +#include + +#include +#include +#include + +#include "NebulaLog.h" +#include "SqlDB.h" +#include "ObjectSQL.h" + + +using namespace std; + +#ifdef MYSQL_DB + +#include + +/** + * SqliteDB class. Provides a wrapper to the mysql database interface. + */ +class MySqlDB : public SqlDB +{ +public: + + MySqlDB(const string& server, + const string& user, + const string& password, + char * database); + + ~MySqlDB(); + + /** + * Wraps the mysql_query function call + * @param cmd the SQL command + * @param obj Callbackable obj to call if the query succeeds + * @return 0 on success + */ + int exec(ostringstream& cmd, Callbackable* obj=0); + + /** + * This function returns a legal SQL string that can be used in an SQL + * statement. The string is encoded to an escaped SQL string, taking into + * account the current character set of the connection. + * @param str the string to be escaped + * @return a valid SQL string or NULL in case of failure + */ + char * escape_str(const string& str); + + /** + * Frees a previously scaped string + * @param str pointer to the str + */ + void free_str(char * str); + +private: + + /** + * The MySql connection handler + */ + MYSQL * db; + + /** + * Fine-grain mutex for DB access + */ + pthread_mutex_t mutex; + + /** + * Function to lock the DB + */ + void lock() + { + pthread_mutex_lock(&mutex); + }; + + /** + * Function to unlock the DB + */ + void unlock() + { + pthread_mutex_unlock(&mutex); + }; +}; +#else +//CLass stub +class MySqlDB : public SqlDB +{ +public: + + MySqlDB( + string server, + string user, + string password, + char * database) + { + throw runtime_error("Aborting oned, MySQL support not compiled!"); + }; + + ~MySqlDB(){}; + + int exec(ostringstream& cmd, Callbackable* obj=0){return -1;}; + + char * escape_str(const string& str){return 0;}; + + void free_str(char * str){}; +}; +#endif + +#endif /*MYSQL_DB_H_*/ \ No newline at end of file diff --git a/include/Nebula.h b/include/Nebula.h index 77790f436c..ec52e26208 100644 --- a/include/Nebula.h +++ b/include/Nebula.h @@ -17,9 +17,8 @@ #ifndef NEBULA_H_ #define NEBULA_H_ -#include +#include "SqlDB.h" -#include "Log.h" #include "NebulaTemplate.h" #include "VirtualMachinePool.h" @@ -38,63 +37,33 @@ class Nebula { public: - - static Nebula& instance() + + static Nebula& instance() { static Nebula nebulad; - + return nebulad; }; - - // --------------------------------------------------------------- - // Logging - // --------------------------------------------------------------- - - static void log( - const char * module, - const Log::MessageType type, - const ostringstream& message, - const char * filename = 0, - Log::MessageType clevel = Log::ERROR) - { - static Log nebula_log(filename,clevel,ios_base::trunc); - static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; - - pthread_mutex_lock(&log_mutex); - nebula_log.log(module,type,message); - pthread_mutex_unlock(&log_mutex); - }; - - static void log( - const char * module, - const Log::MessageType type, - const char * message, - const char * filename = 0) - { - ostringstream os(message); - - Nebula::log(module,type,os,filename); - }; // -------------------------------------------------------------- // Pool Accessors - // -------------------------------------------------------------- - + // -------------------------------------------------------------- + VirtualMachinePool * get_vmpool() { return vmpool; - }; + }; HostPool * get_hpool() { return hpool; - }; - + }; + VirtualNetworkPool * get_vnpool() { return vnpool; }; - + UserPool * get_upool() { return upool; @@ -102,8 +71,8 @@ public: // -------------------------------------------------------------- // Manager Accessors - // -------------------------------------------------------------- - + // -------------------------------------------------------------- + VirtualMachineManager * get_vmm() { return vmm; @@ -113,7 +82,7 @@ public: { return lcm; }; - + InformationManager * get_im() { return im; @@ -128,29 +97,29 @@ public: { return dm; }; - + HookManager * get_hm() { return hm; }; - + // -------------------------------------------------------------- // Environment & Configuration // -------------------------------------------------------------- - + /** - * Returns the value of ONE_LOCATION env variable. When this variable is + * Returns the value of ONE_LOCATION env variable. When this variable is * not defined the nebula location is "/". * @return the nebula location. - */ + */ const string& get_nebula_location() { return nebula_location; }; /** - * Returns the path where mad executables are stored, if ONE_LOCATION is - * defined this path points to $ONE_LOCATION/bin, otherwise it is + * Returns the path where mad executables are stored, if ONE_LOCATION is + * defined this path points to $ONE_LOCATION/bin, otherwise it is * /usr/lib/one/mads. * @return the mad execs location. */ @@ -160,7 +129,7 @@ public: }; /** - * Returns the path where defaults for mads are stored, if ONE_LOCATION is + * Returns the path where defaults for mads are stored, if ONE_LOCATION is * defined this path points to $ONE_LOCATION/etc, otherwise it is /etc/one * @return the mad defaults location. */ @@ -168,10 +137,10 @@ public: { return etc_location; }; - + /** * Returns the path where logs (oned.log, schedd.log,...) are generated - * if ONE_LOCATION is defined this path points to $ONE_LOCATION/var, + * if ONE_LOCATION is defined this path points to $ONE_LOCATION/var, * otherwise it is /var/log/one. * @return the log location. */ @@ -181,8 +150,8 @@ public: }; /** - * Returns the path where the OpenNebula DB and the VM local directories - * are stored. When ONE_LOCATION is defined this path points to + * Returns the path where the OpenNebula DB and the VM local directories + * are stored. When ONE_LOCATION is defined this path points to * $ONE_LOCATION/var, otherwise it is /var/lib/one. * @return the log location. */ @@ -190,7 +159,7 @@ public: { return var_location; }; - + /** * Returns the path of the log file for a VM, depending where OpenNebula is * installed, @@ -202,46 +171,46 @@ public: string get_vm_log_filename(int oid) { ostringstream oss; - + if (nebula_location == "/") { - oss << log_location << oid << ".log"; + oss << log_location << oid << ".log"; } else { - oss << nebula_location << "var/" << oid << "/vm.log"; + oss << nebula_location << "var/" << oid << "/vm.log"; } - + return oss.str(); }; - + const string& get_nebula_hostname() { return hostname; }; - + static string version() { - return "OpenNebula 1.5.0"; + return "OpenNebula 1.5.0"; }; - + void start(); - + void get_configuration_attribute( - const char * name, + const char * name, string& value) const { string _name(name); - - nebula_configuration->Template::get(_name,value); + + nebula_configuration->Template::get(_name,value); }; - + private: - - // ----------------------------------------------------------------------- + + // ----------------------------------------------------------------------- //Constructors and = are private to only access the class through instance // ----------------------------------------------------------------------- - + Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0),upool(0), lcm(0),vmm(0),im(0),tm(0),dm(0),rm(0) { @@ -250,7 +219,7 @@ private: if (nl == 0) //OpenNebula installed under root directory { nebula_location = "/"; - + mad_location = "/usr/lib/one/mads/"; etc_location = "/etc/one/"; log_location = "/var/log/one/"; @@ -259,19 +228,19 @@ private: else { nebula_location = nl; - + if ( nebula_location.at(nebula_location.size()-1) != '/' ) { nebula_location += "/"; } - - mad_location = nebula_location + "lib/mads/"; - etc_location = nebula_location + "etc/"; + + mad_location = nebula_location + "lib/mads/"; + etc_location = nebula_location + "etc/"; log_location = nebula_location + "var/"; - var_location = nebula_location + "var/"; - } + var_location = nebula_location + "var/"; + } }; - + ~Nebula() { if ( vmpool != 0) @@ -303,7 +272,7 @@ private: { delete lcm; } - + if ( im != 0) { delete im; @@ -313,69 +282,69 @@ private: { delete tm; } - + if ( dm != 0) { delete dm; } - + if ( rm != 0) { delete rm; } - + if ( hm != 0) { delete hm; } - + if ( nebula_configuration != 0) { delete nebula_configuration; } - + if ( db != 0 ) { delete db; } }; - + Nebula(Nebula const&){}; - - Nebula& operator=(Nebula const&){return *this;}; - + + Nebula& operator=(Nebula const&){return *this;}; + // --------------------------------------------------------------- // Environment variables // --------------------------------------------------------------- - + string nebula_location; - + string mad_location; string etc_location; string log_location; string var_location; string hostname; - + // --------------------------------------------------------------- // Configuration // --------------------------------------------------------------- NebulaTemplate * nebula_configuration; - + // --------------------------------------------------------------- // Nebula Pools // --------------------------------------------------------------- - - SqliteDB * db; + + SqlDB * db; VirtualMachinePool * vmpool; HostPool * hpool; VirtualNetworkPool * vnpool; UserPool * upool; - + // --------------------------------------------------------------- // Nebula Managers // --------------------------------------------------------------- - + LifeCycleManager * lcm; VirtualMachineManager * vmm; InformationManager * im; @@ -383,11 +352,11 @@ private: DispatchManager * dm; RequestManager * rm; HookManager * hm; - + // --------------------------------------------------------------- // Implementation functions // --------------------------------------------------------------- - + friend void nebula_signal_handler (int sig); }; diff --git a/include/NebulaLog.h b/include/NebulaLog.h new file mode 100644 index 0000000000..3cb3147259 --- /dev/null +++ b/include/NebulaLog.h @@ -0,0 +1,92 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 _NEBULA_LOG_H_ +#define _NEBULA_LOG_H_ + +#include "Log.h" +#include + +using namespace std; + +/** + * The Logger class for the OpenNebula components + */ +class NebulaLog +{ +public: + enum LogType { + FILE = 0, + FILE_TS = 1, + CERR = 2 + }; + + // --------------------------------------------------------------- + // Logging + // --------------------------------------------------------------- + + static void init_log_system( + LogType ltype, + Log::MessageType clevel, + const char * filename = 0, + ios_base::openmode mode = ios_base::trunc) + { + switch(ltype) + { + case FILE: + NebulaLog::logger = new FileLog(filename,clevel,mode); + break; + case FILE_TS: + NebulaLog::logger = new FileLogTS(filename,clevel,mode); + break; + default: + NebulaLog::logger = new CerrLog(clevel); + break; + } + }; + + static void finalize_log_system() + { + delete logger; + } + + static void log( + const char * module, + const Log::MessageType type, + const char * message) + { + logger->log(module,type,message); + }; + + static void log( + const char * module, + const Log::MessageType type, + const ostringstream& message) + { + logger->log(module,type,message.str().c_str()); + }; + +private: + NebulaLog(){}; + ~NebulaLog(){}; + + static Log * logger; +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +#endif /* _NEBULA_LOG_H_ */ diff --git a/include/ObjectSQL.h b/include/ObjectSQL.h index 2a649374fe..ba79b03dbc 100644 --- a/include/ObjectSQL.h +++ b/include/ObjectSQL.h @@ -17,7 +17,8 @@ #ifndef OBJECT_SQL_H_ #define OBJECT_SQL_H_ -#include "SqliteDB.h" +#include "Callbackable.h" +#include "SqlDB.h" using namespace std; @@ -25,8 +26,7 @@ using namespace std; * ObjectSQL class. Provides a SQL backend interface, it should be implemented * by persistent objects. */ - -class ObjectSQL +class ObjectSQL : public Callbackable { public: @@ -41,7 +41,7 @@ protected: * @return 0 on success */ virtual int select( - SqliteDB * db) = 0; + SqlDB * db) = 0; /** * Writes the ObjectSQL in the database. @@ -49,7 +49,7 @@ protected: * @return 0 on success */ virtual int insert( - SqliteDB * db) = 0; + SqlDB * db) = 0; /** * Updates the ObjectSQL in the database. @@ -57,7 +57,7 @@ protected: * @return 0 on success */ virtual int update( - SqliteDB * db) = 0; + SqlDB * db) = 0; /** * Removes the ObjectSQL from the database. @@ -65,7 +65,7 @@ protected: * @return 0 on success */ virtual int drop( - SqliteDB * db) = 0; + SqlDB * db) = 0; }; -#endif /*OBJECT_SQL_H_*/ +#endif /*OBJECT_SQL_H_*/ \ No newline at end of file diff --git a/include/PoolObjectSQL.h b/include/PoolObjectSQL.h index cf6966d6b7..1ac4577700 100644 --- a/include/PoolObjectSQL.h +++ b/include/PoolObjectSQL.h @@ -17,19 +17,18 @@ #ifndef POOL_OBJECT_SQL_H_ #define POOL_OBJECT_SQL_H_ -#include "SqliteDB.h" #include "ObjectSQL.h" #include using namespace std; /** - * PoolObject class. Provides a SQL backend interface for Pool components. Each + * PoolObject class. Provides a SQL backend interface for Pool components. Each * object is identified with and unique OID - * - * Note: The PoolObject provides a synchronization mechanism (mutex). This + * + * Note: The PoolObject provides a synchronization mechanism (mutex). This * implementation assumes that the mutex IS LOCKED when the class destructor - * is called. + * is called. */ class PoolObjectSQL : public ObjectSQL @@ -44,10 +43,10 @@ public: virtual ~PoolObjectSQL() { pthread_mutex_unlock(&mutex); - + pthread_mutex_destroy(&mutex); }; - + int get_oid() const { return oid; @@ -63,7 +62,7 @@ public: }; /** - * Set the object valid flag + * Set the object valid flag * @param _valid new valid flag */ void set_valid(const bool _valid) @@ -86,8 +85,9 @@ public: { pthread_mutex_unlock(&mutex); }; - + protected: + /** * The object unique ID */ @@ -96,7 +96,7 @@ protected: /** * The contents ob this object are valid */ - bool valid; + bool valid; private: @@ -106,8 +106,8 @@ private: friend class PoolSQL; /** - * The mutex for the PoolObject. This implementation assumes that the mutex - * IS LOCKED when the class destructor is called. + * The mutex for the PoolObject. This implementation assumes that the mutex + * IS LOCKED when the class destructor is called. */ pthread_mutex_t mutex; }; diff --git a/include/PoolSQL.h b/include/PoolSQL.h index 83a5163e64..e88223e739 100644 --- a/include/PoolSQL.h +++ b/include/PoolSQL.h @@ -21,7 +21,7 @@ #include #include -#include "SqliteDB.h" +#include "SqlDB.h" #include "PoolObjectSQL.h" #include "Log.h" #include "Hook.h" @@ -30,11 +30,11 @@ using namespace std; /** * PoolSQL class. Provides a base class to implement persistent generic pools. - * The PoolSQL provides a synchronization mechanism (mutex) to operate in - * multithreaded applications. Any modification or access function to the pool + * The PoolSQL provides a synchronization mechanism (mutex) to operate in + * multithreaded applications. Any modification or access function to the pool * SHOULD block the mutex. */ -class PoolSQL: public Hookable +class PoolSQL: public Callbackable, public Hookable { public: @@ -43,10 +43,10 @@ public: * the last used Object identifier by querying the corresponding database * table. This function SHOULD be called before any pool related function. * @param _db a pointer to the database - * @param table the name of the table supporting the pool (to set the oid + * @param table the name of the table supporting the pool (to set the oid * counter). If null the OID counter is not updated. */ - PoolSQL(SqliteDB * _db, const char * table=0); + PoolSQL(SqlDB * _db, const char * table=0); virtual ~PoolSQL(); @@ -60,11 +60,11 @@ public: PoolObjectSQL *objsql); /** - * Gets an object from the pool (if needed the object is loaded from the + * Gets an object from the pool (if needed the object is loaded from the * database). * @param oid the object unique identifier * @param lock locks the object if true - * + * * @return a pointer to the object, 0 in case of failure */ virtual PoolObjectSQL * get( @@ -76,48 +76,70 @@ public: * @param oids a vector with the oids of the objects. * @param the name of the DB table. * @param where condition in SQL format. - * - * @return 0 on success + * + * @return 0 on success */ virtual int search( vector& oids, const char * table, const string& where); - + /** * Updates the object's data in the data base. The object mutex SHOULD be * locked. * @param objsql a pointer to the object - * + * * @return 0 on success. */ virtual int update( PoolObjectSQL * objsql) { int rc; - + rc = objsql->update(db); - + if ( rc == 0 ) { do_hooks(objsql, Hook::UPDATE); } - + return rc; }; - + + /** + * Drops the object's data in the data base. The object mutex SHOULD be + * locked. + * @param objsql a pointer to the object + * @return 0 on success. + */ + virtual int drop( + PoolObjectSQL * objsql) + { + return objsql->drop(db); + }; + /** * Removes all the elements from the pool */ void clean(); - + + /** + * Dumps the pool in XML format. A filter can be also added to the + * query + * @param oss the output stream to dump the pool contents + * @param where filter for the objects, defaults to all + * + * @return 0 on success + */ + virtual int dump(ostringstream& oss, const string& where) = 0; + protected: /** * Pointer to the database. */ - SqliteDB * db; - + SqlDB * db; + /** * Function to lock the pool */ @@ -133,13 +155,13 @@ protected: { pthread_mutex_unlock(&mutex); }; - + private: pthread_mutex_t mutex; /** - * Max size for the pool, to control the memory footprint of the pool. This + * Max size for the pool, to control the memory footprint of the pool. This * number MUST be greater than the max. number of objects that are * accessed simultaneously. */ @@ -152,7 +174,7 @@ private: int lastOID; /** - * The pool is implemented with a Map of SQL object pointers, using the + * The pool is implemented with a Map of SQL object pointers, using the * OID as key. */ map pool; @@ -164,18 +186,28 @@ private: virtual PoolObjectSQL * create() = 0; /** - * OID queue to implement a FIFO-like replacement policy for the pool - * cache. + * OID queue to implement a FIFO-like replacement policy for the pool + * cache. */ queue oid_queue; /** * FIFO-like replacement policy function. Before removing an object (pop) - * from the cache its lock is checked. The object is removed only if - * the associated mutex IS NOT blocked. Otherwise the oid is sent to the - * back of the queue. + * from the cache its lock is checked. The object is removed only if + * the associated mutex IS NOT blocked. Otherwise the oid is sent to the + * back of the queue. */ void replace(); + + /** + * Callback to set the lastOID (PoolSQL::PoolSQL) + */ + int init_cb(void *nil, int num, char **values, char **names); + + /** + * Callback to store the IDs of pool objects (PoolSQL::search) + */ + int search_cb(void *_oids, int num, char **values, char **names); }; #endif /*POOL_SQL_H_*/ diff --git a/include/RangedLeases.h b/include/RangedLeases.h index 1d79f6af93..a97de82627 100644 --- a/include/RangedLeases.h +++ b/include/RangedLeases.h @@ -28,7 +28,7 @@ public: // ************************************************************************* // Constructor // ************************************************************************* - RangedLeases(SqliteDB * db, + RangedLeases(SqlDB * db, int _oid, unsigned long _size, unsigned int _mac_prefix, @@ -53,40 +53,40 @@ public: * @return 0 if success */ int set(int vid, const string& ip, string& mac); - + /** * Release an used lease, which becomes unused * @param ip of the lease in use */ void release(const string& ip) { - del(ip); + del(ip); } - + /** * Loads the leases from the DB. */ - int select(SqliteDB * db) + int select(SqlDB * db) { - //Read the leases from the DB - int rc = Leases::select(db); - - return rc; + //Read the leases from the DB + int rc = Leases::select(db); + + return rc; } - + private: - /** - * The default MAC prefix for the OpenNebula cluster - */ - unsigned int mac_prefix; - - /** - * The Network address to generate leases - */ - unsigned int network_address; - - unsigned int current; - + /** + * The default MAC prefix for the OpenNebula cluster + */ + unsigned int mac_prefix; + + /** + * The Network address to generate leases + */ + unsigned int network_address; + + unsigned int current; + /** * Add a lease, from the Lease interface * @param ip ip of the lease @@ -95,7 +95,7 @@ private: * @return 0 if success */ int add(unsigned int ip, unsigned int mac[], int vid, bool used=true); - + /** * Remove a lease, from the Lease interface * @param db pointer to DB @@ -103,7 +103,7 @@ private: * @return 0 if success */ int del(const string& ip); - + }; -#endif /*RANGED_LEASES_H_*/ +#endif /*RANGED_LEASES_H_*/ \ No newline at end of file diff --git a/include/SchedulerHost.h b/include/SchedulerHost.h deleted file mode 100644 index 5d3c548c66..0000000000 --- a/include/SchedulerHost.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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 SCHEDULER_HOST_H_ -#define SCHEDULER_HOST_H_ - -#include "Host.h" - -using namespace std; - - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -/** - * The SchedulerHost class. It represents the scheduler version of the host, - * only read operations to the pool are allowed for the SchedulerHost class - */ -class SchedulerHost : public Host -{ - -public: - - SchedulerHost(){}; - - ~SchedulerHost(){}; - - /** - * Gets the current host capacity - * @param cpu the host free cpu, scaled according to a given threshold - * @param memory the host free memory - * @param threshold to consider the host totally free - */ - void get_capacity(int& cpu, int& memory, int threshold); - -private: - - // ---------------------------------------- - // Friends - // ---------------------------------------- - friend class SchedulerHostPool; - - // ---------------------------------------- - // SQL functions do not modify the DB! - // ---------------------------------------- - int insert(SqliteDB *db); - - int update(SqliteDB *db); - - int drop(SqliteDB *db); - -}; - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -/** - * The SchedulerHost class. It represents the scheduler version of the host, - * read only operation to the pool are allowed for the SchedulerHost class - */ -class SchedulerHostPool : public PoolSQL -{ -public: - - //-------------------------------------------------------------------------- - // Constructor - //-------------------------------------------------------------------------- - - SchedulerHostPool(SqliteDB *db):PoolSQL(db){}; - - ~SchedulerHostPool(){}; - - /** - * Implements the Pool interface, just prints an error message. This - * class DOES NOT modify the database. - */ - int allocate( - PoolObjectSQL *objsql); - - /** - * Gets an ScheulerHost from the pool (if needed the object is loaded from - * the database). - * @param oid the object unique identifier - * @param lock locks the object if true - * - * @return a pointer to the object, 0 in case of failure - */ - SchedulerHost * get( - int oid, - bool lock) - { - return static_cast(PoolSQL::get(oid,lock)); - }; - - /** - * Set ups the host pool by performing the following actions: - * - All the objects stored in the pool are flushed - * - The ids of the hosts in the database are loaded - * @return 0 on success - */ - int set_up(); - -private: - friend class Scheduler; - - /** - * Hosts ids - */ - vector hids; - - /** - * Factory method for the PoolSQL class - * @return a pointer to a new SchedulerHost object - */ - PoolObjectSQL * create() - { - return new SchedulerHost; - }; - - /** - * Bootstrap method from the PoolSQL interface. It just prints - * an error message as this class MUST not modify the DB. - */ - void bootstrap(); -}; - -#endif /*SCHEDULER_HOST_H_*/ diff --git a/include/SchedulerVirtualMachine.h b/include/SchedulerVirtualMachine.h deleted file mode 100644 index 674d37f7c7..0000000000 --- a/include/SchedulerVirtualMachine.h +++ /dev/null @@ -1,190 +0,0 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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 SCHEDULER_VIRTUAL_MACHINE_H_ -#define SCHEDULER_VIRTUAL_MACHINE_H_ - -#include "VirtualMachine.h" -#include "SchedulerHost.h" - -using namespace std; - - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -/** - * The SchedulerHost class. It represents the scheduler version of the host, - * only read operations to the pool are allowed for the SchedulerHost class - */ -class SchedulerVirtualMachine : public VirtualMachine -{ - -public: - - SchedulerVirtualMachine(){}; - - ~SchedulerVirtualMachine() - { - vector::iterator jt; - - for (jt=hosts.begin();jt!=hosts.end();jt++) - { - delete *jt; - } - }; - - /** - * Adds a new share to the map of suitable shares to start this VM - * @param hid of the selected host - * @param hsid of the selected host share - */ - void add_host(int hid) - { - SchedulerVirtualMachine::Host * ss; - - ss = new SchedulerVirtualMachine::Host(hid); - - hosts.push_back(ss); - }; - - /** - * Gets the matching hosts ids - * @param mh vector with the hids of the matching hosts - */ - void get_matching_hosts(vector& mh) - { - vector::iterator i; - - for(i=hosts.begin();i!=hosts.end();i++) - { - mh.push_back((*i)->hid); - } - }; - - /** - * Sets the priorities for each matching host - */ - void set_priorities(vector& total); - - /** - * - */ - int get_host(int& hid, SchedulerHostPool * hpool); - - /** - * Function to write a Virtual Machine in an output stream - */ - friend ostream& operator<<(ostream& os, SchedulerVirtualMachine& vm); - -private: - - // ------------------------------------------------------------------------- - // Friends - // ------------------------------------------------------------------------- - friend class SchedulerVirtualMachinePool; - - //-------------------------------------------------------------------------- - - struct Host - { - int hid; - float priority; - - Host(int _hid): - hid(_hid), - priority(0){}; - - ~Host(){}; - - bool operator<(const Host& b) const { //Sort by priority - return priority < b.priority; - } - }; - - static bool host_cmp (const Host * a, const Host * b ) - { - return (*a < *b ); - }; - - //-------------------------------------------------------------------------- - - /** - * Matching hosts - */ - vector hosts; - - // ------------------------------------------------------------------------- - // SQL functions do not modify the DB! - // ------------------------------------------------------------------------- - - int insert(SqliteDB *db); - - int update(SqliteDB *db); - - int drop(SqliteDB *db); -}; - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -/** - * The SchedulerHost class. It represents the scheduler version of the host, - * read only operation to the pool are allowed for the SchedulerHost class - */ -class SchedulerVirtualMachinePool : public PoolSQL -{ -public: - - SchedulerVirtualMachinePool(SqliteDB * db):PoolSQL(db){}; - - ~SchedulerVirtualMachinePool(){}; - - int allocate( - PoolObjectSQL *objsql); - - SchedulerVirtualMachine * get( - int oid, - bool lock) - { - return static_cast(PoolSQL::get(oid,lock)); - }; - - /** - * Set ups the VM pool by performing the following actions: - * - All the objects stored in the pool are flushed - * - The ids of the pendings VMs in the database are loaded - * @return 0 on success - */ - int set_up(); - -private: - friend class Scheduler; - - /** - * The ids of the pending VMs - */ - vector pending_vms; - - PoolObjectSQL * create() - { - return new SchedulerVirtualMachine; - }; - - void bootstrap(); -}; - -#endif /*SCHEDULER_VIRTUAL_MACHINE_H_*/ diff --git a/include/SqlDB.h b/include/SqlDB.h new file mode 100644 index 0000000000..6bc34e846a --- /dev/null +++ b/include/SqlDB.h @@ -0,0 +1,60 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 SQL_DB_H_ +#define SQL_DB_H_ + +#include +#include "Callbackable.h" + +using namespace std; + +/** + * SqlDB class.Provides an abstract interface to implement a SQL backend + */ +class SqlDB +{ +public: + + SqlDB(){}; + + virtual ~SqlDB(){}; + + /** + * Performs a DB transaction + * @param sql_cmd the SQL command + * @param callbak function to execute on each data returned + * @param arg to pass to the callback function + * @return 0 on success + */ + virtual int exec(ostringstream& cmd, Callbackable* obj=0) = 0; + + /** + * This function returns a legal SQL string that can be used in an SQL + * statement. + * @param str the string to be escaped + * @return a valid SQL string or NULL in case of failure + */ + virtual char * escape_str(const string& str) = 0; + + /** + * Frees a previously scaped string + * @param str pointer to the str + */ + virtual void free_str(char * str) = 0; +}; + +#endif /*SQL_DB_H_*/ diff --git a/include/SqliteDB.h b/include/SqliteDB.h index 79aee3ef2c..05ff9e7b24 100644 --- a/include/SqliteDB.h +++ b/include/SqliteDB.h @@ -20,49 +20,35 @@ #include #include #include -#include #include #include #include -#include "Log.h" +#include "NebulaLog.h" + +#include "SqlDB.h" +#include "ObjectSQL.h" using namespace std; +#ifdef SQLITE_DB + +#include + /** * SqliteDB class. Provides a wrapper to the sqlite3 database interface. It also - * provides "global" synchronization mechanism to use it in a multithread + * provides "global" synchronization mechanism to use it in a multithread * environment. */ -class SqliteDB +class SqliteDB : public SqlDB { public: - - SqliteDB( - string& db_name, - Log::LogFunction _log = 0 - ):log(_log) - { - int rc; - - pthread_mutex_init(&mutex,0); - - rc = sqlite3_open(db_name.c_str(), &db); - - if ( rc != SQLITE_OK ) - { - throw runtime_error("Could not open database."); - } - }; - - ~SqliteDB() - { - pthread_mutex_destroy(&mutex); - - sqlite3_close(db); - }; - + + SqliteDB(string& db_name); + + ~SqliteDB(); + /** * Wraps the sqlite3_exec function call, and locks the DB mutex. * @param sql_cmd the SQL command @@ -70,84 +56,23 @@ public: * mutex you block in the callback. * @param arg to pass to the callback function * @return 0 on success - */ - int exec( - ostringstream& sql_cmd, - int (*callback)(void*,int,char**,char**)=0, - void * arg=0) - { - int rc; - - const char * c_str; - string str; - - int counter = 0; - - char * err_msg; - char ** ptr = (log==0) ? 0 : &err_msg; - - str = sql_cmd.str(); - c_str = str.c_str(); - - lock(); - - do - { - counter++; - - rc = sqlite3_exec(db, c_str, callback, arg, ptr); - - if (rc == SQLITE_BUSY || rc == SQLITE_IOERR_BLOCKED) - { - struct timeval timeout; - fd_set zero; - - FD_ZERO(&zero); - timeout.tv_sec = 0; - timeout.tv_usec = 100000; - - select(0, &zero, &zero, &zero, &timeout); - } - - }while( (rc == SQLITE_BUSY || rc == SQLITE_IOERR_BLOCKED) && - (counter < 10)); - - unlock(); - - if (rc != SQLITE_OK) - { - if ((log != 0) && (err_msg != 0)) - { - ostringstream oss; - - oss << "SQL command was: " << c_str << ", error: " << err_msg; - log("ONE",Log::ERROR,oss,0,Log::ERROR); - - sqlite3_free(err_msg); - } - - return -1; - } - - return 0; - }; - - /** - * */ - int exec( - const char * sql_c_str, - int (*callback)(void*,int,char**,char**)=0, - void * arg=0) - { - string sql_str = sql_c_str; - ostringstream sql_cmd; - - sql_cmd.str(sql_str); - - return exec(sql_cmd,callback,arg); - }; - + int exec(ostringstream& cmd, Callbackable* obj=0); + + /** + * This function returns a legal SQL string that can be used in an SQL + * statement. + * @param str the string to be escaped + * @return a valid SQL string or NULL in case of failure + */ + char * escape_str(const string& str); + + /** + * Frees a previously scaped string + * @param str pointer to the str + */ + void free_str(char * str); + private: /** * Fine-grain mutex for DB access @@ -159,11 +84,6 @@ private: */ sqlite3 * db; - /** - * Log facility - */ - Log::LogFunction log; - /** * Function to lock the DB */ @@ -178,7 +98,27 @@ private: void unlock() { pthread_mutex_unlock(&mutex); - }; + }; }; +#else +//CLass stub +class SqliteDB : public SqlDB +{ +public: + + SqliteDB(string& db_name) + { + throw runtime_error("Aborting oned, Sqlite support not compiled!"); + }; + + ~SqliteDB(){}; + + int exec(ostringstream& cmd, Callbackable* obj=0){return -1;}; + + char * escape_str(const string& str){return 0;}; + + void free_str(char * str){}; +}; +#endif #endif /*SQLITE_DB_H_*/ diff --git a/include/TemplateSQL.h b/include/TemplateSQL.h index 23dd515faa..912d20b735 100644 --- a/include/TemplateSQL.h +++ b/include/TemplateSQL.h @@ -1,18 +1,18 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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. */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* Copyright 2002-2010, 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 TEMPLATE_SQL_H_ #define TEMPLATE_SQL_H_ @@ -22,7 +22,7 @@ #include #include "Template.h" -#include "SqliteDB.h" +#include "SqlDB.h" #include "ObjectSQL.h" using namespace std; @@ -39,7 +39,7 @@ public: bool replace = false, const char separator = '=', const char * xml_root = "TEMPLATE"): - Template(replace,separator,xml_root),table(_table),id(template_id) + Template(replace,separator,xml_root),table(_table),id(template_id) {}; virtual ~TemplateSQL(){}; @@ -48,7 +48,7 @@ protected: //Database implementation variables - const char * table; + const char * table; static const char * db_names; @@ -64,36 +64,44 @@ protected: * @param db pointer to the database. * @return 0 on success. */ - int insert(SqliteDB * db); + int insert(SqlDB * db); /** * Updates the template in the DB * @param db pointer to the database. * @return 0 on success. */ - int update(SqliteDB *db); + int update(SqlDB *db); /** * Reads the template (identified by its id) from the DB * @param db pointer to the database. * @return 0 on success. */ - int select(SqliteDB *db); + int select(SqlDB *db); /** * Removes the template from the DB * @param db pointer to the database. */ - int drop(SqliteDB *db); + int drop(SqlDB *db); + + /** + * Execute an INSERT or REPLACE Sql query. + * @param db The SQL DB + * @param replace Execute an INSERT or a REPLACE + * @return 0 one success + */ + int insert_replace(SqlDB *db, bool replace); /** * Removes a template attribute from the DB. If there are multiple - * attributes with the same name, only one will be replaced. The attribute - * MUST be allocated in the heap. + * attributes with the same name, only one will be replaced. The + * attribute MUST be allocated in the heap. * @param db pointer to the database. * @param attribute pointer to the new attribute. */ - int replace_attribute(SqliteDB * db, Attribute * attribute); + int replace_attribute(SqlDB * db, Attribute * attribute); /** * Insert a given attribute (MUST be allocated in the heap) in the template @@ -101,10 +109,20 @@ protected: * @param db pointer to the database. * @param attribute pointer to the new attribute */ - int insert_attribute(SqliteDB * db, Attribute * attribute); + int insert_attribute(SqlDB * db, Attribute * attribute); + + /** + * Callback to set the template id (TemplateSQL::insert) + */ + int insert_cb(void *nil, int num, char **values, char **names); + + /** + * Callback to recover template attributes (TemplateSQL::select) + */ + int select_cb(void *nil, int num, char **values, char **names); }; -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -#endif /*TEMPLATE_SQL_H_*/ +#endif /*TEMPLATE_SQL_H_*/ \ No newline at end of file diff --git a/include/User.h b/include/User.h index d34440a657..77d536ab51 100644 --- a/include/User.h +++ b/include/User.h @@ -21,45 +21,35 @@ using namespace std; -extern "C" int user_select_cb (void * _host, - int num, - char ** values, - char ** names); - -extern "C" int user_dump_cb (void * _oss, - int num, - char ** values, - char ** names); - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** - * The User class. It represents a User... + * The User class. */ class User : public PoolObjectSQL { public: - + /** * Function to write a User on an output stream */ - friend ostream& operator<<(ostream& os, User& u); - - /** - * Function to print the User object into a string in plain text - * @param str the resulting string - * @return a reference to the generated string - */ - string& to_str(string& str) const; + friend ostream& operator<<(ostream& os, User& u); + + /** + * Function to print the User object into a string in plain text + * @param str the resulting string + * @return a reference to the generated string + */ + string& to_str(string& str) const; + + /** + * Function to print the User object into a string in XML format + * @param xml the resulting XML string + * @return a reference to the generated string + */ + string& to_xml(string& xml) const; - /** - * Function to print the User object into a string in XML format - * @param xml the resulting XML string - * @return a reference to the generated string - */ - string& to_xml(string& xml) const; - /** * Get the User unique identifier UID, that matches the OID of the object @@ -69,9 +59,7 @@ public: { return oid; }; - - // ----- Getters --------------------------------- - + /** * Check if the user is enabled * @return true if the user is enabled @@ -80,61 +68,59 @@ public: { return enabled; } - + /** * Returns user username * @return username User's hostname */ - const string& get_username() const + const string& get_username() const { - return username; - }; - + return username; + }; + /** * Returns user password * @return username User's hostname */ - const string& get_password() const + const string& get_password() const { - return password; - }; - - // ----- Setters --------------------------------- - - /** + return password; + }; + + /** * Enables the current user - */ + */ void enable() { enabled = true; }; - + /** * Disables the current user - */ + */ void disable() { enabled = false; }; - - /** + + /** * Sets user username */ - void set_username(string _username) + void set_username(string _username) { - username = _username; - }; - - /** + username = _username; + }; + + /** * Sets user password */ - void set_password(string _password) + void set_password(string _password) { - password = _password; - }; - + password = _password; + }; + /** - * Looks for a match between _password and user password + * Looks for a match between _password and user password * @return -1 if disabled or wrong password, uid otherwise **/ int authenticate(string _password); @@ -144,7 +130,7 @@ public: * @param secret, the authentication token * @param username * @param password - * @return 0 on success + * @return 0 on success **/ static int split_secret(const string secret, string& user, string& pass); @@ -159,18 +145,8 @@ private: // ------------------------------------------------------------------------- // Friends // ------------------------------------------------------------------------- - - friend class UserPool; - - friend int user_select_cb (void * _host, - int num, - char ** values, - char ** names); - friend int user_dump_cb (void * _oss, - int num, - char ** values, - char ** names); + friend class UserPool; // ------------------------------------------------------------------------- // User Attributes @@ -190,44 +166,40 @@ private: * Flag marking user enabled/disabled */ bool enabled; - - + // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* /** - * Function to unmarshall a User object - * @param num the number of columns read from the DB - * @para names the column names - * @para vaues the column values - * @return 0 on success - */ - int unmarshall(int num, char **names, char ** values); + * Execute an INSERT or REPLACE Sql query. + * @param db The SQL DB + * @param replace Execute an INSERT or a REPLACE + * @return 0 one success + */ + int insert_replace(SqlDB *db, bool replace); /** - * Function to unmarshall a User object in to an output stream in XML - * @param oss the output stream + * Callback function to unmarshall a User object (User::select) * @param num the number of columns read from the DB * @param names the column names * @param vaues the column values * @return 0 on success */ - static int unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values); + int select_cb(void *nil, int num, char **values, char **names); /** * Bootstraps the database table(s) associated to the User */ - static void bootstrap(SqliteDB * db) - { - db->exec(User::db_bootstrap); + static void bootstrap(SqlDB * db) + { + ostringstream oss_user(User::db_bootstrap); + + db->exec(oss_user); }; protected: - + // ************************************************************************* // Constructor // ************************************************************************* @@ -238,16 +210,16 @@ protected: bool _enabled=true); virtual ~User(); - + // ************************************************************************* // DataBase implementation // ************************************************************************* - + enum ColNames { - OID = 0, - USERNAME = 1, - PASSWORD = 2, + OID = 0, + USERNAME = 1, + PASSWORD = 2, ENABLED = 3, // 0 = false, 1 = true LIMIT = 4 }; @@ -255,7 +227,7 @@ protected: static const char * db_names; static const char * db_bootstrap; - + static const char * table; /** @@ -263,38 +235,38 @@ protected: * @param db pointer to the db * @return 0 on success */ - virtual int select(SqliteDB *db); + virtual int select(SqlDB *db); /** * Writes the User in the database. * @param db pointer to the db * @return 0 on success */ - virtual int insert(SqliteDB *db); + virtual int insert(SqlDB *db); /** * Writes/updates the User data fields in the database. * @param db pointer to the db * @return 0 on success */ - virtual int update(SqliteDB *db); - + virtual int update(SqlDB *db); + /** * Drops USer from the database * @param db pointer to the db * @return 0 on success */ - virtual int drop(SqliteDB *db); - + virtual int drop(SqlDB *db); + /** - * Dumps the contect of a set of User objects in the given stream - * using XML format - * @param db pointer to the db + * Function to output a User object in to an stream in XML format * @param oss the output stream - * @param where string to filter the VirtualMachine objects + * @param num the number of columns read from the DB + * @param names the column names + * @param vaues the column values * @return 0 on success */ - static int dump(SqliteDB * db, ostringstream& oss, const string& where); + static int dump(ostringstream& oss, int num, char **values, char **names); }; #endif /*USER_H_*/ diff --git a/include/UserPool.h b/include/UserPool.h index 75809e21a7..73ecf072b5 100644 --- a/include/UserPool.h +++ b/include/UserPool.h @@ -36,20 +36,20 @@ class UserPool : public PoolSQL { public: - UserPool(SqliteDB * db); + UserPool(SqlDB * db); ~UserPool(){}; /** * Function to allocate a new User object * @param oid the id assigned to the User - * @return 0 on success + * @return the oid assigned to the object or -1 in case of failure */ int allocate ( int * oid, string hostname, string password, - bool enabled); + bool enabled); /** * Function to get a User from the pool, if the object is not in memory @@ -63,10 +63,10 @@ public: bool lock) { User * user = static_cast(PoolSQL::get(oid,lock)); - + return user; } - + /** * Function to get a User from the pool, if the object is not in memory @@ -80,7 +80,7 @@ public: bool lock) { map::iterator index; - + index = known_users.find(username); if ( index != known_users.end() ) @@ -91,46 +91,46 @@ public: return 0; } - /** Update a particular User + /** Update a particular User * @param user pointer to User * @return 0 on success */ int update(User * user) { - return user->update(db); + return user->update(db); }; - - + + /** Drops a user from the DB, the user mutex MUST BE locked * @param user pointer to User */ int drop(User * user) { - int rc = user->drop(db); - - if ( rc == 0) - { + int rc = PoolSQL::drop(user); + + if ( rc == 0) + { known_users.erase(user->get_username()); - } - + } + return rc; }; /** * Bootstraps the database table(s) associated to the User pool */ - static void bootstrap(SqliteDB * _db) + static void bootstrap(SqlDB * _db) { User::bootstrap(_db); }; - + /** * Returns whether there is a user with given username/password or not * @param session, colon separated username and password string * @return -1 if there is no such a user, uid of the user if it exists */ int authenticate(string& session); - + /** * Dumps the User pool in XML format. A filter can be also added to the * query @@ -139,18 +139,7 @@ public: * * @return 0 on success */ - int dump(ostringstream& oss, const string& where) - { - int rc; - - oss << ""; - - rc = User::dump(db,oss,where); - - oss << ""; - - return rc; - } + int dump(ostringstream& oss, const string& where); private: /** @@ -161,12 +150,31 @@ private: { return new User; }; - + /** * This map stores the association between UIDs and Usernames */ map known_users; + /** + * Callback function to get output the user pool in XML format + * (User::dump) + * @param _oss pointer to the output stream + * @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 dump_cb(void * _oss, int num, char **values, char **names); + + /** + * Callback function to build the knwon_user map (User::User) + * @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 init_cb(void *nil, int num, char **values, char **names); }; -#endif /*USER_POOL_H_*/ +#endif /*USER_POOL_H_*/ \ No newline at end of file diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 7fe2b33577..3c28ab7532 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -27,9 +27,6 @@ using namespace std; -extern "C" int vm_select_cb (void * _vm, int num,char ** values, char ** names); -extern "C" int vm_dump_cb (void * _oss, int num,char ** values, char ** names); - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -97,7 +94,7 @@ public: { if (_log != 0) { - _log->log(module,type,message); + _log->log(module,type,message.str().c_str()); } }; @@ -121,22 +118,22 @@ public: */ friend ostream& operator<<(ostream& os, const VirtualMachine& vm); - /** - * Function to print the VirtualMachine object into a string in - * plain text - * @param str the resulting string - * @return a reference to the generated string - */ - string& to_str(string& str) const; + /** + * Function to print the VirtualMachine object into a string in + * plain text + * @param str the resulting string + * @return a reference to the generated string + */ + string& to_str(string& str) const; + + /** + * Function to print the VirtualMachine object into a string in + * XML format + * @param xml the resulting XML string + * @return a reference to the generated string + */ + string& to_xml(string& xml) const; - /** - * Function to print the VirtualMachine object into a string in - * XML format - * @param xml the resulting XML string - * @return a reference to the generated string - */ - string& to_xml(string& xml) const; - // ------------------------------------------------------------------------ // Dynamic Info // ------------------------------------------------------------------------ @@ -291,7 +288,7 @@ public: }; /** - * Returns the TM driver name for the previous host. The + * Returns the TM driver name for the previous host. The * hasPreviousHistory() function MUST be called before this one. * @return the TM mad name */ @@ -608,19 +605,19 @@ public: { vm_template.to_xml(xml); } - + /** - * Parse a string and substitute variables (e.g. $NAME) using the VM + * Parse a string and substitute variables (e.g. $NAME) using the VM * template values: * @param attribute, the string to be parsed * @param parsed, the resulting parsed string * @return 0 on success. - */ + */ int parse_template_attribute(const string& attribute, string& parsed); - + /** - * Parse a string and substitute variables (e.g. $NAME) using the VM + * Parse a string and substitute variables (e.g. $NAME) using the VM * template values (blocking-free version for cross references): * @param vm_id ID of the VM used to substitute the variables * @param attribute, the string to be parsed @@ -632,14 +629,14 @@ public: const string& attribute, string& parsed, char ** error_msg) - { + { return parse_attribute(0,vm_id,attribute,parsed,error_msg); } - + // ------------------------------------------------------------------------ // States // ------------------------------------------------------------------------ - + /** * Returns the VM state (Dispatch Manager) * @return the VM state @@ -747,18 +744,6 @@ private: // ------------------------------------------------------------------------- friend class VirtualMachinePool; - friend int vm_select_cb ( - void * _vm, - int num, - char ** values, - char ** names); - - friend int vm_dump_cb ( - void * _vm, - int num, - char ** values, - char ** names); - // ************************************************************************* // Virtual Machine Attributes // ************************************************************************* @@ -857,11 +842,11 @@ private: /** * Log class for the virtual machine, it writes log messages in - * $ONE_LOCATION/var/$VID/vm.log + * $ONE_LOCATION/var/$VID/vm.log * or, in case that OpenNebula is installed in root - * /var/log/one/$VM_ID.log + * /var/log/one/$VM_ID.log */ - Log * _log; + FileLog * _log; // ************************************************************************* // DataBase implementation (Private) @@ -870,48 +855,45 @@ private: /** * Bootstraps the database table(s) associated to the VirtualMachine */ - static void bootstrap(SqliteDB * db) + static void bootstrap(SqlDB * db) { - db->exec(VirtualMachine::db_bootstrap); + ostringstream oss_vm(VirtualMachine::db_bootstrap); + ostringstream oss_tmpl(VirtualMachineTemplate::db_bootstrap); + ostringstream oss_hist(History::db_bootstrap); - db->exec(VirtualMachineTemplate::db_bootstrap); - - db->exec(History::db_bootstrap); + db->exec(oss_vm); + db->exec(oss_tmpl); + db->exec(oss_hist); }; /** - * Function to unmarshall a VM object, an associated classes. + * Callback function to unmarshall a VirtualMachine object + * (VirtualMachine::select) * @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 unmarshall(int num, char **names, char ** values); - + int select_cb(void *nil, int num, char **names, char ** values); + /** - * Function to unmarshall a VM object into an output stream with XML - * format. - * @param oss the output stream - * @param num the number of columns read from the DB - * @param names the column names - * @param vaues the column values - * @return 0 on success - */ - static int unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values); + * Execute an INSERT or REPLACE Sql query. + * @param db The SQL DB + * @param replace Execute an INSERT or a REPLACE + * @return 0 one success + */ + int insert_replace(SqlDB *db, bool replace); /** * Updates the VM history record * @param db pointer to the db * @return 0 on success */ - int update_history(SqliteDB * db) + int update_history(SqlDB * db) { if ( history != 0 ) { - return history->insert(db); + return history->update(db); } else return -1; @@ -922,11 +904,11 @@ private: * @param db pointer to the db * @return 0 on success */ - int update_previous_history(SqliteDB * db) + int update_previous_history(SqlDB * db) { if ( previous_history != 0 ) { - return previous_history->insert(db); + return previous_history->update(db); } else return -1; @@ -941,9 +923,9 @@ private: * @return 0 on success */ int update_template_attribute( - SqliteDB * db, - string& name, - string& value) + SqlDB * db, + string& name, + string& value) { SingleAttribute * sattr; int rc; @@ -966,7 +948,7 @@ private: * @param attribute the new attribute for the template * @return 0 on success */ - int insert_template_attribute(SqliteDB * db, Attribute * attribute) + int insert_template_attribute(SqlDB * db, Attribute * attribute) { return vm_template.insert_attribute(db,attribute); } @@ -991,13 +973,13 @@ private: * @param parsed, the resulting parsed string * @param error_msg, string describing the syntax error * @return 0 on success. - */ + */ static int parse_attribute(VirtualMachine * vm, int vm_id, const string& attribute, string& parsed, char ** error_msg); - + protected: //************************************************************************** @@ -1042,22 +1024,22 @@ protected: * @param db pointer to the db * @return 0 on success */ - int select(SqliteDB * db); + int select(SqlDB * db); /** * Writes the Virtual Machine and its associated template in the database. * @param db pointer to the db * @return 0 on success */ - virtual int insert(SqliteDB * db); + virtual int insert(SqlDB * db); /** * Writes/updates the Virtual Machine data fields in the database. * @param db pointer to the db * @return 0 on success */ - virtual int update(SqliteDB * db); - + virtual int update(SqlDB * db); + /** * Deletes a VM from the database and all its associated information: * - History records @@ -1065,29 +1047,30 @@ protected: * @param db pointer to the db * @return 0 on success */ - virtual int drop(SqliteDB * db) + virtual int drop(SqlDB * db) { - int rc; + int rc; - rc = vm_template.drop(db); + rc = vm_template.drop(db); - if ( history != 0 ) - { - rc += history->drop(db); - } + if ( history != 0 ) + { + rc += history->drop(db); + } - return rc; + return rc; } /** * Dumps the contect of a set of VirtualMachine objects in the given stream * using XML format - * @param db pointer to the db * @param oss the output stream - * @param where string to filter the VirtualMachine objects + * @param num the number of columns read from the DB + * @param names the column names + * @param vaues the column values * @return 0 on success */ - static int dump(SqliteDB * db, ostringstream& oss, const string& where); + static int dump(ostringstream& oss, int num, char ** values, char ** names); }; #endif /*VIRTUAL_MACHINE_H_*/ diff --git a/include/VirtualMachinePool.h b/include/VirtualMachinePool.h index ccbe76350e..98d15cc032 100644 --- a/include/VirtualMachinePool.h +++ b/include/VirtualMachinePool.h @@ -32,7 +32,7 @@ class VirtualMachinePool : public PoolSQL { public: - VirtualMachinePool(SqliteDB * db, vector hook_mads); + VirtualMachinePool(SqlDB * db, vector hook_mads); ~VirtualMachinePool(){}; @@ -42,7 +42,7 @@ public: * @param stemplate a string describing the VM * @param oid the id assigned to the VM (output) * @param on_hold flag to submit on hold - * @return 0 on success, -1 error inserting in DB or -2 error parsing + * @return oid on success, -1 error inserting in DB or -2 error parsing * the template */ int allocate ( @@ -126,11 +126,11 @@ public: /** * Bootstraps the database table(s) associated to the VirtualMachine pool */ - static void bootstrap(SqliteDB * _db) + static void bootstrap(SqlDB * _db) { VirtualMachine::bootstrap(_db); }; - + /** * Dumps the VM pool in XML format. A filter can be also added to the query * Also the hostname where the VirtualMachine is running is added to the @@ -140,19 +140,8 @@ public: * * @return 0 on success */ - int dump(ostringstream& oss, const string& where) - { - int rc; + int dump(ostringstream& oss, const string& where); - oss << ""; - - rc = VirtualMachine::dump(db,oss,where); - - oss << ""; - - return rc; - } - private: /** * Generate context file to be sourced upon VM booting @@ -169,6 +158,16 @@ private: { return new VirtualMachine; }; + + /** + * Callback function to get output the vm pool in XML format + * (VirtualMachinePool::dump) + * @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 dump_cb(void * _oss, int num, char **values, char **names); }; #endif /*VIRTUAL_MACHINE_POOL_H_*/ diff --git a/include/VirtualNetwork.h b/include/VirtualNetwork.h index 3317f20b00..a057906a0a 100644 --- a/include/VirtualNetwork.h +++ b/include/VirtualNetwork.h @@ -31,10 +31,6 @@ using namespace std; -extern "C" int vn_select_cb (void * _vn, int num,char ** values, char ** names); - -extern "C" int vn_dump_cb (void * _oss, int num, char ** values, char ** names); - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -61,7 +57,6 @@ public: // ************************************************************************* // Virtual Network Public Methods // ************************************************************************* - /** * Gets the uid of the owner of the Virtual Network @@ -128,7 +123,7 @@ public: * Function to print the VirtualNetwork object into a string in * plain text * @param str the resulting string - * @return a reference to the generated string + * @return a reference to the generated string */ string& to_str(string& str) const; @@ -136,10 +131,10 @@ public: * Function to print the VirtualNetwork object into a string in * XML format * @param xml the resulting XML string - * @return a reference to the generated string + * @return a reference to the generated string */ string& to_xml(string& xml) const; - + private: // ------------------------------------------------------------------------- @@ -147,18 +142,6 @@ private: // ------------------------------------------------------------------------- friend class VirtualNetworkPool; - friend int vn_select_cb ( - void * _vm, - int num, - char ** values, - char ** names); - - friend int vn_dump_cb ( - void * _oss, - int num, - char ** values, - char ** names); - // ************************************************************************* // Virtual Network Private Attributes // ************************************************************************* @@ -169,12 +152,12 @@ private: /** * Name of the Virtual Network */ - string name; + string name; /** * Owner of the Virtual Network */ - int uid; + int uid; // ------------------------------------------------------------------------- // Binded physical attributes @@ -183,7 +166,7 @@ private: /** * Name of the bridge this VNW binds to */ - string bridge; + string bridge; // ------------------------------------------------------------------------- // Virtual Network Description @@ -191,13 +174,13 @@ private: /** * Holds the type of this network */ - NetworkType type; + NetworkType type; /** * Pointer to leases class, can be fixed or ranged. * Holds information on given (and, optionally, possible) leases */ - Leases * leases; + Leases * leases; /** * The Virtual Network template, holds the VNW attributes. @@ -211,55 +194,53 @@ private: /** * MAC prefix for this OpenNebula site */ - unsigned int mac_prefix; + unsigned int mac_prefix; /** * Default size for virtual networks */ - int default_size; + int default_size; // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* + /** + * Execute an INSERT or REPLACE Sql query. + * @param db The SQL DB + * @param replace Execute an INSERT or a REPLACE + * @return 0 on success + */ + int insert_replace(SqlDB *db, bool replace); + /** * Bootstraps the database table(s) associated to the Virtual Network */ - static void bootstrap(SqliteDB * db) + static void bootstrap(SqlDB * db) { - db->exec(VirtualNetwork::db_bootstrap); + ostringstream oss_vnet(VirtualNetwork::db_bootstrap); + ostringstream oss_templ(VirtualNetworkTemplate::db_bootstrap); + ostringstream oss_lease(Leases::db_bootstrap); - db->exec(VirtualNetworkTemplate::db_bootstrap); - - db->exec(Leases::db_bootstrap); + db->exec(oss_vnet); + db->exec(oss_templ); + db->exec(oss_lease); }; /** - * Function to unmarshall a VNW object, and associated classes. + * Callback function to unmarshall a VNW object (VirtualNetwork::select) * @param num the number of columns read from the DB - * @para names the column names - * @para vaues the column values + * @param names the column names + * @param vaues the column values * @return 0 on success */ - int unmarshall(int num, char **names, char ** values); + int select_cb(void * nil, int num, char **values, char **names); - /** - * Function to unmarshall a VNW object into an stream in XML format. - * @param oss the output stream - * @param num the number of columns read from the DB - * @para names the column names - * @para vaues the column values - * @return 0 on success - */ - static int unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values); /** * Function to drop VN entry in vn_pool * @return 0 on success */ - int vn_drop(SqliteDB * db); + int vn_drop(SqlDB * db); // ------------------------------------------------------------------------ // Template @@ -321,15 +302,15 @@ private: /** * Updates the template of a VNW, adding a new attribute (replacing it if * already defined), the VN's mutex SHOULD be locked - * @param vm pointer to the virtual network object + * @param db pointer to the DB * @param name of the new attribute * @param value of the new attribute * @return 0 on success */ int update_template_attribute( - SqliteDB * db, - string& name, - string& value) + SqlDB * db, + string& name, + string& value) { SingleAttribute * sattr; int rc; @@ -380,21 +361,21 @@ protected: * @param db pointer to the db * @return 0 on success */ - int select(SqliteDB * db); + int select(SqlDB * db); /** * Writes the Virtual Network and its associated template and leases in the database. * @param db pointer to the db * @return 0 on success */ - int insert(SqliteDB * db); + int insert(SqlDB * db); /** * Writes/updates the Virtual Network data fields in the database. * @param db pointer to the db * @return 0 on success */ - int update(SqliteDB * db); + int update(SqlDB * db); /** * Deletes a VNW from the database and all its associated information: @@ -403,28 +384,29 @@ protected: * @param db pointer to the db * @return 0 on success */ - int drop(SqliteDB * db) + int drop(SqlDB * db) { - int rc; + int rc; - rc = vn_template.drop(db); + rc = vn_template.drop(db); rc += leases->drop(db); rc += vn_drop(db); - return rc; + return rc; } /** - * Dumps the contect of a set of Host objects in the given stream - * using XML format - * @param db pointer to the db + * Dumps the contect of a VirtualNetwork object in the given stream using + * XML format * @param oss the output stream - * @param where string to filter the VirtualMachine objects + * @param num the number of columns read from the DB + * @param names the column names + * @param vaues the column values * @return 0 on success */ - static int dump(SqliteDB * db, ostringstream& oss, const string& where); + static int dump(ostringstream& oss, int num, char **values, char **names); }; #endif /*VIRTUAL_NETWORK_H_*/ diff --git a/include/VirtualNetworkPool.h b/include/VirtualNetworkPool.h index 433d87b33a..4e2c0bee3c 100644 --- a/include/VirtualNetworkPool.h +++ b/include/VirtualNetworkPool.h @@ -32,9 +32,9 @@ class VirtualNetworkPool : public PoolSQL { public: - VirtualNetworkPool(SqliteDB * db, - const string& str_mac_prefix, - int default_size); + VirtualNetworkPool(SqlDB * db, + const string& str_mac_prefix, + int default_size); ~VirtualNetworkPool(){}; @@ -43,7 +43,7 @@ public: * @param uid user identifier * @param stemplate a string describing the VN * @param oid the id assigned to the VM (output) - * @return 0 on success, -1 error inserting in DB,-2 error parsing + * @return oid on success, -1 error inserting in DB,-2 error parsing * the template, -3 wrong attributes in template */ int allocate ( @@ -64,7 +64,7 @@ public: { return static_cast(PoolSQL::get(oid,lock)); }; - + /** * Function to get a VN from the pool using the network name * If the object is not in memory it is loaded from the DB @@ -74,14 +74,14 @@ public: */ VirtualNetwork * get( const string& name, - bool lock); + bool lock); //-------------------------------------------------------------------------- // Virtual Network DB access functions //-------------------------------------------------------------------------- - + /** - * Updates the template of a VN, adding a new attribute (replacing it if + * Updates the template of a VN, adding a new attribute (replacing it if * already defined), the VN's mutex SHOULD be locked * @param vn pointer to the virtual network object * @param name of the new attribute @@ -89,61 +89,42 @@ public: * @return 0 on success */ int update_template_attribute( - VirtualNetwork * vn, - string& name, - string& value) + VirtualNetwork * vn, + string& name, + string& value) { - return vn->update_template_attribute(db,name,value); + return vn->update_template_attribute(db,name,value); }; /** * Bootstraps the database table(s) associated to the VirtualNetwork pool */ - static void bootstrap(SqliteDB * _db) + static void bootstrap(SqlDB * _db) { VirtualNetwork::bootstrap(_db); }; - - /** Drops a VN from the cache & DB, the VN mutex MUST BE locked - * @param vn pointer to VN - */ - int drop(VirtualNetwork * vn) - { - return vn->drop(db); - }; - + /** - * Dumps the HOST pool in XML format. A filter can be also added to the - * query + * Dumps the Virtual Network pool in XML format. A filter can be also added + * to the query * @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(ostringstream& oss, const string& where) - { - int rc; - - oss << ""; - - rc = VirtualNetwork::dump(db,oss,where); - - oss << ""; - - return rc; - } + int dump(ostringstream& oss, const string& where); private: /** * Holds the system-wide MAC prefix */ unsigned int mac_prefix; - + /** * Default size for Virtual Networks */ - unsigned int default_size; - + unsigned int default_size; + /** * Factory method to produce VN objects * @return a pointer to the new VN @@ -152,7 +133,26 @@ private: { return new VirtualNetwork(mac_prefix, default_size); }; - + + /** + * Callback function to get output the virtual network pool in XML format + * (VirtualNetworkPool::dump) + * @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 dump_cb(void * _oss, int num, char **values, char **names); + + /** + * Callback function to get the ID of a given virtual network + * (VirtualNetworkPool::get) + * @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 get_cb(void * _oss, int num, char **values, char **names); }; - -#endif /*VIRTUAL_NETWORK_POOL_H_*/ + +#endif /*VIRTUAL_NETWORK_POOL_H_*/ \ No newline at end of file diff --git a/include/test/PoolTest.h b/include/test/PoolTest.h new file mode 100644 index 0000000000..40010e9dc8 --- /dev/null +++ b/include/test/PoolTest.h @@ -0,0 +1,376 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 POOL_TEST_H_ +#define POOL_TEST_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "SqlDB.h" +#include "SqliteDB.h" +#include "MySqlDB.h" +#include "PoolSQL.h" +#include "Nebula.h" + +// Use this macro in sub-classes to add all the tests defined here +#define ALL_POOLTEST_CPPUNIT_TESTS() \ + CPPUNIT_TEST (oid_assignment); \ + CPPUNIT_TEST (get_from_cache); \ + CPPUNIT_TEST (get_from_db); \ + CPPUNIT_TEST (wrong_get); \ + CPPUNIT_TEST (drop_and_get); \ + +using namespace std; + + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class PoolTest : public CppUnit::TestFixture +{ +private: +// Global flag to use either Sqlite or MySQL +static bool mysql; + + +protected: + + PoolSQL * pool; + SqlDB * db; + + PoolObjectSQL* obj; + + static string db_name; + + /* + * Bootstrap the DB with the neccessary tables for the test + */ + virtual void bootstrap(SqlDB* db) = 0; + + /* + * Create the appropiate pool + */ + virtual PoolSQL* create_pool(SqlDB* db) = 0; + + + /* + * Allocate the indexth sample pool object + */ + virtual int allocate(int index) = 0; + + /* + * Check if the indexth sample object is equal to this one + */ + virtual void check(int index, PoolObjectSQL* obj) = 0; + + PoolTest():pool(0),db(0){}; + virtual ~PoolTest(){}; + +public: + + void setUp() + { + if (mysql) + { + db = new MySqlDB("localhost","oneadmin","onepass",NULL); + + ostringstream oss1; + oss1 << "DROP DATABASE IF EXISTS " << db_name; + db->exec(oss1); + + ostringstream oss; + oss << "CREATE DATABASE " << db_name; + db->exec(oss); + + ostringstream oss2; + oss2 << "use " << db_name; + db->exec(oss2); + } + else + { + unlink(db_name.c_str()); + + db = new SqliteDB(db_name); + } + + bootstrap(db); + + pool = create_pool(db); + }; + + void tearDown() + { + + if (mysql) + { + ostringstream oss; + oss << "DROP DATABASE IF EXISTS " << db_name; + db->exec(oss); + } + else + { + unlink(db_name.c_str()); + } + + if ( pool != 0 ) + { + delete pool; + } + + if ( db != 0 ) + { + delete db; + } + }; + +// ***************************************************************************** + + void oid_assignment() + { + int oid; + + oid = allocate(0); + // first element in the pool should have oid=0 + CPPUNIT_ASSERT(oid == 0); + + oid = allocate(1); + // second element in the pool should have oid=1 + CPPUNIT_ASSERT(oid == 1); + } + + // Try to allocate two objects, and retrieve them + void get_from_cache() + { + int oid_0, oid_1; + + // Allocate two objects + oid_0 = allocate(0); + oid_1 = allocate(1); + + CPPUNIT_ASSERT(oid_0 != -1); + CPPUNIT_ASSERT(oid_1 != -1); + + // --------------------------------- + + // Get first object and check its integrity + obj = pool->get(oid_0, false); + check(0, obj); + + // Same for the second, but ask it to be locked + obj = pool->get(oid_1, true); + if(obj != 0) + { + obj->unlock(); + } + + check(1, obj); + }; + + // Try to allocate two objects, and retrieve them + void get_from_db() + { + int oid_0, oid_1; + + // Allocate two objects + oid_0 = allocate(0); + oid_1 = allocate(1); + + CPPUNIT_ASSERT(oid_0 != -1); + CPPUNIT_ASSERT(oid_1 != -1); + + // Clean the cache, forcing the pool to read the objects from the DB + pool->clean(); + + // --------------------------------- + // Get first object and check its integrity + obj = pool->get(oid_0, false); + check(0, obj); + + // Same for the second one, but ask it to be locked + obj = pool->get(oid_1, true); + if(obj != 0) + { + obj->unlock(); + } + check(1, obj); + + }; + + void wrong_get() + { + // The pool is empty + // Non existing oid + obj = pool->get(13, true); + CPPUNIT_ASSERT( obj == 0 ); + + // Allocate an object + allocate(0); + + // Ask again for a non-existing oid + obj = pool->get(213, true); + CPPUNIT_ASSERT( obj == 0 ); + } + + void drop_and_get() + { + int oid_0, oid_1; + + // Allocate two objects + oid_0 = allocate(0); + oid_1 = allocate(1); + + CPPUNIT_ASSERT(oid_0 != -1); + CPPUNIT_ASSERT(oid_1 != -1); + + // Get the first object + obj = pool->get(oid_0, true); + + if(obj != 0) + { + obj->unlock(); + } + + CPPUNIT_ASSERT(obj != 0); + + obj->lock(); + + // Delete it + pool->drop(obj); + + if(obj != 0) + { + obj->unlock(); + } + + // It should be gone now + obj = pool->get(oid_0, false); + CPPUNIT_ASSERT(obj == 0); + + // The cache is cleaned, the object should be also gone from the DB + pool->clean(); + obj = pool->get(oid_0, true); + CPPUNIT_ASSERT(obj == 0); + + // But the other object must be accessible + obj = pool->get(oid_1, false); + check(1, obj); + }; + + +// ***************************************************************************** + + + static void show_options () + { + cout << "Options:\n"; + cout << " -h --help Show this help\n" + " -s --sqlite Run Sqlite tests (default)\n" + " -m --mysql Run MySQL tests\n" + " -l --log Keep the log file, test.log\n"; + } + + + /* + * Not a true main, but a static method that can be called from the + * child classes' true main. + * Options: + * s: run sqlite tests + * m: run mysql tests + */ + static int main(int argc, char ** argv, CPPUNIT_NS::TestSuite* suite) + { + + // Option flags + bool sqlite_flag = true; + bool log_flag = false; + + // Long options + const struct option long_opt[] = + { + { "sqlite", 0, NULL, 's'}, + { "mysql", 0, NULL, 'm'}, + { "log", 0, NULL, 'l'}, + { "help", 0, NULL, 'h'} + }; + + int c; + while ((c = getopt_long (argc, argv, "smlh", long_opt, NULL)) != -1) + switch (c) + { + case 'm': + sqlite_flag = false; + break; + case 'l': + log_flag = true; + break; + case 'h': + show_options(); + return 0; + } + + + // When a DB query fails, it tries to log the error. + // We need to set the log file, otherwise it will end in a dead-lock + NebulaLog::init_log_system(NebulaLog::FILE, Log::DEBUG, "test.log"); + NebulaLog::log("Test", Log::INFO, "Test started"); + + CppUnit::TextUi::TestRunner runner; + runner.addTest( suite ); + + if (sqlite_flag) + { + PoolTest::mysql = false; + NebulaLog::log("Test", Log::INFO, "Running Sqlite tests..."); + cout << "\nRunning Sqlite tests...\n"; + } + else + { + PoolTest::mysql = true; + NebulaLog::log("Test", Log::INFO, "Running MySQL tests..."); + cout << "\nRunning MySQL tests...\n"; + } + + runner.run(); + + if (!log_flag) + remove("test.log"); + + NebulaLog::finalize_log_system(); + + return 0; + } +}; + +// ----------------------------------------------------------------------------- + +bool PoolTest::mysql; + +string PoolTest::db_name = "ONE_test_database"; + +// ----------------------------------------------------------------------------- + +#endif // POOL_TEST_H_ diff --git a/install.sh b/install.sh index 40218d6af9..4b1ad07b31 100755 --- a/install.sh +++ b/install.sh @@ -250,11 +250,11 @@ INSTALL_ETC_FILES[17]="OCCI_ETC_TEMPLATE_FILES:$ETC_LOCATION/occi_templates" #------------------------------------------------------------------------------- BIN_FILES="src/nebula/oned \ - src/scheduler/mm_sched \ - src/client/ruby/onevm \ - src/client/ruby/onehost \ - src/client/ruby/onevnet \ - src/client/ruby/oneuser \ + src/scheduler/src/sched/mm_sched \ + src/cli/onevm \ + src/cli/onehost \ + src/cli/onevnet \ + src/cli/oneuser \ share/scripts/one" #------------------------------------------------------------------------------- @@ -263,9 +263,8 @@ BIN_FILES="src/nebula/oned \ # Library files, to be installed under $LIB_LOCATION #------------------------------------------------------------------------------- -INCLUDE_FILES="include/OneClient.h" -LIB_FILES="src/client/liboneapi.a \ - src/client/liboneapi.so" +INCLUDE_FILES="" +LIB_FILES="" #------------------------------------------------------------------------------- # Ruby library files, to be installed under $LIB_LOCATION/ruby @@ -278,8 +277,8 @@ RUBY_LIB_FILES="src/mad/ruby/one_mad.rb \ src/mad/ruby/CommandManager.rb \ src/mad/ruby/OpenNebulaDriver.rb \ src/mad/ruby/VirtualMachineDriver.rb \ - src/client/ruby/client_utilities.rb \ - src/client/ruby/command_parse.rb \ + src/cli/client_utilities.rb \ + src/cli/command_parse.rb \ src/oca/ruby/OpenNebula.rb \ src/tm_mad/TMScript.rb" diff --git a/share/etc/oned.conf b/share/etc/oned.conf index 9fc39c6e41..43f81be607 100644 --- a/share/etc/oned.conf +++ b/share/etc/oned.conf @@ -15,6 +15,13 @@ # # PORT: Port where oned will listen for xmlrpc calls. # +# DB: Configuration attributes for the database backend +# backend : can be sqlite or mysql (default is sqlite) +# server : (mysql) host name or an IP address for the MySQL server +# user : (mysql) user's MySQL login ID +# passwd : (mysql) the password for user +# db_name : (mysql) the database name +# # DEBUG_LEVEL: 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG #******************************************************************************* @@ -26,6 +33,15 @@ VM_POLLING_INTERVAL = 60 PORT=2633 +DB = [ backend = "sqlite" ] + +# Sample configuration for MySQL +# DB = [ backend = "mysql", +# server = "localhost", +# user = "oneadmin", +# passwd = "oneadmin", +# db_name = "opennebula" ] + DEBUG_LEVEL=3 #******************************************************************************* diff --git a/share/test/do_tests.sh b/share/test/do_tests.sh new file mode 100755 index 0000000000..5bfedf7b97 --- /dev/null +++ b/share/test/do_tests.sh @@ -0,0 +1,103 @@ +#!/bin/bash +#------------------------------------------------------------------------------- +# COMMAND LINE PARSING +#------------------------------------------------------------------------------- + + +#------------------------------------------------------------------------------- +# COMMAND LINE PARSING +#------------------------------------------------------------------------------- +usage() { + echo + echo "Usage: do_test.sh [-smvgclh]" + echo + echo "-m: use MyQSL backend (defaults to Sqlite)" + echo "-v: run tests using valgrind (memcheck) output will be memgrind.out" + echo "-g: run tests using valgrind (callgrind) output will be callgrind.out" + echo "-l: keep logs" + echo "-c: clear everything" + echo "-b: just build the tests and do not run them" + echo + echo "-h: prints this help" +} +#------------------------------------------------------------------------------- + +TEMP_OPT=`getopt -o mvgclbh -n 'install.sh' -- "$@"` + +if [ $? != 0 ] ; then + usage + exit 1 +fi + +eval set -- "$TEMP_OPT" + +MYSQL="no" +VAL_MEM="no" +VAL_CALL="no" +LOGS="no" +CLEAR="no" +BUILD="no" + +TWD_DIR="../../src" +BASE_DIR=$PWD + +while true ; do + case "$1" in + -h) usage; exit 0;; + -m) MYSQL="yes" ; shift ;; + -v) VAL_MEM="yes" ; shift ;; + -g) VAL_CALL="yes"; shift ;; + -l) LOGS="yes" ; shift ;; + -c) CLEAR="yes" ; shift ;; + -b) BUILD="yes" ; shift ;; + --) shift ; break ;; + *) usage; exit 1 ;; + esac +done + + +#------------------------------------------------------------------------------- +# SETUP ARGUMENTS +#------------------------------------------------------------------------------- + +if [ "$MYSQL" = "yes" ] ; then + TEST_ARGS="-m" +else + TEST_ARGS="-s" +fi + +if [ "$LOGS" = "yes" ] ; then + TEST_ARGS="$TEST_ARGS -l" +fi + +CALLER="" + +if [ "$VAL_MEM" = "yes" ] ; then + CALLER="valgrind --show-reachable=yes --leak-check=full" +elif [ "$VAL_CALL" = "yes" ] ; then + CALLER="valgrind --tool=callgrind" +fi + +TESTS=`find $TWD_DIR -name test -type d` + +for i in $TESTS ; do + cd $BASE_DIR + + echo "Doing $i ..." + cd $i + + if [ "$CLEAR" = "yes" ] ; then + scons -c + rm -f callgrind.out* test.db* test.log* memgrid.out* + elif [ "$BUILD" = "yes" ] ; then + scons + else + for j in `ls test*` ; do + $CALLER ./$j $TEST_ARGS + done + fi +done + +cd $BASE_DIR + +exit 0 diff --git a/src/client/ruby/client_utilities.rb b/src/cli/client_utilities.rb similarity index 100% rename from src/client/ruby/client_utilities.rb rename to src/cli/client_utilities.rb diff --git a/src/client/ruby/command_parse.rb b/src/cli/command_parse.rb similarity index 100% rename from src/client/ruby/command_parse.rb rename to src/cli/command_parse.rb diff --git a/src/client/ruby/onehost b/src/cli/onehost similarity index 100% rename from src/client/ruby/onehost rename to src/cli/onehost diff --git a/src/client/ruby/oneuser b/src/cli/oneuser similarity index 100% rename from src/client/ruby/oneuser rename to src/cli/oneuser diff --git a/src/client/ruby/onevm b/src/cli/onevm similarity index 100% rename from src/client/ruby/onevm rename to src/cli/onevm diff --git a/src/client/ruby/onevnet b/src/cli/onevnet similarity index 100% rename from src/client/ruby/onevnet rename to src/cli/onevnet diff --git a/src/client/OneClient.cc b/src/client/OneClient.cc deleted file mode 100644 index 91097d0047..0000000000 --- a/src/client/OneClient.cc +++ /dev/null @@ -1,487 +0,0 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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 "OneClient.h" -#include -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int OneClient::allocate(string template_file, int& vmid, string& error) -{ - - try{ - - string str_template=""; - ifstream file; - char c; - - file.open(template_file.c_str()); - - if ( file.good() == false ) - { - error = "Could not open file\n"; - return -1; - } - - file.get(c); - - while (file.good()) - { - str_template+=c; - file.get(c); - } - - file.close(); - - xmlrpc_c::value result; - - this->call(url, - "one.vmallocate", - "ss", - &result, - session.c_str(), - str_template.c_str()); - - xmlrpc_c::value_array resultArray = xmlrpc_c::value_array(result); - vector const - paramArrayValue(resultArray.vectorValueValue()); - - //check posible errors - xmlrpc_c::value_boolean const status(paramArrayValue[0]); - - if(static_cast(status) == true) - { - xmlrpc_c::value_int const _vmid (paramArrayValue[1]); - - vmid = static_cast(_vmid); - return 0; - } - else - { - xmlrpc_c::value_string const valueS(paramArrayValue[1]); - - error=static_cast(valueS); - return -1; - } - } - catch (std::exception const &e) - { - ostringstream oss; - oss << "XML-RPC Error: " << e.what() << endl; - - error=oss.str(); - return -1; - } -}; - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int OneClient::allocate_template(const string& str_template, - int& vmid, - string& error) -{ - try{ - xmlrpc_c::value result; - - this->call(url, - "one.vmallocate", - "ss", - &result, - session.c_str(), - str_template.c_str()); - - xmlrpc_c::value_array resultArray = xmlrpc_c::value_array(result); - vector const - paramArrayValue(resultArray.vectorValueValue()); - - //check posible errors - xmlrpc_c::value_boolean const status(paramArrayValue[0]); - - if(static_cast(status) == true) - { - xmlrpc_c::value_int const _vmid (paramArrayValue[1]); - - vmid = static_cast(_vmid); - return 0; - } - else - { - xmlrpc_c::value_string const valueS(paramArrayValue[1]); - - error=static_cast(valueS); - return -1; - } - } - catch (std::exception const &e) - { - ostringstream oss; - oss << "XML-RPC Error: " << e.what() << endl; - - error=oss.str(); - return -1; - } -}; - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int OneClient::deploy(int vmid, int hid, string& error) -{ - try { - xmlrpc_c::value result; - - this->call(url,"one.vmdeploy","sii", &result,session.c_str(),vmid,hid); - - xmlrpc_c::value_array resultArray = xmlrpc_c::value_array(result); - - vector const - paramArrayValue(resultArray.vectorValueValue()); - - //check posible errors - xmlrpc_c::value_boolean const status(paramArrayValue[0]); - - if(static_cast(status) == true) - { - return 0; - } - else - { - xmlrpc_c::value_string const valueS(paramArrayValue[1]); - - error=static_cast(valueS); - return -1; - } - } - catch (std::exception const &e) - { - ostringstream oss; - oss << "XML-RPC Error: " << e.what() << endl; - - error=oss.str(); - return -1; - } -}; - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int OneClient::migrate(int vmid, int hid, bool live, string& error) -{ - try { - xmlrpc_c::value result; - - this->call(url, - "one.vmmigrate", - "siib", - &result, - session.c_str(), - vmid,hid,live); - - xmlrpc_c::value_array resultArray = xmlrpc_c::value_array(result); - vector const - paramArrayValue(resultArray.vectorValueValue()); - - //check posible errors - xmlrpc_c::value_boolean const status(paramArrayValue[0]); - - if(static_cast(status) == true) - { - return 0; - } - else - { - xmlrpc_c::value_string const valueS(paramArrayValue[1]); - - error=static_cast(valueS); - return -1; - } - } - catch (std::exception const &e) - { - ostringstream oss; - oss << "XML-RPC Error: " << e.what() << endl; - - error=oss.str(); - return -1; - } -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int OneClient::action(int vmid, const char * action, string& error) -{ - try { - xmlrpc_c::value result; - - this->call(url, - "one.vmaction", - "ssi", - &result, - session.c_str(), - action, - vmid); - - xmlrpc_c::value_array resultArray = xmlrpc_c::value_array(result); - vector const - paramArrayValue(resultArray.vectorValueValue()); - - //check posible errors - xmlrpc_c::value_boolean const status(paramArrayValue[0]); - - if(static_cast(status) == true) - { - return 0; - } - else - { - xmlrpc_c::value_string const valueS(paramArrayValue[1]); - - error=static_cast(valueS); - return -1; - } - } - catch (std::exception const &e) - { - ostringstream oss; - oss << "XML-RPC Error: " << e.what() << endl; - - error=oss.str(); - return -1; - } -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int OneClient::info(int vmid, string& info, string& error) -{ - try{ - xmlrpc_c::value result; - this->call(url,"one.vmget_info","si",&result,session.c_str(),vmid); - - xmlrpc_c::value_array resultArray = xmlrpc_c::value_array(result); - vector const - paramArrayValue(resultArray.vectorValueValue()); - - //check posible errors - xmlrpc_c::value_boolean const status(paramArrayValue[0]); - - xmlrpc_c::value_string const valueS(paramArrayValue[1]); - - if(static_cast(status) == true) - { - info = static_cast(valueS); - return 0; - } - else - { - error = static_cast(valueS); - return -1; - } - } - catch (std::exception const &e) - { - ostringstream oss; - oss << "XML-RPC Error: " << e.what() << endl; - - error=oss.str(); - return -1; - } -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int OneClient::host_info(int hid, string& info, string& error) -{ - try{ - xmlrpc_c::value result; - this->call(url,"one.hostinfo","si",&result,session.c_str(),hid); - - xmlrpc_c::value_array resultArray = xmlrpc_c::value_array(result); - vector const - paramArrayValue(resultArray.vectorValueValue()); - - //check posible Errors: - xmlrpc_c::value_boolean const status(paramArrayValue[0]); - - xmlrpc_c::value_string const valueS (paramArrayValue[1]); - - if(static_cast(status) == true) - { - info = static_cast(valueS); - return 0; - } - else - { - error = static_cast(valueS); - return -1; - } - } - catch (std::exception const &e) - { - ostringstream oss; - oss << "XML-RPC Error: " << e.what() << endl; - - error=oss.str(); - return -1; - } -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int OneClient::host_delete(int hid, string& error) -{ - try { - xmlrpc_c::value result; - this->call(url, "one.hostdelete", "si", &result,session.c_str(), hid); - - xmlrpc_c::value_array resultArray = xmlrpc_c::value_array(result); - vector const - paramArrayValue(resultArray.vectorValueValue()); - - //check posible errors - xmlrpc_c::value_boolean const status(paramArrayValue[0]); - - if(static_cast(status) == true) - { - return 0; - } - else - { - xmlrpc_c::value_string const valueS(paramArrayValue[1]); - - error=static_cast(valueS); - return -1; - } - } - catch (std::exception const &e) - { - ostringstream oss; - oss << "XML-RPC Error: " << e.what() << endl; - - error=oss.str(); - return -1; - } -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int OneClient::host_available(int hid, bool enable, string& error) -{ - - try{ - xmlrpc_c::value result; - this->call(url, - "one.hostenable", - "sib", - &result, - session.c_str(), - hid, - enable); - - xmlrpc_c::value_array resultArray = xmlrpc_c::value_array(result); - vector const - paramArrayValue(resultArray.vectorValueValue()); - - //check posible errors - xmlrpc_c::value_boolean const status(paramArrayValue[0]); - - if(static_cast(status) == true) - { - return 0; - } - else - { - xmlrpc_c::value_string const valueS(paramArrayValue[1]); - - error=static_cast(valueS); - return -1; - } - } - catch (std::exception const &e) - { - ostringstream oss; - oss << "XML-RPC Error: " << e.what() << endl; - - error=oss.str(); - return -1; - } -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int OneClient::host_allocate(string& name, - string& im_mad, - string& vmm_mad, - int& hid, - string& error) -{ - - try{ - xmlrpc_c::value result; - this->call(url, - "one.hostallocate", - "sssssb", - &result, - session.c_str(), - name.c_str(), - im_mad.c_str(), - vmm_mad.c_str(), - "tm_mad", - true); - - xmlrpc_c::value_array resultArray = xmlrpc_c::value_array(result); - vector const - paramArrayValue(resultArray.vectorValueValue()); - - //check posible errors: - xmlrpc_c::value_boolean const status(paramArrayValue[0]); - - if (static_cast(status) == true) - { - xmlrpc_c::value_int const valueI (paramArrayValue[1]); - - hid = static_cast(valueI); - return 0; - - } - else - { - xmlrpc_c::value_string const valueS = (paramArrayValue[1]); - - error=static_cast(valueS); - return -1; - } - } - catch (std::exception const &e) - { - ostringstream oss; - oss << "XML-RPC Error: " << e.what() << endl; - - error=oss.str(); - return -1; - } -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - diff --git a/src/client/OneClient_C_Wrapper.cc b/src/client/OneClient_C_Wrapper.cc deleted file mode 100644 index a8acc4a04a..0000000000 --- a/src/client/OneClient_C_Wrapper.cc +++ /dev/null @@ -1,263 +0,0 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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 "OneClient.h" -#include -#include -using namespace std; - -/* ************************************************************************** */ -#define ONED_PORT 60222 -OneClient* client=0; -/* ************************************************************************** */ - - -void c_oneStart() -{ -#ifdef ONED_PORT - client=new OneClient("localhost",ONED_PORT); -#else - client=new OneClient("localhost"); -#endif -}; - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -void c_oneFree() -{ - if(client) - delete client; -}; - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int c_oneDeploy(int vmid, int hid) -{ - string info; - - if(!client) - return -1; - - if(client->deploy(vmid,hid,info) <0) - { - cerr<migrate(vmid,hid,(bool)flag,info) <0) - { - cerr<allocate(template_file,vmid, info)) <0) - { - cerr<allocate_template(template_str,vmid, info)) <0) - { - cerr<shutdown(vmid,info) <0) - { - cerr<suspend(vmid,info) <0) - { - cerr<stop(vmid,info) <0) - { - cerr<resume(vmid,info) <0) - { - cerr<cancel(vmid,info) <0) - { - cerr<finalize(vmid,info) <0) - { - cerr<info(vmid,info,error) <0) - { - cerr<first << ">" << it->second - << "first << ">"; + oss << "<" << it->first << ">second + << "]]>first << ">"; } oss << ""; diff --git a/src/common/test/SConstruct b/src/common/test/SConstruct new file mode 100644 index 0000000000..fc5564ef47 --- /dev/null +++ b/src/common/test/SConstruct @@ -0,0 +1,64 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad # +# Complutense de Madrid (dsa-research.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +import os +import sys +import shutil +sys.path.append("../../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located +cwd="../../../" + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) + +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include', + '/usr/include/cppunit/' +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd + '/src/common', +]) + +main_env.Append(LIBS=[ + 'nebula_common', + 'cppunit', + 'dl', + 'pthread' +]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# Linking flags +main_env.Append(LDFLAGS=["-g"]) + +main_env.Program('test_sa','single_attribute.cc') +main_env.Program('test_va','vector_attribute.cc') +main_env.Program('test_am','action_manager.cc') diff --git a/src/common/test/action_manager.cc b/src/common/test/action_manager.cc new file mode 100644 index 0000000000..134c30e899 --- /dev/null +++ b/src/common/test/action_manager.cc @@ -0,0 +1,183 @@ +#include "ActionManager.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; + +extern "C" void * addsub_loop(void *arg); + +class AddSub : public ActionListener +{ +public: + AddSub(int i):am(),counter(i) + { + am.addListener(this); + }; + + ~AddSub(){}; + + void add(int i) + { + int * p; + + p = new int(i); + + am.trigger("ADD",(void *) p); + } + + void sub(int i) + { + int * p; + + p = new int(i); + + am.trigger("SUB",(void *) p); + } + + int value() + { + return counter; + } + + pthread_t id() + { + return pid; + } + + void start() + { + pthread_attr_t pattr; + + pthread_attr_init (&pattr); + pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); + + pthread_create(&pid,&pattr,addsub_loop,(void *) this); + } + + void end() + { + am.trigger(ActionListener::ACTION_FINALIZE,0); + } + +private: + ActionManager am; + + int counter; + pthread_t pid; + + friend void * addsub_loop(void *arg); + + void do_action(const string &action, void * arg) + { + int * i = static_cast(arg); + + if ( i == 0 ) + { + return; + } + else if ( action == "ADD" ) + { + counter = counter + *i; + } + else if ( action == "SUB" ) + { + counter = counter - *i; + } + + delete i; + } +}; + +extern "C" void * addsub_loop(void *arg) +{ + AddSub *as; + + as = static_cast(arg); + + as->am.loop(0,0); + + return 0; +}; + +class ActionManagerTest : public CppUnit::TestFixture +{ +private: + AddSub *as; + +public: + void setUp() + { + as = new AddSub(10); + as->start(); + } + + void tearDown() + { + delete as; + } + + void test_add() + { + as->add(23); + as->add(5); + + sleep(1); + + CPPUNIT_ASSERT(as->value() == 38); + + as->end(); + + pthread_join(as->id(),0); + + CPPUNIT_ASSERT(as->value() == 38); + } + + void test_sub() + { + as->sub(3); + as->sub(15); + + sleep(1); + + CPPUNIT_ASSERT(as->value() == -8); + + as->end(); + + pthread_join(as->id(),0); + + CPPUNIT_ASSERT(as->value() == -8); + } + + static CppUnit::TestSuite * suite() + { + CppUnit::TestSuite *ts=new CppUnit::TestSuite("ActionManager Tests"); + + ts->addTest(new CppUnit::TestCaller( + "add() Test", + &ActionManagerTest::test_add)); + + ts->addTest(new CppUnit::TestCaller( + "sub() Test", + &ActionManagerTest::test_sub)); + return ts; + } +}; + +int main(int argc, char ** argv) +{ + + CppUnit::TextUi::TestRunner tr; + + tr.addTest(ActionManagerTest::suite()); + tr.run(); + + return 0; +} diff --git a/src/common/test/single_attribute.cc b/src/common/test/single_attribute.cc new file mode 100644 index 0000000000..cd9462e0d4 --- /dev/null +++ b/src/common/test/single_attribute.cc @@ -0,0 +1,131 @@ +#include "Attribute.h" + +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; + +class SingleAttributeTest : public CppUnit::TestFixture +{ +private: + SingleAttribute *a, *b; + +public: + void setUp() + { + string a_name = "single_a"; + + string b_name = "single_b"; + string b_value= "value_b"; + + a = new SingleAttribute(a_name); + b = new SingleAttribute(b_name, b_value); + } + + void tearDown() + { + delete a; + delete b; + } + + void test_type() + { + CPPUNIT_ASSERT(a->type() == Attribute::SIMPLE); + CPPUNIT_ASSERT(b->type() == Attribute::SIMPLE); + } + + void test_name() + { + CPPUNIT_ASSERT(a->name() == "SINGLE_A"); + CPPUNIT_ASSERT(b->name() == "SINGLE_B"); + } + + void test_value() + { + CPPUNIT_ASSERT(a->value().empty() == true); + CPPUNIT_ASSERT(b->value() == "value_b"); + } + + void test_marshall() + { + string *am, *bm; + + am = a->marshall(); + bm = b->marshall(); + + CPPUNIT_ASSERT(am->empty() == true); + CPPUNIT_ASSERT(*bm == "value_b"); + + delete am; + delete bm; + } + + void test_xml() + { + string *am, *bm; + + am = a->to_xml(); + bm = b->to_xml(); + + CPPUNIT_ASSERT(*am == ""); + CPPUNIT_ASSERT(*bm == ""); + + delete am; + delete bm; + } + + void test_replace() + { + string nv = "new_value_b"; + + b->replace(nv); + + CPPUNIT_ASSERT(b->value() == "new_value_b"); + } + + static CppUnit::TestSuite * suite() + { + CppUnit::TestSuite *ts=new CppUnit::TestSuite("SingleAttribute Tests"); + + ts->addTest(new CppUnit::TestCaller( + "type() Test", + &SingleAttributeTest::test_type)); + + ts->addTest(new CppUnit::TestCaller( + "name() Test", + &SingleAttributeTest::test_name)); + + ts->addTest(new CppUnit::TestCaller( + "value() Test", + &SingleAttributeTest::test_value)); + + ts->addTest(new CppUnit::TestCaller( + "marshall() Test", + &SingleAttributeTest::test_marshall)); + + ts->addTest(new CppUnit::TestCaller( + "to_xml() Test", + &SingleAttributeTest::test_xml)); + + ts->addTest(new CppUnit::TestCaller( + "replace() Test", + &SingleAttributeTest::test_replace)); + return ts; + } +}; + +int main(int argc, char ** argv) +{ + CppUnit::TextUi::TestRunner tr; + + tr.addTest(SingleAttributeTest::suite()); + tr.run(); + + return 0; +} diff --git a/src/common/test/vector_attribute.cc b/src/common/test/vector_attribute.cc new file mode 100644 index 0000000000..5c6b3d634d --- /dev/null +++ b/src/common/test/vector_attribute.cc @@ -0,0 +1,164 @@ +#include "Attribute.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; + +class VectorAttributeTest : public CppUnit::TestFixture +{ +private: + VectorAttribute *a, *b; + map b_value; + +public: + void setUp() + { + string a_name = "vector_a"; + string b_name = "vector_b"; + + b_value.insert(make_pair("attr1","val1")); + b_value.insert(make_pair("attr2","val2")); + b_value.insert(make_pair("attr3","val3")); + + a = new VectorAttribute(a_name); + b = new VectorAttribute(b_name, b_value); + } + + void tearDown() + { + delete a; + delete b; + } + + void test_type() + { + CPPUNIT_ASSERT(a->type() == Attribute::VECTOR); + CPPUNIT_ASSERT(b->type() == Attribute::VECTOR); + } + + void test_name() + { + CPPUNIT_ASSERT(a->name() == "VECTOR_A"); + CPPUNIT_ASSERT(b->name() == "VECTOR_B"); + } + + void test_value() + { + CPPUNIT_ASSERT(a->value().empty() == true); + CPPUNIT_ASSERT(b->value() == b_value); + + CPPUNIT_ASSERT(a->vector_value("NAME").empty() == true); + CPPUNIT_ASSERT(b->vector_value("NAME").empty() == true); + + CPPUNIT_ASSERT(b->vector_value("attr1") == "val1"); + CPPUNIT_ASSERT(b->vector_value("attr2") == "val2"); + CPPUNIT_ASSERT(b->vector_value("attr3") == "val3"); + } + + void test_marshall() + { + string *am, *bm; + + am = a->marshall(); + bm = b->marshall(); + + CPPUNIT_ASSERT(am == 0); + CPPUNIT_ASSERT(*bm == "attr1=val1@^_^@attr2=val2@^_^@attr3=val3"); + + VectorAttribute c("vector_c"); + c.unmarshall(*bm); + + CPPUNIT_ASSERT(c.vector_value("attr1") == "val1"); + CPPUNIT_ASSERT(c.vector_value("attr2") == "val2"); + CPPUNIT_ASSERT(c.vector_value("attr3") == "val3"); + + delete am; + delete bm; + } + + void test_xml() + { + string *am, *bm; + + am = a->to_xml(); + bm = b->to_xml(); + + CPPUNIT_ASSERT(*am == ""); + CPPUNIT_ASSERT(*bm == "" + "" + ""); + delete am; + delete bm; + } + + void test_replace() + { + map nm; + string nv = "new_val1"; + + b->replace("attr1",nv); + + CPPUNIT_ASSERT(b->vector_value("attr1") == "new_val1"); + + nm.insert(make_pair("other_attr1","other_val1")); + nm.insert(make_pair("other_attr2","other_val2")); + + b->replace(nm); + + CPPUNIT_ASSERT(b->vector_value("other_attr1") == "other_val1"); + CPPUNIT_ASSERT(b->vector_value("other_attr2") == "other_val2"); + CPPUNIT_ASSERT(b->vector_value("attr3").empty() == true); + CPPUNIT_ASSERT(b->value() == nm); + } + + static CppUnit::TestSuite * suite() + { + CppUnit::TestSuite *ts=new CppUnit::TestSuite("VectorAttribute Tests"); + + ts->addTest(new CppUnit::TestCaller( + "type() Test", + &VectorAttributeTest::test_type)); + + ts->addTest(new CppUnit::TestCaller( + "name() Test", + &VectorAttributeTest::test_name)); + + ts->addTest(new CppUnit::TestCaller( + "value() Test", + &VectorAttributeTest::test_value)); + + ts->addTest(new CppUnit::TestCaller( + "marshall() Test", + &VectorAttributeTest::test_marshall)); + + ts->addTest(new CppUnit::TestCaller( + "to_xml() Test", + &VectorAttributeTest::test_xml)); + + ts->addTest(new CppUnit::TestCaller( + "replace() Test", + &VectorAttributeTest::test_replace)); + + return ts; + } + +}; + +int main(int argc, char ** argv) +{ + + CppUnit::TextUi::TestRunner tr; + + tr.addTest(VectorAttributeTest::suite()); + tr.run(); + + return 0; +} diff --git a/src/dm/DispatchManager.cc b/src/dm/DispatchManager.cc index efd1eb47d5..ea8796bbb0 100644 --- a/src/dm/DispatchManager.cc +++ b/src/dm/DispatchManager.cc @@ -15,7 +15,8 @@ /* -------------------------------------------------------------------------- */ #include "DispatchManager.h" -#include "Nebula.h" +#include "NebulaLog.h" + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -27,15 +28,15 @@ extern "C" void * dm_action_loop(void *arg) { return 0; } - + dm = static_cast(arg); - Nebula::log("DiM",Log::INFO,"Dispatch Manager started."); - + NebulaLog::log("DiM",Log::INFO,"Dispatch Manager started."); + dm->am.loop(0,0); - Nebula::log("DiM",Log::INFO,"Dispatch Manager stopped."); - + NebulaLog::log("DiM",Log::INFO,"Dispatch Manager stopped."); + return 0; } @@ -49,7 +50,7 @@ int DispatchManager::start() pthread_attr_init (&pattr); pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); - Nebula::log("DiM",Log::INFO,"Starting Dispatch Manager..."); + NebulaLog::log("DiM",Log::INFO,"Starting Dispatch Manager..."); rc = pthread_create(&dm_thread,&pattr,dm_action_loop,(void *) this); @@ -83,14 +84,14 @@ void DispatchManager::trigger(Actions action, int _vid) case FAILED: aname = "FAILED"; break; - + case FINALIZE: aname = ACTION_FINALIZE; break; - + default: delete vid; - return; + return; } am.trigger(aname,vid); @@ -103,7 +104,7 @@ void DispatchManager::do_action(const string &action, void * arg) { int vid; ostringstream oss; - + if (arg == 0) { return; @@ -112,7 +113,7 @@ void DispatchManager::do_action(const string &action, void * arg) vid = *(static_cast(arg)); delete static_cast(arg); - + if (action == "SUSPEND_SUCCESS") { suspend_success_action(vid); @@ -128,16 +129,16 @@ void DispatchManager::do_action(const string &action, void * arg) else if (action == "FAILED") { failed_action(vid); - } + } else if (action == ACTION_FINALIZE) { - Nebula::log("DiM",Log::INFO,"Stopping Dispatch Manager..."); + NebulaLog::log("DiM",Log::INFO,"Stopping Dispatch Manager..."); } else { ostringstream oss; oss << "Unknown action name: " << action; - - Nebula::log("DiM", Log::ERROR, oss); + + NebulaLog::log("DiM", Log::ERROR, oss); } } diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 330cee2f87..1d24990b50 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -15,8 +15,9 @@ /* -------------------------------------------------------------------------- */ #include "DispatchManager.h" -#include "Nebula.h" +#include "NebulaLog.h" +#include "Nebula.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -25,7 +26,7 @@ int DispatchManager::allocate ( const string& stemplate, int * oid) { - Nebula::log("DiM",Log::DEBUG,"Allocating a new VM"); + NebulaLog::log("DiM",Log::DEBUG,"Allocating a new VM"); return vmpool->allocate(uid,stemplate,oid); }; @@ -47,7 +48,7 @@ int DispatchManager::deploy ( vid = vm->get_oid(); oss << "Deploying VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); if ( vm->get_state() == VirtualMachine::PENDING ) { @@ -75,7 +76,7 @@ error: oss.str(""); oss << "Could not deploy VM " << vid << ", wrong state."; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -1; @@ -98,7 +99,7 @@ int DispatchManager::migrate( vid = vm->get_oid(); oss << "Migrating VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) @@ -120,7 +121,7 @@ int DispatchManager::migrate( error: oss.str(""); oss << "Could not migrate VM " << vid << ", wrong state."; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -1; @@ -143,7 +144,7 @@ int DispatchManager::live_migrate( vid = vm->get_oid(); oss << "Live-migrating VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) @@ -165,7 +166,7 @@ int DispatchManager::live_migrate( error: oss.str(""); oss << "Could not live-migrate VM " << vid << ", wrong state."; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -1; @@ -188,7 +189,7 @@ int DispatchManager::shutdown ( } oss << "Shutting down VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) @@ -211,7 +212,7 @@ error: oss.str(""); oss << "Could not shutdown VM " << vid << ", wrong state."; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; @@ -234,7 +235,7 @@ int DispatchManager::hold( } oss << "Holding VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::PENDING) { @@ -257,7 +258,7 @@ error: oss.str(""); oss << "Could not hold VM " << vid << ", wrong state."; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; @@ -280,7 +281,7 @@ int DispatchManager::release( } oss << "Releasing VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::HOLD) { @@ -302,7 +303,7 @@ int DispatchManager::release( error: oss.str(""); oss << "Could not release VM " << vid << ", wrong state."; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; @@ -325,7 +326,7 @@ int DispatchManager::stop( } oss << "Stopping VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) @@ -347,7 +348,7 @@ int DispatchManager::stop( error: oss.str(""); oss << "Could not stop VM " << vid << ", wrong state."; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; @@ -370,7 +371,7 @@ int DispatchManager::cancel( } oss << "Cancelling VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) @@ -392,7 +393,7 @@ int DispatchManager::cancel( error: oss.str(""); oss << "Could not cancel VM " << vid << ", wrong state."; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; @@ -415,7 +416,7 @@ int DispatchManager::suspend( } oss << "Suspending VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) @@ -437,7 +438,7 @@ int DispatchManager::suspend( error: oss.str(""); oss << "Could not suspend VM " << vid << ", wrong state."; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; @@ -460,7 +461,7 @@ int DispatchManager::resume( } oss << "Resuming VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::STOPPED ) { @@ -495,7 +496,7 @@ int DispatchManager::resume( error: oss.str(""); oss << "Could not resume VM " << vid << ", wrong state."; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; @@ -517,9 +518,9 @@ int DispatchManager::restart(int vid) } oss << "Restarting VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); - if (vm->get_state() == VirtualMachine::ACTIVE && + if (vm->get_state() == VirtualMachine::ACTIVE && (vm->get_lcm_state() == VirtualMachine::UNKNOWN || vm->get_lcm_state() == VirtualMachine::BOOT)) { @@ -540,7 +541,7 @@ int DispatchManager::restart(int vid) error: oss.str(""); oss << "Could not restart VM " << vid << ", wrong state."; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); @@ -567,7 +568,7 @@ int DispatchManager::finalize( state = vm->get_state(); oss << "Finalizing VM " << vid; - Nebula::log("DiM",Log::DEBUG,oss); + NebulaLog::log("DiM",Log::DEBUG,oss); Nebula& nd = Nebula::instance(); TransferManager * tm = nd.get_tm(); diff --git a/src/dm/DispatchManagerStates.cc b/src/dm/DispatchManagerStates.cc index 658fdf5743..d1cb7c597e 100644 --- a/src/dm/DispatchManagerStates.cc +++ b/src/dm/DispatchManagerStates.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "DispatchManager.h" -#include "Nebula.h" +#include "NebulaLog.h" void DispatchManager::suspend_success_action(int vid) { @@ -44,7 +44,7 @@ void DispatchManager::suspend_success_action(int vid) oss << "suspend_success action received but VM " << vid << " not in ACTIVE state"; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); } vm->unlock(); @@ -82,7 +82,7 @@ void DispatchManager::stop_success_action(int vid) oss << "stop_success action received but VM " << vid << " not in ACTIVE state"; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); } vm->unlock(); @@ -123,7 +123,7 @@ void DispatchManager::done_action(int vid) ostringstream oss; oss << "done action received but VM " << vid << " not in ACTIVE state"; - Nebula::log("DiM",Log::ERROR,oss); + NebulaLog::log("DiM",Log::ERROR,oss); } vm->unlock(); diff --git a/src/hm/HookManager.cc b/src/hm/HookManager.cc index 5e87d224eb..3071249761 100644 --- a/src/hm/HookManager.cc +++ b/src/hm/HookManager.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "HookManager.h" -#include "Nebula.h" +#include "NebulaLog.h" const char * HookManager::hook_driver_name = "hook_exe"; @@ -31,13 +31,13 @@ extern "C" void * hm_action_loop(void *arg) return 0; } - Nebula::log("HKM",Log::INFO,"Hook Manager started."); + NebulaLog::log("HKM",Log::INFO,"Hook Manager started."); hm = static_cast(arg); hm->am.loop(0,0); - Nebula::log("HKM",Log::INFO,"Hook Manager stopped."); + NebulaLog::log("HKM",Log::INFO,"Hook Manager stopped."); return 0; } @@ -52,13 +52,13 @@ void HookManager::load_mads(int uid) const VectorAttribute * vattr; int rc; - Nebula::log("HKM",Log::INFO,"Loading Hook Manager driver."); + NebulaLog::log("HKM",Log::INFO,"Loading Hook Manager driver."); vattr = static_cast(mad_conf[0]); if ( vattr == 0 ) { - Nebula::log("HKM",Log::INFO,"Failed to load Hook Manager driver."); + NebulaLog::log("HKM",Log::INFO,"Failed to load Hook Manager driver."); return; } @@ -75,7 +75,7 @@ void HookManager::load_mads(int uid) oss.str(""); oss << "\tHook Manager loaded"; - Nebula::log("HKM",Log::INFO,oss); + NebulaLog::log("HKM",Log::INFO,oss); } } @@ -94,7 +94,7 @@ int HookManager::start() return -1; } - Nebula::log("HKM",Log::INFO,"Starting Hook Manager..."); + NebulaLog::log("HKM",Log::INFO,"Starting Hook Manager..."); pthread_attr_init (&pattr); pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); @@ -111,7 +111,7 @@ void HookManager::do_action(const string &action, void * arg) { if (action == ACTION_FINALIZE) { - Nebula::log("HKM",Log::INFO,"Stopping Hook Manager..."); + NebulaLog::log("HKM",Log::INFO,"Stopping Hook Manager..."); MadManager::stop(); } @@ -120,7 +120,7 @@ void HookManager::do_action(const string &action, void * arg) ostringstream oss; oss << "Unknown action name: " << action; - Nebula::log("HKM", Log::ERROR, oss); + NebulaLog::log("HKM", Log::ERROR, oss); } } diff --git a/src/hm/HookManagerDriver.cc b/src/hm/HookManagerDriver.cc index 454e9fa2c5..a52c4844aa 100644 --- a/src/hm/HookManagerDriver.cc +++ b/src/hm/HookManagerDriver.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "HookManagerDriver.h" -#include "Nebula.h" +#include "NebulaLog.h" #include /* ************************************************************************** */ @@ -92,7 +92,7 @@ void HookManagerDriver::protocol( // Parse the driver message os << "Message received: " << message; - Nebula::log("HKM", Log::DEBUG, os); + NebulaLog::log("HKM", Log::DEBUG, os); // Parse the driver message if ( is.good() ) @@ -125,7 +125,7 @@ void HookManagerDriver::protocol( is.clear(); getline(is,info); - Nebula::log("HKM",Log::INFO, info.c_str()); + NebulaLog::log("HKM",Log::INFO, info.c_str()); } return; @@ -190,6 +190,6 @@ void HookManagerDriver::protocol( void HookManagerDriver::recover() { - Nebula::log("HKM", Log::ERROR, "Hook driver crashed, recovering..."); + NebulaLog::log("HKM", Log::ERROR, "Hook driver crashed, recovering..."); + } - diff --git a/src/host/Host.cc b/src/host/Host.cc index a4bc25a75c..9309869286 100644 --- a/src/host/Host.cc +++ b/src/host/Host.cc @@ -1,18 +1,18 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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. */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* Copyright 2002-2010, 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 #include @@ -21,10 +21,11 @@ #include #include "Host.h" +#include "NebulaLog.h" -/* ************************************************************************** */ -/* Host :: Constructor/Destructor */ -/* ************************************************************************** */ +/* ************************************************************************ */ +/* Host :: Constructor/Destructor */ +/* ************************************************************************ */ Host::Host( int id, @@ -45,23 +46,24 @@ Host::Host( Host::~Host(){}; -/* ************************************************************************** */ -/* Host :: Database Access Functions */ -/* ************************************************************************** */ +/* ************************************************************************ */ +/* Host :: Database Access Functions */ +/* ************************************************************************ */ const char * Host::table = "host_pool"; const char * Host::db_names = "(oid,host_name,state,im_mad,vm_mad," "tm_mad,last_mon_time)"; -const char * Host::db_bootstrap = "CREATE TABLE host_pool (" - "oid INTEGER PRIMARY KEY,host_name TEXT,state INTEGER," - "im_mad TEXT,vm_mad TEXT,tm_mad TEXT,last_mon_time INTEGER)"; +const char * Host::db_bootstrap = "CREATE TABLE IF NOT EXISTS host_pool (" + "oid INTEGER PRIMARY KEY,host_name VARCHAR(512), state INTEGER," + "im_mad VARCHAR(128),vm_mad VARCHAR(128),tm_mad VARCHAR(128)," + "last_mon_time INTEGER, UNIQUE(host_name, im_mad, vm_mad, tm_mad) )"; -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int Host::unmarshall(int num, char **names, char ** values) +int Host::select_cb(void * nil, int num, char **values, char ** names) { if ((!values[OID]) || (!values[HOST_NAME]) || @@ -78,11 +80,11 @@ int Host::unmarshall(int num, char **names, char ** values) oid = atoi(values[OID]); hostname = values[HOST_NAME]; state = static_cast(atoi(values[STATE])); - + im_mad_name = values[IM_MAD]; vmm_mad_name = values[VM_MAD]; tm_mad_name = values[TM_MAD]; - + last_monitored = static_cast(atoi(values[LAST_MON_TIME])); host_template.id = oid; @@ -91,41 +93,22 @@ int Host::unmarshall(int num, char **names, char ** values) return 0; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ -extern "C" int host_select_cb ( - void * _host, - int num, - char ** values, - char ** names) -{ - Host * host; - - host = static_cast(_host); - - if (host == 0) - { - return -1; - } - - return host->unmarshall(num,names,values); -}; - -/* -------------------------------------------------------------------------- */ - -int Host::select(SqliteDB *db) +int Host::select(SqlDB *db) { ostringstream oss; int rc; int boid; - + + set_callback(static_cast(&Host::select_cb)); + oss << "SELECT * FROM " << table << " WHERE oid = " << oid; boid = oid; oid = -1; - rc = db->exec(oss, host_select_cb, (void *) this); + rc = db->exec(oss, this); if ((rc != 0) || (oid != boid )) { @@ -153,55 +136,66 @@ int Host::select(SqliteDB *db) return 0; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -int Host::insert(SqliteDB *db) +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int Host::insert(SqlDB *db) { int rc; map::iterator iter; // Set up the template ID, to insert it - if ( host_template.id == -1 ) { host_template.id = oid; } // Set up the share ID, to insert it - if ( host_share.hsid == -1 ) { - host_share.hsid = oid; + host_share.hsid = oid; } - - //Insert the Host and its template - rc = update(db); + + // Update the Template + rc = host_template.insert(db); if ( rc != 0 ) { return rc; } + // Update the HostShare + rc = host_share.insert(db); + + if ( rc != 0 ) + { + host_template.drop(db); + return rc; + } + + //Insert the Host + rc = insert_replace(db, false); + + if ( rc != 0 ) + { + host_template.drop(db); + host_share.drop(db); + + return rc; + } + return 0; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int Host::update(SqliteDB *db) +int Host::update(SqlDB *db) { - ostringstream oss; - int rc; - char * sql_hostname; - char * sql_im_mad_name; - char * sql_tm_mad_name; - char * sql_vmm_mad_name; - // Update the Template - rc = host_template.update(db); if ( rc != 0 ) @@ -210,7 +204,6 @@ int Host::update(SqliteDB *db) } // Update the HostShare - rc = host_share.update(db); if ( rc != 0 ) @@ -218,39 +211,74 @@ int Host::update(SqliteDB *db) return rc; } - // Update the Host - - sql_hostname = sqlite3_mprintf("%q",hostname.c_str()); + rc = insert_replace(db, true); + + if ( rc != 0 ) + { + return rc; + } + + return 0; + + +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int Host::insert_replace(SqlDB *db, bool replace) +{ + ostringstream oss; + + int rc; + + char * sql_hostname; + char * sql_im_mad_name; + char * sql_tm_mad_name; + char * sql_vmm_mad_name; + + // Update the Host + + sql_hostname = db->escape_str(hostname.c_str()); if ( sql_hostname == 0 ) { goto error_hostname; } - - sql_im_mad_name = sqlite3_mprintf("%q",im_mad_name.c_str()); + + sql_im_mad_name = db->escape_str(im_mad_name.c_str()); if ( sql_im_mad_name == 0 ) { goto error_im; } - - sql_tm_mad_name = sqlite3_mprintf("%q",tm_mad_name.c_str()); + + sql_tm_mad_name = db->escape_str(tm_mad_name.c_str()); if ( sql_tm_mad_name == 0 ) { goto error_tm; } - sql_vmm_mad_name = sqlite3_mprintf("%q",vmm_mad_name.c_str()); + sql_vmm_mad_name = db->escape_str(vmm_mad_name.c_str()); if ( sql_vmm_mad_name == 0 ) { goto error_vmm; } - - // Construct the SQL statement to Insert or Replace (effectively, update) - oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES (" + if(replace) + { + oss << "REPLACE"; + } + else + { + oss << "INSERT"; + } + + // Construct the SQL statement to Insert or Replace + + oss <<" INTO "<< table <<" "<< db_names <<" VALUES (" << oid << "," << "'" << sql_hostname << "'," << state << "," @@ -261,30 +289,27 @@ int Host::update(SqliteDB *db) rc = db->exec(oss); - sqlite3_free(sql_hostname); - sqlite3_free(sql_im_mad_name); - sqlite3_free(sql_tm_mad_name); - sqlite3_free(sql_vmm_mad_name); + db->free_str(sql_hostname); + db->free_str(sql_im_mad_name); + db->free_str(sql_tm_mad_name); + db->free_str(sql_vmm_mad_name); return rc; - + error_vmm: - sqlite3_free(sql_tm_mad_name); + db->free_str(sql_tm_mad_name); error_tm: - sqlite3_free(sql_im_mad_name); + db->free_str(sql_im_mad_name); error_im: - sqlite3_free(sql_hostname); + db->free_str(sql_hostname); error_hostname: return -1; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int Host::unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values) +int Host::dump(ostringstream& oss, int num, char **values, char **names) { if ((!values[OID]) || (!values[HOST_NAME]) || @@ -301,65 +326,24 @@ int Host::unmarshall(ostringstream& oss, oss << "" << "" << values[OID] <<"" << - "" << values[HOST_NAME] <<"" << - "" << values[STATE] <<"" << - "" << values[IM_MAD] <<"" << - "" << values[VM_MAD] <<"" << - "" << values[TM_MAD] <<"" << - ""<< values[LAST_MON_TIME]<<""; - - HostShare::unmarshall(oss,num - LIMIT, names + LIMIT, values + LIMIT); - + "" << values[HOST_NAME] <<"" << + "" << values[STATE] <<"" << + "" << values[IM_MAD] <<"" << + "" << values[VM_MAD] <<"" << + "" << values[TM_MAD] <<"" << + ""<< values[LAST_MON_TIME]<<""; + + HostShare::dump(oss,num - LIMIT, values + LIMIT, names + LIMIT); + oss << ""; return 0; - } -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -extern "C" int host_dump_cb ( - void * _oss, - int num, - char ** values, - char ** names) -{ - ostringstream * oss; - - oss = static_cast(_oss); - - if (oss == 0) - { - return -1; - } - - return Host::unmarshall(*oss,num,names,values); -}; - -/* -------------------------------------------------------------------------- */ - -int Host::dump(SqliteDB * db, ostringstream& oss, const string& where) -{ - int rc; - ostringstream cmd; - - cmd << "SELECT * FROM " << Host::table << "," << HostShare::table - << " ON " << Host::table << ".oid = " << HostShare::table << ".hid"; - - if ( !where.empty() ) - { - cmd << " WHERE " << where; - } - - rc = db->exec(cmd,host_dump_cb,(void *) &oss); - - return rc; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int Host::drop(SqliteDB * db) +int Host::drop(SqlDB * db) { ostringstream oss; int rc; @@ -380,8 +364,8 @@ int Host::drop(SqliteDB * db) return rc; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ int Host::update_info(string &parse_str) { @@ -389,15 +373,15 @@ int Host::update_info(string &parse_str) int rc; rc = host_template.parse(parse_str, &error_msg); - + if ( rc != 0 ) { - //Nebula::log("ONE", Log::ERROR, error_msg); - + NebulaLog::log("ONE", Log::ERROR, error_msg); + free(error_msg); return -1; } - + get_template_attribute("TOTALCPU",host_share.max_cpu); get_template_attribute("TOTALMEMORY",host_share.max_mem); @@ -410,40 +394,40 @@ int Host::update_info(string &parse_str) return 0; } -/* ************************************************************************** */ -/* Host :: Misc */ -/* ************************************************************************** */ +/* ************************************************************************ */ +/* Host :: Misc */ +/* ************************************************************************ */ ostream& operator<<(ostream& os, Host& host) { string host_str; - + os << host.to_xml(host_str); - + return os; }; -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ string& Host::to_xml(string& xml) const { string template_xml; string share_xml; ostringstream oss; - - oss << - "" - "" << oid << "" << - "" << hostname << "" << - "" << state << "" << - "" << im_mad_name << "" << - "" << vmm_mad_name << "" << - "" << tm_mad_name << "" << - "" << last_monitored << "" << - host_share.to_xml(share_xml) << - host_template.to_xml(template_xml) << + + oss << + "" + "" << oid << "" << + "" << hostname << "" << + "" << state << "" << + "" << im_mad_name << "" << + "" << vmm_mad_name << "" << + "" << tm_mad_name << "" << + "" << last_monitored << "" << + host_share.to_xml(share_xml) << + host_template.to_xml(template_xml) << ""; xml = oss.str(); @@ -451,17 +435,17 @@ string& Host::to_xml(string& xml) const return xml; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ string& Host::to_str(string& str) const { string template_str; string share_str; - + ostringstream os; - os << + os << "ID = " << oid << endl << "NAME = " << hostname << endl << "STATE = " << state << endl << @@ -473,113 +457,6 @@ string& Host::to_str(string& str) const "HOST SHARES" << endl << host_share.to_str(share_str) < * discovered_hosts; + string im_mad(values[1]); + int hid; + + discovered_hosts = static_cast *>(_map); + + if ( (num<=0) || (values[0] == 0) ) { - map * discovered_hosts; - string im_mad(values[1]); - int hid; + return -1; + } - discovered_hosts = static_cast *>(_discovered_hosts); + hid = atoi(values[0]); + im_mad = values[1]; - if ( (discovered_hosts == 0) || (num<=0) || (values[0] == 0) ) - { - return -1; - } + discovered_hosts->insert(make_pair(hid,im_mad)); - hid = atoi(values[0]); - im_mad = values[1]; - - discovered_hosts->insert(make_pair(hid,im_mad)); - - return 0; - }; + return 0; } /* -------------------------------------------------------------------------- */ int HostPool::discover(map * discovered_hosts) { - ostringstream sql; int rc; lock(); + set_callback(static_cast(&HostPool::discover_cb), + static_cast(discovered_hosts)); + sql << "SELECT oid, im_mad FROM " << Host::table << " WHERE state != " << Host::DISABLED << " ORDER BY last_mon_time LIMIT 10"; - rc = db->exec(sql,discover_cb,(void *) discovered_hosts); + rc = db->exec(sql,this); unlock(); @@ -99,3 +93,39 @@ int HostPool::discover(map * discovered_hosts) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +int HostPool::dump_cb(void * _oss, int num, char **values, char **names) +{ + ostringstream * oss; + + oss = static_cast(_oss); + + return Host::dump(*oss, num, values, names); +} + +/* -------------------------------------------------------------------------- */ + +int HostPool::dump(ostringstream& oss, const string& where) +{ + int rc; + ostringstream cmd; + + oss << ""; + + set_callback(static_cast(&HostPool::dump_cb), + static_cast(&oss)); + + cmd << "SELECT * FROM " << Host::table << " JOIN " << HostShare::table + << " ON " << Host::table << ".oid = " << HostShare::table << ".hid"; + + if ( !where.empty() ) + { + cmd << " WHERE " << where; + } + + rc = db->exec(cmd, this); + + oss << ""; + + return rc; +} diff --git a/src/host/HostShare.cc b/src/host/HostShare.cc index d40285d4a5..eb1cbf9e51 100644 --- a/src/host/HostShare.cc +++ b/src/host/HostShare.cc @@ -1,30 +1,31 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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. */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------*/ +/* Copyright 2002-2010, 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 #include #include #include -#include +#include #include "HostShare.h" -/* ************************************************************************** */ -/* HostShare :: Constructor/Destructor */ -/* ************************************************************************** */ +/* ************************************************************************ */ +/* HostShare :: Constructor/Destructor */ +/* ************************************************************************ */ HostShare::HostShare( int _hsid, @@ -49,9 +50,9 @@ HostShare::HostShare( { } -/* ************************************************************************** */ -/* HostShare :: Database Access Functions */ -/* ************************************************************************** */ +/* ************************************************************************ */ +/* HostShare :: Database Access Functions */ +/* ************************************************************************ */ const char * HostShare::table = "host_shares"; @@ -62,18 +63,18 @@ const char * HostShare::db_names = "(hid," "used_disk, used_mem, used_cpu," "running_vms)"; -const char * HostShare::db_bootstrap = "CREATE TABLE host_shares (" - "hid INTEGER PRIMARY KEY," +const char * HostShare::db_bootstrap = "CREATE TABLE IF NOT EXISTS host_shares(" + "hid INTEGER PRIMARY KEY," "disk_usage INTEGER, mem_usage INTEGER, cpu_usage INTEGER," "max_disk INTEGER, max_mem INTEGER, max_cpu INTEGER," "free_disk INTEGER, free_mem INTEGER, free_cpu INTEGER," "used_disk INTEGER, used_mem INTEGER, used_cpu INTEGER," "running_vms INTEGER)"; -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int HostShare::unmarshall(int num, char **names, char ** values) +int HostShare::select_cb(void * nil, int num, char **values, char **names) { if ((!values[HID]) || (!values[DISK_USAGE]) || @@ -99,7 +100,7 @@ int HostShare::unmarshall(int num, char **names, char ** values) disk_usage = atoi(values[DISK_USAGE]); mem_usage = atoi(values[MEM_USAGE]); cpu_usage = atoi(values[CPU_USAGE]); - + max_disk = atoi(values[MAX_DISK]); max_mem = atoi(values[MAX_MEMORY]); max_cpu = atoi(values[MAX_CPU]); @@ -113,93 +114,75 @@ int HostShare::unmarshall(int num, char **names, char ** values) used_cpu = atoi(values[USED_CPU]); running_vms = atoi(values[RUNNING_VMS]); - + return 0; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int HostShare::unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values) +int HostShare::dump(ostringstream& oss, + int num, + char ** values, + char ** names) { - if ((!values[HID]) || + if ((!values[HID]) || (!values[DISK_USAGE]) || - (!values[MEM_USAGE]) || - (!values[CPU_USAGE]) || - (!values[MAX_DISK]) || - (!values[MAX_MEMORY]) || - (!values[MAX_CPU]) || - (!values[FREE_DISK]) || - (!values[FREE_MEMORY]) || - (!values[FREE_CPU]) || - (!values[USED_DISK]) || - (!values[USED_MEMORY]) || - (!values[USED_CPU]) || - (!values[RUNNING_VMS]) || - (num != LIMIT)) - { - return -1; - } - - oss << - "" << - "" << values[HID] << "" << - ""<< values[DISK_USAGE] << ""<< - "" << values[MEM_USAGE] << "" << - "" << values[CPU_USAGE] << "" << - "" << values[MAX_DISK] << "" << - "" << values[MAX_MEMORY] << "" << - "" << values[MAX_CPU] << "" << - "" << values[FREE_DISK] << "" << - "" << values[FREE_MEMORY] << "" << - "" << values[FREE_CPU] << "" << - "" << values[USED_DISK] << "" << - "" << values[USED_MEMORY] << "" << - "" << values[USED_CPU] << "" << - ""<"<< - ""; - - return 0; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -extern "C" int host_share_select_cb ( - void * _hs, - int num, - char ** values, - char ** names) -{ - HostShare * hs; - - hs = static_cast(_hs); - - if (hs == 0) + (!values[MEM_USAGE]) || + (!values[CPU_USAGE]) || + (!values[MAX_DISK]) || + (!values[MAX_MEMORY]) || + (!values[MAX_CPU]) || + (!values[FREE_DISK]) || + (!values[FREE_MEMORY]) || + (!values[FREE_CPU]) || + (!values[USED_DISK]) || + (!values[USED_MEMORY]) || + (!values[USED_CPU]) || + (!values[RUNNING_VMS]) || + (num != LIMIT)) { return -1; } - return hs->unmarshall(num,names,values); -}; + oss << + "" << + "" << values[HID] << "" << + ""<< values[DISK_USAGE] << ""<< + "" << values[MEM_USAGE] << "" << + "" << values[CPU_USAGE] << "" << + "" << values[MAX_DISK] << "" << + "" << values[MAX_MEMORY] << "" << + "" << values[MAX_CPU] << "" << + "" << values[FREE_DISK] << "" << + "" << values[FREE_MEMORY] << "" << + "" << values[FREE_CPU] << "" << + "" << values[USED_DISK] << "" << + "" << values[USED_MEMORY] << "" << + "" << values[USED_CPU] << "" << + ""<"<< + ""; -/* -------------------------------------------------------------------------- */ + return 0; +} -int HostShare::select(SqliteDB * db) +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int HostShare::select(SqlDB * db) { ostringstream oss; int rc; int bhsid; + set_callback(static_cast(&HostShare::select_cb)); + oss << "SELECT * FROM " << table << " WHERE hid = " << hsid; bhsid = hsid; hsid = -1; - rc = db->exec(oss,host_share_select_cb,(void *) this); + rc = db->exec(oss,this); if (hsid != bhsid ) { @@ -209,48 +192,64 @@ int HostShare::select(SqliteDB * db) return rc; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int HostShare::insert(SqliteDB * db) +int HostShare::insert(SqlDB * db) { int rc; - rc = update(db); + rc = insert_replace(db, false); - if ( rc != 0 ) - { - return rc; - } - - return 0; + return rc; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int HostShare::update(SqliteDB * db) +int HostShare::update(SqlDB * db) +{ + int rc; + + rc = insert_replace(db, true); + + return rc; +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int HostShare::insert_replace(SqlDB *db, bool replace) { ostringstream oss; int rc; - - oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES (" + + if(replace) + { + oss << "REPLACE"; + } + else + { + oss << "INSERT"; + } + + oss << " INTO " << table << " "<< db_names <<" VALUES (" << hsid << "," << disk_usage <<","<< mem_usage <<","<< cpu_usage<< "," << max_disk <<","<< max_mem <<","<< max_cpu << "," << free_disk <<","<< free_mem <<","<< free_cpu << "," << used_disk <<","<< used_mem <<","<< used_cpu << "," << running_vms<< ")"; - + rc = db->exec(oss); return rc; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int HostShare::drop(SqliteDB * db) +int HostShare::drop(SqlDB * db) { ostringstream oss; @@ -259,21 +258,21 @@ int HostShare::drop(SqliteDB * db) return db->exec(oss); } -/* ************************************************************************** */ -/* HostShare :: Misc */ -/* ************************************************************************** */ +/* ************************************************************************ */ +/* HostShare :: Misc */ +/* ************************************************************************ */ ostream& operator<<(ostream& os, HostShare& hs) { string str; os << hs.to_xml(str); - + return os; }; -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ string& HostShare::to_xml(string& xml) const { @@ -281,19 +280,19 @@ string& HostShare::to_xml(string& xml) const ostringstream oss; oss << "" - << "" << hsid << "" + << "" << hsid << "" << "" << disk_usage << "" << "" << mem_usage << "" - << "" << cpu_usage << "" + << "" << cpu_usage << "" << "" << max_disk << "" << "" << max_mem << "" - << "" << max_cpu << "" + << "" << max_cpu << "" << "" << free_disk << "" << "" << free_mem << "" - << "" << free_cpu << "" + << "" << free_cpu << "" << "" << used_disk << "" << "" << used_mem << "" - << "" << used_cpu << "" + << "" << used_cpu << "" << ""<" << ""; @@ -302,18 +301,18 @@ string& HostShare::to_xml(string& xml) const return xml; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ string& HostShare::to_str(string& str) const { string template_xml; ostringstream oss; - oss<< "\tHID = " << hsid + oss<< "\tHID = " << hsid << "\tCPU_USAGE = " << cpu_usage << endl << "\tMEMORY_USAGE = " << mem_usage << endl - << "\tDISK_USAGE = " << disk_usage<< endl + << "\tDISK_USAGE = " << disk_usage<< endl << "\tMAX_CPU = " << max_cpu << endl << "\tMAX_MEMORY = " << max_mem << endl << "\tMAX_DISK = " << max_disk<< endl @@ -330,5 +329,5 @@ string& HostShare::to_str(string& str) const return str; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ diff --git a/src/host/HostTemplate.cc b/src/host/HostTemplate.cc index 3e8d04a0e3..0f5c6ccfa1 100644 --- a/src/host/HostTemplate.cc +++ b/src/host/HostTemplate.cc @@ -17,7 +17,8 @@ #include "HostTemplate.h" const char * HostTemplate::table = "host_attributes"; - -const char * HostTemplate::db_bootstrap = "CREATE TABLE host_attributes" - " (id INTEGER, name TEXT, type INTEGER, value TEXT, PRIMARY KEY(id,name))"; + +const char * HostTemplate::db_bootstrap = "CREATE TABLE IF NOT EXISTS " + "host_attributes (id INTEGER, name VARCHAR(256), type INTEGER, value TEXT, " + "PRIMARY KEY(id,name))"; diff --git a/src/host/SConstruct b/src/host/SConstruct index bbd6f87a3b..49026a400b 100644 --- a/src/host/SConstruct +++ b/src/host/SConstruct @@ -44,9 +44,6 @@ source_files=[ 'HostShare.cc', 'HostPool.cc', 'HostTemplate.cc', - 'host_parser.c', - 'host_requirements.cc', - 'host_rank.cc', ] # Build library diff --git a/src/host/host_rank.y b/src/host/host_rank.y deleted file mode 100644 index 43084a2011..0000000000 --- a/src/host/host_rank.y +++ /dev/null @@ -1,192 +0,0 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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 -#include -#include -#include -#include - -#include -#include -#include - -#include "host_rank.h" -#include "Host.h" - -#define YYERROR_VERBOSE -#define host_rank_lex host_lex - -extern "C" -{ -void host_rank_error( - YYLTYPE * llocp, - Host * host, - int& result, - char ** error_msg, - const char * str); - -int host_rank_lex (YYSTYPE *lvalp, YYLTYPE *llocp); - -int host_rank_parse(Host * host, int& result, char ** errmsg); -} - -%} - -%parse-param {Host * host} -%parse-param {int& result} -%parse-param {char ** error_msg} - -%union { - char * val_str; - int val_int; - float val_float; -}; - -%defines -%locations -%pure_parser -%name-prefix = "host_rank_" -%output = "host_rank.cc" - -%left '+' '-' -%left '*' '/' -%token INTEGER -%token STRING -%token FLOAT -%type stmt -%type expr - -%% - -stmt: expr { result = static_cast($1);} - | { result = 0; } - ; - -expr: STRING { string val; - string attr($1); - - if (attr == "RUNNING_VMS") - { - $$ = static_cast - (host->get_share_running_vms()); - } - else if (attr == "ALLOCATED_MEMORY") - { - $$ = static_cast - (host->get_share_mem_usage()); - } - else if (attr == "ALLOCATED_CPU") - { - $$ = static_cast - (host->get_share_cpu_usage()); - } - else if (attr == "ALLOCATED_DISK") - { - $$ = static_cast - (host->get_share_disk_usage()); - } - else if (attr == "USED_MEMORY") - { - $$ = static_cast - (host->get_share_used_mem()); - } - else if (attr == "USED_CPU") - { - $$ = static_cast - (host->get_share_used_cpu()); - } - else if (attr == "USED_DISK") - { - $$ = static_cast - (host->get_share_used_disk()); - } - else if (attr == "FREE_MEMORY") - { - $$ = static_cast - (host->get_share_free_mem()); - } - else if (attr == "FREE_CPU") - { - $$ = static_cast - (host->get_share_free_cpu()); - } - else if (attr == "FREE_DISK") - { - $$ = static_cast - (host->get_share_free_disk()); - } - else if (attr == "MAX_MEMORY") - { - $$ = static_cast - (host->get_share_max_mem()); - } - else if (attr == "MAX_CPU") - { - $$ = static_cast - (host->get_share_max_cpu()); - } - else if (attr == "MAX_DISK") - { - $$ = static_cast - (host->get_share_max_disk()); - } - else - { - host->get_template_attribute($1,val); - $$ = val.empty() ? 0.0 : atof(val.c_str()); - } - - free($1); - } - | FLOAT { $$ = $1; } - | INTEGER { $$ = static_cast($1); } - | expr '+' expr { $$ = $1 + $3;} - | expr '-' expr { $$ = $1 - $3;} - | expr '*' expr { $$ = $1 * $3;} - | expr '/' expr { $$ = $1 / $3;} - | '-' expr { $$ = - $2;} - | '(' expr ')' { $$ = $2;} - ; - -%% - -extern "C" void host_rank_error( - YYLTYPE * llocp, - Host * host, - int& result, - char ** error_msg, - const char * str) -{ - int length; - - length = strlen(str)+ 64; - - *error_msg = (char *) malloc(sizeof(char)*length); - - if (*error_msg != 0) - { - snprintf(*error_msg, - length, - "%s at line %i, columns %i:%i", - str, - llocp->first_line, - llocp->first_column, - llocp->last_column); - } -} - diff --git a/src/host/host_requirements.y b/src/host/host_requirements.y deleted file mode 100644 index a0e55ac4b7..0000000000 --- a/src/host/host_requirements.y +++ /dev/null @@ -1,181 +0,0 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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 -#include -#include -#include -#include - -#include -#include -#include - -#include "host_requirements.h" -#include "Host.h" - -#define YYERROR_VERBOSE -#define host_requirements_lex host_lex - -extern "C" -{ -void host_requirements_error( - YYLTYPE * llocp, - Host * host, - bool& result, - char ** error_msg, - const char * str); - -int host_requirements_lex (YYSTYPE *lvalp, YYLTYPE *llocp); - -int host_requirements_parse(Host * host, bool& result, char ** errmsg); -} - -%} - -%parse-param {Host * host} -%parse-param {bool& result} -%parse-param {char ** error_msg} - -%union { - char * val_str; - int val_int; - float val_float; -}; - -%defines -%locations -%pure_parser -%name-prefix = "host_requirements_" -%output = "host_requirements.cc" - -%left '!' '&' '|' -%token INTEGER -%token STRING -%token FLOAT -%type stmt expr - -%% - -stmt: expr { result=$1; } - | { result=true; } /* TRUE BY DEFAULT, ON EMPTY STRINGS */ - ; - -expr: STRING '=' INTEGER { int val; - - host->get_template_attribute($1,val); - $$ = val == $3; - - free($1);} - - | STRING '!' '=' INTEGER { int val; - - host->get_template_attribute($1,val); - $$ = val != $4; - - free($1);} - - | STRING '>' INTEGER { int val; - - host->get_template_attribute($1,val); - $$ = val > $3; - - free($1);} - - | STRING '<' INTEGER { int val; - - host->get_template_attribute($1,val); - $$ = val < $3; - - free($1);} - - | STRING '=' FLOAT { string val; - - host->get_template_attribute($1,val); - $$ = val.empty() ? false : atof(val.c_str()) == $3; - - free($1);} - - | STRING '!' '=' FLOAT { string val; - - host->get_template_attribute($1,val); - $$ = val.empty() ? false : atof(val.c_str()) != $4; - - free($1);} - - | STRING '>' FLOAT { string val; - - host->get_template_attribute($1,val); - $$ = val.empty() ? false : atof(val.c_str()) > $3; - - free($1);} - - | STRING '<' FLOAT { string val; - - host->get_template_attribute($1,val); - $$ = val.empty() ? false : atof(val.c_str()) < $3; - - free($1);} - - | STRING '=' STRING { string val; - - host->get_template_attribute($1,val); - $$ = val.empty() ? false :fnmatch($3, val.c_str(), 0) == 0; - - free($1); - free($3);} - - | STRING '!''=' STRING { string val; - - host->get_template_attribute($1,val); - $$ = val.empty() ? false : fnmatch($4, val.c_str(), 0) != 0; - - free($1); - free($4);} - - | expr '&' expr { $$ = $1 && $3; } - | expr '|' expr { $$ = $1 || $3; } - | '!' expr { $$ = ! $2; } - | '(' expr ')' { $$ = $2; } - ; - -%% - -extern "C" void host_requirements_error( - YYLTYPE * llocp, - Host * host, - bool& result, - char ** error_msg, - const char * str) -{ - int length; - - length = strlen(str)+ 64; - - *error_msg = (char *) malloc(sizeof(char)*length); - - if (*error_msg != 0) - { - snprintf(*error_msg, - length, - "%s at line %i, columns %i:%i", - str, - llocp->first_line, - llocp->first_column, - llocp->last_column); - } -} diff --git a/src/host/test/HostPoolTest.cc b/src/host/test/HostPoolTest.cc new file mode 100644 index 0000000000..a3c444b8ba --- /dev/null +++ b/src/host/test/HostPoolTest.cc @@ -0,0 +1,358 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include +#include + +#include "HostPool.h" +#include "PoolTest.h" + +using namespace std; + +const string im_mad = "im_mad"; +const string vmm_mad = "vmm_mad"; +const string tm_mad = "tm_mad"; + +const string names[] = {"Host one", "Second host"}; + +const string xmls[] = +{ + "0Host one0" + "im_madvmm_madtm_mad" + "00000000000" + "000" + "000" + "000" + "000" + "0", + + "1Second host0" + "im_madvmm_madtm_mad" + "00000000001" + "000" + "000" + "000" + "000" + "0" +}; + +// This xml dump result has the LAST_MON_TIMEs modified to 0000000000 +const string xml_dump = + "0a0im_madvmm_madtm_mad000000" + "000000000000000000" + "1a name0im_madvmm_madtm_mad0000000000100000" + "000000002a_name0im_madvmm_madtm_mad0000000000200000000000003another " + "name0im_madvmm_mad" + "tm_mad0000000000300000000000004host0im_madvmm_madtm_mad" + "00000000004" + "000" + "0000" + "000000"; + +const string xml_dump_like_a = + "0a0im_madvmm_madtm_mad000000" + "000000000000000000" + "1a name0im_madvmm_madtm_mad0000000000100000" + "000000002a_name0im_madvmm_madtm_mad0000000000200000000000003another " + "name0im_madvmm_mad" + "tm_mad000000000030000000000000"; + +const string replacement = "0000000000"; + + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class HostPoolTest : public PoolTest +{ + CPPUNIT_TEST_SUITE (HostPoolTest); + + ALL_POOLTEST_CPPUNIT_TESTS(); + + CPPUNIT_TEST (update); + CPPUNIT_TEST (dump); + CPPUNIT_TEST (dump_where); + CPPUNIT_TEST (discover); + CPPUNIT_TEST (duplicates); + + CPPUNIT_TEST_SUITE_END (); + +protected: + + void bootstrap(SqlDB* db) + { + HostPool::bootstrap(db); + }; + + PoolSQL* create_pool(SqlDB* db) + { + return new HostPool(db); + }; + + int allocate(int index) + { + int oid; + return ((HostPool*)pool)->allocate(&oid, names[index], im_mad, + vmm_mad, tm_mad); + }; + + void check(int index, PoolObjectSQL* obj) + { + Host * host = static_cast(obj); + + CPPUNIT_ASSERT( obj != 0 ); + + string xml_str = ""; + string name = host->get_hostname(); + + CPPUNIT_ASSERT( name == names[index] ); + + // Get the xml and replace the LAST_MON_TIME to 0, so we can compare + // it with a prepared string. + host->to_xml(xml_str); + xml_str.replace( xml_str.find("")+15, 10, "0000000000"); + + CPPUNIT_ASSERT( xml_str == xmls[index]); + + }; + + +public: + HostPoolTest(){}; + + ~HostPoolTest(){}; + + + /* ********************************************************************* */ + /* ********************************************************************* */ + + + void update() + { + HostPool * hp = static_cast(pool); + int oid_1 = allocate(0); + + Host* host = hp->get(oid_1, true); + CPPUNIT_ASSERT( host != 0 ); + + // Host object should be cached. Let's update its status + host->set_state(Host::DISABLED); + pool->update(host); + + host->unlock(); + + host = hp->get(oid_1,false); + CPPUNIT_ASSERT( host != 0 ); + CPPUNIT_ASSERT( host->get_state() == Host::DISABLED ); + + //Now force access to DB + + pool->clean(); + host = hp->get(oid_1,false); + + CPPUNIT_ASSERT( host != 0 ); + CPPUNIT_ASSERT( host->get_state() == Host::DISABLED ); + }; + + void duplicates() + { + int rc, oid_0, oid_1; + HostPool * hp = static_cast(pool); + Host * host; + + string tm_mad_2 = "another_tm_mad"; + + + // If we try to allocate two hosts with the same name and drivers, + // should fail + rc = hp->allocate(&oid_0, names[0], im_mad, vmm_mad, tm_mad); + CPPUNIT_ASSERT( oid_0 == 0 ); + CPPUNIT_ASSERT( rc == oid_0 ); + + rc = hp->allocate(&oid_1, names[0], im_mad, vmm_mad, tm_mad); + CPPUNIT_ASSERT( oid_1 == -1 ); + CPPUNIT_ASSERT( rc == oid_1 ); + + // But if the drivers change, the hostname can be repeated + rc = hp->allocate(&oid_1, names[0], im_mad, vmm_mad, tm_mad_2); + CPPUNIT_ASSERT( oid_1 == 1 ); + CPPUNIT_ASSERT( rc == oid_1 ); + + // Get the hosts and check them + host = hp->get(oid_0, false); + CPPUNIT_ASSERT( host != 0 ); + CPPUNIT_ASSERT( host->get_tm_mad() == tm_mad ); + + host = hp->get(oid_1, false); + CPPUNIT_ASSERT( host != 0 ); + CPPUNIT_ASSERT( host->get_tm_mad() == tm_mad_2 ); + } + + + void dump() + { + string names[] = {"a", "a name", "a_name", "another name", "host"}; + int rc, oid; + + for(int i=0; i<5; i++) + { + ((HostPool*)pool)->allocate(&oid, names[i], im_mad, vmm_mad, tm_mad); + } + + ostringstream oss; + + rc = ((HostPool*)pool)->dump(oss, ""); + CPPUNIT_ASSERT(rc == 0); + + // To be able to compare one string to another, the monitoring times + // have to be changed + string result = oss.str(); + result.replace( 142, 10, replacement); + result.replace( 648, 10, replacement); + result.replace(1154, 10, replacement); + result.replace(1666, 10, replacement); + result.replace(2170, 10, replacement); + + CPPUNIT_ASSERT( result == xml_dump ); + } + + void dump_where() + { + string names[] = {"a", "a name", "a_name", "another name", "host"}; + int rc, oid; + + for(int i=0; i<5; i++) + { + ((HostPool*)pool)->allocate(&oid, names[i], im_mad, vmm_mad, tm_mad); + } + + + ostringstream oss; + rc = ((HostPool*)pool)->dump(oss, "host_name LIKE 'a%'"); + CPPUNIT_ASSERT(rc == 0); + + // To be able to compare one string to another, the monitoring times + // have to be changed + string result = oss.str(); + result.replace( 142, 10, replacement); + result.replace( 648, 10, replacement); + result.replace(1154, 10, replacement); + result.replace(1666, 10, replacement); + + + CPPUNIT_ASSERT( result == xml_dump_like_a ); + } + + void discover() + { + int rc, oid, i; + + map dh; + map::iterator it; + + Host * host; + HostPool * hp = static_cast(pool); + ostringstream oss; + + for(i=0, oss.str(""); i<20; i++,oss.str("")) + { + oss << "host" << i; + + hp->allocate(&oid, oss.str().c_str(), im_mad, vmm_mad, tm_mad); + CPPUNIT_ASSERT(oid == i); + + if (i >=8 ) + { + host = hp->get(oid, false); + CPPUNIT_ASSERT(host!=0); + host->disable(); + hp->update(host); + } + } + + // Discover the enabled hosts + rc = hp->discover(&dh); + CPPUNIT_ASSERT(rc == 0); + CPPUNIT_ASSERT(dh.size() == 8); + + for(i=0,it=dh.begin(),oss.str("");it!=dh.end();it++,i++,oss.str("")) + { + CPPUNIT_ASSERT(it->first == i); + CPPUNIT_ASSERT(it->second == im_mad); + + host = hp->get(i, false); + CPPUNIT_ASSERT(host!=0); + CPPUNIT_ASSERT(host->isEnabled()); + } + } +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + return PoolTest::main(argc, argv, HostPoolTest::suite()); +} diff --git a/src/host/test/SConstruct b/src/host/test/SConstruct new file mode 100644 index 0000000000..26a0c4d5b6 --- /dev/null +++ b/src/host/test/SConstruct @@ -0,0 +1,91 @@ +# -------------------------------------------------------------------------- +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# -------------------------------------------------------------------------- + +import os +import sys +import shutil +sys.path.append("../../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located +cwd="../../../" + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) + +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include', + cwd + '/include/test', + '/usr/include/cppunit/', +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd + '/src/common', + cwd + '/src/log', + cwd + '/src/nebula', + cwd + '/src/sql', + cwd + '/src/pool', + cwd + '/src/template', + cwd + '/src/host', +]) + +main_env.Append(LIBS=[ + 'nebula_log', + 'nebula_host', + 'nebula_template', + 'nebula_pool', + 'nebula_common', + 'nebula_core', + 'nebula_sql', + 'cppunit', + 'dl', + 'pthread', +]) + +# MYSQL +main_env.Append(LIBPATH=["/usr/lib/mysql"]) +main_env.Append(CPPPATH=["/usr/include/mysql"]) + + +sqlite=ARGUMENTS.get('sqlite', 'yes') +if sqlite=='yes': + main_env.Append(CPPFLAGS=["-DSQLITE_DB"]) + main_env.Append(LIBS=[ 'sqlite3', ]) + +# MySQL +mysql=ARGUMENTS.get('mysql', 'no') +if mysql=='yes': + main_env.Append(CPPFLAGS=["-DMYSQL_DB"]) + main_env.Append(LIBS=[ 'mysqlclient', ]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# Linking flags +main_env.Append(LDFLAGS=["-g "]) + +main_env.Program('test','HostPoolTest.cc') + diff --git a/src/im/InformationManager.cc b/src/im/InformationManager.cc index 76866c1e4f..1ef6f846e9 100644 --- a/src/im/InformationManager.cc +++ b/src/im/InformationManager.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "InformationManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -29,13 +29,13 @@ extern "C" void * im_action_loop(void *arg) return 0; } - Nebula::log("InM",Log::INFO,"Information Manager started."); + NebulaLog::log("InM",Log::INFO,"Information Manager started."); im = static_cast(arg); im->am.loop(im->timer_period,0); - Nebula::log("InM",Log::INFO,"Information Manager stopped."); + NebulaLog::log("InM",Log::INFO,"Information Manager stopped."); return 0; } @@ -51,7 +51,7 @@ void InformationManager::load_mads(int uid) const VectorAttribute * vattr; int rc; - Nebula::log("InM",Log::INFO,"Loading Information Manager drivers."); + NebulaLog::log("InM",Log::INFO,"Loading Information Manager drivers."); for(i=0;ivector_value("NAME"); - Nebula::log("InM",Log::INFO,oss); + NebulaLog::log("InM",Log::INFO,oss); im_mad = new InformationManagerDriver(0,vattr->value(),false,hpool); @@ -71,7 +71,7 @@ void InformationManager::load_mads(int uid) oss.str(""); oss << "\tDriver " << vattr->vector_value("NAME") << " loaded"; - Nebula::log("InM",Log::INFO,oss); + NebulaLog::log("InM",Log::INFO,oss); } } } @@ -91,7 +91,7 @@ int InformationManager::start() return -1; } - Nebula::log("InM",Log::INFO,"Starting Information Manager..."); + NebulaLog::log("InM",Log::INFO,"Starting Information Manager..."); pthread_attr_init (&pattr); pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); @@ -112,7 +112,7 @@ void InformationManager::do_action(const string &action, void * arg) } else if (action == ACTION_FINALIZE) { - Nebula::log("InM",Log::INFO,"Stopping Information Manager..."); + NebulaLog::log("InM",Log::INFO,"Stopping Information Manager..."); MadManager::stop(); } @@ -121,7 +121,7 @@ void InformationManager::do_action(const string &action, void * arg) ostringstream oss; oss << "Unknown action name: " << action; - Nebula::log("InM", Log::ERROR, oss); + NebulaLog::log("InM", Log::ERROR, oss); } } @@ -148,7 +148,7 @@ void InformationManager::timer_action() if ( mark >= 600 ) { - Nebula::log("InM",Log::INFO,"--Mark--"); + NebulaLog::log("InM",Log::INFO,"--Mark--"); mark = 0; } @@ -187,7 +187,7 @@ void InformationManager::timer_action() oss.str(""); oss << "Monitoring host " << host->get_hostname() << " (" << it->first << ")"; - Nebula::log("InM",Log::INFO,oss); + NebulaLog::log("InM",Log::INFO,oss); imd = get(it->second); @@ -195,7 +195,7 @@ void InformationManager::timer_action() { oss.str(""); oss << "Could not find information driver " << it->second; - Nebula::log("InM",Log::ERROR,oss); + NebulaLog::log("InM",Log::ERROR,oss); host->set_state(Host::ERROR); } diff --git a/src/im/InformationManagerDriver.cc b/src/im/InformationManagerDriver.cc index c49e1f61ee..8c0d6141f9 100644 --- a/src/im/InformationManagerDriver.cc +++ b/src/im/InformationManagerDriver.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "InformationManagerDriver.h" -#include "Nebula.h" +#include "NebulaLog.h" #include @@ -111,7 +111,7 @@ void InformationManagerDriver::protocol( hinfo += "\n"; oss << "Host " << id << " successfully monitored."; //, info: "<< hinfo; - Nebula::log("InM",Log::DEBUG,oss); + NebulaLog::log("InM",Log::DEBUG,oss); rc = host->update_info(hinfo); @@ -136,20 +136,20 @@ void InformationManagerDriver::protocol( string info; getline(is,info); - Nebula::log("InM",Log::INFO,info.c_str()); + NebulaLog::log("InM",Log::INFO,info.c_str()); } return; error_driver_info: ess << "Error monitoring host " << id << " : " << is.str(); - Nebula::log("InM", Log::ERROR, ess); + NebulaLog::log("InM", Log::ERROR, ess); goto error_common_info; error_parse_info: ess << "Error parsing host information: " << hinfo; - Nebula::log("InM",Log::ERROR,ess); + NebulaLog::log("InM",Log::ERROR,ess); error_common_info: @@ -163,14 +163,14 @@ error_common_info: error_host: ess << "Could not get host " << id; - Nebula::log("InM",Log::ERROR,ess); + NebulaLog::log("InM",Log::ERROR,ess); return; error_parse: ess << "Error while parsing driver message: " << message; - Nebula::log("InM",Log::ERROR,ess); + NebulaLog::log("InM",Log::ERROR,ess); return; } @@ -180,6 +180,6 @@ error_parse: void InformationManagerDriver::recover() { - Nebula::log("InM", Log::ERROR, "Information driver crashed, recovering..."); + NebulaLog::log("InM", Log::ERROR, + "Information driver crashed, recovering..."); } - diff --git a/src/lcm/LifeCycleManager.cc b/src/lcm/LifeCycleManager.cc index c04ad68dca..be5aa4af37 100644 --- a/src/lcm/LifeCycleManager.cc +++ b/src/lcm/LifeCycleManager.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "LifeCycleManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -31,11 +31,11 @@ extern "C" void * lcm_action_loop(void *arg) lcm = static_cast(arg); - Nebula::log("LCM",Log::INFO,"Life-cycle Manager started."); + NebulaLog::log("LCM",Log::INFO,"Life-cycle Manager started."); lcm->am.loop(0,0); - Nebula::log("LCM",Log::INFO,"Life-cycle Manager stopped."); + NebulaLog::log("LCM",Log::INFO,"Life-cycle Manager stopped."); return 0; } @@ -50,7 +50,7 @@ int LifeCycleManager::start() pthread_attr_init (&pattr); pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); - Nebula::log("LCM",Log::INFO,"Starting Life-cycle Manager..."); + NebulaLog::log("LCM",Log::INFO,"Starting Life-cycle Manager..."); rc = pthread_create(&lcm_thread,&pattr,lcm_action_loop,(void *) this); @@ -300,14 +300,14 @@ void LifeCycleManager::do_action(const string &action, void * arg) } else if (action == ACTION_FINALIZE) { - Nebula::log("LCM",Log::INFO,"Stopping Life-cycle Manager..."); + NebulaLog::log("LCM",Log::INFO,"Stopping Life-cycle Manager..."); } else { ostringstream oss; oss << "Unknown action name: " << action; - Nebula::log("LCM", Log::ERROR, oss); + NebulaLog::log("LCM", Log::ERROR, oss); } } diff --git a/src/nebula/Log.cc b/src/log/Log.cc similarity index 78% rename from src/nebula/Log.cc rename to src/log/Log.cc index ec2bb163ac..80e7aa21d2 100644 --- a/src/nebula/Log.cc +++ b/src/log/Log.cc @@ -15,10 +15,12 @@ /* -------------------------------------------------------------------------- */ #include "Log.h" + #include -#include +#include #include #include +#include /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -28,14 +30,13 @@ const char Log::error_names[] ={ 'E', 'W', 'I', 'D' }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -Log::Log(const string& file_name, - const MessageType level, - ios_base::openmode mode): - log_level(level), - log_file(0) +FileLog::FileLog(const string& file_name, + const MessageType level, + ios_base::openmode mode) + :Log(level), log_file(0) { ofstream file; - + log_file = strdup(file_name.c_str()); file.open(log_file, mode); @@ -44,7 +45,7 @@ Log::Log(const string& file_name, { throw runtime_error("Could not open log file"); } - + if ( file.is_open() == true ) { file.close(); @@ -54,62 +55,18 @@ Log::Log(const string& file_name, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -Log::~Log() +FileLog::~FileLog() { - if ( log_file != 0 ) - { - free(log_file); - } -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -void Log::log( - const char * module, - const MessageType type, - const ostringstream& message) -{ - char str[26]; - time_t the_time; - ofstream file; - - if( type <= log_level) + if ( log_file != 0 ) { - - file.open(log_file, ios_base::app); - - if (file.fail() == true) - { - return; - } - - the_time = time(NULL); - -#ifdef SOLARIS - ctime_r(&(the_time),str,sizeof(char)*26); -#else - ctime_r(&(the_time),str); -#endif - // Get rid of final enter character - str[24] = '\0'; - - file << str << " "; - file << "[" << module << "]"; - file << "[" << error_names[type] << "]: "; - file << message.str(); - file << endl; - - file.flush(); - - file.close(); + free(log_file); } } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void Log::log( +void FileLog::log( const char * module, const MessageType type, const char * message) @@ -126,9 +83,9 @@ void Log::log( { return; } - + the_time = time(NULL); - + #ifdef SOLARIS ctime_r(&(the_time),str,sizeof(char)*26); #else @@ -142,9 +99,9 @@ void Log::log( file << "[" << error_names[type] << "]: "; file << message; file << endl; - + file.flush(); - + file.close(); } } @@ -152,3 +109,33 @@ void Log::log( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +void CerrLog::log( + const char * module, + const MessageType type, + const char * message) +{ + char str[26]; + time_t the_time; + ofstream file; + + if( type <= log_level) + { + the_time = time(NULL); + +#ifdef SOLARIS + ctime_r(&(the_time),str,sizeof(char)*26); +#else + ctime_r(&(the_time),str); +#endif + // Get rid of final enter character + str[24] = '\0'; + + cerr << str << " "; + cerr << "[" << module << "]"; + cerr << "[" << error_names[type] << "]: "; + cerr << message; + cerr << endl; + + cerr.flush(); + } +} diff --git a/src/log/NebulaLog.cc b/src/log/NebulaLog.cc new file mode 100644 index 0000000000..8d477860d0 --- /dev/null +++ b/src/log/NebulaLog.cc @@ -0,0 +1,26 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 "NebulaLog.h" + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +Log * NebulaLog::logger; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ \ No newline at end of file diff --git a/src/client/SConstruct b/src/log/SConstruct similarity index 87% rename from src/client/SConstruct rename to src/log/SConstruct index e4eb8e5186..00cf92ef54 100644 --- a/src/client/SConstruct +++ b/src/log/SConstruct @@ -1,4 +1,4 @@ -# SConstruct for src/mad +# SConstruct for src/log # -------------------------------------------------------------------------- # # Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) # @@ -18,18 +18,13 @@ Import('env') -lib_name='oneapi' +lib_name='nebula_log' # Sources to generate the library source_files=[ - 'OneClient.cc', - 'OneClient_C_Wrapper.cc' + 'NebulaLog.cc', + 'Log.cc' ] -# Compiling flags -env.Append(CPPFLAGS=["-fPIC"]) - # Build library env.StaticLibrary(lib_name, source_files) -env.SharedLibrary(lib_name, source_files) - diff --git a/src/mad/Mad.cc b/src/mad/Mad.cc index 7676e6bf40..9a849f223a 100644 --- a/src/mad/Mad.cc +++ b/src/mad/Mad.cc @@ -24,6 +24,8 @@ #include #include "Mad.h" +#include "NebulaLog.h" + #include "Nebula.h" #include @@ -237,43 +239,43 @@ int Mad::start() error_exec: oss.str(""); oss << "Can not load driver " << executable << ", " << strerror(errno); - Nebula::log("MAD", Log::ERROR, oss); + NebulaLog::log("MAD", Log::ERROR, oss); exit(-1); error_dup2: oss.str(""); oss << "Can not duplicate descriptors, " << strerror(errno); - Nebula::log("MAD", Log::ERROR, oss); + NebulaLog::log("MAD", Log::ERROR, oss); exit(-1); error_mad_result: oss.str(""); oss << "MAD initialization failed, " << info; - Nebula::log("MAD", Log::ERROR, oss); + NebulaLog::log("MAD", Log::ERROR, oss); return -1; error_mad_action: - Nebula::log("MAD", Log::ERROR,"Wrong action in MAD response"); + NebulaLog::log("MAD", Log::ERROR,"Wrong action in MAD response"); return -1; error_mad_init: - Nebula::log("MAD", Log::ERROR, "MAD did not answer INIT command"); + NebulaLog::log("MAD", Log::ERROR, "MAD did not answer INIT command"); return -1; error_fork: oss.str(""); oss << "Error forking to start MAD, " << strerror(errno); - Nebula::log("MAD", Log::ERROR, oss); + NebulaLog::log("MAD", Log::ERROR, oss); return -1; error_attributes: - Nebula::log("MAD", Log::ERROR, "Wrong attributes for the driver"); + NebulaLog::log("MAD", Log::ERROR, "Wrong attributes for the driver"); return -1; error_pipes: oss.str(""); oss << "Can not create driver pipes, " << strerror(errno); - Nebula::log("MAD", Log::ERROR, oss); + NebulaLog::log("MAD", Log::ERROR, oss); return -1; } diff --git a/src/nebula/Nebula.cc b/src/nebula/Nebula.cc index 491401c662..398a8d99dd 100644 --- a/src/nebula/Nebula.cc +++ b/src/nebula/Nebula.cc @@ -15,7 +15,10 @@ /* -------------------------------------------------------------------------- */ #include "Nebula.h" +#include "NebulaLog.h" #include "VirtualMachine.h" +#include "SqliteDB.h" +#include "MySqlDB.h" #include #include @@ -39,31 +42,31 @@ void Nebula::start() sigset_t mask; int signal; char hn[80]; - + if ( gethostname(hn,79) != 0 ) { throw runtime_error("Error getting hostname"); } - + hostname = hn; - // ----------------------------------------------------------- - // Configuration - // ----------------------------------------------------------- + // ----------------------------------------------------------- + // Configuration + // ----------------------------------------------------------- nebula_configuration = new NebulaTemplate(etc_location, var_location); - + rc = nebula_configuration->load_configuration(); - + if ( rc != 0 ) { throw runtime_error("Could not load nebula configuration file."); } - - // ----------------------------------------------------------- - // Log system - // ----------------------------------------------------------- - + + // ----------------------------------------------------------- + // Log system + // ----------------------------------------------------------- + ostringstream os; try @@ -71,149 +74,211 @@ void Nebula::start() string log_fname; int log_level_int; Log::MessageType clevel = Log::ERROR; - + log_fname = log_location + "oned.log"; - + nebula_configuration->get("DEBUG_LEVEL", log_level_int); - + if (0 <= log_level_int && log_level_int <= 3 ) { clevel = static_cast(log_level_int); } - os << "Init OpenNebula Log system"; - // Initializing ONE Daemon log system - - Nebula::log("ONE", - Log::INFO, - os, - log_fname.c_str(), - clevel); - - os.str(""); + + NebulaLog::init_log_system(NebulaLog::FILE_TS, + clevel, + log_fname.c_str(), + ios_base::trunc); + + NebulaLog::log("ONE",Log::INFO,"Init OpenNebula Log system"); + os << "Log Level: " << clevel << " [0=ERROR,1=WARNING,2=INFO,3=DEBUG]"; - // Initializing ONE Daemon log system - - Nebula::log("ONE", - Log::INFO, - os, - log_fname.c_str(), - clevel); + NebulaLog::log("ONE",Log::INFO,os); } catch(runtime_error&) { throw; } - - Nebula::log("ONE",Log::INFO,"----------------------------------------------"); - Nebula::log("ONE",Log::INFO," OpenNebula Configuration File "); - Nebula::log("ONE",Log::INFO,"----------------------------------------------"); + + + NebulaLog::log("ONE",Log::INFO,"----------------------------------------"); + NebulaLog::log("ONE",Log::INFO," OpenNebula Configuration File "); + NebulaLog::log("ONE",Log::INFO,"----------------------------------------"); os.str(""); - + os << "\n--------------------------------------------"; os << *nebula_configuration; os << "\n--------------------------------------------"; - - Nebula::log("ONE",Log::INFO,os); - - // ----------------------------------------------------------- + + NebulaLog::log("ONE",Log::INFO,os); + + // ----------------------------------------------------------- // Pools - // ----------------------------------------------------------- + // ----------------------------------------------------------- try { - string db_name = var_location + "one.db"; - struct stat db_stat; - bool db_bootstrap = stat(db_name.c_str(), &db_stat) != 0; - - db = new SqliteDB(db_name,Nebula::log); + vector dbs; + int rc; - if (db_bootstrap) - { - Nebula::log("ONE",Log::INFO,"Bootstraping OpenNebula database."); - - VirtualMachinePool::bootstrap(db); - HostPool::bootstrap(db); - VirtualNetworkPool::bootstrap(db); - UserPool::bootstrap(db); - } + bool db_is_sqlite = true; + + string server = "localhost"; + string user = "oneadmin"; + string passwd = "oneadmin"; + string db_name = "opennebula"; + + rc = nebula_configuration->get("DB", dbs); + + if ( rc != 0 ) + { + string value; + const VectorAttribute * db = static_cast + (dbs[0]); + value = db->vector_value("BACKEND"); + + if (value == "mysql") + { + db_is_sqlite = false; + + value = db->vector_value("SERVER"); + if (!value.empty()) + { + server = value; + } + + value = db->vector_value("USER"); + if (!value.empty()) + { + user = value; + } + + value = db->vector_value("PASSWD"); + if (!value.empty()) + { + passwd = value; + } + + value = db->vector_value("DB_NAME"); + if (!value.empty()) + { + db_name = value; + } + } + } + + if ( db_is_sqlite ) + { + string db_name = var_location + "one.db"; + + db = new SqliteDB(db_name); + } + else + { + ostringstream oss; + + db = new MySqlDB(server,user,passwd,0); + + oss << "CREATE DATABASE IF NOT EXISTS " << db_name; + rc = db->exec(oss); + + if ( rc != 0 ) + { + throw runtime_error("Could not create database."); + } + + oss.str(""); + oss << "USE " << db_name; + rc = db->exec(oss); + if ( rc != 0 ) + { + throw runtime_error("Could not open database."); + } + } + + NebulaLog::log("ONE",Log::INFO,"Bootstraping OpenNebula database."); + + VirtualMachinePool::bootstrap(db); + HostPool::bootstrap(db); + VirtualNetworkPool::bootstrap(db); + UserPool::bootstrap(db); } catch (exception&) { throw; } - + try - { + { string mac_prefix; int size; - + vector vm_hooks; - + nebula_configuration->get("VM_HOOK", vm_hooks); - + vmpool = new VirtualMachinePool(db, vm_hooks); hpool = new HostPool(db); - + nebula_configuration->get("MAC_PREFIX", mac_prefix); nebula_configuration->get("NETWORK_SIZE", size); - + vnpool = new VirtualNetworkPool(db,mac_prefix,size); - + upool = new UserPool(db); } catch (exception&) { throw; } - - // ----------------------------------------------------------- - // Close stds, we no longer need them - // ----------------------------------------------------------- - + + // ----------------------------------------------------------- + // Close stds, we no longer need them + // ----------------------------------------------------------- + fd = open("/dev/null", O_RDWR|O_CREAT); - + dup2(fd,0); - dup2(fd,1); + dup2(fd,1); dup2(fd,2); - - close(fd); - + + close(fd); + fcntl(0,F_SETFD,0); // Keep them open across exec funcs fcntl(1,F_SETFD,0); fcntl(2,F_SETFD,0); - - // ----------------------------------------------------------- - // Block all signals before creating any Nebula thread - // ----------------------------------------------------------- - + + // ----------------------------------------------------------- + // Block all signals before creating any Nebula thread + // ----------------------------------------------------------- + sigfillset(&mask); - - pthread_sigmask(SIG_BLOCK, &mask, NULL); - - // ----------------------------------------------------------- + + pthread_sigmask(SIG_BLOCK, &mask, NULL); + + // ----------------------------------------------------------- //Managers // ----------------------------------------------------------- - + MadManager::mad_manager_system_init(); time_t timer_period; - + nebula_configuration->get("MANAGER_TIMER", timer_period); - - // ---- Virtual Machine Manager ---- + + // ---- Virtual Machine Manager ---- try { time_t poll_period; vector vmm_mads; nebula_configuration->get("VM_POLLING_INTERVAL", poll_period); - + nebula_configuration->get("VM_MAD", vmm_mads); - + vmm = new VirtualMachineManager( vmpool, hpool, @@ -225,15 +290,15 @@ void Nebula::start() { throw; } - + rc = vmm->start(); - + if ( rc != 0 ) { throw runtime_error("Could not start the Virtual Machine Manager"); - } - - // ---- Life-cycle Manager ---- + } + + // ---- Life-cycle Manager ---- try { lcm = new LifeCycleManager(vmpool,hpool); @@ -244,22 +309,22 @@ void Nebula::start() } rc = lcm->start(); - + if ( rc != 0 ) { throw runtime_error("Could not start the Life-cycle Manager"); } - + // ---- Information Manager ---- try { vector im_mads; time_t monitor_period; - + nebula_configuration->get("HOST_MONITORING_INTERVAL", monitor_period); - + nebula_configuration->get("IM_MAD", im_mads); - + im = new InformationManager(hpool,timer_period,monitor_period,im_mads); } catch (bad_alloc&) @@ -268,7 +333,7 @@ void Nebula::start() } rc = im->start(); - + if ( rc != 0 ) { throw runtime_error("Could not start the Information Manager"); @@ -278,9 +343,9 @@ void Nebula::start() try { vector tm_mads; - + nebula_configuration->get("TM_MAD", tm_mads); - + tm = new TransferManager(vmpool, hpool, tm_mads); } catch (bad_alloc&) @@ -289,24 +354,24 @@ void Nebula::start() } rc = tm->start(); - + if ( rc != 0 ) { throw runtime_error("Could not start the Transfer Manager"); } - + // ---- Dispatch Manager ---- try - { + { dm = new DispatchManager(vmpool,hpool); } catch (bad_alloc&) { throw; } - + rc = dm->start(); - + if ( rc != 0 ) { throw runtime_error("Could not start the Dispatch Manager"); @@ -314,11 +379,11 @@ void Nebula::start() // ---- Request Manager ---- try - { + { int rm_port = 0; nebula_configuration->get("PORT", rm_port); - + rm = new RequestManager( vmpool, hpool, @@ -329,24 +394,24 @@ void Nebula::start() } catch (bad_alloc&) { - Nebula::log("ONE", Log::ERROR, "Error starting RM"); + NebulaLog::log("ONE", Log::ERROR, "Error starting RM"); throw; } - + rc = rm->start(); - + if ( rc != 0 ) { throw runtime_error("Could not start the Request Manager"); } - // ---- Hook Manager ---- + // ---- Hook Manager ---- try { vector hm_mads; - + nebula_configuration->get("HM_MAD", hm_mads); - + hm = new HookManager(hm_mads,vmpool); } catch (bad_alloc&) @@ -355,12 +420,12 @@ void Nebula::start() } rc = hm->start(); - + if ( rc != 0 ) { throw runtime_error("Could not start the Hook Manager"); } - + // ----------------------------------------------------------- // Load mads // ----------------------------------------------------------- @@ -372,43 +437,43 @@ void Nebula::start() im->load_mads(0); tm->load_mads(0); hm->load_mads(0); - + // ----------------------------------------------------------- // Wait for a SIGTERM or SIGINT signal // ----------------------------------------------------------- - + sigemptyset(&mask); - + sigaddset(&mask, SIGINT); sigaddset(&mask, SIGTERM); - + sigwait(&mask, &signal); - // ----------------------------------------------------------- + // ----------------------------------------------------------- // Stop the managers & free resources // ----------------------------------------------------------- - + vmm->trigger(VirtualMachineManager::FINALIZE,0); - lcm->trigger(LifeCycleManager::FINALIZE,0); + lcm->trigger(LifeCycleManager::FINALIZE,0); tm->trigger(TransferManager::FINALIZE,0); dm->trigger(DispatchManager::FINALIZE,0); - - im->finalize(); + + im->finalize(); rm->finalize(); hm->finalize(); //sleep to wait drivers??? - + pthread_join(vmm->get_thread_id(),0); pthread_join(lcm->get_thread_id(),0); pthread_join(tm->get_thread_id(),0); pthread_join(dm->get_thread_id(),0); - + pthread_join(im->get_thread_id(),0); pthread_join(rm->get_thread_id(),0); pthread_join(hm->get_thread_id(),0); - - Nebula::log("ONE", Log::INFO, "All modules finalized, exiting.\n"); + + NebulaLog::log("ONE", Log::INFO, "All modules finalized, exiting.\n"); } diff --git a/src/nebula/SConstruct b/src/nebula/SConstruct index e6e59b3014..82fefed6a8 100644 --- a/src/nebula/SConstruct +++ b/src/nebula/SConstruct @@ -24,7 +24,6 @@ lib_name='nebula_core' source_files=[ 'Nebula.cc', 'NebulaTemplate.cc', - 'Log.cc' ] # Build library @@ -48,10 +47,18 @@ env.Append(LIBS=[ 'nebula_vnm', 'nebula_vm', 'nebula_common', - 'sqlite3', + 'nebula_sql', + 'nebula_log', 'crypto' ]) +# Sources to generate the library +if env['sqlite']=='yes': + env.Append(LIBS=['sqlite3']) + +if env['mysql']=='yes': + env.Append(LIBS=['mysqlclient']) + if not env.GetOption('clean'): env.ParseConfig('../../share/scons/get_xmlrpc_config server') diff --git a/src/pool/PoolSQL.cc b/src/pool/PoolSQL.cc index 832e616896..00d8524f11 100644 --- a/src/pool/PoolSQL.cc +++ b/src/pool/PoolSQL.cc @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include "PoolSQL.h" @@ -36,49 +36,31 @@ const unsigned int PoolSQL::MAX_POOL_SIZE = 500; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -extern "C" +int PoolSQL::init_cb(void *nil, int num, char **values, char **names) { - int init_cb ( - void * _i, - int num, - char ** values, - char ** names) + lastOID = -1; + + if ( values[0] != 0 ) { - int * i; + lastOID = atoi(values[0]); + } - i = static_cast(_i); - - if ( (i == 0) || (num<=0) || (values[0] == 0) ) - { - *i = -1; - - return -1; - } - - *i = atoi(values[0]); - - return 0; - }; + return 0; } /* -------------------------------------------------------------------------- */ -PoolSQL::PoolSQL(SqliteDB * _db, const char * table): Hookable(), db(_db) +PoolSQL::PoolSQL(SqlDB * _db, const char * table): db(_db), lastOID(-1) { ostringstream oss; pthread_mutex_init(&mutex,0); - // Get next id from the DB table - - lastOID = -1; - - if ( table != 0 ) - { - oss << "SELECT MAX(oid) FROM " << table; + set_callback(static_cast(&PoolSQL::init_cb)); - db->exec(oss,init_cb,(void *) &lastOID); - } + oss << "SELECT MAX(oid) FROM " << table; + + db->exec(oss,this); }; /* -------------------------------------------------------------------------- */ @@ -93,10 +75,10 @@ PoolSQL::~PoolSQL() for ( it = pool.begin(); it != pool.end(); it++) { it->second->lock(); - + delete it->second; } - + pthread_mutex_unlock(&mutex); pthread_mutex_destroy(&mutex); @@ -138,7 +120,7 @@ int PoolSQL::allocate( } do_hooks(objsql, Hook::ALLOCATE); - + objsql->unlock(); delete objsql; @@ -164,7 +146,7 @@ PoolObjectSQL * PoolSQL::get( index = pool.find(oid); if ( index != pool.end() ) - { + { if ( index->second->isValid() == false ) { objectsql = 0; @@ -184,7 +166,7 @@ PoolObjectSQL * PoolSQL::get( return objectsql; } else - { + { objectsql = create(); objectsql->oid = oid; @@ -196,7 +178,7 @@ PoolObjectSQL * PoolSQL::get( delete objectsql; unlock(); - + return 0; } @@ -228,7 +210,7 @@ void PoolSQL::replace() bool removed = false; int oid; int rc; - + map::iterator index; while (!removed) @@ -238,14 +220,14 @@ void PoolSQL::replace() if ( index == pool.end()) { - oid_queue.pop(); + oid_queue.pop(); break; } rc = pthread_mutex_trylock(&(index->second->mutex)); if ( rc == EBUSY ) // In use by other thread, move to back - { + { oid_queue.pop(); oid_queue.push(oid); } @@ -254,8 +236,8 @@ void PoolSQL::replace() delete index->second; pool.erase(index); - - oid_queue.pop(); + + oid_queue.pop(); removed = true; } } @@ -273,7 +255,7 @@ void PoolSQL::clean() for ( it = pool.begin(); it != pool.end(); it++) { it->second->lock(); - + delete it->second; } @@ -284,33 +266,24 @@ void PoolSQL::clean() /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +int PoolSQL:: search_cb(void * _oids, int num, char **values, char **names) +{ + vector * oids; -extern "C" -{ -static int search_cb( - void * _oids, - int num, - char ** values, - char ** names) -{ - vector * oids; - oids = static_cast *>(_oids); - + if ( num == 0 || values == 0 || values[0] == 0 ) { return -1; } - + oids->push_back(atoi(values[0])); - + return 0; } -} - /* -------------------------------------------------------------------------- */ - + int PoolSQL::search( vector& oids, const char * table, @@ -318,14 +291,17 @@ int PoolSQL::search( { ostringstream sql; int rc; - + lock(); - + + set_callback(static_cast(&PoolSQL::search_cb), + static_cast(&oids)); + sql << "SELECT oid FROM " << table << " WHERE " << where; - - rc = db->exec(sql, search_cb, (void *) &oids); - + + rc = db->exec(sql, this); + unlock(); - + return rc; -} +} \ No newline at end of file diff --git a/src/pool/test/SConstruct b/src/pool/test/SConstruct new file mode 100644 index 0000000000..615372a2fc --- /dev/null +++ b/src/pool/test/SConstruct @@ -0,0 +1,86 @@ +# -------------------------------------------------------------------------- +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# -------------------------------------------------------------------------- + +import os +import sys +import shutil +sys.path.append("../../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located +cwd="../../../" + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) + +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include', + '/usr/include/cppunit/', +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd + '/src/common', + cwd + '/src/log', + cwd + '/src/pool', + cwd + '/src/sql', + cwd + '/src/pool/test', + cwd + '/src/nebula', +]) + +main_env.Append(LIBS=[ + 'nebula_pool', + 'nebula_common', + 'nebula_log', + 'nebula_core', + 'nebula_sql', + 'cppunit', + 'dl', + 'pthread', + 'test_object' +]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# MYSQL +main_env.Append(LIBPATH=["/usr/lib/mysql"]) +main_env.Append(CPPPATH=["/usr/include/mysql"]) + +sqlite=ARGUMENTS.get('sqlite', 'yes') +if sqlite=='yes': + main_env.Append(CPPFLAGS=["-DSQLITE_DB"]) + main_env.Append(LIBS=[ 'sqlite3', ]) + +# MySQL +mysql=ARGUMENTS.get('mysql', 'no') +if mysql=='yes': + main_env.Append(CPPFLAGS=["-DMYSQL_DB"]) + main_env.Append(LIBS=[ 'mysqlclient', ]) + + +main_env.StaticLibrary('test_object', ['TestPoolSQL.cc', 'TestPoolSQL.h']) +main_env.Program('test','pool.cc') + diff --git a/src/pool/test/TestPoolSQL.cc b/src/pool/test/TestPoolSQL.cc new file mode 100644 index 0000000000..ee730b56b8 --- /dev/null +++ b/src/pool/test/TestPoolSQL.cc @@ -0,0 +1,131 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include +#include + +#include +#include + +#include +#include + +#include "TestPoolSQL.h" + +/* ************************************************************************** */ +/* Database Access Functions */ +/* ************************************************************************** */ + +const char * TestObjectSQL::table = "test_pool"; + +const char * TestObjectSQL::db_names = "(oid,number,text)"; + +const char * TestObjectSQL::db_bootstrap = "CREATE TABLE test_pool (" + "oid INTEGER, number INTEGER, text TEXT, PRIMARY KEY(oid))"; + +/* -------------------------------------------------------------------------- */ + +int TestObjectSQL::unmarshall(void * nil, int num, char **values, char **names) +{ + if ((!values[OID]) || + (!values[NUMBER]) || + (!values[TEXT]) || + (num != LIMIT )) + { + return -1; + } + + oid = atoi(values[OID]); + number = atoi(values[NUMBER]); + text = values[TEXT]; + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +int TestObjectSQL::select(SqlDB *db) +{ + ostringstream oss; + int rc; + int boid; + + set_callback( + static_cast(&TestObjectSQL::unmarshall),0); + oss << "SELECT * FROM " << table << " WHERE oid = " << oid; + + boid = oid; + oid = -1; + + rc = db->exec(oss, this); + + if ((rc != 0) || (oid != boid )) + { + return -1; + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +int TestObjectSQL::insert(SqlDB *db) +{ + return update(db); +} + +/* -------------------------------------------------------------------------- */ + +int TestObjectSQL::update(SqlDB *db) +{ + ostringstream oss; + + int rc; + char * sql_text; + + sql_text = db->escape_str(text.c_str()); + + oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES (" + << oid << "," + << number << "," + << "'" << sql_text << "')"; + + rc = db->exec(oss); + + db->free_str(sql_text); + + return rc; +} + +/* -------------------------------------------------------------------------- */ + +int TestObjectSQL::drop(SqlDB * db) +{ + ostringstream oss; + int rc; + + oss << "DELETE FROM " << table << " WHERE oid=" << oid; + + rc = db->exec(oss); + + if ( rc == 0 ) + { + set_valid(false); + } + + return rc; +} diff --git a/src/pool/test/TestPoolSQL.h b/src/pool/test/TestPoolSQL.h new file mode 100644 index 0000000000..77228ea580 --- /dev/null +++ b/src/pool/test/TestPoolSQL.h @@ -0,0 +1,102 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 TESTSQL_H_ +#define TESTSQL_H_ + +#include +#include "PoolSQL.h" + +using namespace std; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +// THE OBJECT +class TestObjectSQL : public PoolObjectSQL +{ +public: + //OBJECT ATTRIBUTES + TestObjectSQL(int n=-1, string t="default"):number(n),text(t){}; + + ~TestObjectSQL(){}; + + int number; + + string text; + + // OBJECTSQL INTERFACE + int unmarshall(void * nil, int num, char **names, char ** values); + + int select(SqlDB *db); + + int insert(SqlDB *db); + + int update(SqlDB *db); + + int drop(SqlDB *db); + + // DATABASE IMPLEMENTATION + enum ColNames + { + OID = 0, + NUMBER = 1, + TEXT = 2, + LIMIT = 3 + }; + + static const char * db_names; + + static const char * db_bootstrap; + + static const char * table; + + static void bootstrap(SqlDB * db) + { + ostringstream oss; + oss.str(TestObjectSQL::db_bootstrap); + + db->exec(oss,0); + }; +}; + +// THE POOL +class TestPool : public PoolSQL +{ + +public: + TestPool(SqlDB *db):PoolSQL(db,"test_pool"){}; + ~TestPool(){}; + + TestObjectSQL * get( + int oid, + bool lock) + { + return static_cast(PoolSQL::get(oid,lock));; + } + + int dump(std::ostringstream&, const std::string&){return -1;}; + +private: + + TestObjectSQL * create() + { + return new TestObjectSQL; + }; + +}; + +#endif diff --git a/src/pool/test/pool.cc b/src/pool/test/pool.cc new file mode 100644 index 0000000000..ac6282dffe --- /dev/null +++ b/src/pool/test/pool.cc @@ -0,0 +1,224 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "PoolSQL.h" +#include "TestPoolSQL.h" +#include "SqliteDB.h" + +using namespace std; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class PoolTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE (PoolTest); + CPPUNIT_TEST (allocate_get); + CPPUNIT_TEST (wrong_get); + CPPUNIT_TEST (search); + CPPUNIT_TEST (cache_test); + CPPUNIT_TEST_SUITE_END (); + +private: + TestPool * pool; + SqliteDB * db; + + int create_allocate(int n, string st) + { + TestObjectSQL *obj = new TestObjectSQL(n,st); + + return pool->allocate(obj); + }; + +public: + PoolTest(){}; + + ~PoolTest(){}; + + void setUp() + { + string db_name = "test.db"; + unlink("test.db"); + + db = new SqliteDB(db_name); + + TestObjectSQL::bootstrap(db); + + pool = new TestPool(db); + }; + + void tearDown() + { + delete db; + delete pool; + }; + + /* ********************************************************************* */ + /* ********************************************************************* */ + + // Try to allocate two objects, and retrieve them + void allocate_get() + { + int n1 = 3; + int n2 = 7; + string st1 = "text number one"; + string st2 = "another text"; + + TestObjectSQL *obj; + int oid; + + oid = create_allocate(n1,st1); + // first element in the pool should have oid=0 + CPPUNIT_ASSERT(oid == 0); + + oid = create_allocate(n2,st2); + // second element in the pool should have oid=1 + CPPUNIT_ASSERT(oid == 1); + + // --------------------------------- + obj = pool->get(0, false); + CPPUNIT_ASSERT(obj != 0); + + CPPUNIT_ASSERT(obj->number == n1); + CPPUNIT_ASSERT(obj->text == st1); + + // --------------------------------- + obj = pool->get(1, true); + CPPUNIT_ASSERT(obj != 0); + + CPPUNIT_ASSERT(obj->number == n2); + CPPUNIT_ASSERT(obj->text == st2); + obj->unlock(); + }; + + void wrong_get() + { + int n1 = 2; + string st1 = "object 2"; + + TestObjectSQL *obj; + int oid; + + oid = create_allocate(n1,st1); + + obj = pool->get(oid,true); + CPPUNIT_ASSERT(obj != 0); + + obj->drop(db); + obj->unlock(); + + obj = pool->get(oid,true); + CPPUNIT_ASSERT(obj == 0); + + pool->clean(); + obj = pool->get(oid,true); + CPPUNIT_ASSERT(obj == 0); + }; + + void search() + { + int nA = 13; + int nB = 17; + string stA = "String value for number 13"; + string stB = "String value for number 17"; + + int oidA = create_allocate(nA, stA); + int oidB = create_allocate(nB, stB); + + vector results; + const char * table = "test_pool"; + string where = "text = '" + stB + "'"; + int ret; + + ret = pool->search(results, table, where); + CPPUNIT_ASSERT(ret == 0); + CPPUNIT_ASSERT(results.size() == 1); + CPPUNIT_ASSERT(results.at(0) == oidB); + + results.erase(results.begin(), results.end()); + + where = "number < 18"; + + ret = pool->search(results, table, where); + CPPUNIT_ASSERT(ret == 0); + CPPUNIT_ASSERT(results.size() == 2); + CPPUNIT_ASSERT(results.at(0) == oidA); + CPPUNIT_ASSERT(results.at(1) == oidB); + }; + + void cache_test() + { + TestObjectSQL *obj; + TestObjectSQL *obj_lock; + + //pin object in the cache, it can't be removed - + for (int i=0 ; i < 499 ; i++) + { + create_allocate(i,"A Test object"); + + obj_lock = pool->get(i, true); + CPPUNIT_ASSERT(obj_lock != 0); + } + + for (int i=499 ; i < 2000 ; i++) + { + create_allocate(i,"A Test object"); + } + + for (int i=499; i < 2000 ; i++) + { + obj = pool->get(i, true); + CPPUNIT_ASSERT(obj != 0); + + CPPUNIT_ASSERT(obj->number == i); + CPPUNIT_ASSERT(obj->text == "A Test object"); + obj->unlock(); + } + + for (int i=0 ; i < 499 ; i++) + { + obj_lock = pool->get(i, false);//pin object in the cache, it can't be removed + obj_lock->unlock(); + } + }; +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + CppUnit::TextUi::TestRunner runner; + + NebulaLog::init_log_system(NebulaLog::FILE, Log::ERROR, "test.log"); + runner.addTest( PoolTest::suite() ); + runner.run(); + NebulaLog::finalize_log_system(); + + return 0; +} diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index f7b17e82ee..357d5a1bf8 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" #include #include @@ -39,13 +39,13 @@ extern "C" void * rm_action_loop(void *arg) return 0; } - Nebula::log("ReM",Log::INFO,"Request Manager started."); + NebulaLog::log("ReM",Log::INFO,"Request Manager started."); rm = static_cast(arg); rm->am.loop(0,0); - Nebula::log("ReM",Log::INFO,"Request Manager stopped."); + NebulaLog::log("ReM",Log::INFO,"Request Manager stopped."); return 0; } @@ -98,7 +98,7 @@ int RequestManager::setup_socket() ostringstream oss; oss << "Can not open server socket: " << strerror(errno); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); return -1; } @@ -110,7 +110,7 @@ int RequestManager::setup_socket() ostringstream oss; oss << "Can not set socket options: " << strerror(errno); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); close(socket_fd); @@ -130,7 +130,7 @@ int RequestManager::setup_socket() ostringstream oss; oss << "Can not bind to port " << port << " : " << strerror(errno); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); close(socket_fd); @@ -148,7 +148,7 @@ int RequestManager::start() pthread_attr_t pattr; ostringstream oss; - Nebula::log("ReM",Log::INFO,"Starting Request Manager..."); + NebulaLog::log("ReM",Log::INFO,"Starting Request Manager..."); int rc = setup_socket(); @@ -168,7 +168,7 @@ int RequestManager::start() pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); oss << "Starting XML-RPC server, port " << port << " ..."; - Nebula::log("ReM",Log::INFO,oss); + NebulaLog::log("ReM",Log::INFO,oss); pthread_create(&rm_xml_server_thread,&pattr,rm_xml_server_loop,(void *)this); @@ -184,13 +184,13 @@ void RequestManager::do_action( { if (action == ACTION_FINALIZE) { - Nebula::log("ReM",Log::INFO,"Stopping Request Manager..."); + NebulaLog::log("ReM",Log::INFO,"Stopping Request Manager..."); pthread_cancel(rm_xml_server_thread); pthread_join(rm_xml_server_thread,0); - Nebula::log("ReM",Log::INFO,"XML-RPC server stopped."); + NebulaLog::log("ReM",Log::INFO,"XML-RPC server stopped."); delete AbyssServer; @@ -204,7 +204,7 @@ void RequestManager::do_action( ostringstream oss; oss << "Unknown action name: " << action; - Nebula::log("ReM", Log::ERROR, oss); + NebulaLog::log("ReM", Log::ERROR, oss); } }; diff --git a/src/rm/RequestManagerAction.cc b/src/rm/RequestManagerAction.cc index b7c013a263..af279c87cf 100644 --- a/src/rm/RequestManagerAction.cc +++ b/src/rm/RequestManagerAction.cc @@ -15,6 +15,8 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" +#include "NebulaLog.h" + #include "Nebula.h" /* -------------------------------------------------------------------------- */ @@ -41,7 +43,7 @@ void RequestManager::VirtualMachineAction::execute( ostringstream oss; - Nebula::log("ReM",Log::DEBUG,"VirtualMachineAction invoked"); + NebulaLog::log("ReM",Log::DEBUG,"VirtualMachineAction invoked"); session = xmlrpc_c::value_string(paramList.getString(0)); action = xmlrpc_c::value_string(paramList.getString(1)); diff --git a/src/rm/RequestManagerAllocate.cc b/src/rm/RequestManagerAllocate.cc index 707c51c382..285f6c4d9b 100644 --- a/src/rm/RequestManagerAllocate.cc +++ b/src/rm/RequestManagerAllocate.cc @@ -15,6 +15,8 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" +#include "NebulaLog.h" + #include "Nebula.h" /* -------------------------------------------------------------------------- */ @@ -42,10 +44,10 @@ void RequestManager::VirtualMachineAllocate::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - - - Nebula::log("ReM",Log::DEBUG,"VirtualMachineAllocate invoked"); - + + + NebulaLog::log("ReM",Log::DEBUG,"VirtualMachineAllocate invoked"); + session = xmlrpc_c::value_string(paramList.getString(0)); vm_template = xmlrpc_c::value_string(paramList.getString(1)); vm_template += "\n"; @@ -60,7 +62,7 @@ void RequestManager::VirtualMachineAllocate::execute( } User::split_secret(session,username,password); - + // Now let's get the user user = VirtualMachineAllocate::upool->get(username,true); @@ -72,24 +74,24 @@ void RequestManager::VirtualMachineAllocate::execute( uid = user->get_uid(); user->unlock(); - + rc = dm->allocate(uid,vm_template,&vid); - - if ( rc != 0 ) + + if ( rc < 0 ) { goto error_allocate; } - + arrayData.push_back(xmlrpc_c::value_boolean(true)); arrayData.push_back(xmlrpc_c::value_int(vid)); - + // Copy arrayresult into retval mem space arrayresult = new xmlrpc_c::value_array(arrayData); *retval = *arrayresult; delete arrayresult; // and get rid of the original - + return; @@ -108,7 +110,7 @@ error_allocate: } else { - oss << "Error parsing VM template"; + oss << "Error parsing VM template"; } goto error_common; @@ -116,7 +118,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/rm/RequestManagerDeploy.cc b/src/rm/RequestManagerDeploy.cc index 3364872b3f..433b2c0139 100644 --- a/src/rm/RequestManagerDeploy.cc +++ b/src/rm/RequestManagerDeploy.cc @@ -15,6 +15,8 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" +#include "NebulaLog.h" + #include "Nebula.h" /* -------------------------------------------------------------------------- */ @@ -46,7 +48,7 @@ void RequestManager::VirtualMachineDeploy::execute( ostringstream oss; - Nebula::log("ReM",Log::DEBUG,"VirtualMachineDeploy invoked"); + NebulaLog::log("ReM",Log::DEBUG,"VirtualMachineDeploy invoked"); //Parse Arguments diff --git a/src/rm/RequestManagerHostAllocate.cc b/src/rm/RequestManagerHostAllocate.cc index 9f02bc02f6..7d3393f4d0 100644 --- a/src/rm/RequestManagerHostAllocate.cc +++ b/src/rm/RequestManagerHostAllocate.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -40,7 +40,7 @@ void RequestManager::HostAllocate::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"HostAllocate method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"HostAllocate method invoked"); // Get the parameters session = xmlrpc_c::value_string(paramList.getString(0)); @@ -62,7 +62,7 @@ void RequestManager::HostAllocate::execute( im_mad_name, vmm_mad_name, tm_mad_name); - if ( rc != 0 ) + if ( rc == -1 ) { goto error_host_allocate; } @@ -92,7 +92,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/rm/RequestManagerHostDelete.cc b/src/rm/RequestManagerHostDelete.cc index f8f4ffda32..9bafd227d2 100644 --- a/src/rm/RequestManagerHostDelete.cc +++ b/src/rm/RequestManagerHostDelete.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -36,7 +36,7 @@ void RequestManager::HostDelete::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"HostDelete method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"HostDelete method invoked"); // Get the parameters session = xmlrpc_c::value_string(paramList.getString(0)); @@ -82,7 +82,7 @@ error_host_get: goto error_common; error_common: - Nebula::log ("Rem",Log::ERROR,oss); + NebulaLog::log ("Rem",Log::ERROR,oss); arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); diff --git a/src/rm/RequestManagerHostEnable.cc b/src/rm/RequestManagerHostEnable.cc index 27e187e4b8..4e000dadbd 100644 --- a/src/rm/RequestManagerHostEnable.cc +++ b/src/rm/RequestManagerHostEnable.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -36,7 +36,7 @@ void RequestManager::HostEnable::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"HostEnable method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"HostEnable method invoked"); // Get the parameters & host session = xmlrpc_c::value_string(paramList.getString(0)); @@ -91,7 +91,7 @@ error_host_get: goto error_common; error_common: - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); arrayData.push_back(xmlrpc_c::value_boolean(false)); arrayData.push_back(xmlrpc_c::value_string(oss.str())); diff --git a/src/rm/RequestManagerHostInfo.cc b/src/rm/RequestManagerHostInfo.cc index 4c779987c2..7c85823838 100644 --- a/src/rm/RequestManagerHostInfo.cc +++ b/src/rm/RequestManagerHostInfo.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -36,7 +36,7 @@ void RequestManager::HostInfo::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"HostInfo method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"HostInfo method invoked"); // Get the parameters session = xmlrpc_c::value_string(paramList.getString(0)); @@ -87,7 +87,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/rm/RequestManagerHostPoolInfo.cc b/src/rm/RequestManagerHostPoolInfo.cc index 70d80b6f56..ba598a803d 100755 --- a/src/rm/RequestManagerHostPoolInfo.cc +++ b/src/rm/RequestManagerHostPoolInfo.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -32,7 +32,7 @@ void RequestManager::HostPoolInfo::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"HostPoolInfo method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"HostPoolInfo method invoked"); // Get the parameters session = xmlrpc_c::value_string(paramList.getString(0)); @@ -81,7 +81,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/rm/RequestManagerInfo.cc b/src/rm/RequestManagerInfo.cc index 9c07d718ba..35574ad663 100644 --- a/src/rm/RequestManagerInfo.cc +++ b/src/rm/RequestManagerInfo.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -35,7 +35,7 @@ void RequestManager::VirtualMachineInfo::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"VirtualMachineInfo method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"VirtualMachineInfo method invoked"); // Get the parameters session = xmlrpc_c::value_string(paramList.getString(0)); @@ -74,7 +74,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/rm/RequestManagerMigrate.cc b/src/rm/RequestManagerMigrate.cc index dfb391a56e..a3091a9660 100644 --- a/src/rm/RequestManagerMigrate.cc +++ b/src/rm/RequestManagerMigrate.cc @@ -15,6 +15,8 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" +#include "NebulaLog.h" + #include "Nebula.h" /* -------------------------------------------------------------------------- */ @@ -48,7 +50,7 @@ void RequestManager::VirtualMachineMigrate::execute( ostringstream oss; time_t thetime; - Nebula::log("ReM",Log::DEBUG,"VirtualMachineMigrate invoked"); + NebulaLog::log("ReM",Log::DEBUG,"VirtualMachineMigrate invoked"); //Parse Arguments diff --git a/src/rm/RequestManagerPoolInfo.cc b/src/rm/RequestManagerPoolInfo.cc index 0da0a811ed..7461ff9d39 100644 --- a/src/rm/RequestManagerPoolInfo.cc +++ b/src/rm/RequestManagerPoolInfo.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -40,7 +40,7 @@ void RequestManager::VirtualMachinePoolInfo::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"VirtualMachinePoolInfo method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"VirtualMachinePoolInfo method invoked"); // Get the parameters session = xmlrpc_c::value_string(paramList.getString(0)); @@ -119,7 +119,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/rm/RequestManagerUserAllocate.cc b/src/rm/RequestManagerUserAllocate.cc index 757e856449..63aa6d18af 100644 --- a/src/rm/RequestManagerUserAllocate.cc +++ b/src/rm/RequestManagerUserAllocate.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -40,7 +40,7 @@ void RequestManager::UserAllocate::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"UserAllocate method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"UserAllocate method invoked"); // Get the parameters session = xmlrpc_c::value_string(paramList.getString(0)); @@ -67,7 +67,7 @@ void RequestManager::UserAllocate::execute( // Now let's add the user rc = UserAllocate::upool->allocate(&uid,username,password,true); - if ( rc != 0 ) + if ( rc == -1 ) { goto error_allocate; } @@ -102,7 +102,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/rm/RequestManagerUserDelete.cc b/src/rm/RequestManagerUserDelete.cc index a9d472c96d..508580c1a3 100644 --- a/src/rm/RequestManagerUserDelete.cc +++ b/src/rm/RequestManagerUserDelete.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -36,7 +36,7 @@ void RequestManager::UserDelete::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"UserDelete method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"UserDelete method invoked"); // Get the parameters session = xmlrpc_c::value_string(paramList.getString(0)); @@ -104,7 +104,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/rm/RequestManagerUserInfo.cc b/src/rm/RequestManagerUserInfo.cc index 188a63b41d..1c7ea7fc19 100644 --- a/src/rm/RequestManagerUserInfo.cc +++ b/src/rm/RequestManagerUserInfo.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -36,7 +36,7 @@ void RequestManager::UserInfo::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"UserInfo method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"UserInfo method invoked"); // Get the parameters session = xmlrpc_c::value_string(paramList.getString(0)); @@ -87,7 +87,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/rm/RequestManagerUserPoolInfo.cc b/src/rm/RequestManagerUserPoolInfo.cc index 1882034929..96bd11f977 100644 --- a/src/rm/RequestManagerUserPoolInfo.cc +++ b/src/rm/RequestManagerUserPoolInfo.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -33,7 +33,7 @@ void RequestManager::UserPoolInfo::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"UserPoolInfo method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"UserPoolInfo method invoked"); // Get the parameters session = xmlrpc_c::value_string(paramList.getString(0)); @@ -79,7 +79,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/rm/RequestManagerVirtualNetworkAllocate.cc b/src/rm/RequestManagerVirtualNetworkAllocate.cc index 4480271802..791d0f4b57 100644 --- a/src/rm/RequestManagerVirtualNetworkAllocate.cc +++ b/src/rm/RequestManagerVirtualNetworkAllocate.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -23,17 +23,17 @@ void RequestManager::VirtualNetworkAllocate::execute( xmlrpc_c::paramList const& paramList, xmlrpc_c::value * const retval) -{ +{ string session; string username; string password; string name; string stemplate; - + int nid; int uid; int rc; - + User * user; ostringstream oss; @@ -42,7 +42,7 @@ void RequestManager::VirtualNetworkAllocate::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"VirtualNetworkAllocate method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"VirtualNetworkAllocate method invoked"); // Get the parameters & host session = xmlrpc_c::value_string(paramList.getString(0)); @@ -52,7 +52,7 @@ void RequestManager::VirtualNetworkAllocate::execute( { goto error_session; } - + // Now let's get the user user = VirtualNetworkAllocate::upool->get(username,true); @@ -64,19 +64,19 @@ void RequestManager::VirtualNetworkAllocate::execute( uid = user->get_uid(); user->unlock(); - + rc = vnpool->allocate(uid,stemplate,&nid); - - if ( rc != 0 ) - { - goto error_vn_allocate; + + if ( rc < 0 ) + { + goto error_vn_allocate; } - + //Result arrayData.push_back(xmlrpc_c::value_boolean(true)); // SUCCESS arrayData.push_back(xmlrpc_c::value_int(nid)); arrayresult = new xmlrpc_c::value_array(arrayData); - + *retval = *arrayresult; delete arrayresult; @@ -93,11 +93,11 @@ error_get_user: goto error_common; error_vn_allocate: - oss << "Error allocating VN with template: " << endl << stemplate; + oss << "Error allocating VN with template: " << endl << stemplate; goto error_common; -error_common: - Nebula::log("ReM",Log::ERROR,oss); +error_common: + NebulaLog::log("ReM",Log::ERROR,oss); arrayData.push_back(xmlrpc_c::value_boolean(false)); arrayData.push_back(xmlrpc_c::value_string(oss.str())); @@ -105,7 +105,7 @@ error_common: xmlrpc_c::value_array arrayresult_error(arrayData); *retval = arrayresult_error; - + return; } diff --git a/src/rm/RequestManagerVirtualNetworkDelete.cc b/src/rm/RequestManagerVirtualNetworkDelete.cc index 8b390dfd59..b16e9803aa 100644 --- a/src/rm/RequestManagerVirtualNetworkDelete.cc +++ b/src/rm/RequestManagerVirtualNetworkDelete.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -39,7 +39,7 @@ void RequestManager::VirtualNetworkDelete::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"VirtualNetworkDelete method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"VirtualNetworkDelete method invoked"); // Get the parameters & host session = xmlrpc_c::value_string(paramList.getString(0)); @@ -88,7 +88,7 @@ error_vn_get: goto error_common; error_common: - Nebula::log ("Rem",Log::ERROR,oss); + NebulaLog::log ("Rem",Log::ERROR,oss); arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); diff --git a/src/rm/RequestManagerVirtualNetworkInfo.cc b/src/rm/RequestManagerVirtualNetworkInfo.cc index 113536d457..046f74b20d 100644 --- a/src/rm/RequestManagerVirtualNetworkInfo.cc +++ b/src/rm/RequestManagerVirtualNetworkInfo.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -38,7 +38,7 @@ void RequestManager::VirtualNetworkInfo::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"VirtualNetworkInfo method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"VirtualNetworkInfo method invoked"); // Get the parameters & host session = xmlrpc_c::value_string(paramList.getString(0)); @@ -88,7 +88,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/rm/RequestManagerVirtualNetworkPoolInfo.cc b/src/rm/RequestManagerVirtualNetworkPoolInfo.cc index a85e8b4489..ac1294d203 100755 --- a/src/rm/RequestManagerVirtualNetworkPoolInfo.cc +++ b/src/rm/RequestManagerVirtualNetworkPoolInfo.cc @@ -15,7 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" -#include "Nebula.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -40,7 +40,7 @@ void RequestManager::VirtualNetworkPoolInfo::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; - Nebula::log("ReM",Log::DEBUG,"VirtualNetworkPoolInfo method invoked"); + NebulaLog::log("ReM",Log::DEBUG,"VirtualNetworkPoolInfo method invoked"); // Get the parameters session = xmlrpc_c::value_string(paramList.getString(0)); @@ -121,7 +121,7 @@ error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); - Nebula::log("ReM",Log::ERROR,oss); + NebulaLog::log("ReM",Log::ERROR,oss); xmlrpc_c::value_array arrayresult_error(arrayData); diff --git a/src/scheduler/SConstruct b/src/scheduler/SConstruct index 2988ac6f65..faf7577778 100644 --- a/src/scheduler/SConstruct +++ b/src/scheduler/SConstruct @@ -1,5 +1,3 @@ -# SConstruct for src/nebula - # -------------------------------------------------------------------------- # # Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) # # # @@ -17,46 +15,90 @@ #--------------------------------------------------------------------------- # import os -Import('env') +import sys +import shutil +sys.path.append("../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located cwd=os.getcwd() -env.Append(LIBPATH=cwd) -lib_name='nebula_scheduler' +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] -# Sources to generate the library -source_files=[ - 'Scheduler.cc', - 'SchedulerHost.cc', - 'SchedulerVirtualMachine.cc', -] +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) -scheduler_names=[ - 'mm_sched' -] - -# Build library -env.StaticLibrary(lib_name, source_files) - -env.Append(LIBS=[ - 'sqlite3', - 'crypto', - lib_name, - 'nebula_core', - 'nebula_host', - 'nebula_vm', - 'nebula_vnm', - 'nebula_pool', - 'nebula_template', - 'nebula_common', - 'nebula_um', +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include/', + cwd + '../../../include/' ]) +# Library dirs +main_env.Append(LIBPATH=[ + cwd+'/src/xml', + cwd+'/src/pool', + cwd+'/src/sched', + cwd+'/../log', + cwd+'/../common', +]) -if not env.GetOption('clean'): - env.ParseConfig('../../share/scons/get_xmlrpc_config client') +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) +# Linking flags +main_env.Append(LDFLAGS=["-g"]) -# Build tests -for sched in scheduler_names: - env.Program(sched, sched+'.cc') +################################################################################ +# EXTRA CONFIGURATION +################################################################################ + +#------------------------------------------------------------------------------- +# xmlrpc +#------------------------------------------------------------------------------- + +xmlrpc_dir=ARGUMENTS.get('xmlrpc', 'none') + +if xmlrpc_dir!='none': + main_env.Append(LIBPATH=[xmlrpc_dir+"/lib"]) + main_env.Append(CPPPATH=[xmlrpc_dir+"/include"]) + +main_env.ParseConfig('../../share/scons/get_xmlrpc_config client') + +#------------------------------------------------------------------------------- +# build lex/bison +#------------------------------------------------------------------------------- + +build_parsers=ARGUMENTS.get('parsers', 'no') + +if build_parsers=='yes': + main_env.Append(parsers='yes') +else: + main_env.Append(parsers='no') + +#------------------------------------------------------------------------------- +# libxml2 +#------------------------------------------------------------------------------- + +main_env.ParseConfig('xml2-config --libs --cflags') + +################################################################################ +# SCONS scripts to build +################################################################################ + +build_scripts=[ + 'src/xml/SConstruct', + 'src/pool/SConstruct', + 'src/sched/SConstruct' +] + +for script in build_scripts: + env=main_env.Clone() + SConscript(script, exports='env') diff --git a/src/scheduler/SchedulerHost.cc b/src/scheduler/SchedulerHost.cc deleted file mode 100644 index 7b1b167a41..0000000000 --- a/src/scheduler/SchedulerHost.cc +++ /dev/null @@ -1,177 +0,0 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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 -#include - -#include -#include - -#include "SchedulerHost.h" -#include "Scheduler.h" - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -void SchedulerHost::get_capacity(int& cpu, int& memory, int threshold) -{ - int total_cpu; - - memory = get_share_free_mem(); - cpu = get_share_free_cpu(); - - total_cpu = get_share_max_cpu(); - - /* eg. 96.7 >= 0.9 * 100, We need to round */ - if ( cpu >= threshold * total_cpu ) - { - cpu = (int) ceil((float)cpu/100.0) * 100; - } -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int SchedulerHost::insert(SqliteDB *db) -{ - Scheduler::log("HOST",Log::ERROR, - "Scheduler can not insert hosts in database"); - - return -1; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int SchedulerHost::update(SqliteDB *db) -{ - Scheduler::log("HOST",Log::ERROR, - "Scheduler can not update hosts in database"); - - return -1; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int SchedulerHost::drop(SqliteDB *db) -{ - Scheduler::log("HOST",Log::ERROR, - "Scheduler can not delete hosts from database"); - - return -1; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int SchedulerHostPool::allocate( - PoolObjectSQL *objsql) -{ - Scheduler::log("HOST",Log::ERROR, - "Scheduler can not allocate hosts in database"); - - return -1; -}; - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -void SchedulerHostPool::bootstrap() -{ - Scheduler::log("HOST",Log::ERROR, - "Scheduler can not bootstrap database"); -} - -/* ************************************************************************** */ -/* SchedulerHostPool */ -/* ************************************************************************** */ - -extern "C" -{ - static int set_up_cb ( - void * _hids, - int num, - char ** values, - char ** names) - { - vector * hids; - - hids = static_cast *>(_hids); - - if ((hids==0)||(num<=0)||(values[0]==0)) - { - return -1; - } - - hids->push_back(atoi(values[0])); - - return 0; - }; -} - -/* -------------------------------------------------------------------------- */ - -int SchedulerHostPool::set_up() -{ - ostringstream oss; - int rc; - - // ------------------------------------------------------------------------- - // Clean the pool to get updated data from db - // ------------------------------------------------------------------------- - - clean(); - - hids.clear(); - - // ------------------------------------------------------------------------- - // Load the ids (to get an updated list of hosts) - // ------------------------------------------------------------------------- - - lock(); - - oss << "SELECT oid FROM " << Host::table - << " WHERE state != " << Host::DISABLED - << " AND state != " << Host::ERROR; - - rc = db->exec(oss,set_up_cb,(void *) &hids); - - if ( rc != 0 ) - { - unlock(); - - return -1; - } - - oss.str(""); - oss << "Discovered Hosts (enabled):"; - - for (unsigned int i=0 ; i < hids.size() ; i++) - { - oss << " " << hids[i]; - } - - Scheduler::log("HOST",Log::DEBUG,oss); - - unlock(); - - return 0; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - diff --git a/src/scheduler/SchedulerVirtualMachine.cc b/src/scheduler/SchedulerVirtualMachine.cc deleted file mode 100644 index 5897d7a096..0000000000 --- a/src/scheduler/SchedulerVirtualMachine.cc +++ /dev/null @@ -1,206 +0,0 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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 -#include - -#include -#include - -#include "SchedulerHost.h" -#include "Scheduler.h" - -/* ************************************************************************** */ -/* SchedulerVirtualMachine */ -/* ************************************************************************** */ - -int SchedulerVirtualMachine::insert(SqliteDB *db) -{ - Scheduler::log("VM",Log::ERROR, - "Scheduler can not insert VMs in database"); - - return -1; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int SchedulerVirtualMachine::update(SqliteDB *db) -{ - Scheduler::log("VM",Log::ERROR, - "Scheduler can not update VMs in database"); - - return -1; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int SchedulerVirtualMachine::drop(SqliteDB *db) -{ - Scheduler::log("VM",Log::ERROR, - "Scheduler can not delete VMs in database"); - - return -1; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -void SchedulerVirtualMachine::set_priorities(vector& total) -{ - if ( hosts.size() != total.size() ) - { - Scheduler::log("VM",Log::ERROR,"Wrong size for priority vector"); - return; - } - - for (unsigned int i=0; ipriority = total[i]; - } - - //Sort the shares using the priority - - sort(hosts.begin(),hosts.end(),SchedulerVirtualMachine::host_cmp); -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int SchedulerVirtualMachine::get_host( - int& hid, - SchedulerHostPool * hpool) -{ - vector::reverse_iterator i; - - vector::iterator j; - SchedulerHost * host; - - int cpu; - int mem; - int dsk; - - get_requirements(cpu,mem,dsk); - - for (i=hosts.rbegin();i!=hosts.rend();i++) - { - host = hpool->get((*i)->hid,false); - - if ( host == 0 ) - { - continue; - } - - if (host->test_capacity(cpu,mem,dsk)==true) - { - host->add_capacity(cpu,mem,dsk); - hid = (*i)->hid; - - return 0; - } - } - - hid = -1; - - return -1; -} - -/* ************************************************************************** */ -/* Scheuler Virtual Machine :: Misc */ -/* ************************************************************************** */ - -ostream& operator<<(ostream& os, SchedulerVirtualMachine& vm) -{ - vector::reverse_iterator i; - vector::iterator j; - - for (i=vm.hosts.rbegin();i!=vm.hosts.rend();i++) - { - os << "\t" << (*i)->priority << "\t" << (*i)->hid << endl; - } - - return os; -}; - -/* ************************************************************************** */ -/* SchedulerVirtualMachinePool */ -/* ************************************************************************** */ - -int SchedulerVirtualMachinePool::allocate( - PoolObjectSQL *objsql) -{ - Scheduler::log("HOST",Log::ERROR, - "Scheduler can not allocate VMs in database"); - - return -1; -}; - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -void SchedulerVirtualMachinePool::bootstrap() -{ - Scheduler::log("HOST",Log::ERROR, - "Scheduler can not bootstrap database"); -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int SchedulerVirtualMachinePool::set_up() -{ - ostringstream oss; - string where; - int rc; - - // ------------------------------------------------------------------------- - // Clean the pool to get updated data from db - // ------------------------------------------------------------------------- - - clean(); - - pending_vms.clear(); - - // ------------------------------------------------------------------------- - // Load an updated list of pending VMs - // ------------------------------------------------------------------------- - - oss << "state == " << VirtualMachine::PENDING; - - where = oss.str(); - - rc = PoolSQL::search( - pending_vms, - VirtualMachine::table, - where); - - oss.str(""); - oss << "Pending virtual machines :"; - - - for (unsigned int i=0 ; i < pending_vms.size() ; i++) - { - oss << " " << pending_vms[i]; - } - - Scheduler::log("VM",Log::DEBUG,oss); - - return rc; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ diff --git a/src/scheduler/include/Client.h b/src/scheduler/include/Client.h new file mode 100644 index 0000000000..47bad049b0 --- /dev/null +++ b/src/scheduler/include/Client.h @@ -0,0 +1,104 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 ONE_CLIENT_H_ +#define ONE_CLIENT_H_ + +#include +#include + +#include +#include +#include + +#include "NebulaLog.h" + +using namespace std; + +// ============================================================================= +// Doc: +// http://xmlrpc-c.sourceforge.net/doc/#clientexamplepp +// http://xmlrpc-c.sourceforge.net/doc/libxmlrpc_client++.html#simple_client +// ============================================================================= + +//TODO add documentation to the Client methods... + +/** + * This class represents the connection with the core and handles the + * xml-rpc calls. + */ +class Client : public xmlrpc_c::clientSimple +{ +public: + //-------------------------------------------------------------------------- + // PUBLIC INTERFACE + //-------------------------------------------------------------------------- + + /** + * Creates a new xml-rpc client with specified options. + * + * @param secret A string containing the ONE user:password tuple. + * If not set, the auth. file will be assumed to be at $ONE_AUTH + * @param endpoint Where the rpc server is listening, must be something + * like "http://localhost:2633/RPC2". If not set, the endpoint will be set + * to $ONE_XMLRPC. + * @throws Exception if the authorization options are invalid + */ + Client( string secret = "", + string endpoint = "") + { + set_one_auth(secret); + set_one_endpoint(endpoint); + + xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, 1024*MESSAGE_SIZE); + } + + const string& get_oneauth() + { + return one_auth; + } + + const string& get_endpoint() + { + return one_endpoint; + } + + //-------------------------------------------------------------------------- + // PRIVATE ATTRIBUTES AND METHODS + //-------------------------------------------------------------------------- + +private: + + string one_auth; + string one_endpoint; + + void set_one_auth(string secret); + + void set_one_endpoint(string endpoint); + + int read_oneauth(string &secret); + + int split_secret(const string secret, string& user, string& pass); + + string sha1_digest(const string& pass); + + /** + * Default message size for XML data off the network + */ + static const int MESSAGE_SIZE; +}; + +#endif /*ONECLIENT_H_*/ diff --git a/src/scheduler/include/HostPoolXML.h b/src/scheduler/include/HostPoolXML.h new file mode 100644 index 0000000000..c0fc31a972 --- /dev/null +++ b/src/scheduler/include/HostPoolXML.h @@ -0,0 +1,57 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 HOST_POOL_XML_H_ +#define HOST_POOL_XML_H_ + +#include "PoolXML.h" +#include "HostXML.h" + +using namespace std; + +class HostPoolXML : public PoolXML +{ +public: + + HostPoolXML(Client* client):PoolXML(client){}; + + int set_up(); + + /** + * Gets an object from the pool + * @param oid the object unique identifier + * + * @return a pointer to the object, 0 in case of failure + */ + HostXML * get(int oid) const + { + return static_cast(PoolXML::get(oid)); + }; + +protected: + + int get_suitable_nodes(vector& content) + { + return get_nodes("/HOST_POOL/HOST[STATE<3]", content); + }; + + virtual void add_object(xmlNodePtr node); + + virtual int load_info(xmlrpc_c::value &result); +}; + +#endif /* HOST_POOL_XML_H_ */ diff --git a/src/scheduler/include/HostXML.h b/src/scheduler/include/HostXML.h new file mode 100644 index 0000000000..18f4b97939 --- /dev/null +++ b/src/scheduler/include/HostXML.h @@ -0,0 +1,107 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 HOST_XML_H_ +#define HOST_XML_H_ + +#include "ObjectXML.h" + +using namespace std; + +class HostXML : public ObjectXML +{ +public: + + HostXML(const string &xml_doc):ObjectXML(xml_doc) + { + init_attributes(); + }; + + int get_hid() const + { + return oid; + }; + + /** + * Gets the current host capacity + * @param cpu the host free cpu, scaled according to a given threshold + * @param memory the host free memory + * @param threshold to consider the host totally free + */ + void get_capacity(int& cpu, int& memory, int threshold) const; + + /** + * Tests whether a new VM can be hosted by the host or not + * @param cpu needed by the VM (percentage) + * @param mem needed by the VM (in Kb) + * @param disk needed by the VM + * @return true if the share can host the VM + */ + bool test_capacity(int cpu, int mem, int disk) const + { + return (((max_cpu - cpu_usage ) >= cpu) && + ((max_mem - mem_usage ) >= mem) && + ((max_disk - disk_usage) >= disk)); + }; + + /** + * Adds a new VM to the given share by incrementing the cpu,mem and disk + * counters + * @param cpu needed by the VM (percentage) + * @param mem needed by the VM (in Kb) + * @param disk needed by the VM + * @return 0 on success + */ + void add_capacity(int cpu, int mem, int disk) + { + cpu_usage += cpu; + mem_usage += mem; + disk_usage += disk; + + running_vms++; + }; + + +protected: + + // TODO Check if any of these are not needed, and delete them. + int oid; + + // Host share values + int disk_usage; /**< Disk allocated to VMs (in Mb). */ + int mem_usage; /**< Memory allocated to VMs (in Mb) */ + int cpu_usage; /**< CPU allocated to VMs (in percentage) */ + + int max_disk; /**< Total disk capacity (in Mb) */ + int max_mem; /**< Total memory capacity (in Mb) */ + int max_cpu; /**< Total cpu capacity (in percentage) */ + + int free_disk; /**< Free disk from the IM monitor */ + int free_mem; /**< Free memory from the IM monitor */ + int free_cpu; /**< Free cpu from the IM monitor */ + + int used_disk; /**< Used disk from the IM monitor */ + int used_mem; /**< Used memory from the IM monitor */ + int used_cpu; /**< Used cpu from the IM monitor */ + + int running_vms; /**< Number of running VMs in this Host */ + + + void init_attributes(); +}; + +#endif /* HOST_XML_H_ */ diff --git a/src/scheduler/include/ObjectXML.h b/src/scheduler/include/ObjectXML.h new file mode 100644 index 0000000000..be27cac09d --- /dev/null +++ b/src/scheduler/include/ObjectXML.h @@ -0,0 +1,138 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 OBJECT_XML_H_ +#define OBJECT_XML_H_ + +#include +#include + +#include +#include +#include +#include + +using namespace std; + +/** + * This class represents a generic Object supported by a xml document. + * The class provides basic methods to query attributes, and get xml nodes + */ +class ObjectXML +{ +public: + + // ---------------------- Constructors ------------------------------------ + + ObjectXML():xml(0),ctx(0){}; + + /** + * Constructs an object using a XML document + */ + ObjectXML(const string &xml_doc); + + /** + * Constructs an object using a XML Node. The node is copied to the new + * object + */ + ObjectXML(const xmlNodePtr node); + + virtual ~ObjectXML(); + + /** + * Access Object elements using Xpath + * @param xpath_expr the Xpath of the element + * @return a vector with the elements + */ + vector operator[] (const char * xpath_expr); + + /** + * Get xml nodes by Xpath + * @param xpath_expr the Xpath for the elements + * @param content nodes for the given Xpath expression. The nodes are + * returned as pointers to the object nodes. + * @return the number of nodes found + */ + int get_nodes (const char * xpath_expr, vector& content); + + /** + * Updates the object representation with a new XML document. Previous + * XML resources are freed + * @param xml_doc the new xml document + */ + int update(const string &xml_doc); + + // --------------------------------------------------------- + // Lex & bison parser for requirements and rank expressions + // --------------------------------------------------------- + + /** + * Evaluates a requirement expression on the given host. + * @param requirements string + * @param result true if the host matches the requirements + * @param errmsg string describing the error, must be freed by the + * calling function + * @return 0 on success + */ + int eval_bool(const string& expr, bool& result, char **errmsg); + + /** + * Evaluates a rank expression on the given host. + * @param rank string + * @param result of the rank evaluation + * @param errmsg string describing the error, must be freed by the + * calling function + * @return 0 on success + */ + int eval_arith(const string& expr, int& result, char **errmsg); + + /** + * Function to write the Object in an output stream + */ + friend ostream& operator<<(ostream& os, ObjectXML& oxml) + { + xmlChar * mem; + int size; + + xmlDocDumpMemory(oxml.xml,&mem,&size); + + string str(reinterpret_cast(mem)); + os << str; + + xmlFree(mem); + + return os; + }; + +private: + /** + * XML representation of the Object + */ + xmlDocPtr xml; + + /** + * XPath Context to access Object elements + */ + xmlXPathContextPtr ctx; + + /** + * Parse a XML documents and initializes XPath contexts + */ + void xml_parse(const string &xml_doc); +}; + +#endif /*OBJECT_XML_H_*/ diff --git a/src/scheduler/include/PoolXML.h b/src/scheduler/include/PoolXML.h new file mode 100644 index 0000000000..7a4ed1d629 --- /dev/null +++ b/src/scheduler/include/PoolXML.h @@ -0,0 +1,196 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 POOL_XML_H_ +#define POOL_XML_H_ + +#include "NebulaLog.h" +#include "ObjectXML.h" +#include "Client.h" + +using namespace std; + +class PoolXML : public ObjectXML +{ +public: + /** + * + * + */ + const map& get_objects() const + { + return objects; + }; + + /** + * Set ups the pool by performing the following actions: + * - All the objects stored in the pool are flushed + * - The suitable objects in the database are loaded + * @return 0 on success + */ + virtual int set_up() + { + int rc; + + // ------------------------------------------------------------------------- + // Clean the pool to get updated data from OpenNebula + // ------------------------------------------------------------------------- + + flush(); + + // ------------------------------------------------------------------------- + // Load the ids (to get an updated list of hosts) + // ------------------------------------------------------------------------- + + xmlrpc_c::value result; + + rc = load_info(result); + + if ( rc != 0 ) + { + NebulaLog::log("POOL",Log::ERROR, + "Could not retrieve pool info from ONE"); + return -1; + } + + vector values = + xmlrpc_c::value_array(result).vectorValueValue(); + + bool success = xmlrpc_c::value_boolean( values[0] ); + string message = xmlrpc_c::value_string( values[1] ); + + if( !success ) + { + ostringstream oss; + + oss << "ONE returned error while retrieving pool info:" << endl; + oss << message; + + NebulaLog::log("POOL", Log::ERROR, oss); + return -1; + } + + update(message); + + vector nodes; + int num_objs; + + num_objs = get_suitable_nodes(nodes); + + for (unsigned int i=0 ; + i < nodes.size() && ( pool_limit <= 0 || i < pool_limit ) ; + i++) + { + add_object(nodes[i]); + } + + return 0; + }; + + /** + * Gets an object from the pool + * @param oid the object unique identifier + * + * @return a pointer to the object, 0 in case of failure + */ + virtual ObjectXML * get(int oid) const + { + map::const_iterator it; + + it = objects.find(oid); + + if ( it == objects.end() ) + { + return 0; + } + else + { + return it->second; + } + }; + +protected: + + // ------------------------------------------------------------------------ + + PoolXML(Client* client, unsigned int pool_limit = 0):ObjectXML() + { + this->client = client; + this->pool_limit = pool_limit; + }; + + virtual ~PoolXML() + { + flush(); + }; + + // ------------------------------------------------------------------------ + + /** + * Inserts a new ObjectXML into the objects map + */ + virtual void add_object(xmlNodePtr node) = 0; + + /** + * + */ + virtual int get_suitable_nodes(vector& content) = 0; + + /** + * + */ + virtual int load_info(xmlrpc_c::value &result) = 0; + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + /** + * XML-RPC client + */ + Client * client; + + /** + * Limit of pool elements to process (request individual info) + * from the pool. + */ + unsigned int pool_limit; + + /** + * Hash map contains the suitable [id, object] pairs. + */ + map objects; + + +private: + /** + * Deletes pool objects and frees resources. + */ + void flush() + { + map::iterator it; + + for (it=objects.begin();it!=objects.end();it++) + { + delete it->second; + } + + objects.clear(); + } +}; + +#endif /* POOL_XML_H_ */ diff --git a/src/scheduler/RankPolicy.h b/src/scheduler/include/RankPolicy.h similarity index 64% rename from src/scheduler/RankPolicy.h rename to src/scheduler/include/RankPolicy.h index 1f43705bc6..7b11b79342 100644 --- a/src/scheduler/RankPolicy.h +++ b/src/scheduler/include/RankPolicy.h @@ -22,68 +22,68 @@ using namespace std; -class RankPolicy : public SchedulerHostPolicy +class RankPolicy : public SchedulerHostPolicy { public: - + RankPolicy( - SchedulerVirtualMachinePool * vmpool, - SchedulerHostPool * hpool, + VirtualMachinePoolXML * vmpool, + HostPoolXML * hpool, float w=1.0):SchedulerHostPolicy(vmpool,hpool,w){}; - + ~RankPolicy(){}; private: void policy( - SchedulerVirtualMachine * vm) - { + VirtualMachineXML * vm) + { string srank; int rank; - + char * errmsg; int rc; - + vector hids; unsigned int i; - - SchedulerHost * host; - + + HostXML * host; + vm->get_matching_hosts(hids); - - vm->get_template_attribute("RANK",srank); - + + srank = vm->get_rank(); + if (srank == "") { - Scheduler::log("RANK",Log::WARNING,"No rank defined for VM"); + NebulaLog::log("RANK",Log::WARNING,"No rank defined for VM"); } for (i=0;iget(hids[i],false); - + host = hpool->get(hids[i]); + if ( host != 0 ) - { - rc = host->rank(srank, rank, &errmsg); - - if (rc != 0) - { - ostringstream oss; - - oss << "Computing host rank, expression: " << srank - << ", error: " << errmsg; - Scheduler::log("RANK",Log::ERROR,oss); - - free(errmsg); - } + { + rc = host->eval_arith(srank, rank, &errmsg); + + if (rc != 0) + { + ostringstream oss; + + oss << "Computing host rank, expression: " << srank + << ", error: " << errmsg; + NebulaLog::log("RANK",Log::ERROR,oss); + + free(errmsg); + } } } - - priority.push_back(rank); + + priority.push_back(rank); } } }; diff --git a/include/Scheduler.h b/src/scheduler/include/Scheduler.h similarity index 59% rename from include/Scheduler.h rename to src/scheduler/include/Scheduler.h index d0e45d1aff..bd972185ff 100644 --- a/include/Scheduler.h +++ b/src/scheduler/include/Scheduler.h @@ -18,20 +18,13 @@ #define SCHEDULER_H_ #include "Log.h" -#include "SchedulerHost.h" -#include "SchedulerVirtualMachine.h" +#include "HostPoolXML.h" +#include "VirtualMachinePoolXML.h" #include "SchedulerPolicy.h" #include "ActionManager.h" -#include -#include -#include -#include -#include - using namespace std; - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -44,160 +37,128 @@ extern "C" void * scheduler_action_loop(void *arg); class Scheduler: public ActionListener { public: - - // --------------------------------------------------------------- - // Loggging - // --------------------------------------------------------------- - - static void log( - const char * module, - const Log::MessageType type, - const ostringstream& message, - const char * filename = 0, - Log::MessageType clevel = Log::DEBUG) - { - static Log scheduler_log(filename,clevel); - static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; - - pthread_mutex_lock(&log_mutex); - scheduler_log.log(module,type,message); - pthread_mutex_unlock(&log_mutex); - }; - static void log( - const char * module, - const Log::MessageType type, - const char * message, - const char * filename = 0) - { - ostringstream os(message); - - Scheduler::log(module,type,os,filename); - }; - void start(); - + virtual void register_policies() = 0; - + protected: - - Scheduler(string& url, time_t _timer) - :hpool(0),vmpool(0),db(0),one_url(url),timer(_timer),threshold(0.9) + + Scheduler(string& _url, time_t _timer, + int _machines_limit, int _dispatch_limit): + hpool(0), + vmpool(0), + timer(_timer), + url(_url), + machines_limit(_machines_limit), + dispatch_limit(_dispatch_limit), + threshold(0.9), + client(0) { am.addListener(this); }; - + virtual ~Scheduler() - { + { if ( hpool != 0) { delete hpool; } - + if ( vmpool != 0) { delete vmpool; } - if (db != 0) + if ( client != 0) { - delete db; + delete client; } }; // --------------------------------------------------------------- // Pools // --------------------------------------------------------------- - - SchedulerHostPool * hpool; - SchedulerVirtualMachinePool * vmpool; - + + HostPoolXML * hpool; + VirtualMachinePoolXML * vmpool; + // --------------------------------------------------------------- // Scheduler Policies // --------------------------------------------------------------- - + void add_host_policy(SchedulerHostPolicy *policy) { - host_policies.push_back(policy); + host_policies.push_back(policy); } - + // --------------------------------------------------------------- // Scheduler main methods // --------------------------------------------------------------- /** - * Gets the hosts that match the requirements of the pending VMs, also - * the capacity of the host is checked. If there is enough room to host the - * VM a share vector is added to the VM. + * Gets the hosts that match the requirements of the pending VMs, also + * the capacity of the host is checked. If there is enough room to host the + * VM a share vector is added to the VM. */ virtual void match(); - + virtual void dispatch(); virtual int schedule(); - + virtual int set_up_pools(); - + private: Scheduler(Scheduler const&){}; - - Scheduler& operator=(Scheduler const&){return *this;}; - - friend void * scheduler_action_loop(void *arg); - - // --------------------------------------------------------------- - // Database - // --------------------------------------------------------------- - SqliteDB * db; - + Scheduler& operator=(Scheduler const&){return *this;}; + + friend void * scheduler_action_loop(void *arg); + + // --------------------------------------------------------------- // Scheduling Policies // --------------------------------------------------------------- - + vector host_policies; // --------------------------------------------------------------- // Configuration attributes // --------------------------------------------------------------- - - /** - * the URL of the XML-RPC server - */ - string one_url; - time_t timer; - + + string url; + + /** + * Limit of pending virtual machines to process from the pool. + */ + unsigned int machines_limit; + + /** + * Limit of virtual machines to ask OpenNebula core to deploy. + */ + unsigned int dispatch_limit; + /** * Threshold value to round up freecpu */ float threshold; - + + /** + * XML_RPC client + */ + Client * client; + // --------------------------------------------------------------- // Timer to periodically schedule and dispatch VMs // --------------------------------------------------------------- - + pthread_t sched_thread; ActionManager am; void do_action(const string &name, void *args); - - // --------------------------------------------------------------- - // XML_RPC related variables - // --------------------------------------------------------------- - - /** - * The authentication token - */ - string secret; - - /** - * NOTE (from lib doc): "you may not have more than one object of this - * class in a program. The code is not re-entrant -- it uses global - * variables." - */ - xmlrpc_c::clientSimple xmlrpc_client; }; #endif /*SCHEDULER_H_*/ diff --git a/include/SchedulerPolicy.h b/src/scheduler/include/SchedulerPolicy.h similarity index 82% rename from include/SchedulerPolicy.h rename to src/scheduler/include/SchedulerPolicy.h index 09efa5dc7b..d5bc802089 100644 --- a/include/SchedulerPolicy.h +++ b/src/scheduler/include/SchedulerPolicy.h @@ -17,45 +17,46 @@ #ifndef SCHEDULER_POLICY_H_ #define SCHEDULER_POLICY_H_ -#include "SchedulerHost.h" -#include "SchedulerVirtualMachine.h" +#include "HostPoolXML.h" +#include "VirtualMachinePoolXML.h" #include +#include using namespace std; class SchedulerHostPolicy { public: - + SchedulerHostPolicy( - SchedulerVirtualMachinePool * _vmpool, - SchedulerHostPool * _hpool, + VirtualMachinePoolXML * _vmpool, + HostPoolXML * _hpool, float w=1.0): vmpool(_vmpool),hpool(_hpool),sw(w){}; - + virtual ~SchedulerHostPolicy(){}; - + const vector& get( - SchedulerVirtualMachine * vm) + VirtualMachineXML * vm) { priority.clear(); - + policy(vm); - - if(priority.empty()!=true) - { + + if(priority.empty()!=true) + { sw.max = fabs(*max_element( priority.begin(), priority.end(), SchedulerHostPolicy::abs_cmp)); - + transform( priority.begin(), priority.end(), priority.begin(), sw); } - + return priority; }; @@ -63,27 +64,27 @@ protected: vector priority; - virtual void policy(SchedulerVirtualMachine * vm) = 0; - - SchedulerVirtualMachinePool * vmpool; - SchedulerHostPool * hpool; - + virtual void policy(VirtualMachineXML * vm) = 0; + + VirtualMachinePoolXML * vmpool; + HostPoolXML * hpool; + private: static bool abs_cmp(float fl1, float fl2) { return fabs(fl1)(PoolXML::get(oid)); + }; + + int dispatch(int vid, int hid) const; + +protected: + + int get_suitable_nodes(vector& content) + { + // Return VMs in PENDING state (PENDING = 1) + return get_nodes("/VM_POOL/VM[STATE=1]", content); + }; + + virtual void add_object(xmlNodePtr node); + + virtual int load_info(xmlrpc_c::value &result); +}; + +#endif /* VM_POOL_XML_H_ */ diff --git a/src/scheduler/include/VirtualMachineXML.h b/src/scheduler/include/VirtualMachineXML.h new file mode 100644 index 0000000000..01433fce58 --- /dev/null +++ b/src/scheduler/include/VirtualMachineXML.h @@ -0,0 +1,138 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 VM_XML_H_ +#define VM_XML_H_ + +#include + +#include "ObjectXML.h" +#include "HostPoolXML.h" + +using namespace std; + +class VirtualMachineXML : public ObjectXML +{ +public: + VirtualMachineXML(const string &xml_doc); + + ~VirtualMachineXML(); + + + int get_oid() const + { + return oid; + }; + + /** + * Adds a new share to the map of suitable shares to start this VM + * @param hid of the selected host + * @param hsid of the selected host share + */ + void add_host(int hid); + + /** + * Gets the matching hosts ids + * @param mh vector with the hids of the matching hosts + */ + void get_matching_hosts(vector& mh); + + /** + * Sets the priorities for each matching host + */ + void set_priorities(vector& total); + + /** + * + */ + int get_host(int& hid, HostPoolXML * hpool); + + void get_requirements (int& cpu, int& memory, int& disk); + + const string& get_rank() + { + return rank; + }; + + const string& get_requirements() + { + return requirements; + }; + + /** + * Function to write a Virtual Machine in an output stream + */ + friend ostream& operator<<(ostream& os, VirtualMachineXML& vm) + { + vector::reverse_iterator i; + vector::iterator j; + + for (i=vm.hosts.rbegin();i!=vm.hosts.rend();i++) + { + os << "\t" << (*i)->priority << "\t" << (*i)->hid << endl; + } + + return os; + }; + +protected: + + //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + struct Host + { + int hid; + float priority; + + Host(int _hid): + hid(_hid), + priority(0){}; + + ~Host(){}; + + bool operator<(const Host& b) const { //Sort by priority + return priority < b.priority; + } + }; + + static bool host_cmp (const Host * a, const Host * b ) + { + return (*a < *b ); + }; + //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + + // ----------------------- VIRTUAL MACHINE ATTRIBUTES -------------------- + /** + * + */ + int oid; + + int memory; + float cpu; + + string rank; + string requirements; + + /** + * Matching hosts + */ + vector hosts; + +}; + +#endif /* VM_XML_H_ */ diff --git a/src/scheduler/src/pool/HostPoolXML.cc b/src/scheduler/src/pool/HostPoolXML.cc new file mode 100644 index 0000000000..ddaccb64ce --- /dev/null +++ b/src/scheduler/src/pool/HostPoolXML.cc @@ -0,0 +1,126 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 "HostPoolXML.h" + + +int HostPoolXML::set_up() +{ + ostringstream oss; + int rc; + + rc = PoolXML::set_up(); + + if ( rc == 0 ) + { + oss.str(""); + oss << "Discovered Hosts (enabled):"; + + map::iterator it; + + for (it=objects.begin();it!=objects.end();it++) + { + oss << " " << it->first; + } + + NebulaLog::log("HOST",Log::DEBUG,oss); + } + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void HostPoolXML::add_object(xmlNodePtr node) +{ + if ( node == 0 || node->children == 0 ) + { + NebulaLog::log("HOST",Log::ERROR, + "XML Node does not represent a valid Host"); + + return; + } + + xmlChar * str_ptr = xmlNodeGetContent(node->children); + istringstream iss(reinterpret_cast(str_ptr)); + + int hid; + xmlrpc_c::value result; + + iss >> hid; + xmlFree(str_ptr); + + client->call(client->get_endpoint(), // serverUrl + "one.host.info", // methodName + "si", // arguments format + &result, // resultP + client->get_oneauth().c_str(), // argument 0 + hid); // argument 1 + + vector values = + xmlrpc_c::value_array(result).vectorValueValue(); + + bool success = xmlrpc_c::value_boolean( values[0] ); + string message = xmlrpc_c::value_string( values[1] ); + + if( !success ) + { + ostringstream oss; + + oss << "ONE returned error while retrieving info for Host " << hid; + oss << ":" << endl; + oss << message; + + NebulaLog::log("HOST",Log::ERROR,oss); + } + else + { + HostXML* host = new HostXML( message ); + + objects.insert( pair(hid, host) ); + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int HostPoolXML::load_info(xmlrpc_c::value &result) +{ + try + { + client->call( client->get_endpoint(), // serverUrl + "one.hostpool.info", // methodName + "s", // arguments format + &result, // resultP + client->get_oneauth().c_str() // argument + ); + return 0; + } + catch (exception const& e) + { + ostringstream oss; + oss << "Exception raised: " << e.what(); + + NebulaLog::log("HOST", Log::ERROR, oss); + + return -1; + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + diff --git a/src/scheduler/src/pool/HostXML.cc b/src/scheduler/src/pool/HostXML.cc new file mode 100644 index 0000000000..bde76da7a7 --- /dev/null +++ b/src/scheduler/src/pool/HostXML.cc @@ -0,0 +1,65 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include "HostXML.h" + + +void HostXML::get_capacity(int& cpu, int& memory, int threshold) const +{ + int total_cpu; + vector result; + + memory = free_mem; + cpu = free_cpu; + total_cpu = max_cpu; + + /* eg. 96.7 >= 0.9 * 100, We need to round */ + if ( cpu >= threshold * total_cpu ) + { + cpu = (int) ceil((float)cpu/100.0) * 100; + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void HostXML::init_attributes() +{ + oid = atoi(((*this)["/HOST/ID"] )[0].c_str() ); + + disk_usage = atoi(((*this)["/HOST/HOST_SHARE/DISK_USAGE"])[0].c_str()); + mem_usage = atoi(((*this)["/HOST/HOST_SHARE/MEM_USAGE"])[0].c_str()); + cpu_usage = atoi(((*this)["/HOST/HOST_SHARE/CPU_USAGE"])[0].c_str()); + + max_disk = atoi(((*this)["/HOST/HOST_SHARE/MAX_DISK"])[0].c_str()); + max_mem = atoi(((*this)["/HOST/HOST_SHARE/MAX_MEM"])[0].c_str()); + max_cpu = atoi(((*this)["/HOST/HOST_SHARE/MAX_CPU"])[0].c_str()); + + free_disk = atoi(((*this)["/HOST/HOST_SHARE/FREE_DISK"])[0].c_str()); + free_mem = atoi(((*this)["/HOST/HOST_SHARE/FREE_MEM"])[0].c_str()); + free_cpu = atoi(((*this)["/HOST/HOST_SHARE/FREE_CPU"])[0].c_str()); + + used_disk = atoi(((*this)["/HOST/HOST_SHARE/USED_DISK"])[0].c_str()); + used_mem = atoi(((*this)["/HOST/HOST_SHARE/USED_MEM"])[0].c_str()); + used_cpu = atoi(((*this)["/HOST/HOST_SHARE/USED_CPU"])[0].c_str()); + + running_vms = atoi(((*this)["/HOST/HOST_SHARE/RUNNING_VMS"])[0].c_str()); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + diff --git a/src/scheduler/src/pool/SConstruct b/src/scheduler/src/pool/SConstruct new file mode 100644 index 0000000000..cea4c527b5 --- /dev/null +++ b/src/scheduler/src/pool/SConstruct @@ -0,0 +1,30 @@ +# SConstruct for src/pool + +# -------------------------------------------------------------------------- # +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +Import('env') + +lib_name='scheduler_pool' + +source_files=[ + 'HostPoolXML.cc', + 'HostXML.cc', + 'VirtualMachinePoolXML.cc', + 'VirtualMachineXML.cc'] + +# Build library +env.StaticLibrary(lib_name, source_files) diff --git a/src/scheduler/src/pool/VirtualMachinePoolXML.cc b/src/scheduler/src/pool/VirtualMachinePoolXML.cc new file mode 100644 index 0000000000..93667fd186 --- /dev/null +++ b/src/scheduler/src/pool/VirtualMachinePoolXML.cc @@ -0,0 +1,191 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 "VirtualMachinePoolXML.h" +#include + +int VirtualMachinePoolXML::set_up() +{ + ostringstream oss; + int rc; + + rc = PoolXML::set_up(); + + if ( rc == 0 ) + { + oss.str(""); + oss << "Pending virtual machines :"; + + map::iterator it; + + for (it=objects.begin();it!=objects.end();it++) + { + oss << " " << it->first; + } + + NebulaLog::log("VM",Log::DEBUG,oss); + } + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachinePoolXML::add_object(xmlNodePtr node) +{ + if ( node == 0 || node->children == 0 || node->children->next==0 ) + { + NebulaLog::log("VM",Log::ERROR, + "XML Node does not represent a valid Virtual Machine"); + + return; + } + + xmlChar * str_ptr = xmlNodeGetContent(node->children); + istringstream iss(reinterpret_cast(str_ptr)); + + int vid; + xmlrpc_c::value result; + + iss >> vid; + xmlFree(str_ptr); + + client->call(client->get_endpoint(), // serverUrl + "one.vm.info", // methodName + "si", // arguments format + &result, // resultP + client->get_oneauth().c_str(), // argument 0 + vid); // argument 1 + + vector values = + xmlrpc_c::value_array(result).vectorValueValue(); + + bool success = xmlrpc_c::value_boolean( values[0] ); + string message = xmlrpc_c::value_string( values[1] ); + + if( !success ) + { + ostringstream oss; + + oss << "ONE returned error while retrieving info for VM " << vid; + oss << ":" << endl; + oss << message; + + NebulaLog::log("VM",Log::ERROR,oss); + } + else + { + try + { + VirtualMachineXML* vm = new VirtualMachineXML( message ); + + objects.insert( pair(vid, vm) ); + } + catch(runtime_error& re) + { + ostringstream oss_re; + + oss_re << re.what(); + NebulaLog::log("VM",Log::ERROR,oss_re); + } + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachinePoolXML::load_info(xmlrpc_c::value &result) +{ + try + { + client->call(client->get_endpoint(), // serverUrl + "one.vmpool.info", // methodName + "si", // arguments format + &result, // resultP + client->get_oneauth().c_str(), // argument 0 + -2); // argument 1 + return 0; + } + catch (exception const& e) + { + ostringstream oss; + oss << "Exception raised: " << e.what(); + + NebulaLog::log("VM", Log::ERROR, oss); + + return -1; + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + + +int VirtualMachinePoolXML::dispatch(int vid, int hid) const +{ + ostringstream oss; + xmlrpc_c::value deploy_result; + + oss.str(""); + oss << "Dispatching virtual machine " << vid + << " to HID: " << hid; + + NebulaLog::log("VM",Log::INFO,oss); + + try + { + client->call( client->get_endpoint(), // serverUrl + "one.vm.deploy", // methodName + "sii", // arguments format + &deploy_result, // resultP + client->get_oneauth().c_str(), // argument 0 + vid, // argument 1 + hid // argument 2 + ); + } + catch (exception const& e) + { + oss.str(""); + oss << "Exception raised: " << e.what() << '\n'; + + NebulaLog::log("VM",Log::ERROR,oss); + + return -1; + } + + // See how ONE handled the deployment + + vector values = + xmlrpc_c::value_array(deploy_result).vectorValueValue(); + + bool success = xmlrpc_c::value_boolean( values[0] ); + + if ( !success ) + { + string message = xmlrpc_c::value_string( values[1] ); + + oss.str(""); + oss << "Error deploying virtual machine " << vid + << " to HID: " << hid << ". Reason: " << message; + + NebulaLog::log("VM",Log::ERROR,oss); + + return -1; + } + + return 0; +} diff --git a/src/scheduler/src/pool/VirtualMachineXML.cc b/src/scheduler/src/pool/VirtualMachineXML.cc new file mode 100644 index 0000000000..e5943fee99 --- /dev/null +++ b/src/scheduler/src/pool/VirtualMachineXML.cc @@ -0,0 +1,186 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 + +#include "VirtualMachineXML.h" + +VirtualMachineXML::VirtualMachineXML(const string &xml_doc):ObjectXML(xml_doc) +{ + vector result; + + oid = atoi(((*this)["/VM/ID"] )[0].c_str() ); + + result = ((*this)["/VM/TEMPLATE/MEMORY"]); + if (result.size() > 0) + { + memory = atoi(result[0].c_str()); + } + else + { + memory = 0; + } + + result = ((*this)["/VM/TEMPLATE/CPU"]); + if (result.size() > 0) + { + istringstream iss; + iss.str( result[0] ); + iss >> cpu; + } + else + { + cpu = 0; + } + + result = ((*this)["/VM/TEMPLATE/RANK"]); + if (result.size() > 0) + { + rank = result[0]; + } + else + { + rank = ""; + } + + result = ((*this)["/VM/TEMPLATE/REQUIREMENTS"]); + if (result.size() > 0) + { + requirements = result[0]; + } + else + { + requirements = ""; + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +VirtualMachineXML::~VirtualMachineXML() +{ + vector::iterator jt; + + for (jt=hosts.begin();jt!=hosts.end();jt++) + { + delete *jt; + } + + hosts.clear(); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachineXML::add_host(int hid) +{ + VirtualMachineXML::Host * ss; + + ss = new VirtualMachineXML::Host(hid); + + hosts.push_back(ss); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachineXML::get_matching_hosts(vector& mh) +{ + vector::iterator i; + + for(i=hosts.begin();i!=hosts.end();i++) + { + mh.push_back((*i)->hid); + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachineXML::set_priorities(vector& total) +{ + if ( hosts.size() != total.size() ) + { + NebulaLog::log("VM",Log::ERROR,"Wrong size for priority vector"); + return; + } + + for (unsigned int i=0; ipriority = total[i]; + } + + //Sort the shares using the priority + sort(hosts.begin(),hosts.end(),VirtualMachineXML::host_cmp); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachineXML::get_host(int& hid, HostPoolXML * hpool) +{ + vector::reverse_iterator i; + + vector::iterator j; + HostXML * host; + + int cpu; + int mem; + int dsk; + + get_requirements(cpu,mem,dsk); + + for (i=hosts.rbegin();i!=hosts.rend();i++) + { + host = hpool->get( (*i)->hid ); + + if ( host == 0 ) + { + continue; + } + + if (host->test_capacity(cpu,mem,dsk)==true) + { + host->add_capacity(cpu,mem,dsk); + hid = (*i)->hid; + + return 0; + } + } + + hid = -1; + + return -1; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachineXML::get_requirements (int& cpu, int& memory, int& disk) +{ + if (this->memory == 0 || this->cpu == 0) + { + cpu = 0; + memory = 0; + disk = 0; + + return; + } + + cpu = (int) (this->cpu * 100);//now in 100% + memory = this->memory * 1024; //now in bytes + disk = 0; +} diff --git a/src/scheduler/src/pool/test/HostXMLTest.cc b/src/scheduler/src/pool/test/HostXMLTest.cc new file mode 100644 index 0000000000..1fbca65e84 --- /dev/null +++ b/src/scheduler/src/pool/test/HostXMLTest.cc @@ -0,0 +1,452 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include + +#include "ObjectXML.h" +#include "HostPoolXML.h" + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class FriendHostPool : public HostPoolXML +{ +public: + FriendHostPool(Client* client):HostPoolXML(client){}; + + friend class HostXMLTest; + + static const string host_dump; + static const string xmls[]; + +protected: + + void add_object(xmlNodePtr node) + { + xmlChar * str_ptr = xmlNodeGetContent(node->children->next); + + int hid; + + if (str_ptr != 0) + { + hid = atoi(reinterpret_cast(str_ptr)); + xmlFree(str_ptr); + } + else + { + + } + + HostXML* vm = new HostXML( xmls[hid] ); + objects.insert( pair(hid, vm) ); + }; + + int load_info(xmlrpc_c::value &result) + { + vector arrayData; + arrayData.push_back(xmlrpc_c::value_boolean(true)); + arrayData.push_back(xmlrpc_c::value_string(host_dump)); + + // Make an XML-RPC array out of it + xmlrpc_c::value_array array(arrayData); + result = array; + + return 0; + }; +}; + + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class HostXMLTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( HostXMLTest ); + + CPPUNIT_TEST( initialization ); + CPPUNIT_TEST( get_capacity ); + CPPUNIT_TEST( test_capacity ); + CPPUNIT_TEST( add_capacity ); + + CPPUNIT_TEST_SUITE_END (); + +private: + FriendHostPool * hp; + +public: + void setUp() + { + xmlInitParser(); + + try + { + hp = new FriendHostPool(NULL); + } + catch(runtime_error& re) + { + cerr << re.what() << endl; + } + }; + + void tearDown() + { + xmlCleanupParser(); + + if (hp != 0) + { + delete hp; + } + }; + + HostXMLTest(){}; + + ~HostXMLTest(){}; + + /* ********************************************************************* */ + + void initialization() + { + int rc; + + + CPPUNIT_ASSERT( hp != 0 ); + + rc = hp->set_up(); + CPPUNIT_ASSERT( rc == 0 ); + + CPPUNIT_ASSERT( hp->objects.size() == 4 ); + CPPUNIT_ASSERT( hp->objects.count(0) == 0); + CPPUNIT_ASSERT( hp->objects.count(1) == 1); + CPPUNIT_ASSERT( hp->objects.count(2) == 1); + CPPUNIT_ASSERT( hp->objects.count(3) == 0); + CPPUNIT_ASSERT( hp->objects.count(4) == 1); + CPPUNIT_ASSERT( hp->objects.count(5) == 1); + CPPUNIT_ASSERT( hp->objects.count(6) == 0); + CPPUNIT_ASSERT( hp->objects.count(7) == 0); + }; + + void get_capacity() + { + int rc; + + + CPPUNIT_ASSERT( hp != 0 ); + + rc = hp->set_up(); + CPPUNIT_ASSERT( rc == 0 ); + + CPPUNIT_ASSERT( hp->objects.size() == 4 ); + + // TODO QUÉ ES THRESHOLD? + int cpu, mem, threshold; + threshold = 100; + + HostXML* host = (HostXML*) hp->objects[5]; + CPPUNIT_ASSERT(host != 0); + + host->get_capacity(cpu, mem, threshold); + + CPPUNIT_ASSERT(mem == 384); + CPPUNIT_ASSERT(cpu == 180); + }; + + void test_capacity() + { + int rc; + + + CPPUNIT_ASSERT( hp != 0 ); + + rc = hp->set_up(); + CPPUNIT_ASSERT( rc == 0 ); + + CPPUNIT_ASSERT( hp->objects.size() == 4 ); + + HostXML* host = (HostXML*) hp->objects[5]; + CPPUNIT_ASSERT(host != 0); + + /* + 256" + 128" + 20" + 512" + 512" + 200" + + 256" + 384" + 180" + */ + + int n_test = 4; + + int disk[] = {256, 260, 0, 100}; + int mem[] = {384, 384, 0, 100}; + int cpu[] = {180, 180, 0, 200}; + bool result[] = {true, false, true, false}; + + for(int i = 0; i < n_test; i++) + { + bool test = host->test_capacity(cpu[i], mem[i], disk[i]); + CPPUNIT_ASSERT(test == result[i]); + } + + }; + + void add_capacity() + { + int rc; + + + CPPUNIT_ASSERT( hp != 0 ); + + rc = hp->set_up(); + CPPUNIT_ASSERT( rc == 0 ); + + CPPUNIT_ASSERT( hp->objects.size() == 4 ); + + HostXML* host = (HostXML*) hp->objects[5]; + CPPUNIT_ASSERT(host != 0); + + // add cpu, mem, disk + host->add_capacity(100, 128, 128); + + + int n_test = 2; + + int disk[] = {256, 128}; + int mem[] = {384, 256}; + int cpu[] = {180, 80}; + bool result[] = {false, true}; + + for(int i = 0; i < n_test; i++) + { + bool test = host->test_capacity(cpu[i], mem[i], disk[i]); + CPPUNIT_ASSERT(test == result[i]); + } + }; +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + // We need to set the log file + NebulaLog::init_log_system(NebulaLog::FILE, Log::DEBUG, "test.log"); + NebulaLog::log("Test", Log::INFO, "Test started"); + + CppUnit::TextUi::TestRunner runner; + + runner.addTest(HostXMLTest::suite()); + runner.run(); + + +// remove("test.log"); + NebulaLog::finalize_log_system(); + + return 0; +} + +// ---------------------------------------------------------------------------- + +const string FriendHostPool::xmls[] = +{ +"", + +"\ + 1\ + ursa12\ + 2\ + im_kvm\ + vmm_kvm\ + tm_nfs\ + 1274107238\ + \ + 1\ + 0\ + 0\ + 0\ + 0\ + 8194368\ + 800\ + 0\ + 7954812\ + 800\ + 0\ + 536220\ + 0\ + 0\ + \ + \ +", + +"\ + 2\ + ursa\ + 2\ + im_kvm\ + vmm_kvm\ + tm_nfs\ + 1274107299\ + \ + 2\ + 0\ + 4280320\ + 700\ + 0\ + 16468252\ + 800\ + 0\ + 9104256\ + 613\ + 0\ + 13897924\ + 186\ + 7\ + \ + \ +", + +"", + +"\ + 4\ + ursa11\ + 2\ + im_kvm\ + vmm_kvm\ + tm_nfs\ + 1274107328\ + \ + 4\ + 0\ + 0\ + 0\ + 0\ + 8194368\ + 800\ + 0\ + 7958684\ + 800\ + 0\ + 621616\ + 0\ + 0\ + \ + \ +", + +"\ + 5\ + ursa10\ + 2\ + im_kvm\ + vmm_kvm\ + tm_nfs\ + 1274107300\ + \ + 5\ + 256\ + 128\ + 20\ + 512\ + 512\ + 200\ + 256\ + 384\ + 180\ + 0\ + 2191756\ + 6\ + 0\ + \ + \ +" +}; + +const string FriendHostPool::host_dump = +" 1 ursa12 2 im_kvm vmm_kvm tm_nfs 1274107145 1 0 0 0 0 8194368 800 0 7955180 800 0 535848 0 0 2 ursa 2 im_kvm vmm_kvm tm_nfs 1274107206 2 0 4280320 700 0 16468252 800 0 9109156 628 0 13891232 172 7 4 ursa11 2 im_kvm vmm_kvm tm_nfs 1274107145 4 0 0 0 0 8194368 800 0 7958684 800 0 621616 0 0 5 ursa10 2 im_kvm vmm_kvm tm_nfs 1274107207 5 0 0 0 0 8194368 800 0 7870776 796 0 2192424 4 0 6 ursa08 3 im_kvm vmm_kvm tm_nfs 1274107176 6 0 0 0 0 0 0 0 6585200 0 0 1132608 0 0 7 ursa09 3 im_kvm vmm_kvm tm_nfs 1274107146 7 0 524288 100 0 8194368 800 0 7286128 798 0 8011908 1 1 "; + + diff --git a/src/scheduler/src/pool/test/SConstruct b/src/scheduler/src/pool/test/SConstruct new file mode 100644 index 0000000000..ad97e0adca --- /dev/null +++ b/src/scheduler/src/pool/test/SConstruct @@ -0,0 +1,94 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +import os +import sys +import shutil +sys.path.append("../../../../../share/scons") + +# This is the absolute path where the project is located +cwd=os.getcwd() + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Include dirs +main_env.Append(CPPPATH=[ + cwd+'/../../../include', + cwd+'/../../../../../include', + '/usr/include/cppunit/' +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd+'/..', + cwd+'/../../xml', + cwd+'/../../../../log' +]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# Linking flags +main_env.Append(LDFLAGS=["-g"]) + +# Libraries +main_env.Append(LIBS=[ + 'cppunit', + 'scheduler_xml', + 'scheduler_pool', + 'nebula_log' +]) + +main_env.Program('test_vm','VirtualMachineXMLTest.cc') +main_env.Program('test_host','HostXMLTest.cc') + +################################################################################ +# EXTRA CONFIGURATION +################################################################################ + +#------------------------------------------------------------------------------- +# xmlrpc +#------------------------------------------------------------------------------- + +xmlrpc_dir=ARGUMENTS.get('xmlrpc', 'none') + +if xmlrpc_dir!='none': + main_env.Append(LIBPATH=[xmlrpc_dir+"/lib"]) + main_env.Append(CPPPATH=[xmlrpc_dir+"/include"]) + +main_env.ParseConfig('../../../../../share/scons/get_xmlrpc_config client') + +#------------------------------------------------------------------------------- +# build lex/bison +#------------------------------------------------------------------------------- + +build_parsers=ARGUMENTS.get('parsers', 'no') + +if build_parsers=='yes': + main_env.Append(parsers='yes') +else: + main_env.Append(parsers='no') + +#------------------------------------------------------------------------------- +# libxml2 +#------------------------------------------------------------------------------- + +main_env.ParseConfig('xml2-config --libs --cflags') diff --git a/src/scheduler/src/pool/test/VirtualMachineXMLTest.cc b/src/scheduler/src/pool/test/VirtualMachineXMLTest.cc new file mode 100644 index 0000000000..8b06d56910 --- /dev/null +++ b/src/scheduler/src/pool/test/VirtualMachineXMLTest.cc @@ -0,0 +1,517 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include + +#include "ObjectXML.h" +#include "VirtualMachinePoolXML.h" +#include "HostPoolXML.h" + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class FriendHostPool : public HostPoolXML +{ +public: + FriendHostPool(Client* client):HostPoolXML(client){}; + + friend class HostXMLTest; + + static const string host_dump; + static const string xmls[]; + +protected: + + void add_object(xmlNodePtr node) + { + xmlChar * str_ptr = xmlNodeGetContent(node->children->next); + + int hid; + + if (str_ptr != 0) + { + hid = atoi(reinterpret_cast(str_ptr)); + xmlFree(str_ptr); + } + else + { + + } + + HostXML* vm = new HostXML( xmls[hid] ); + objects.insert( pair(hid, vm) ); + }; + + int load_info(xmlrpc_c::value &result) + { + vector arrayData; + arrayData.push_back(xmlrpc_c::value_boolean(true)); + arrayData.push_back(xmlrpc_c::value_string(host_dump)); + + // Make an XML-RPC array out of it + xmlrpc_c::value_array array(arrayData); + result = array; + + return 0; + }; +}; + +class FriendVirtualMachinePool : public VirtualMachinePoolXML +{ +public: + FriendVirtualMachinePool + ( + Client* client, + unsigned int m_limit = 0 + ):VirtualMachinePoolXML(client, m_limit){}; + + friend class VirtualMachineXMLTest; + + static const string vm_dump; + static const string xmls[]; + +protected: + + + void add_object(xmlNodePtr node) + { + xmlNodePtr nodeID; + nodeID = node->children->next; + + + xmlChar * str_ptr = xmlNodeGetContent(nodeID); + + int vid; + + if (str_ptr != 0) + { + vid = atoi(reinterpret_cast(str_ptr)); + xmlFree(str_ptr); + } + else + { + // TODO + } + + VirtualMachineXML* vm = new VirtualMachineXML( xmls[vid] ); + objects.insert( pair(vid, vm) ); + }; + + int load_info(xmlrpc_c::value &result) + { + vector arrayData; + arrayData.push_back(xmlrpc_c::value_boolean(true)); + arrayData.push_back(xmlrpc_c::value_string(vm_dump)); + + // Make an XML-RPC array out of it + xmlrpc_c::value_array array(arrayData); + result = array; + + return 0; + }; +}; + + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class VirtualMachineXMLTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( VirtualMachineXMLTest ); + + CPPUNIT_TEST( initialization ); + CPPUNIT_TEST( add_host ); + CPPUNIT_TEST( get_host ); + + CPPUNIT_TEST_SUITE_END (); + +private: + static const string host_dump; + + FriendVirtualMachinePool * vmp; + + FriendHostPool* set_up_hpool() + { + FriendHostPool* hpool; + + hpool = new FriendHostPool(NULL); + hpool->set_up(); + + return hpool; + }; + +public: + + VirtualMachineXMLTest(){}; + + ~VirtualMachineXMLTest(){}; + + void setUp() + { + xmlInitParser(); + + try + { + vmp = new FriendVirtualMachinePool(NULL); + } + catch(runtime_error& re) + { + cerr << re.what() << endl; + } + }; + + void tearDown() + { + xmlCleanupParser(); + + if (vmp != 0) + { + delete vmp; + } + }; + + /* ********************************************************************* */ + + void initialization() + { + int rc; + + CPPUNIT_ASSERT( vmp != 0 ); + + rc = vmp->set_up(); + CPPUNIT_ASSERT( rc == 0 ); + + CPPUNIT_ASSERT( vmp->objects.size() == 3 ); + + CPPUNIT_ASSERT( vmp->objects.count(0) == 1); + CPPUNIT_ASSERT( vmp->objects.count(1) == 1); + CPPUNIT_ASSERT( vmp->objects.count(2) == 1); + CPPUNIT_ASSERT( vmp->objects.count(3) == 0); + }; + + void add_host() + { + int rc; + VirtualMachineXML* vm; + vector mh; + + CPPUNIT_ASSERT( vmp != 0 ); + + rc = vmp->set_up(); + CPPUNIT_ASSERT( rc == 0 ); + + vm = ((VirtualMachineXML*)vmp->objects[0]); + CPPUNIT_ASSERT( vm != 0 ); + + + vm->get_matching_hosts(mh); + CPPUNIT_ASSERT( mh.size() == 0 ); + + vm->add_host( 2 ); + vm->add_host( 9 ); + vm->add_host( 4 ); + + mh.clear(); + vm->get_matching_hosts(mh); + + CPPUNIT_ASSERT( mh.size() == 3 ); + + CPPUNIT_ASSERT( mh[0] == 2 ); + CPPUNIT_ASSERT( mh[1] == 9 ); + CPPUNIT_ASSERT( mh[2] == 4 ); + }; + + + void get_host() + { + VirtualMachineXML* vm; + HostPoolXML* hpool; + vector priorities; + int hid; + int rc; + + CPPUNIT_ASSERT( vmp != 0 ); + + rc = vmp->set_up(); + CPPUNIT_ASSERT( rc == 0 ); + + hpool = set_up_hpool(); + CPPUNIT_ASSERT( hpool != 0 ); + + + vm = vmp->get(0); + CPPUNIT_ASSERT( vm != 0 ); + + rc = vm->get_host(hid, hpool); + CPPUNIT_ASSERT( rc == -1 ); + + // get_host will iterate in reverse order the available hosts, and + // return the first to fit the requirements; in this case + // cpu: 50 mem: 128 + vm->add_host( 5 ); + vm->add_host( 4 ); + vm->add_host( 2 ); + vm->add_host( 1 ); + + rc = vm->get_host(hid, hpool); + + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( hid == 4 ); + + // If we set host 5 to have the greatest priority, get_host should + // return it. + + priorities.push_back(1.0); // hid 5 + priorities.push_back(0.8); // hid 4 + priorities.push_back(0.5); // hid 2 + priorities.push_back(0.3); // hid 1 + + vm->set_priorities(priorities); + + rc = vm->get_host(hid, hpool); + + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( hid == 5 ); + + delete hpool; + }; + + + +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + // We need to set the log file + NebulaLog::init_log_system(NebulaLog::FILE, Log::DEBUG, "test.log"); + NebulaLog::log("Test", Log::INFO, "Test started"); + + CppUnit::TextUi::TestRunner runner; + + runner.addTest(VirtualMachineXMLTest::suite()); + runner.run(); + + remove("test.log"); + NebulaLog::finalize_log_system(); + + return 0; +} + +// ---------------------------------------------------------------------------- + + +const string FriendVirtualMachinePool::xmls[] = +{ +" 0 0 vm-example 0 1 0 1274087556 1274087589 0 0 0 0 0 host16 15 1274087589 1274087589 1274087589 1274087589 0 0 0 0 1 ", + +" 1 0 vm-example 0 1 0 1274087557 1274087590 0 0 0 0 0 host16 15 1274087589 1274087589 1274087589 1274087589 0 0 0 0 1 ", + +" 2 0 vm-example 0 1 0 1274087557 1274087590 0 0 0 0 0 host16 15 1274087589 1274087590 1274087589 1274087590 0 0 0 0 1 " +}; + +const string FriendVirtualMachinePool::vm_dump = +" 0 0 carlos vm-example 0 1 0 1274087556 1274087589 0 0 0 0 0 host16 15 1274087589 1274087589 1274087589 1274087589 0 0 0 0 1 1 0 carlos vm-example 0 1 0 1274087557 1274087590 0 0 0 0 0 host16 15 1274087589 1274087589 1274087589 1274087589 0 0 0 0 1 2 0 carlos vm-example 0 1 0 1274087557 1274087590 0 0 0 0 0 host16 15 1274087589 1274087590 1274087589 1274087590 0 0 0 0 1 3 0 carlos vm-example 0 7 0 1274087557 1274087590 0 0 0 0 0 host16 15 1274087589 1274087590 1274087589 1274087590 0 0 0 0 1 4 0 carlos vm-example 0 7 0 1274087558 1274087590 0 0 0 0 0 host16 15 1274087590 1274087590 1274087590 1274087590 0 0 0 0 1 5 0 carlos vm-example 0 7 0 1274087558 1274087590 0 0 0 0 0 host16 15 1274087590 1274087590 1274087590 1274087590 0 0 0 0 1 6 0 carlos vm-example 0 7 0 1274087559 1274087591 0 0 0 0 0 host16 15 1274087590 1274087590 1274087590 1274087590 0 0 0 0 1 "; + +const string FriendHostPool::xmls[] = +{ +"", + +"\ + 1\ + ursa12\ + 2\ + im_kvm\ + vmm_kvm\ + tm_nfs\ + 1274107238\ + \ + 1\ + 0\ + 262144\ + 80\ + 0\ + 524288\ + 100\ + 0\ + 0\ + 0\ + 0\ + 536220\ + 0\ + 0\ + \ + \ +", + +"\ + 2\ + ursa\ + 2\ + im_kvm\ + vmm_kvm\ + tm_nfs\ + 1274107299\ + \ + 2\ + 0\ + 458752\ + 20\ + 0\ + 524288\ + 100\ + 0\ + 9104256\ + 613\ + 0\ + 13897924\ + 186\ + 7\ + \ + \ +", + +"", + +"\ + 4\ + ursa11\ + 2\ + im_kvm\ + vmm_kvm\ + tm_nfs\ + 1274107328\ + \ + 4\ + 0\ + 262144\ + 10\ + 0\ + 524288\ + 100\ + 0\ + 7958684\ + 800\ + 0\ + 621616\ + 0\ + 0\ + \ + \ +", + +"\ + 5\ + ursa10\ + 2\ + im_kvm\ + vmm_kvm\ + tm_nfs\ + 1274107300\ + \ + 5\ + 256\ + 0\ + 30\ + 512\ + 524288\ + 100\ + 256\ + 384\ + 180\ + 0\ + 2191756\ + 6\ + 0\ + \ + \ +" +}; + +const string FriendHostPool::host_dump = +" 1 ursa12 2 im_kvm vmm_kvm tm_nfs 1274107145 1 0 0 0 0 8194368 800 0 7955180 800 0 535848 0 0 2 ursa 2 im_kvm vmm_kvm tm_nfs 1274107206 2 0 4280320 700 0 16468252 800 0 9109156 628 0 13891232 172 7 4 ursa11 2 im_kvm vmm_kvm tm_nfs 1274107145 4 0 0 0 0 8194368 800 0 7958684 800 0 621616 0 0 5 ursa10 2 im_kvm vmm_kvm tm_nfs 1274107207 5 0 0 0 0 8194368 800 0 7870776 796 0 2192424 4 0 6 ursa08 3 im_kvm vmm_kvm tm_nfs 1274107176 6 0 0 0 0 0 0 0 6585200 0 0 1132608 0 0 7 ursa09 3 im_kvm vmm_kvm tm_nfs 1274107146 7 0 524288 100 0 8194368 800 0 7286128 798 0 8011908 1 1 "; + + diff --git a/src/scheduler/src/sched/SConstruct b/src/scheduler/src/sched/SConstruct new file mode 100644 index 0000000000..0a4350277e --- /dev/null +++ b/src/scheduler/src/sched/SConstruct @@ -0,0 +1,42 @@ +# SConstruct for src/pool + +# -------------------------------------------------------------------------- # +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +Import('env') + +lib_name='scheduler_sched' + +source_files=['Scheduler.cc'] + +# Build library +env.StaticLibrary(lib_name, source_files) + + +# Build daemon +env.Append(LIBS=[ + 'nebula_common', + 'scheduler_sched', + 'scheduler_pool', + 'nebula_log', + 'scheduler_xml', + 'crypto' +]) + +if not env.GetOption('clean'): + env.ParseConfig('../../../../share/scons/get_xmlrpc_config client') + +env.Program('mm_sched.cc') diff --git a/src/scheduler/Scheduler.cc b/src/scheduler/src/sched/Scheduler.cc similarity index 62% rename from src/scheduler/Scheduler.cc rename to src/scheduler/src/sched/Scheduler.cc index bf12223fcb..383161d76e 100644 --- a/src/scheduler/Scheduler.cc +++ b/src/scheduler/src/sched/Scheduler.cc @@ -31,8 +31,7 @@ #include "Scheduler.h" #include "RankPolicy.h" -#include "Nebula.h" -#include "User.h" +#include "NebulaLog.h" using namespace std; @@ -50,12 +49,12 @@ extern "C" void * scheduler_action_loop(void *arg) sched = static_cast(arg); - Scheduler::log("SCHED",Log::INFO,"Scheduler loop started."); - + NebulaLog::log("SCHED",Log::INFO,"Scheduler loop started."); + sched->am.loop(sched->timer,0); - Scheduler::log("SCHED",Log::INFO,"Scheduler loop stopped."); - + NebulaLog::log("SCHED",Log::INFO,"Scheduler loop stopped."); + return 0; } @@ -64,103 +63,64 @@ extern "C" void * scheduler_action_loop(void *arg) void Scheduler::start() { - int rc; - Nebula& nd = Nebula::instance(); + int rc; + ifstream file; pthread_attr_t pattr; - const char * one_auth; - - string one_name; - string one_pass; - string one_token; - - ifstream file; - // ----------------------------------------------------------- // Log system // ----------------------------------------------------------- try { - string log_fname; + ostringstream oss; + const char * nl = getenv("ONE_LOCATION"); - log_fname = nd.get_log_location() + "sched.log"; + if (nl == 0) //OpenNebula installed under root directory + { + oss << "/var/log/one/"; + } + else + { + oss << nl << "/var/"; + } - Scheduler::log("SCHED", - Log::INFO, - "Init Scheduler Log system", - log_fname.c_str()); + oss << "sched.log"; + + NebulaLog::init_log_system(NebulaLog::FILE, + Log::DEBUG, + oss.str().c_str()); + + NebulaLog::log("SCHED", Log::INFO, "Init Scheduler Log system"); } catch(runtime_error &) { throw; } - one_auth = getenv("ONE_AUTH"); + // ----------------------------------------------------------- + // XML-RPC Client + // ----------------------------------------------------------- - if (!one_auth) + try { - struct passwd * pw_ent; - - pw_ent = getpwuid(getuid()); - - if ((pw_ent != NULL) && (pw_ent->pw_dir != NULL)) - { - - string one_auth_file = pw_ent->pw_dir; - - one_auth_file += "/.one/one_auth"; - one_auth = one_auth_file.c_str(); - } - else - { - throw runtime_error("Could not get one_auth file location"); - } + client = new Client("",url); } - - file.open(one_auth); - - if (file.good()) + catch(runtime_error &) { - getline(file,one_token); - - if (file.fail()) - { - throw runtime_error("Error reading $ONE_AUTH file"); - } - } - else - { - throw runtime_error("Could not open $ONE_AUTH file"); + throw; } - file.close(); - - if ( User::split_secret(one_token,one_name,one_pass) != 0 ) - { - throw runtime_error("Wrong format must be :"); - } - secret = one_name + ":" + User::sha1_digest(one_pass); + xmlInitParser(); // ----------------------------------------------------------- // Pools // ----------------------------------------------------------- - try - { - string db_name = nd.get_var_location() + "one.db"; - - db = new SqliteDB(db_name,Scheduler::log); - } - catch (exception&) - { - throw; - } - - hpool = new SchedulerHostPool(db); - vmpool = new SchedulerVirtualMachinePool(db); + hpool = new HostPoolXML(client); + vmpool = new VirtualMachinePoolXML(client, machines_limit); // ----------------------------------------------------------- // Load scheduler policies @@ -185,7 +145,7 @@ void Scheduler::start() fcntl(0,F_SETFD,0); // Keep them open across exec funcs fcntl(1,F_SETFD,0); fcntl(2,F_SETFD,0); - + // ----------------------------------------------------------- // Block all signals before creating any thread // ----------------------------------------------------------- @@ -201,8 +161,8 @@ void Scheduler::start() // Create the scheduler loop // ----------------------------------------------------------- - Scheduler::log("SCHED",Log::INFO,"Starting scheduler loop..."); - + NebulaLog::log("SCHED",Log::INFO,"Starting scheduler loop..."); + pthread_attr_init (&pattr); pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); @@ -210,9 +170,9 @@ void Scheduler::start() if ( rc != 0 ) { - Scheduler::log("SCHED",Log::ERROR, + NebulaLog::log("SCHED",Log::ERROR, "Could not start scheduler loop, exiting"); - + return; } @@ -230,6 +190,10 @@ void Scheduler::start() am.trigger(ActionListener::ACTION_FINALIZE,0); //Cancel sched loop pthread_join(sched_thread,0); + + xmlCleanupParser(); + + NebulaLog::finalize_log_system(); } /* -------------------------------------------------------------------------- */ @@ -278,39 +242,36 @@ int Scheduler::set_up_pools() void Scheduler::match() { - SchedulerVirtualMachine * vm; - int vm_memory; - int vm_cpu; - int vm_disk; - string reqs; + VirtualMachineXML * vm; + int vm_memory; + int vm_cpu; + int vm_disk; + string reqs; - SchedulerHost * host; - int host_memory; - int host_cpu; - char * error; - bool matched; + HostXML * host; + int host_memory; + int host_cpu; + char * error; + bool matched; - int rc; + int rc; - for (unsigned int i= 0; i < vmpool->pending_vms.size(); i++) + map::const_iterator vm_it; + map::const_iterator h_it; + + const map pending_vms = vmpool->get_objects(); + const map hosts = hpool->get_objects(); + + + for (vm_it=pending_vms.begin(); vm_it != pending_vms.end(); vm_it++) { - vm = vmpool->get(vmpool->pending_vms[i],false); + vm = static_cast(vm_it->second); - if ( vm == 0 ) + reqs = vm->get_requirements(); + + for (h_it=hosts.begin(); h_it != hosts.end(); h_it++) { - continue; - } - - vm->get_template_attribute("REQUIREMENTS",reqs); - - for (unsigned int j=0;jhids.size();j++) - { - host = hpool->get(hpool->hids[j],false); - - if ( host == 0 ) - { - continue; - } + host = static_cast(h_it->second); // ----------------------------------------------------------------- // Evaluate VM requirements @@ -318,7 +279,7 @@ void Scheduler::match() if (reqs != "") { - rc = host->match(reqs,matched,&error); + rc = host->eval_bool(reqs,matched,&error); if ( rc != 0 ) { @@ -328,7 +289,7 @@ void Scheduler::match() oss << "Error evaluating expresion: " << reqs << ", error: " << error; - Scheduler::log("HOST",Log::ERROR,oss); + NebulaLog::log("SCHED",Log::ERROR,oss); free(error); } @@ -375,25 +336,20 @@ static float sum_operator (float i, float j) int Scheduler::schedule() { vector::iterator it; - vector::iterator jt; - vector::iterator kt; - SchedulerVirtualMachine * vm; - ostringstream oss; + VirtualMachineXML * vm; + ostringstream oss; vector total; vector policy; - for (jt=vmpool->pending_vms.begin();jt!=vmpool->pending_vms.end();jt++) + map::const_iterator vm_it; + + const map pending_vms = vmpool->get_objects(); + + for (vm_it=pending_vms.begin(); vm_it != pending_vms.end(); vm_it++) { - vm = vmpool->get(*jt,false); - - if ( vm == 0 ) - { - oss << "Can not get VM id=" << *jt; - Scheduler::log("HOST",Log::ERROR,oss); - continue; - } + vm = static_cast(vm_it->second); total.clear(); @@ -427,89 +383,46 @@ int Scheduler::schedule() void Scheduler::dispatch() { - vector::iterator it; + VirtualMachineXML * vm; + ostringstream oss; - SchedulerVirtualMachine * vm; - ostringstream oss; + int hid; + int rc; + unsigned int dispatched_vms; - int hid; - int rc; + map::const_iterator vm_it; + const map pending_vms = vmpool->get_objects(); oss << "Select hosts" << endl; oss << "\tPRI\tHID" << endl; oss << "\t-------------------" << endl; - for (it=vmpool->pending_vms.begin();it!=vmpool->pending_vms.end();it++) + for (vm_it=pending_vms.begin(); vm_it != pending_vms.end(); vm_it++) { - vm = vmpool->get(*it,false); - - if ( vm != 0 ) - { - oss << "Virtual Machine: " << vm->get_oid() << "\n" << *vm << endl; - } + vm = static_cast(vm_it->second); + + oss << "Virtual Machine: " << vm->get_oid() << "\n" << *vm << endl; } - Scheduler::log("SCHED",Log::INFO,oss); + NebulaLog::log("SCHED",Log::INFO,oss); - for (it=vmpool->pending_vms.begin();it!=vmpool->pending_vms.end();it++) + dispatched_vms = 0; + for (vm_it=pending_vms.begin(); + vm_it != pending_vms.end() && ( dispatch_limit <= 0 || + dispatched_vms < dispatch_limit ); + vm_it++) { - vm = vmpool->get(*it,false); - - if ( vm == 0 ) - { - continue; - } + vm = static_cast(vm_it->second); rc = vm->get_host(hid,hpool); if (rc == 0) { - xmlrpc_c::value deploy_result; - - oss.str(""); - oss << "Dispatching virtual machine " << vm->get_oid() - << " to HID: " << hid; - - Scheduler::log("SCHED",Log::INFO,oss); + rc = vmpool->dispatch(vm_it->first,hid); - // Tell ONE about the decision - - try + if (rc == 0) { - xmlrpc_client.call( - one_url, - "one.vm.deploy", - "sii", - &deploy_result, - secret.c_str(), - vm->get_oid(), - hid); - } - catch (exception &e) - { - oss.str(""); - oss << "Exception raised: " << e.what() << '\n'; - - Scheduler::log("SCHED",Log::ERROR,oss); - break; - } - - // See how ONE handled the deployment - - xmlrpc_c::value_array result(deploy_result); - vector const param_array(result.vectorValueValue()); - xmlrpc_c::value_boolean const result_correct(param_array[0]); - - if ( static_cast(result_correct) != true ) - { - xmlrpc_c::value_string const info(param_array[1]); - - oss.str(""); - oss << "Error deploying virtual machine " << vm->get_oid() - << " to HID: " << hid - << ". Reason: " << static_cast(info); - - Scheduler::log("SCHED",Log::ERROR,oss); + dispatched_vms++; } } } @@ -542,6 +455,6 @@ void Scheduler::do_action(const string &name, void *args) } else if (name == ACTION_FINALIZE) { - Scheduler::log("SCHED",Log::INFO,"Stopping the scheduler..."); + NebulaLog::log("SCHED",Log::INFO,"Stopping the scheduler..."); } } diff --git a/src/scheduler/mm_sched.cc b/src/scheduler/src/sched/mm_sched.cc similarity index 75% rename from src/scheduler/mm_sched.cc rename to src/scheduler/src/sched/mm_sched.cc index 8df1f74a5a..619bbeb1c1 100644 --- a/src/scheduler/mm_sched.cc +++ b/src/scheduler/src/sched/mm_sched.cc @@ -31,8 +31,12 @@ class RankScheduler : public Scheduler { public: - RankScheduler(string url,time_t timer=1):Scheduler(url,timer),rp(0){}; - + RankScheduler(string url, + time_t timer, + unsigned int machines_limit, + unsigned int dispatch_limit + ):Scheduler(url,timer,machines_limit, dispatch_limit),rp(0){}; + ~RankScheduler() { if ( rp != 0 ) @@ -40,17 +44,17 @@ public: delete rp; } }; - + void register_policies() { rp = new RankPolicy(vmpool,hpool,1.0); - - add_host_policy(rp); + + add_host_policy(rp); }; - + private: RankPolicy * rp; - + }; int main(int argc, char **argv) @@ -58,11 +62,13 @@ int main(int argc, char **argv) RankScheduler * ss; int port = 2633; time_t timer= 30; + unsigned int machines_limit = 400; + unsigned int dispatch_limit = 300; char opt; - + ostringstream oss; - - while((opt = getopt(argc,argv,"p:t:")) != -1) + + while((opt = getopt(argc,argv,"p:t:m:d:")) != -1) { switch(opt) { @@ -72,31 +78,38 @@ int main(int argc, char **argv) case 't': timer = atoi(optarg); break; + case 'm': + machines_limit = atoi(optarg); + break; + case 'd': + dispatch_limit = atoi(optarg); + break; default: - cerr << "usage: " << argv[0] << " [-p port] [-t timer]\n"; + cerr << "usage: " << argv[0] << " [-p port] [-t timer] "; + cerr << "[-m machines limit] [-d dispatch limit]\n"; exit(-1); break; } }; - + /* ---------------------------------------------------------------------- */ - + oss << "http://localhost:" << port << "/RPC2"; - - ss = new RankScheduler(oss.str(),timer); - + + ss = new RankScheduler(oss.str(),timer, machines_limit, dispatch_limit); + try { - ss->start(); + ss->start(); } catch (exception &e) { cout << e.what() << endl; - + return -1; } - + delete ss; - + return 0; } diff --git a/src/scheduler/src/xml/Client.cc b/src/scheduler/src/xml/Client.cc new file mode 100644 index 0000000000..a2480ce813 --- /dev/null +++ b/src/scheduler/src/xml/Client.cc @@ -0,0 +1,210 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 "Client.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +const int Client::MESSAGE_SIZE = 51200; +// +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void Client::set_one_auth(string secret) +{ + string user = ""; + string pass = ""; + + int rc = 0; + + if( secret == "" ) + { + rc = read_oneauth(secret); + } + + if ( rc == 0 ) + { + rc = split_secret(secret, user, pass); + + if( rc == 0 ) + { + string sha1_pass = sha1_digest(pass); + + one_auth = user + ":" + sha1_pass; + } + else + { + throw runtime_error("Wrong format for auth token, must " + "be :"); + } + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int Client::read_oneauth(string &secret) +{ + ostringstream oss; + string one_auth_file; + + const char * one_auth_env; + ifstream file; + + bool rc = -1; + + // Read $ONE_AUTH file and copy its contents into secret. + one_auth_env = getenv("ONE_AUTH"); + + if (!one_auth_env) + { + // If $ONE_AUTH doesn't exist, read $HOME/.one/one_auth + struct passwd * pw_ent; + + pw_ent = getpwuid(getuid()); + + if ((pw_ent != NULL) && (pw_ent->pw_dir != NULL)) + { + one_auth_file = pw_ent->pw_dir; + one_auth_file += "/.one/one_auth"; + + one_auth_env = one_auth_file.c_str(); + } + else + { + oss << "Could not get one_auth file location"; + } + } + + file.open(one_auth_env); + + if (file.good()) + { + getline(file, secret); + + if (file.fail()) + { + oss << "Error reading file: " << one_auth_env; + } + else + { + rc = 0; + } + } + else + { + oss << "Could not open file: " << one_auth_env; + } + + file.close(); + + if (rc != 0) + { + NebulaLog::log("XMLRPC",Log::ERROR,oss); + } + + return rc; +} + + +int Client::split_secret(const string secret, string& user, string& pass) +{ + size_t pos; + int rc = -1; + + pos=secret.find(":"); + + if (pos != string::npos) + { + user = secret.substr(0,pos); + pass = secret.substr(pos+1); + + rc = 0; + } + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +string Client::sha1_digest(const string& pass) +{ + EVP_MD_CTX mdctx; + unsigned char md_value[EVP_MAX_MD_SIZE]; + unsigned int md_len; + ostringstream oss; + + EVP_MD_CTX_init(&mdctx); + EVP_DigestInit_ex(&mdctx, EVP_sha1(), NULL); + + EVP_DigestUpdate(&mdctx, pass.c_str(), pass.length()); + + EVP_DigestFinal_ex(&mdctx,md_value,&md_len); + EVP_MD_CTX_cleanup(&mdctx); + + for(unsigned int i = 0; i +#include +#include + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +ObjectXML::ObjectXML(const string &xml_doc):xml(0),ctx(0) +{ + try + { + xml_parse(xml_doc); + } + catch(runtime_error& re) + { + throw; + } +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +ObjectXML::ObjectXML(const xmlNodePtr node):xml(0),ctx(0) +{ + xml = xmlNewDoc(reinterpret_cast("1.0")); + + if (xml == 0) + { + throw("Error allocating XML Document"); + } + + ctx = xmlXPathNewContext(xml); + + if (ctx == 0) + { + xmlFreeDoc(xml); + throw("Unable to create new XPath context"); + } + + xmlNodePtr root_node = xmlDocCopyNode(node,xml,1); + + if (root_node == 0) + { + xmlXPathFreeContext(ctx); + xmlFreeDoc(xml); + throw("Unable to allocate node"); + } + + xmlDocSetRootElement(xml, root_node); +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +ObjectXML::~ObjectXML() +{ + if (xml != 0) + { + xmlFreeDoc(xml); + } + + if ( ctx != 0) + { + xmlXPathFreeContext(ctx); + } +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +vector ObjectXML::operator[] (const char * xpath_expr) +{ + xmlXPathObjectPtr obj; + vector content; + + obj = xmlXPathEvalExpression( + reinterpret_cast(xpath_expr), ctx); + + if (obj == 0 || obj->nodesetval == 0) + { + return content; + } + + xmlNodeSetPtr ns = obj->nodesetval; + int size = ns->nodeNr; + xmlNodePtr cur; + xmlChar * str_ptr; + + for(int i = 0; i < size; ++i) + { + cur = ns->nodeTab[i]; + + if ( cur == 0 || cur->type != XML_ELEMENT_NODE ) + { + continue; + } + + str_ptr = xmlNodeGetContent(cur); + + if (str_ptr != 0) + { + string element_content = reinterpret_cast(str_ptr); + + content.push_back(element_content); + + xmlFree(str_ptr); + } + } + + xmlXPathFreeObject(obj); + + return content; +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int ObjectXML::get_nodes (const char * xpath_expr, vector& content) +{ + xmlXPathObjectPtr obj; + + obj = xmlXPathEvalExpression( + reinterpret_cast(xpath_expr), ctx); + + if (obj == 0 || obj->nodesetval == 0) + { + return 0; + } + + xmlNodeSetPtr ns = obj->nodesetval; + int size = ns->nodeNr; + int num_nodes = 0; + xmlNodePtr cur; + + for(int i = 0; i < size; ++i) + { + cur = ns->nodeTab[i]; + + if ( cur == 0 || cur->type != XML_ELEMENT_NODE ) + { + continue; + } + + content.push_back(cur); + num_nodes++; + } + + xmlXPathFreeObject(obj); + + return num_nodes; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int ObjectXML::update(const string &xml_doc) +{ + if (xml != 0) + { + xmlFreeDoc(xml); + } + + if ( ctx != 0) + { + xmlXPathFreeContext(ctx); + } + + try + { + xml_parse(xml_doc); + } + catch(runtime_error& re) + { + return -1; + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void ObjectXML::xml_parse(const string &xml_doc) +{ + xml = xmlParseMemory (xml_doc.c_str(),xml_doc.length()); + + if (xml == 0) + { + throw runtime_error("Error parsing XML Document"); + } + + ctx = xmlXPathNewContext(xml); + + if (ctx == 0) + { + xmlFreeDoc(xml); + throw runtime_error("Unable to create new XPath context"); + } +} + + +/* ************************************************************************ */ +/* Host :: Parse functions to compute rank and evaluate requirements */ +/* ************************************************************************ */ + +extern "C" +{ + typedef struct yy_buffer_state * YY_BUFFER_STATE; + + int expr_bool_parse(ObjectXML * oxml, bool& result, char ** errmsg); + + int expr_arith_parse(ObjectXML * oxml, int& result, char ** errmsg); + + int expr_lex_destroy(); + + YY_BUFFER_STATE expr__scan_string(const char * str); + + void expr__delete_buffer(YY_BUFFER_STATE); +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int ObjectXML::eval_bool(const string& expr, bool& result, char **errmsg) +{ + YY_BUFFER_STATE str_buffer = 0; + const char * str; + int rc; + + *errmsg = 0; + + str = expr.c_str(); + + str_buffer = expr__scan_string(str); + + if (str_buffer == 0) + { + goto error_yy; + } + + rc = expr_bool_parse(this,result,errmsg); + + expr__delete_buffer(str_buffer); + + expr_lex_destroy(); + + return rc; + +error_yy: + + *errmsg=strdup("Error setting scan buffer"); + + return -1; +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int ObjectXML::eval_arith(const string& expr, int& result, char **errmsg) +{ + YY_BUFFER_STATE str_buffer = 0; + const char * str; + int rc; + + *errmsg = 0; + + str = expr.c_str(); + + str_buffer = expr__scan_string(str); + + if (str_buffer == 0) + { + goto error_yy; + } + + rc = expr_arith_parse(this,result,errmsg); + + expr__delete_buffer(str_buffer); + + expr_lex_destroy(); + + return rc; + +error_yy: + + *errmsg=strdup("Error setting scan buffer"); + + return -1; +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + diff --git a/src/scheduler/src/xml/SConstruct b/src/scheduler/src/xml/SConstruct new file mode 100644 index 0000000000..ceb04e358a --- /dev/null +++ b/src/scheduler/src/xml/SConstruct @@ -0,0 +1,48 @@ +# SConstruct for src/pool + +# -------------------------------------------------------------------------- # +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +Import('env') + +lib_name='scheduler_xml' + +if env['parsers']=='yes': + # LEX + parser=env.Lex( + source='expr_parser.l' + ) + env.NoClean(parser) + + # BISON + parser=env.Bison( + source='expr_arith.y' + ) + env.NoClean(parser) + + parser=env.Bison( + source='expr_bool.y' + ) + env.NoClean(parser) + +source_files=['ObjectXML.cc', + 'Client.cc', + 'expr_parser.c', + 'expr_bool.cc', + 'expr_arith.cc'] + +# Build library +env.StaticLibrary(lib_name, source_files) diff --git a/src/host/host_rank.cc b/src/scheduler/src/xml/expr_arith.cc similarity index 84% rename from src/host/host_rank.cc rename to src/scheduler/src/xml/expr_arith.cc index a353006530..37f1607267 100644 --- a/src/host/host_rank.cc +++ b/src/scheduler/src/xml/expr_arith.cc @@ -1,10 +1,9 @@ - -/* A Bison parser, made by GNU Bison 2.4.1. */ +/* A Bison parser, made by GNU Bison 2.4.2. */ /* Skeleton implementation for Bison's Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software + Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,7 +45,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.1" +#define YYBISON_VERSION "2.4.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -64,19 +63,19 @@ #define YYLSP_NEEDED 1 /* Substitute the variable and function names. */ -#define yyparse host_rank_parse -#define yylex host_rank_lex -#define yyerror host_rank_error -#define yylval host_rank_lval -#define yychar host_rank_char -#define yydebug host_rank_debug -#define yynerrs host_rank_nerrs -#define yylloc host_rank_lloc +#define yyparse expr_arith_parse +#define yylex expr_arith_lex +#define yyerror expr_arith_error +#define yylval expr_arith_lval +#define yychar expr_arith_char +#define yydebug expr_arith_debug +#define yynerrs expr_arith_nerrs +#define yylloc expr_arith_lloc /* Copy the first part of user declarations. */ /* Line 189 of yacc.c */ -#line 17 "host_rank.y" +#line 17 "expr_arith.y" #include #include @@ -88,30 +87,30 @@ #include #include -#include "host_rank.h" -#include "Host.h" +#include "expr_arith.h" +#include "ObjectXML.h" #define YYERROR_VERBOSE -#define host_rank_lex host_lex +#define expr_arith_lex expr_lex -extern "C" +extern "C" { -void host_rank_error( - YYLTYPE * llocp, - Host * host, - int& result, - char ** error_msg, - const char * str); +void expr_arith_error( + YYLTYPE * llocp, + ObjectXML * oxml, + int& result, + char ** error_msg, + const char * str); -int host_rank_lex (YYSTYPE *lvalp, YYLTYPE *llocp); +int expr_arith_lex (YYSTYPE *lvalp, YYLTYPE *llocp); -int host_rank_parse(Host * host, int& result, char ** errmsg); +int expr_arith_parse(ObjectXML *oxml, int& result, char ** errmsg); } /* Line 189 of yacc.c */ -#line 115 "host_rank.cc" +#line 114 "expr_arith.cc" /* Enabling traces. */ #ifndef YYDEBUG @@ -151,7 +150,7 @@ typedef union YYSTYPE { /* Line 214 of yacc.c */ -#line 54 "host_rank.y" +#line 54 "expr_arith.y" char * val_str; int val_int; @@ -160,7 +159,7 @@ typedef union YYSTYPE /* Line 214 of yacc.c */ -#line 164 "host_rank.cc" +#line 163 "expr_arith.cc" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -185,7 +184,7 @@ typedef struct YYLTYPE /* Line 264 of yacc.c */ -#line 189 "host_rank.cc" +#line 188 "expr_arith.cc" #ifdef short # undef short @@ -235,7 +234,7 @@ typedef short int yytype_int16; #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ -# if YYENABLE_NLS +# if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) @@ -473,8 +472,8 @@ static const yytype_int8 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 76, 76, 77, 80, 156, 157, 158, 159, 160, - 161, 162, 163 + 0, 76, 76, 77, 80, 107, 108, 109, 110, 111, + 112, 113, 114 }; #endif @@ -581,9 +580,18 @@ static const yytype_uint8 yystos[] = /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ #define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif #define YYRECOVERING() (!!yyerrstatus) @@ -599,7 +607,7 @@ do \ } \ else \ { \ - yyerror (&yylloc, host, result, error_msg, YY_("syntax error: cannot back up")); \ + yyerror (&yylloc, oxml, result, error_msg, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) @@ -640,7 +648,7 @@ while (YYID (0)) we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ @@ -679,7 +687,7 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value, Location, host, result, error_msg); \ + Type, Value, Location, oxml, result, error_msg); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) @@ -693,23 +701,23 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, Host * host, int& result, char ** error_msg) +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ObjectXML * oxml, int& result, char ** error_msg) #else static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, host, result, error_msg) +yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, oxml, result, error_msg) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; YYLTYPE const * const yylocationp; - Host * host; - int& result; - char ** error_msg; + ObjectXML * oxml; + int& result; + char ** error_msg; #endif { if (!yyvaluep) return; YYUSE (yylocationp); - YYUSE (host); + YYUSE (oxml); YYUSE (result); YYUSE (error_msg); # ifdef YYPRINT @@ -733,17 +741,17 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, host, result, er #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, Host * host, int& result, char ** error_msg) +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ObjectXML * oxml, int& result, char ** error_msg) #else static void -yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, host, result, error_msg) +yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, oxml, result, error_msg) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; YYLTYPE const * const yylocationp; - Host * host; - int& result; - char ** error_msg; + ObjectXML * oxml; + int& result; + char ** error_msg; #endif { if (yytype < YYNTOKENS) @@ -753,7 +761,7 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, host, result, error_ms YY_LOCATION_PRINT (yyoutput, *yylocationp); YYFPRINTF (yyoutput, ": "); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, host, result, error_msg); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, oxml, result, error_msg); YYFPRINTF (yyoutput, ")"); } @@ -796,16 +804,16 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, Host * host, int& result, char ** error_msg) +yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, ObjectXML * oxml, int& result, char ** error_msg) #else static void -yy_reduce_print (yyvsp, yylsp, yyrule, host, result, error_msg) +yy_reduce_print (yyvsp, yylsp, yyrule, oxml, result, error_msg) YYSTYPE *yyvsp; YYLTYPE *yylsp; int yyrule; - Host * host; - int& result; - char ** error_msg; + ObjectXML * oxml; + int& result; + char ** error_msg; #endif { int yynrhs = yyr2[yyrule]; @@ -819,7 +827,7 @@ yy_reduce_print (yyvsp, yylsp, yyrule, host, result, error_msg) YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) - , &(yylsp[(yyi + 1) - (yynrhs)]) , host, result, error_msg); + , &(yylsp[(yyi + 1) - (yynrhs)]) , oxml, result, error_msg); YYFPRINTF (stderr, "\n"); } } @@ -827,7 +835,7 @@ yy_reduce_print (yyvsp, yylsp, yyrule, host, result, error_msg) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, yylsp, Rule, host, result, error_msg); \ + yy_reduce_print (yyvsp, yylsp, Rule, oxml, result, error_msg); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that @@ -1078,22 +1086,22 @@ yysyntax_error (char *yyresult, int yystate, int yychar) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, Host * host, int& result, char ** error_msg) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, ObjectXML * oxml, int& result, char ** error_msg) #else static void -yydestruct (yymsg, yytype, yyvaluep, yylocationp, host, result, error_msg) +yydestruct (yymsg, yytype, yyvaluep, yylocationp, oxml, result, error_msg) const char *yymsg; int yytype; YYSTYPE *yyvaluep; YYLTYPE *yylocationp; - Host * host; - int& result; - char ** error_msg; + ObjectXML * oxml; + int& result; + char ** error_msg; #endif { YYUSE (yyvaluep); YYUSE (yylocationp); - YYUSE (host); + YYUSE (oxml); YYUSE (result); YYUSE (error_msg); @@ -1118,7 +1126,7 @@ int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus -int yyparse (Host * host, int& result, char ** error_msg); +int yyparse (ObjectXML * oxml, int& result, char ** error_msg); #else int yyparse (); #endif @@ -1146,13 +1154,13 @@ yyparse (YYPARSE_PARAM) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int -yyparse (Host * host, int& result, char ** error_msg) +yyparse (ObjectXML * oxml, int& result, char ** error_msg) #else int -yyparse (host, result, error_msg) - Host * host; - int& result; - char ** error_msg; +yyparse (oxml, result, error_msg) + ObjectXML * oxml; + int& result; + char ** error_msg; #endif #endif { @@ -1243,7 +1251,7 @@ YYLTYPE yylloc; yyvsp = yyvs; yylsp = yyls; -#if YYLTYPE_IS_TRIVIAL +#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL /* Initialize the default location before parsing starts. */ yylloc.first_line = yylloc.last_line = 1; yylloc.first_column = yylloc.last_column = 1; @@ -1433,160 +1441,111 @@ yyreduce: { case 2: -/* Line 1455 of yacc.c */ -#line 76 "host_rank.y" +/* Line 1464 of yacc.c */ +#line 76 "expr_arith.y" { result = static_cast((yyvsp[(1) - (1)].val_float));;} break; case 3: -/* Line 1455 of yacc.c */ -#line 77 "host_rank.y" +/* Line 1464 of yacc.c */ +#line 77 "expr_arith.y" { result = 0; ;} break; case 4: -/* Line 1455 of yacc.c */ -#line 80 "host_rank.y" - { string val; - string attr((yyvsp[(1) - (1)].val_str)); +/* Line 1464 of yacc.c */ +#line 80 "expr_arith.y" + { float val = 0.0; - if (attr == "RUNNING_VMS") + ostringstream xpath_t; + ostringstream xpath_s; + + vector results; + + xpath_t << "/HOST/TEMPLATE/" << (yyvsp[(1) - (1)].val_str); + xpath_s << "/HOST/HOST_SHARE/" << (yyvsp[(1) - (1)].val_str); + + results = (*oxml)[xpath_t.str().c_str()]; + + if (results.size() == 0) { - (yyval.val_float) = static_cast - (host->get_share_running_vms()); + results = (*oxml)[xpath_s.str().c_str()]; } - else if (attr == "ALLOCATED_MEMORY") + + if (results.size() != 0) { - (yyval.val_float) = static_cast - (host->get_share_mem_usage()); - } - else if (attr == "ALLOCATED_CPU") - { - (yyval.val_float) = static_cast - (host->get_share_cpu_usage()); - } - else if (attr == "ALLOCATED_DISK") - { - (yyval.val_float) = static_cast - (host->get_share_disk_usage()); - } - else if (attr == "USED_MEMORY") - { - (yyval.val_float) = static_cast - (host->get_share_used_mem()); - } - else if (attr == "USED_CPU") - { - (yyval.val_float) = static_cast - (host->get_share_used_cpu()); - } - else if (attr == "USED_DISK") - { - (yyval.val_float) = static_cast - (host->get_share_used_disk()); - } - else if (attr == "FREE_MEMORY") - { - (yyval.val_float) = static_cast - (host->get_share_free_mem()); - } - else if (attr == "FREE_CPU") - { - (yyval.val_float) = static_cast - (host->get_share_free_cpu()); - } - else if (attr == "FREE_DISK") - { - (yyval.val_float) = static_cast - (host->get_share_free_disk()); - } - else if (attr == "MAX_MEMORY") - { - (yyval.val_float) = static_cast - (host->get_share_max_mem()); - } - else if (attr == "MAX_CPU") - { - (yyval.val_float) = static_cast - (host->get_share_max_cpu()); - } - else if (attr == "MAX_DISK") - { - (yyval.val_float) = static_cast - (host->get_share_max_disk()); - } - else - { - host->get_template_attribute((yyvsp[(1) - (1)].val_str),val); - (yyval.val_float) = val.empty() ? 0.0 : atof(val.c_str()); + istringstream iss(results[0]); + iss >> val; } + (yyval.val_float) = val; + free((yyvsp[(1) - (1)].val_str)); ;} break; case 5: -/* Line 1455 of yacc.c */ -#line 156 "host_rank.y" +/* Line 1464 of yacc.c */ +#line 107 "expr_arith.y" { (yyval.val_float) = (yyvsp[(1) - (1)].val_float); ;} break; case 6: -/* Line 1455 of yacc.c */ -#line 157 "host_rank.y" +/* Line 1464 of yacc.c */ +#line 108 "expr_arith.y" { (yyval.val_float) = static_cast((yyvsp[(1) - (1)].val_int)); ;} break; case 7: -/* Line 1455 of yacc.c */ -#line 158 "host_rank.y" +/* Line 1464 of yacc.c */ +#line 109 "expr_arith.y" { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) + (yyvsp[(3) - (3)].val_float);;} break; case 8: -/* Line 1455 of yacc.c */ -#line 159 "host_rank.y" +/* Line 1464 of yacc.c */ +#line 110 "expr_arith.y" { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) - (yyvsp[(3) - (3)].val_float);;} break; case 9: -/* Line 1455 of yacc.c */ -#line 160 "host_rank.y" +/* Line 1464 of yacc.c */ +#line 111 "expr_arith.y" { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) * (yyvsp[(3) - (3)].val_float);;} break; case 10: -/* Line 1455 of yacc.c */ -#line 161 "host_rank.y" +/* Line 1464 of yacc.c */ +#line 112 "expr_arith.y" { (yyval.val_float) = (yyvsp[(1) - (3)].val_float) / (yyvsp[(3) - (3)].val_float);;} break; case 11: -/* Line 1455 of yacc.c */ -#line 162 "host_rank.y" +/* Line 1464 of yacc.c */ +#line 113 "expr_arith.y" { (yyval.val_float) = - (yyvsp[(2) - (2)].val_float);;} break; case 12: -/* Line 1455 of yacc.c */ -#line 163 "host_rank.y" +/* Line 1464 of yacc.c */ +#line 114 "expr_arith.y" { (yyval.val_float) = (yyvsp[(2) - (3)].val_float);;} break; -/* Line 1455 of yacc.c */ -#line 1590 "host_rank.cc" +/* Line 1464 of yacc.c */ +#line 1549 "expr_arith.cc" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -1622,7 +1581,7 @@ yyerrlab: { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (&yylloc, host, result, error_msg, YY_("syntax error")); + yyerror (&yylloc, oxml, result, error_msg, YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); @@ -1646,11 +1605,11 @@ yyerrlab: if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (&yylloc, host, result, error_msg, yymsg); + yyerror (&yylloc, oxml, result, error_msg, yymsg); } else { - yyerror (&yylloc, host, result, error_msg, YY_("syntax error")); + yyerror (&yylloc, oxml, result, error_msg, YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } @@ -1674,7 +1633,7 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval, &yylloc, host, result, error_msg); + yytoken, &yylval, &yylloc, oxml, result, error_msg); yychar = YYEMPTY; } } @@ -1731,7 +1690,7 @@ yyerrlab1: yyerror_range[0] = *yylsp; yydestruct ("Error: popping", - yystos[yystate], yyvsp, yylsp, host, result, error_msg); + yystos[yystate], yyvsp, yylsp, oxml, result, error_msg); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); @@ -1771,7 +1730,7 @@ yyabortlab: | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (&yylloc, host, result, error_msg, YY_("memory exhausted")); + yyerror (&yylloc, oxml, result, error_msg, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif @@ -1779,7 +1738,7 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc, host, result, error_msg); + yytoken, &yylval, &yylloc, oxml, result, error_msg); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -1787,7 +1746,7 @@ yyreturn: while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, yylsp, host, result, error_msg); + yystos[*yyssp], yyvsp, yylsp, oxml, result, error_msg); YYPOPSTACK (1); } #ifndef yyoverflow @@ -1804,33 +1763,32 @@ yyreturn: -/* Line 1675 of yacc.c */ -#line 166 "host_rank.y" +/* Line 1684 of yacc.c */ +#line 117 "expr_arith.y" -extern "C" void host_rank_error( - YYLTYPE * llocp, - Host * host, - int& result, - char ** error_msg, - const char * str) +extern "C" void expr_arith_error( + YYLTYPE * llocp, + ObjectXML * oxml, + int& result, + char ** error_msg, + const char * str) { - int length; - - length = strlen(str)+ 64; - - *error_msg = (char *) malloc(sizeof(char)*length); - - if (*error_msg != 0) - { - snprintf(*error_msg, - length, - "%s at line %i, columns %i:%i", - str, - llocp->first_line, - llocp->first_column, - llocp->last_column); - } -} + int length; + length = strlen(str)+ 64; + + *error_msg = (char *) malloc(sizeof(char)*length); + + if (*error_msg != 0) + { + snprintf(*error_msg, + length, + "%s at line %i, columns %i:%i", + str, + llocp->first_line, + llocp->first_column, + llocp->last_column); + } +} diff --git a/src/host/host_rank.h b/src/scheduler/src/xml/expr_arith.h similarity index 89% rename from src/host/host_rank.h rename to src/scheduler/src/xml/expr_arith.h index 0218495b62..7959e24cf1 100644 --- a/src/host/host_rank.h +++ b/src/scheduler/src/xml/expr_arith.h @@ -1,10 +1,9 @@ - -/* A Bison parser, made by GNU Bison 2.4.1. */ +/* A Bison parser, made by GNU Bison 2.4.2. */ /* Skeleton interface for Bison's Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software + Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -51,8 +50,8 @@ typedef union YYSTYPE { -/* Line 1676 of yacc.c */ -#line 54 "host_rank.y" +/* Line 1685 of yacc.c */ +#line 54 "expr_arith.y" char * val_str; int val_int; @@ -60,8 +59,8 @@ typedef union YYSTYPE -/* Line 1676 of yacc.c */ -#line 65 "host_rank.hh" +/* Line 1685 of yacc.c */ +#line 64 "expr_arith.hh" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/src/scheduler/src/xml/expr_arith.y b/src/scheduler/src/xml/expr_arith.y new file mode 100644 index 0000000000..83be574636 --- /dev/null +++ b/src/scheduler/src/xml/expr_arith.y @@ -0,0 +1,142 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include +#include +#include +#include + +#include +#include +#include + +#include "expr_arith.h" +#include "ObjectXML.h" + +#define YYERROR_VERBOSE +#define expr_arith_lex expr_lex + +extern "C" +{ +void expr_arith_error( + YYLTYPE * llocp, + ObjectXML * oxml, + int& result, + char ** error_msg, + const char * str); + +int expr_arith_lex (YYSTYPE *lvalp, YYLTYPE *llocp); + +int expr_arith_parse(ObjectXML *oxml, int& result, char ** errmsg); +} + +%} + +%parse-param {ObjectXML * oxml} +%parse-param {int& result} +%parse-param {char ** error_msg} + +%union { + char * val_str; + int val_int; + float val_float; +}; + +%defines +%locations +%pure_parser +%name-prefix = "expr_arith_" +%output = "expr_arith.cc" + +%left '+' '-' +%left '*' '/' +%token INTEGER +%token STRING +%token FLOAT +%type stmt +%type expr + +%% + +stmt: expr { result = static_cast($1);} + | { result = 0; } + ; + //TODO Pass Xpath base for search +expr: STRING { float val = 0.0; + + ostringstream xpath_t; + ostringstream xpath_s; + + vector results; + + xpath_t << "/HOST/TEMPLATE/" << $1; + xpath_s << "/HOST/HOST_SHARE/" << $1; + + results = (*oxml)[xpath_t.str().c_str()]; + + if (results.size() == 0) + { + results = (*oxml)[xpath_s.str().c_str()]; + } + + if (results.size() != 0) + { + istringstream iss(results[0]); + iss >> val; + } + + $$ = val; + + free($1); + } + | FLOAT { $$ = $1; } + | INTEGER { $$ = static_cast($1); } + | expr '+' expr { $$ = $1 + $3;} + | expr '-' expr { $$ = $1 - $3;} + | expr '*' expr { $$ = $1 * $3;} + | expr '/' expr { $$ = $1 / $3;} + | '-' expr { $$ = - $2;} + | '(' expr ')' { $$ = $2;} + ; + +%% + +extern "C" void expr_arith_error( + YYLTYPE * llocp, + ObjectXML * oxml, + int& result, + char ** error_msg, + const char * str) +{ + int length; + + length = strlen(str)+ 64; + + *error_msg = (char *) malloc(sizeof(char)*length); + + if (*error_msg != 0) + { + snprintf(*error_msg, + length, + "%s at line %i, columns %i:%i", + str, + llocp->first_line, + llocp->first_column, + llocp->last_column); + } +} diff --git a/src/host/host_requirements.cc b/src/scheduler/src/xml/expr_bool.cc similarity index 85% rename from src/host/host_requirements.cc rename to src/scheduler/src/xml/expr_bool.cc index d62eda1064..f34f5f0159 100644 --- a/src/host/host_requirements.cc +++ b/src/scheduler/src/xml/expr_bool.cc @@ -1,10 +1,9 @@ - -/* A Bison parser, made by GNU Bison 2.4.1. */ +/* A Bison parser, made by GNU Bison 2.4.2. */ /* Skeleton implementation for Bison's Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software + Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,7 +45,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.1" +#define YYBISON_VERSION "2.4.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -64,19 +63,19 @@ #define YYLSP_NEEDED 1 /* Substitute the variable and function names. */ -#define yyparse host_requirements_parse -#define yylex host_requirements_lex -#define yyerror host_requirements_error -#define yylval host_requirements_lval -#define yychar host_requirements_char -#define yydebug host_requirements_debug -#define yynerrs host_requirements_nerrs -#define yylloc host_requirements_lloc +#define yyparse expr_bool_parse +#define yylex expr_bool_lex +#define yyerror expr_bool_error +#define yylval expr_bool_lval +#define yychar expr_bool_char +#define yydebug expr_bool_debug +#define yynerrs expr_bool_nerrs +#define yylloc expr_bool_lloc /* Copy the first part of user declarations. */ /* Line 189 of yacc.c */ -#line 17 "host_requirements.y" +#line 17 "expr_bool.y" #include #include @@ -88,30 +87,36 @@ #include #include -#include "host_requirements.h" -#include "Host.h" +#include "expr_bool.h" +#include "ObjectXML.h" #define YYERROR_VERBOSE -#define host_requirements_lex host_lex +#define expr_bool_lex expr_lex -extern "C" +extern "C" { -void host_requirements_error( - YYLTYPE * llocp, - Host * host, - bool& result, - char ** error_msg, - const char * str); +void expr_bool_error( + YYLTYPE * llocp, + ObjectXML * oxml, + bool& result, + char ** error_msg, + const char * str); -int host_requirements_lex (YYSTYPE *lvalp, YYLTYPE *llocp); +int expr_bool_lex (YYSTYPE *lvalp, YYLTYPE *llocp); -int host_requirements_parse(Host * host, bool& result, char ** errmsg); +int expr_bool_parse(ObjectXML * oxml, bool& result, char ** errmsg); } +void get_xml_attribute(ObjectXML * oxml, const char* attr, int& val); + +void get_xml_attribute(ObjectXML * oxml, const char* attr, float& val); + +void get_xml_attribute(ObjectXML * oxml, const char* attr, string& val); + /* Line 189 of yacc.c */ -#line 115 "host_requirements.cc" +#line 120 "expr_bool.cc" /* Enabling traces. */ #ifndef YYDEBUG @@ -151,7 +156,7 @@ typedef union YYSTYPE { /* Line 214 of yacc.c */ -#line 54 "host_requirements.y" +#line 60 "expr_bool.y" char * val_str; int val_int; @@ -160,7 +165,7 @@ typedef union YYSTYPE /* Line 214 of yacc.c */ -#line 164 "host_requirements.cc" +#line 169 "expr_bool.cc" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -185,7 +190,7 @@ typedef struct YYLTYPE /* Line 264 of yacc.c */ -#line 189 "host_requirements.cc" +#line 194 "expr_bool.cc" #ifdef short # undef short @@ -235,7 +240,7 @@ typedef short int yytype_int16; #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ -# if YYENABLE_NLS +# if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) @@ -476,8 +481,8 @@ static const yytype_int8 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 74, 74, 75, 78, 85, 92, 99, 106, 113, - 120, 127, 134, 142, 150, 151, 152, 153 + 0, 80, 80, 81, 84, 91, 98, 105, 112, 119, + 126, 133, 140, 148, 156, 157, 158, 159 }; #endif @@ -587,9 +592,18 @@ static const yytype_uint8 yystos[] = /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ #define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif #define YYRECOVERING() (!!yyerrstatus) @@ -605,7 +619,7 @@ do \ } \ else \ { \ - yyerror (&yylloc, host, result, error_msg, YY_("syntax error: cannot back up")); \ + yyerror (&yylloc, oxml, result, error_msg, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) @@ -646,7 +660,7 @@ while (YYID (0)) we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ @@ -685,7 +699,7 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value, Location, host, result, error_msg); \ + Type, Value, Location, oxml, result, error_msg); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) @@ -699,15 +713,15 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, Host * host, bool& result, char ** error_msg) +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ObjectXML * oxml, bool& result, char ** error_msg) #else static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, host, result, error_msg) +yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, oxml, result, error_msg) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; YYLTYPE const * const yylocationp; - Host * host; + ObjectXML * oxml; bool& result; char ** error_msg; #endif @@ -715,7 +729,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, host, result, er if (!yyvaluep) return; YYUSE (yylocationp); - YYUSE (host); + YYUSE (oxml); YYUSE (result); YYUSE (error_msg); # ifdef YYPRINT @@ -739,15 +753,15 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, host, result, er #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, Host * host, bool& result, char ** error_msg) +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ObjectXML * oxml, bool& result, char ** error_msg) #else static void -yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, host, result, error_msg) +yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, oxml, result, error_msg) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; YYLTYPE const * const yylocationp; - Host * host; + ObjectXML * oxml; bool& result; char ** error_msg; #endif @@ -759,7 +773,7 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, host, result, error_ms YY_LOCATION_PRINT (yyoutput, *yylocationp); YYFPRINTF (yyoutput, ": "); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, host, result, error_msg); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, oxml, result, error_msg); YYFPRINTF (yyoutput, ")"); } @@ -802,14 +816,14 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, Host * host, bool& result, char ** error_msg) +yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, ObjectXML * oxml, bool& result, char ** error_msg) #else static void -yy_reduce_print (yyvsp, yylsp, yyrule, host, result, error_msg) +yy_reduce_print (yyvsp, yylsp, yyrule, oxml, result, error_msg) YYSTYPE *yyvsp; YYLTYPE *yylsp; int yyrule; - Host * host; + ObjectXML * oxml; bool& result; char ** error_msg; #endif @@ -825,7 +839,7 @@ yy_reduce_print (yyvsp, yylsp, yyrule, host, result, error_msg) YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) - , &(yylsp[(yyi + 1) - (yynrhs)]) , host, result, error_msg); + , &(yylsp[(yyi + 1) - (yynrhs)]) , oxml, result, error_msg); YYFPRINTF (stderr, "\n"); } } @@ -833,7 +847,7 @@ yy_reduce_print (yyvsp, yylsp, yyrule, host, result, error_msg) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, yylsp, Rule, host, result, error_msg); \ + yy_reduce_print (yyvsp, yylsp, Rule, oxml, result, error_msg); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that @@ -1084,22 +1098,22 @@ yysyntax_error (char *yyresult, int yystate, int yychar) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, Host * host, bool& result, char ** error_msg) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, ObjectXML * oxml, bool& result, char ** error_msg) #else static void -yydestruct (yymsg, yytype, yyvaluep, yylocationp, host, result, error_msg) +yydestruct (yymsg, yytype, yyvaluep, yylocationp, oxml, result, error_msg) const char *yymsg; int yytype; YYSTYPE *yyvaluep; YYLTYPE *yylocationp; - Host * host; + ObjectXML * oxml; bool& result; char ** error_msg; #endif { YYUSE (yyvaluep); YYUSE (yylocationp); - YYUSE (host); + YYUSE (oxml); YYUSE (result); YYUSE (error_msg); @@ -1124,7 +1138,7 @@ int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus -int yyparse (Host * host, bool& result, char ** error_msg); +int yyparse (ObjectXML * oxml, bool& result, char ** error_msg); #else int yyparse (); #endif @@ -1152,11 +1166,11 @@ yyparse (YYPARSE_PARAM) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int -yyparse (Host * host, bool& result, char ** error_msg) +yyparse (ObjectXML * oxml, bool& result, char ** error_msg) #else int -yyparse (host, result, error_msg) - Host * host; +yyparse (oxml, result, error_msg) + ObjectXML * oxml; bool& result; char ** error_msg; #endif @@ -1249,7 +1263,7 @@ YYLTYPE yylloc; yyvsp = yyvs; yylsp = yyls; -#if YYLTYPE_IS_TRIVIAL +#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL /* Initialize the default location before parsing starts. */ yylloc.first_line = yylloc.last_line = 1; yylloc.first_column = yylloc.last_column = 1; @@ -1439,25 +1453,25 @@ yyreduce: { case 2: -/* Line 1455 of yacc.c */ -#line 74 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 80 "expr_bool.y" { result=(yyvsp[(1) - (1)].val_int); ;} break; case 3: -/* Line 1455 of yacc.c */ -#line 75 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 81 "expr_bool.y" { result=true; ;} break; case 4: -/* Line 1455 of yacc.c */ -#line 78 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 84 "expr_bool.y" { int val; - host->get_template_attribute((yyvsp[(1) - (3)].val_str),val); + get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); (yyval.val_int) = val == (yyvsp[(3) - (3)].val_int); free((yyvsp[(1) - (3)].val_str));;} @@ -1465,11 +1479,11 @@ yyreduce: case 5: -/* Line 1455 of yacc.c */ -#line 85 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 91 "expr_bool.y" { int val; - host->get_template_attribute((yyvsp[(1) - (4)].val_str),val); + get_xml_attribute(oxml,(yyvsp[(1) - (4)].val_str),val); (yyval.val_int) = val != (yyvsp[(4) - (4)].val_int); free((yyvsp[(1) - (4)].val_str));;} @@ -1477,11 +1491,11 @@ yyreduce: case 6: -/* Line 1455 of yacc.c */ -#line 92 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 98 "expr_bool.y" { int val; - host->get_template_attribute((yyvsp[(1) - (3)].val_str),val); + get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); (yyval.val_int) = val > (yyvsp[(3) - (3)].val_int); free((yyvsp[(1) - (3)].val_str));;} @@ -1489,11 +1503,11 @@ yyreduce: case 7: -/* Line 1455 of yacc.c */ -#line 99 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 105 "expr_bool.y" { int val; - host->get_template_attribute((yyvsp[(1) - (3)].val_str),val); + get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); (yyval.val_int) = val < (yyvsp[(3) - (3)].val_int); free((yyvsp[(1) - (3)].val_str));;} @@ -1501,59 +1515,59 @@ yyreduce: case 8: -/* Line 1455 of yacc.c */ -#line 106 "host_requirements.y" - { string val; +/* Line 1464 of yacc.c */ +#line 112 "expr_bool.y" + { float val; - host->get_template_attribute((yyvsp[(1) - (3)].val_str),val); - (yyval.val_int) = val.empty() ? false : atof(val.c_str()) == (yyvsp[(3) - (3)].val_float); + get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); + (yyval.val_int) = val == (yyvsp[(3) - (3)].val_float); free((yyvsp[(1) - (3)].val_str));;} break; case 9: -/* Line 1455 of yacc.c */ -#line 113 "host_requirements.y" - { string val; +/* Line 1464 of yacc.c */ +#line 119 "expr_bool.y" + { float val; - host->get_template_attribute((yyvsp[(1) - (4)].val_str),val); - (yyval.val_int) = val.empty() ? false : atof(val.c_str()) != (yyvsp[(4) - (4)].val_float); + get_xml_attribute(oxml,(yyvsp[(1) - (4)].val_str),val); + (yyval.val_int) = val != (yyvsp[(4) - (4)].val_float); free((yyvsp[(1) - (4)].val_str));;} break; case 10: -/* Line 1455 of yacc.c */ -#line 120 "host_requirements.y" - { string val; +/* Line 1464 of yacc.c */ +#line 126 "expr_bool.y" + {float val; - host->get_template_attribute((yyvsp[(1) - (3)].val_str),val); - (yyval.val_int) = val.empty() ? false : atof(val.c_str()) > (yyvsp[(3) - (3)].val_float); + get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); + (yyval.val_int) = val > (yyvsp[(3) - (3)].val_float); free((yyvsp[(1) - (3)].val_str));;} break; case 11: -/* Line 1455 of yacc.c */ -#line 127 "host_requirements.y" - { string val; +/* Line 1464 of yacc.c */ +#line 133 "expr_bool.y" + {float val; - host->get_template_attribute((yyvsp[(1) - (3)].val_str),val); - (yyval.val_int) = val.empty() ? false : atof(val.c_str()) < (yyvsp[(3) - (3)].val_float); + get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); + (yyval.val_int) = val < (yyvsp[(3) - (3)].val_float); free((yyvsp[(1) - (3)].val_str));;} break; case 12: -/* Line 1455 of yacc.c */ -#line 134 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 140 "expr_bool.y" { string val; - - host->get_template_attribute((yyvsp[(1) - (3)].val_str),val); + + get_xml_attribute(oxml,(yyvsp[(1) - (3)].val_str),val); (yyval.val_int) = val.empty() ? false :fnmatch((yyvsp[(3) - (3)].val_str), val.c_str(), 0) == 0; free((yyvsp[(1) - (3)].val_str)); @@ -1562,11 +1576,11 @@ yyreduce: case 13: -/* Line 1455 of yacc.c */ -#line 142 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 148 "expr_bool.y" { string val; - - host->get_template_attribute((yyvsp[(1) - (4)].val_str),val); + + get_xml_attribute(oxml,(yyvsp[(1) - (4)].val_str),val); (yyval.val_int) = val.empty() ? false : fnmatch((yyvsp[(4) - (4)].val_str), val.c_str(), 0) != 0; free((yyvsp[(1) - (4)].val_str)); @@ -1575,36 +1589,36 @@ yyreduce: case 14: -/* Line 1455 of yacc.c */ -#line 150 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 156 "expr_bool.y" { (yyval.val_int) = (yyvsp[(1) - (3)].val_int) && (yyvsp[(3) - (3)].val_int); ;} break; case 15: -/* Line 1455 of yacc.c */ -#line 151 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 157 "expr_bool.y" { (yyval.val_int) = (yyvsp[(1) - (3)].val_int) || (yyvsp[(3) - (3)].val_int); ;} break; case 16: -/* Line 1455 of yacc.c */ -#line 152 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 158 "expr_bool.y" { (yyval.val_int) = ! (yyvsp[(2) - (2)].val_int); ;} break; case 17: -/* Line 1455 of yacc.c */ -#line 153 "host_requirements.y" +/* Line 1464 of yacc.c */ +#line 159 "expr_bool.y" { (yyval.val_int) = (yyvsp[(2) - (3)].val_int); ;} break; -/* Line 1455 of yacc.c */ -#line 1608 "host_requirements.cc" +/* Line 1464 of yacc.c */ +#line 1622 "expr_bool.cc" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -1640,7 +1654,7 @@ yyerrlab: { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (&yylloc, host, result, error_msg, YY_("syntax error")); + yyerror (&yylloc, oxml, result, error_msg, YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); @@ -1664,11 +1678,11 @@ yyerrlab: if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (&yylloc, host, result, error_msg, yymsg); + yyerror (&yylloc, oxml, result, error_msg, yymsg); } else { - yyerror (&yylloc, host, result, error_msg, YY_("syntax error")); + yyerror (&yylloc, oxml, result, error_msg, YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } @@ -1692,7 +1706,7 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval, &yylloc, host, result, error_msg); + yytoken, &yylval, &yylloc, oxml, result, error_msg); yychar = YYEMPTY; } } @@ -1749,7 +1763,7 @@ yyerrlab1: yyerror_range[0] = *yylsp; yydestruct ("Error: popping", - yystos[yystate], yyvsp, yylsp, host, result, error_msg); + yystos[yystate], yyvsp, yylsp, oxml, result, error_msg); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); @@ -1789,7 +1803,7 @@ yyabortlab: | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (&yylloc, host, result, error_msg, YY_("memory exhausted")); + yyerror (&yylloc, oxml, result, error_msg, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif @@ -1797,7 +1811,7 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc, host, result, error_msg); + yytoken, &yylval, &yylloc, oxml, result, error_msg); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -1805,7 +1819,7 @@ yyreturn: while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, yylsp, host, result, error_msg); + yystos[*yyssp], yyvsp, yylsp, oxml, result, error_msg); YYPOPSTACK (1); } #ifndef yyoverflow @@ -1822,32 +1836,111 @@ yyreturn: -/* Line 1675 of yacc.c */ -#line 156 "host_requirements.y" +/* Line 1684 of yacc.c */ +#line 162 "expr_bool.y" -extern "C" void host_requirements_error( - YYLTYPE * llocp, - Host * host, - bool& result, - char ** error_msg, - const char * str) +extern "C" void expr_bool_error( + YYLTYPE * llocp, + ObjectXML * oxml, + bool& result, + char ** error_msg, + const char * str) { - int length; - - length = strlen(str)+ 64; - - *error_msg = (char *) malloc(sizeof(char)*length); - - if (*error_msg != 0) - { - snprintf(*error_msg, - length, - "%s at line %i, columns %i:%i", - str, - llocp->first_line, - llocp->first_column, - llocp->last_column); - } -} + int length; + length = strlen(str)+ 64; + + *error_msg = (char *) malloc(sizeof(char)*length); + + if (*error_msg != 0) + { + snprintf(*error_msg, + length, + "%s at line %i, columns %i:%i", + str, + llocp->first_line, + llocp->first_column, + llocp->last_column); + } +} + +void get_xml_attribute(ObjectXML * oxml, const char* attr, int& val) +{ + //TODO: pass xpath base + ostringstream xpath_t; + ostringstream xpath_s; + + vector results; + + xpath_t << "/HOST/TEMPLATE/" << attr; + xpath_s << "/HOST/HOST_SHARE/" << attr; + + val = 0; + + results = (*oxml)[xpath_t.str().c_str()]; + + if (results.size() == 0) + { + results = (*oxml)[xpath_s.str().c_str()]; + } + + if (results.size() != 0) + { + istringstream iss(results[0]); + iss >> val; + } +} + +void get_xml_attribute(ObjectXML * oxml, const char* attr, float& val) +{ + //TODO: pass xpath base + ostringstream xpath_t; + ostringstream xpath_s; + + vector results; + + xpath_t << "/HOST/TEMPLATE/" << attr; + xpath_s << "/HOST/HOST_SHARE/" << attr; + + val = 0.0; + + results = (*oxml)[xpath_t.str().c_str()]; + + if (results.size() == 0) + { + results = (*oxml)[xpath_s.str().c_str()]; + } + + if (results.size() != 0) + { + istringstream iss(results[0]); + iss >> val; + } +} + +void get_xml_attribute(ObjectXML * oxml, const char* attr, string& val) +{ + //TODO: pass xpath base + ostringstream xpath_t; + ostringstream xpath_s; + + vector results; + + xpath_t << "/HOST/TEMPLATE/" << attr; + xpath_s << "/HOST/HOST_SHARE/" << attr; + + val = ""; + + results = (*oxml)[xpath_t.str().c_str()]; + + if (results.size() == 0) + { + results = (*oxml)[xpath_s.str().c_str()]; + } + + if (results.size() != 0) + { + val = results[0]; + } +} diff --git a/src/host/host_requirements.h b/src/scheduler/src/xml/expr_bool.h similarity index 89% rename from src/host/host_requirements.h rename to src/scheduler/src/xml/expr_bool.h index 4958488af2..74a5306442 100644 --- a/src/host/host_requirements.h +++ b/src/scheduler/src/xml/expr_bool.h @@ -1,10 +1,9 @@ - -/* A Bison parser, made by GNU Bison 2.4.1. */ +/* A Bison parser, made by GNU Bison 2.4.2. */ /* Skeleton interface for Bison's Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software + Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -51,8 +50,8 @@ typedef union YYSTYPE { -/* Line 1676 of yacc.c */ -#line 54 "host_requirements.y" +/* Line 1685 of yacc.c */ +#line 60 "expr_bool.y" char * val_str; int val_int; @@ -60,8 +59,8 @@ typedef union YYSTYPE -/* Line 1676 of yacc.c */ -#line 65 "host_requirements.hh" +/* Line 1685 of yacc.c */ +#line 64 "expr_bool.hh" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/src/scheduler/src/xml/expr_bool.y b/src/scheduler/src/xml/expr_bool.y new file mode 100644 index 0000000000..a4298d5d2c --- /dev/null +++ b/src/scheduler/src/xml/expr_bool.y @@ -0,0 +1,267 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include +#include +#include +#include + +#include +#include +#include + +#include "expr_bool.h" +#include "ObjectXML.h" + +#define YYERROR_VERBOSE +#define expr_bool_lex expr_lex + +extern "C" +{ +void expr_bool_error( + YYLTYPE * llocp, + ObjectXML * oxml, + bool& result, + char ** error_msg, + const char * str); + +int expr_bool_lex (YYSTYPE *lvalp, YYLTYPE *llocp); + +int expr_bool_parse(ObjectXML * oxml, bool& result, char ** errmsg); +} + +void get_xml_attribute(ObjectXML * oxml, const char* attr, int& val); + +void get_xml_attribute(ObjectXML * oxml, const char* attr, float& val); + +void get_xml_attribute(ObjectXML * oxml, const char* attr, string& val); + +%} + +%parse-param {ObjectXML * oxml} +%parse-param {bool& result} +%parse-param {char ** error_msg} + +%union { + char * val_str; + int val_int; + float val_float; +}; + +%defines +%locations +%pure_parser +%name-prefix = "expr_bool_" +%output = "expr_bool.cc" + +%left '!' '&' '|' +%token INTEGER +%token STRING +%token FLOAT +%type stmt expr + +%% + +stmt: expr { result=$1; } + | { result=true; } /* TRUE BY DEFAULT, ON EMPTY STRINGS */ + ; + +expr: STRING '=' INTEGER { int val; + + get_xml_attribute(oxml,$1,val); + $$ = val == $3; + + free($1);} + + | STRING '!' '=' INTEGER { int val; + + get_xml_attribute(oxml,$1,val); + $$ = val != $4; + + free($1);} + + | STRING '>' INTEGER { int val; + + get_xml_attribute(oxml,$1,val); + $$ = val > $3; + + free($1);} + + | STRING '<' INTEGER { int val; + + get_xml_attribute(oxml,$1,val); + $$ = val < $3; + + free($1);} + + | STRING '=' FLOAT { float val; + + get_xml_attribute(oxml,$1,val); + $$ = val == $3; + + free($1);} + + | STRING '!' '=' FLOAT { float val; + + get_xml_attribute(oxml,$1,val); + $$ = val != $4; + + free($1);} + + | STRING '>' FLOAT {float val; + + get_xml_attribute(oxml,$1,val); + $$ = val > $3; + + free($1);} + + | STRING '<' FLOAT {float val; + + get_xml_attribute(oxml,$1,val); + $$ = val < $3; + + free($1);} + + | STRING '=' STRING { string val; + + get_xml_attribute(oxml,$1,val); + $$ = val.empty() ? false :fnmatch($3, val.c_str(), 0) == 0; + + free($1); + free($3);} + + | STRING '!''=' STRING { string val; + + get_xml_attribute(oxml,$1,val); + $$ = val.empty() ? false : fnmatch($4, val.c_str(), 0) != 0; + + free($1); + free($4);} + + | expr '&' expr { $$ = $1 && $3; } + | expr '|' expr { $$ = $1 || $3; } + | '!' expr { $$ = ! $2; } + | '(' expr ')' { $$ = $2; } + ; + +%% + +extern "C" void expr_bool_error( + YYLTYPE * llocp, + ObjectXML * oxml, + bool& result, + char ** error_msg, + const char * str) +{ + int length; + + length = strlen(str)+ 64; + + *error_msg = (char *) malloc(sizeof(char)*length); + + if (*error_msg != 0) + { + snprintf(*error_msg, + length, + "%s at line %i, columns %i:%i", + str, + llocp->first_line, + llocp->first_column, + llocp->last_column); + } +} + +void get_xml_attribute(ObjectXML * oxml, const char* attr, int& val) +{ + //TODO: pass xpath base + ostringstream xpath_t; + ostringstream xpath_s; + + vector results; + + xpath_t << "/HOST/TEMPLATE/" << attr; + xpath_s << "/HOST/HOST_SHARE/" << attr; + + val = 0; + + results = (*oxml)[xpath_t.str().c_str()]; + + if (results.size() == 0) + { + results = (*oxml)[xpath_s.str().c_str()]; + } + + if (results.size() != 0) + { + istringstream iss(results[0]); + iss >> val; + } +} + +void get_xml_attribute(ObjectXML * oxml, const char* attr, float& val) +{ + //TODO: pass xpath base + ostringstream xpath_t; + ostringstream xpath_s; + + vector results; + + xpath_t << "/HOST/TEMPLATE/" << attr; + xpath_s << "/HOST/HOST_SHARE/" << attr; + + val = 0.0; + + results = (*oxml)[xpath_t.str().c_str()]; + + if (results.size() == 0) + { + results = (*oxml)[xpath_s.str().c_str()]; + } + + if (results.size() != 0) + { + istringstream iss(results[0]); + iss >> val; + } +} + +void get_xml_attribute(ObjectXML * oxml, const char* attr, string& val) +{ + //TODO: pass xpath base + ostringstream xpath_t; + ostringstream xpath_s; + + vector results; + + xpath_t << "/HOST/TEMPLATE/" << attr; + xpath_s << "/HOST/HOST_SHARE/" << attr; + + val = ""; + + results = (*oxml)[xpath_t.str().c_str()]; + + if (results.size() == 0) + { + results = (*oxml)[xpath_s.str().c_str()]; + } + + if (results.size() != 0) + { + val = results[0]; + } +} \ No newline at end of file diff --git a/src/host/host_parser.c b/src/scheduler/src/xml/expr_parser.c similarity index 79% rename from src/host/host_parser.c rename to src/scheduler/src/xml/expr_parser.c index 4accae72dd..648d37f6fd 100644 --- a/src/host/host_parser.c +++ b/src/scheduler/src/xml/expr_parser.c @@ -1,29 +1,29 @@ -#line 2 "host_parser.c" +#line 2 "expr_parser.c" -#line 4 "host_parser.c" +#line 4 "expr_parser.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ -#define yy_create_buffer host__create_buffer -#define yy_delete_buffer host__delete_buffer -#define yy_flex_debug host__flex_debug -#define yy_init_buffer host__init_buffer -#define yy_flush_buffer host__flush_buffer -#define yy_load_buffer_state host__load_buffer_state -#define yy_switch_to_buffer host__switch_to_buffer -#define yyin host_in -#define yyleng host_leng -#define yylex host_lex -#define yylineno host_lineno -#define yyout host_out -#define yyrestart host_restart -#define yytext host_text -#define yywrap host_wrap -#define yyalloc host_alloc -#define yyrealloc host_realloc -#define yyfree host_free +#define yy_create_buffer expr__create_buffer +#define yy_delete_buffer expr__delete_buffer +#define yy_flex_debug expr__flex_debug +#define yy_init_buffer expr__init_buffer +#define yy_flush_buffer expr__flush_buffer +#define yy_load_buffer_state expr__load_buffer_state +#define yy_switch_to_buffer expr__switch_to_buffer +#define yyin expr_in +#define yyleng expr_leng +#define yylex expr_lex +#define yylineno expr_lineno +#define yyout expr_out +#define yyrestart expr_restart +#define yytext expr_text +#define yywrap expr_wrap +#define yyalloc expr_alloc +#define yyrealloc expr_realloc +#define yyfree expr_free #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 @@ -154,7 +154,7 @@ typedef unsigned int flex_uint32_t; #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE host_restart(host_in ) +#define YY_NEW_FILE expr_restart(expr_in ) #define YY_END_OF_BUFFER_CHAR 0 @@ -172,9 +172,9 @@ typedef unsigned int flex_uint32_t; typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif -extern int host_leng; +extern int expr_leng; -extern FILE *host_in, *host_out; +extern FILE *expr_in, *expr_out; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 @@ -182,30 +182,30 @@ extern FILE *host_in, *host_out; /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires * access to the local variable yy_act. Since yyless() is a macro, it would break - * existing scanners that call yyless() from OUTSIDE host_lex. + * existing scanners that call yyless() from OUTSIDE expr_lex. * One obvious solution it to make yy_act a global. I tried that, and saw - * a 5% performance hit in a non-host_lineno scanner, because yy_act is + * a 5% performance hit in a non-expr_lineno scanner, because yy_act is * normally declared as a register variable-- so it is not worth it. */ #define YY_LESS_LINENO(n) \ do { \ int yyl;\ - for ( yyl = n; yyl < host_leng; ++yyl )\ - if ( host_text[yyl] == '\n' )\ - --host_lineno;\ + for ( yyl = n; yyl < expr_leng; ++yyl )\ + if ( expr_text[yyl] == '\n' )\ + --expr_lineno;\ }while(0) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ - /* Undo effects of setting up host_text. */ \ + /* Undo effects of setting up expr_text. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up host_text again */ \ + YY_DO_BEFORE_ACTION; /* set up expr_text again */ \ } \ while ( 0 ) @@ -273,8 +273,8 @@ struct yy_buffer_state * possible backing-up. * * When we actually see the EOF, we change the status to "new" - * (via host_restart()), so that the user can continue scanning by - * just pointing host_in at a new input file. + * (via expr_restart()), so that the user can continue scanning by + * just pointing expr_in at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 @@ -301,51 +301,51 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] -/* yy_hold_char holds the character lost when host_text is formed. */ +/* yy_hold_char holds the character lost when expr_text is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ -int host_leng; +int expr_leng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ -/* Flag which is used to allow host_wrap()'s to do buffer switches - * instead of setting up a fresh host_in. A bit of a hack ... +/* Flag which is used to allow expr_wrap()'s to do buffer switches + * instead of setting up a fresh expr_in. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; -void host_restart (FILE *input_file ); -void host__switch_to_buffer (YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE host__create_buffer (FILE *file,int size ); -void host__delete_buffer (YY_BUFFER_STATE b ); -void host__flush_buffer (YY_BUFFER_STATE b ); -void host_push_buffer_state (YY_BUFFER_STATE new_buffer ); -void host_pop_buffer_state (void ); +void expr_restart (FILE *input_file ); +void expr__switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE expr__create_buffer (FILE *file,int size ); +void expr__delete_buffer (YY_BUFFER_STATE b ); +void expr__flush_buffer (YY_BUFFER_STATE b ); +void expr_push_buffer_state (YY_BUFFER_STATE new_buffer ); +void expr_pop_buffer_state (void ); -static void host_ensure_buffer_stack (void ); -static void host__load_buffer_state (void ); -static void host__init_buffer (YY_BUFFER_STATE b,FILE *file ); +static void expr_ensure_buffer_stack (void ); +static void expr__load_buffer_state (void ); +static void expr__init_buffer (YY_BUFFER_STATE b,FILE *file ); -#define YY_FLUSH_BUFFER host__flush_buffer(YY_CURRENT_BUFFER ) +#define YY_FLUSH_BUFFER expr__flush_buffer(YY_CURRENT_BUFFER ) -YY_BUFFER_STATE host__scan_buffer (char *base,yy_size_t size ); -YY_BUFFER_STATE host__scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE host__scan_bytes (yyconst char *bytes,int len ); +YY_BUFFER_STATE expr__scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE expr__scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE expr__scan_bytes (yyconst char *bytes,int len ); -void *host_alloc (yy_size_t ); -void *host_realloc (void *,yy_size_t ); -void host_free (void * ); +void *expr_alloc (yy_size_t ); +void *expr_realloc (void *,yy_size_t ); +void expr_free (void * ); -#define yy_new_buffer host__create_buffer +#define yy_new_buffer expr__create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ - host_ensure_buffer_stack (); \ + expr_ensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ - host__create_buffer(host_in,YY_BUF_SIZE ); \ + expr__create_buffer(expr_in,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } @@ -353,9 +353,9 @@ void host_free (void * ); #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ - host_ensure_buffer_stack (); \ + expr_ensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ - host__create_buffer(host_in,YY_BUF_SIZE ); \ + expr__create_buffer(expr_in,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } @@ -366,16 +366,16 @@ void host_free (void * ); typedef unsigned char YY_CHAR; -FILE *host_in = (FILE *) 0, *host_out = (FILE *) 0; +FILE *expr_in = (FILE *) 0, *expr_out = (FILE *) 0; typedef int yy_state_type; -extern int host_lineno; +extern int expr_lineno; -int host_lineno = 1; +int expr_lineno = 1; -extern char *host_text; -#define yytext_ptr host_text +extern char *expr_text; +#define yytext_ptr expr_text static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); @@ -383,11 +383,11 @@ static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the - * corresponding action - sets up host_text. + * corresponding action - sets up expr_text. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ - host_leng = (size_t) (yy_cp - yy_bp); \ + expr_leng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; @@ -482,8 +482,8 @@ static yyconst flex_int32_t yy_rule_can_match_eol[9] = static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; -extern int host__flex_debug; -int host__flex_debug = 0; +extern int expr__flex_debug; +int expr__flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. @@ -492,8 +492,8 @@ int host__flex_debug = 0; #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET -char *host_text; -#line 1 "host_parser.l" +char *expr_text; +#line 1 "expr_parser.l" /* -------------------------------------------------------------------------- */ /* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */ /* */ @@ -509,21 +509,20 @@ char *host_text; /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ -#line 18 "host_parser.l" +#line 18 "expr_parser.l" #include #include #include -#include -#include "host_requirements.h" -#include "host_rank.h" +#include "expr_bool.h" +#include "expr_arith.h" -#define YY_DECL int host_lex (YYSTYPE *lvalp, YYLTYPE *llocp) +#define YY_DECL int expr_lex (YYSTYPE *lvalp, YYLTYPE *llocp) -#define YY_USER_ACTION llocp->first_line = host_lineno; \ +#define YY_USER_ACTION llocp->first_line = expr_lineno; \ llocp->first_column = llocp->last_column; \ - llocp->last_column += host_leng; -#line 527 "host_parser.c" + llocp->last_column += expr_leng; +#line 526 "expr_parser.c" #define INITIAL 0 @@ -544,31 +543,31 @@ static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ -int host_lex_destroy (void ); +int expr_lex_destroy (void ); -int host_get_debug (void ); +int expr_get_debug (void ); -void host_set_debug (int debug_flag ); +void expr_set_debug (int debug_flag ); -YY_EXTRA_TYPE host_get_extra (void ); +YY_EXTRA_TYPE expr_get_extra (void ); -void host_set_extra (YY_EXTRA_TYPE user_defined ); +void expr_set_extra (YY_EXTRA_TYPE user_defined ); -FILE *host_get_in (void ); +FILE *expr_get_in (void ); -void host_set_in (FILE * in_str ); +void expr_set_in (FILE * in_str ); -FILE *host_get_out (void ); +FILE *expr_get_out (void ); -void host_set_out (FILE * out_str ); +void expr_set_out (FILE * out_str ); -int host_get_leng (void ); +int expr_get_leng (void ); -char *host_get_text (void ); +char *expr_get_text (void ); -int host_get_lineno (void ); +int expr_get_lineno (void ); -void host_set_lineno (int line_number ); +void expr_set_lineno (int line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. @@ -576,9 +575,9 @@ void host_set_lineno (int line_number ); #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus -extern "C" int host_wrap (void ); +extern "C" int expr_wrap (void ); #else -extern int host_wrap (void ); +extern int expr_wrap (void ); #endif #endif @@ -610,7 +609,7 @@ static int input (void ); /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ -#define ECHO fwrite( host_text, host_leng, 1, host_out ) +#define ECHO fwrite( expr_text, expr_leng, 1, expr_out ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, @@ -623,18 +622,18 @@ static int input (void ); int c = '*'; \ int n; \ for ( n = 0; n < max_size && \ - (c = getc( host_in )) != EOF && c != '\n'; ++n ) \ + (c = getc( expr_in )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ - if ( c == EOF && ferror( host_in ) ) \ + if ( c == EOF && ferror( expr_in ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ - while ( (result = fread(buf, 1, max_size, host_in))==0 && ferror(host_in)) \ + while ( (result = fread(buf, 1, max_size, expr_in))==0 && ferror(expr_in)) \ { \ if( errno != EINTR) \ { \ @@ -642,7 +641,7 @@ static int input (void ); break; \ } \ errno=0; \ - clearerr(host_in); \ + clearerr(expr_in); \ } \ }\ \ @@ -675,12 +674,12 @@ static int input (void ); #ifndef YY_DECL #define YY_DECL_IS_OURS 1 -extern int host_lex (void); +extern int expr_lex (void); -#define YY_DECL int host_lex (void) +#define YY_DECL int expr_lex (void) #endif /* !YY_DECL */ -/* Code executed at the beginning of each rule, after host_text and host_leng +/* Code executed at the beginning of each rule, after expr_text and expr_leng * have been set up. */ #ifndef YY_USER_ACTION @@ -703,11 +702,11 @@ YY_DECL register char *yy_cp, *yy_bp; register int yy_act; -#line 38 "host_parser.l" +#line 37 "expr_parser.l" /* --- Tokens --- */ -#line 711 "host_parser.c" +#line 710 "expr_parser.c" if ( !(yy_init) ) { @@ -720,26 +719,26 @@ YY_DECL if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ - if ( ! host_in ) - host_in = stdin; + if ( ! expr_in ) + expr_in = stdin; - if ( ! host_out ) - host_out = stdout; + if ( ! expr_out ) + expr_out = stdout; if ( ! YY_CURRENT_BUFFER ) { - host_ensure_buffer_stack (); + expr_ensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = - host__create_buffer(host_in,YY_BUF_SIZE ); + expr__create_buffer(expr_in,YY_BUF_SIZE ); } - host__load_buffer_state( ); + expr__load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); - /* Support of host_text. */ + /* Support of expr_text. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of @@ -782,10 +781,10 @@ yy_find_action: if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) { int yyl; - for ( yyl = 0; yyl < host_leng; ++yyl ) - if ( host_text[yyl] == '\n' ) + for ( yyl = 0; yyl < expr_leng; ++yyl ) + if ( expr_text[yyl] == '\n' ) - host_lineno++; + expr_lineno++; ; } @@ -802,55 +801,55 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 41 "host_parser.l" -{ return *host_text;} +#line 40 "expr_parser.l" +{ return *expr_text;} YY_BREAK /* --- Strings, also quoted form --- */ case 2: YY_RULE_SETUP -#line 45 "host_parser.l" -{ lvalp->val_str = strdup(host_text); - return STRING;} +#line 44 "expr_parser.l" +{ lvalp->val_str = strdup(expr_text); + return STRING;} YY_BREAK case 3: YY_RULE_SETUP -#line 48 "host_parser.l" -{ lvalp->val_str = NULL; - return STRING;} +#line 47 "expr_parser.l" +{ lvalp->val_str = NULL; + return STRING;} YY_BREAK case 4: /* rule 4 can match eol */ YY_RULE_SETUP -#line 51 "host_parser.l" -{ lvalp->val_str = strdup(host_text+1); - lvalp->val_str[host_leng-2] = '\0'; - return STRING;} +#line 50 "expr_parser.l" +{ lvalp->val_str = strdup(expr_text+1); + lvalp->val_str[expr_leng-2] = '\0'; + return STRING;} YY_BREAK /* --- Numbers --- */ case 5: YY_RULE_SETUP -#line 56 "host_parser.l" -{ lvalp->val_int = atoi(host_text); +#line 56 "expr_parser.l" +{ lvalp->val_int = atoi(expr_text); return INTEGER;} YY_BREAK case 6: YY_RULE_SETUP -#line 59 "host_parser.l" -{ lvalp->val_float = atof(host_text); - return FLOAT;} +#line 59 "expr_parser.l" +{ lvalp->val_float = atof(expr_text); + return FLOAT;} YY_BREAK /* --- blanks --- */ case 7: YY_RULE_SETUP -#line 63 "host_parser.l" +#line 64 "expr_parser.l" YY_BREAK case 8: YY_RULE_SETUP -#line 65 "host_parser.l" +#line 66 "expr_parser.l" ECHO; YY_BREAK -#line 854 "host_parser.c" +#line 853 "expr_parser.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -867,15 +866,15 @@ case YY_STATE_EOF(INITIAL): { /* We're scanning a new file or input source. It's * possible that this happened because the user - * just pointed host_in at a new source and called - * host_lex(). If so, then we have to assure + * just pointed expr_in at a new source and called + * expr_lex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = host_in; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = expr_in; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } @@ -928,11 +927,11 @@ case YY_STATE_EOF(INITIAL): { (yy_did_buffer_switch_on_eof) = 0; - if ( host_wrap( ) ) + if ( expr_wrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up - * host_text, we can now set up + * expr_text, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the @@ -981,7 +980,7 @@ case YY_STATE_EOF(INITIAL): "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ -} /* end of host_lex */ +} /* end of expr_lex */ /* yy_get_next_buffer - try to read in a new buffer * @@ -1059,7 +1058,7 @@ static int yy_get_next_buffer (void) b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ - host_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + expr_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ @@ -1091,7 +1090,7 @@ static int yy_get_next_buffer (void) if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; - host_restart(host_in ); + expr_restart(expr_in ); } else @@ -1108,7 +1107,7 @@ static int yy_get_next_buffer (void) if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) host_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) expr_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } @@ -1220,13 +1219,13 @@ static int yy_get_next_buffer (void) */ /* Reset buffer status. */ - host_restart(host_in ); + expr_restart(expr_in ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { - if ( host_wrap( ) ) + if ( expr_wrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) @@ -1246,12 +1245,12 @@ static int yy_get_next_buffer (void) } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve host_text */ + *(yy_c_buf_p) = '\0'; /* preserve expr_text */ (yy_hold_char) = *++(yy_c_buf_p); if ( c == '\n' ) - host_lineno++; + expr_lineno++; ; return c; @@ -1263,32 +1262,32 @@ static int yy_get_next_buffer (void) * * @note This function does not reset the start condition to @c INITIAL . */ - void host_restart (FILE * input_file ) + void expr_restart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ - host_ensure_buffer_stack (); + expr_ensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = - host__create_buffer(host_in,YY_BUF_SIZE ); + expr__create_buffer(expr_in,YY_BUF_SIZE ); } - host__init_buffer(YY_CURRENT_BUFFER,input_file ); - host__load_buffer_state( ); + expr__init_buffer(YY_CURRENT_BUFFER,input_file ); + expr__load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ - void host__switch_to_buffer (YY_BUFFER_STATE new_buffer ) + void expr__switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with - * host_pop_buffer_state(); - * host_push_buffer_state(new_buffer); + * expr_pop_buffer_state(); + * expr_push_buffer_state(new_buffer); */ - host_ensure_buffer_stack (); + expr_ensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; @@ -1301,21 +1300,21 @@ static int yy_get_next_buffer (void) } YY_CURRENT_BUFFER_LVALUE = new_buffer; - host__load_buffer_state( ); + expr__load_buffer_state( ); /* We don't actually know whether we did this switch during - * EOF (host_wrap()) processing, but the only time this flag - * is looked at is after host_wrap() is called, so it's safe + * EOF (expr_wrap()) processing, but the only time this flag + * is looked at is after expr_wrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } -static void host__load_buffer_state (void) +static void expr__load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - host_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + expr_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } @@ -1325,35 +1324,35 @@ static void host__load_buffer_state (void) * * @return the allocated buffer state. */ - YY_BUFFER_STATE host__create_buffer (FILE * file, int size ) + YY_BUFFER_STATE expr__create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; - b = (YY_BUFFER_STATE) host_alloc(sizeof( struct yy_buffer_state ) ); + b = (YY_BUFFER_STATE) expr_alloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in host__create_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in expr__create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (char *) host_alloc(b->yy_buf_size + 2 ); + b->yy_ch_buf = (char *) expr_alloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in host__create_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in expr__create_buffer()" ); b->yy_is_our_buffer = 1; - host__init_buffer(b,file ); + expr__init_buffer(b,file ); return b; } /** Destroy the buffer. - * @param b a buffer created with host__create_buffer() + * @param b a buffer created with expr__create_buffer() * */ - void host__delete_buffer (YY_BUFFER_STATE b ) + void expr__delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) @@ -1363,9 +1362,9 @@ static void host__load_buffer_state (void) YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) - host_free((void *) b->yy_ch_buf ); + expr_free((void *) b->yy_ch_buf ); - host_free((void *) b ); + expr_free((void *) b ); } #ifndef __cplusplus @@ -1374,20 +1373,20 @@ extern int isatty (int ); /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, - * such as during a host_restart() or at EOF. + * such as during a expr_restart() or at EOF. */ - static void host__init_buffer (YY_BUFFER_STATE b, FILE * file ) + static void expr__init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; - host__flush_buffer(b ); + expr__flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; - /* If b is the current buffer, then host__init_buffer was _probably_ - * called from host_restart() or through yy_get_next_buffer. + /* If b is the current buffer, then expr__init_buffer was _probably_ + * called from expr_restart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ @@ -1404,7 +1403,7 @@ extern int isatty (int ); * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ - void host__flush_buffer (YY_BUFFER_STATE b ) + void expr__flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; @@ -1424,7 +1423,7 @@ extern int isatty (int ); b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) - host__load_buffer_state( ); + expr__load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes @@ -1433,14 +1432,14 @@ extern int isatty (int ); * @param new_buffer The new state. * */ -void host_push_buffer_state (YY_BUFFER_STATE new_buffer ) +void expr_push_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; - host_ensure_buffer_stack(); + expr_ensure_buffer_stack(); - /* This block is copied from host__switch_to_buffer. */ + /* This block is copied from expr__switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ @@ -1454,8 +1453,8 @@ void host_push_buffer_state (YY_BUFFER_STATE new_buffer ) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; - /* copied from host__switch_to_buffer. */ - host__load_buffer_state( ); + /* copied from expr__switch_to_buffer. */ + expr__load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } @@ -1463,18 +1462,18 @@ void host_push_buffer_state (YY_BUFFER_STATE new_buffer ) * The next element becomes the new top. * */ -void host_pop_buffer_state (void) +void expr_pop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; - host__delete_buffer(YY_CURRENT_BUFFER ); + expr__delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { - host__load_buffer_state( ); + expr__load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } @@ -1482,7 +1481,7 @@ void host_pop_buffer_state (void) /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ -static void host_ensure_buffer_stack (void) +static void expr_ensure_buffer_stack (void) { int num_to_alloc; @@ -1493,11 +1492,11 @@ static void host_ensure_buffer_stack (void) * immediate realloc on the next call. */ num_to_alloc = 1; - (yy_buffer_stack) = (struct yy_buffer_state**)host_alloc + (yy_buffer_stack) = (struct yy_buffer_state**)expr_alloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in host_ensure_buffer_stack()" ); + YY_FATAL_ERROR( "out of dynamic memory in expr_ensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); @@ -1512,12 +1511,12 @@ static void host_ensure_buffer_stack (void) int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)host_realloc + (yy_buffer_stack) = (struct yy_buffer_state**)expr_realloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in host_ensure_buffer_stack()" ); + YY_FATAL_ERROR( "out of dynamic memory in expr_ensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); @@ -1531,7 +1530,7 @@ static void host_ensure_buffer_stack (void) * * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE host__scan_buffer (char * base, yy_size_t size ) +YY_BUFFER_STATE expr__scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; @@ -1541,9 +1540,9 @@ YY_BUFFER_STATE host__scan_buffer (char * base, yy_size_t size ) /* They forgot to leave room for the EOB's. */ return 0; - b = (YY_BUFFER_STATE) host_alloc(sizeof( struct yy_buffer_state ) ); + b = (YY_BUFFER_STATE) expr_alloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in host__scan_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in expr__scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; @@ -1555,33 +1554,33 @@ YY_BUFFER_STATE host__scan_buffer (char * base, yy_size_t size ) b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; - host__switch_to_buffer(b ); + expr__switch_to_buffer(b ); return b; } -/** Setup the input buffer state to scan a string. The next call to host_lex() will +/** Setup the input buffer state to scan a string. The next call to expr_lex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use - * host__scan_bytes() instead. + * expr__scan_bytes() instead. */ -YY_BUFFER_STATE host__scan_string (yyconst char * yystr ) +YY_BUFFER_STATE expr__scan_string (yyconst char * yystr ) { - return host__scan_bytes(yystr,strlen(yystr) ); + return expr__scan_bytes(yystr,strlen(yystr) ); } -/** Setup the input buffer state to scan the given bytes. The next call to host_lex() will +/** Setup the input buffer state to scan the given bytes. The next call to expr_lex() will * scan from a @e copy of @a bytes. * @param bytes the byte buffer to scan * @param len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE host__scan_bytes (yyconst char * yybytes, int _yybytes_len ) +YY_BUFFER_STATE expr__scan_bytes (yyconst char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; @@ -1590,18 +1589,18 @@ YY_BUFFER_STATE host__scan_bytes (yyconst char * yybytes, int _yybytes_len ) /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; - buf = (char *) host_alloc(n ); + buf = (char *) expr_alloc(n ); if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in host__scan_bytes()" ); + YY_FATAL_ERROR( "out of dynamic memory in expr__scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - b = host__scan_buffer(buf,n ); + b = expr__scan_buffer(buf,n ); if ( ! b ) - YY_FATAL_ERROR( "bad buffer in host__scan_bytes()" ); + YY_FATAL_ERROR( "bad buffer in expr__scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. @@ -1627,14 +1626,14 @@ static void yy_fatal_error (yyconst char* msg ) #define yyless(n) \ do \ { \ - /* Undo effects of setting up host_text. */ \ + /* Undo effects of setting up expr_text. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ - host_text[host_leng] = (yy_hold_char); \ - (yy_c_buf_p) = host_text + yyless_macro_arg; \ + expr_text[expr_leng] = (yy_hold_char); \ + (yy_c_buf_p) = expr_text + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ - host_leng = yyless_macro_arg; \ + expr_leng = yyless_macro_arg; \ } \ while ( 0 ) @@ -1643,89 +1642,89 @@ static void yy_fatal_error (yyconst char* msg ) /** Get the current line number. * */ -int host_get_lineno (void) +int expr_get_lineno (void) { - return host_lineno; + return expr_lineno; } /** Get the input stream. * */ -FILE *host_get_in (void) +FILE *expr_get_in (void) { - return host_in; + return expr_in; } /** Get the output stream. * */ -FILE *host_get_out (void) +FILE *expr_get_out (void) { - return host_out; + return expr_out; } /** Get the length of the current token. * */ -int host_get_leng (void) +int expr_get_leng (void) { - return host_leng; + return expr_leng; } /** Get the current token. * */ -char *host_get_text (void) +char *expr_get_text (void) { - return host_text; + return expr_text; } /** Set the current line number. * @param line_number * */ -void host_set_lineno (int line_number ) +void expr_set_lineno (int line_number ) { - host_lineno = line_number; + expr_lineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * - * @see host__switch_to_buffer + * @see expr__switch_to_buffer */ -void host_set_in (FILE * in_str ) +void expr_set_in (FILE * in_str ) { - host_in = in_str ; + expr_in = in_str ; } -void host_set_out (FILE * out_str ) +void expr_set_out (FILE * out_str ) { - host_out = out_str ; + expr_out = out_str ; } -int host_get_debug (void) +int expr_get_debug (void) { - return host__flex_debug; + return expr__flex_debug; } -void host_set_debug (int bdebug ) +void expr_set_debug (int bdebug ) { - host__flex_debug = bdebug ; + expr__flex_debug = bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. - * This function is called from host_lex_destroy(), so don't allocate here. + * This function is called from expr_lex_destroy(), so don't allocate here. */ - /* We do not touch host_lineno unless the option is enabled. */ - host_lineno = 1; + /* We do not touch expr_lineno unless the option is enabled. */ + expr_lineno = 1; (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; @@ -1736,36 +1735,36 @@ static int yy_init_globals (void) /* Defined in main.c */ #ifdef YY_STDINIT - host_in = stdin; - host_out = stdout; + expr_in = stdin; + expr_out = stdout; #else - host_in = (FILE *) 0; - host_out = (FILE *) 0; + expr_in = (FILE *) 0; + expr_out = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by - * host_lex_init() + * expr_lex_init() */ return 0; } -/* host_lex_destroy is for both reentrant and non-reentrant scanners. */ -int host_lex_destroy (void) +/* expr_lex_destroy is for both reentrant and non-reentrant scanners. */ +int expr_lex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ - host__delete_buffer(YY_CURRENT_BUFFER ); + expr__delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; - host_pop_buffer_state(); + expr_pop_buffer_state(); } /* Destroy the stack itself. */ - host_free((yy_buffer_stack) ); + expr_free((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time - * host_lex() is called, initialization will occur. */ + * expr_lex() is called, initialization will occur. */ yy_init_globals( ); return 0; @@ -1795,12 +1794,12 @@ static int yy_flex_strlen (yyconst char * s ) } #endif -void *host_alloc (yy_size_t size ) +void *expr_alloc (yy_size_t size ) { return (void *) malloc( size ); } -void *host_realloc (void * ptr, yy_size_t size ) +void *expr_realloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those @@ -1812,19 +1811,19 @@ void *host_realloc (void * ptr, yy_size_t size ) return (void *) realloc( (char *) ptr, size ); } -void host_free (void * ptr ) +void expr_free (void * ptr ) { - free( (char *) ptr ); /* see host_realloc() for (char *) cast */ + free( (char *) ptr ); /* see expr_realloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" -#line 65 "host_parser.l" +#line 66 "expr_parser.l" -int host_wrap() +int expr_wrap() { return 1; -} +} diff --git a/src/host/host_parser.l b/src/scheduler/src/xml/expr_parser.l similarity index 74% rename from src/host/host_parser.l rename to src/scheduler/src/xml/expr_parser.l index 0fd5a2851d..75a956303d 100644 --- a/src/host/host_parser.l +++ b/src/scheduler/src/xml/expr_parser.l @@ -18,12 +18,11 @@ #include #include #include -#include -#include "host_requirements.h" -#include "host_rank.h" +#include "expr_bool.h" +#include "expr_arith.h" -#define YY_DECL int host_lex (YYSTYPE *lvalp, YYLTYPE *llocp) +#define YY_DECL int expr_lex (YYSTYPE *lvalp, YYLTYPE *llocp) #define YY_USER_ACTION llocp->first_line = yylineno; \ llocp->first_column = llocp->last_column; \ @@ -31,8 +30,8 @@ %} %option nounput -%option prefix="host_" -%option outfile="host_parser.c" +%option prefix="expr_" +%option outfile="expr_parser.c" %option yylineno %% @@ -40,31 +39,33 @@ [!&|=><()\*\+/\^-] { return *yytext;} - /* --- Strings, also quoted form --- */ - -[A-Za-z][0-9A-Za-z_]* { lvalp->val_str = strdup(yytext); - return STRING;} + /* --- Strings, also quoted form --- */ -\"\" { lvalp->val_str = NULL; - return STRING;} +[A-Za-z][0-9A-Za-z_]* { lvalp->val_str = strdup(yytext); + return STRING;} -\"[^\"]*\" { lvalp->val_str = strdup(yytext+1); - lvalp->val_str[yyleng-2] = '\0'; - return STRING;} - /* --- Numbers --- */ +\"\" { lvalp->val_str = NULL; + return STRING;} + +\"[^\"]*\" { lvalp->val_str = strdup(yytext+1); + lvalp->val_str[yyleng-2] = '\0'; + return STRING;} + + /* --- Numbers --- */ -?[0-9]+ { lvalp->val_int = atoi(yytext); return INTEGER;} -?[0-9]+\.[0-9]+ { lvalp->val_float = atof(yytext); - return FLOAT;} + return FLOAT;} + /* --- blanks --- */ -[[:blank:]]* +[[:blank:]]* %% -int host_wrap() +int expr_wrap() { return 1; -} +} diff --git a/src/scheduler/src/xml/test/ObjectXMLTest.cc b/src/scheduler/src/xml/test/ObjectXMLTest.cc new file mode 100644 index 0000000000..e02a8c25be --- /dev/null +++ b/src/scheduler/src/xml/test/ObjectXMLTest.cc @@ -0,0 +1,419 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include + +#include "ObjectXML.h" + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class ObjectXMLTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( ObjectXMLTest ); + + CPPUNIT_TEST( xpath_access ); + CPPUNIT_TEST( node_constructor ); + CPPUNIT_TEST( doc_update ); + CPPUNIT_TEST( requirements ); + CPPUNIT_TEST( rank ); + + CPPUNIT_TEST_SUITE_END (); + +public: + void setUp() + { + xmlInitParser(); + }; + + void tearDown() + { + xmlCleanupParser(); + }; + + ObjectXMLTest(){}; + + ~ObjectXMLTest(){}; + + /* ********************************************************************* */ + /* ********************************************************************* */ + + void xpath_access() + { + try + { + ObjectXML obj(xml_history_dump); + vector hostnames; + + hostnames = obj["/VM_POOL/VM/HISTORY/HOSTNAME"]; + + CPPUNIT_ASSERT(hostnames.size() == 2); + CPPUNIT_ASSERT(hostnames[0] == "A_hostname"); + CPPUNIT_ASSERT(hostnames[1] == "C_hostname"); + } + catch(runtime_error& re) + { + cerr << re.what() << endl; + CPPUNIT_ASSERT(1 == 0); + } + }; + + + void node_constructor() + { + try + { + ObjectXML obj(xml_history_dump); + vector vms; + int num_vms; + + num_vms = obj.get_nodes("/VM_POOL/VM",vms); + + CPPUNIT_ASSERT(num_vms == 3); + + ObjectXML obj_vm_1(vms[0]); + ObjectXML obj_vm_2(vms[1]); + + vector results; + + results = obj_vm_1["/VM/HISTORY/HOSTNAME"]; + + CPPUNIT_ASSERT(results.size() == 0); + + results.clear(); + + results = obj_vm_2["/VM/HISTORY/HOSTNAME"]; + + CPPUNIT_ASSERT(results.size() == 1); + CPPUNIT_ASSERT(results[0] == "A_hostname"); + + } + catch(runtime_error& re) + { + cerr << re.what() << endl; + CPPUNIT_ASSERT(1 == 0); + } + }; + + void doc_update() + { + try + { + ObjectXML obj(xml_history_dump); + vector hostnames; + + hostnames = obj["/VM_POOL/VM/HISTORY/HOSTNAME"]; + + CPPUNIT_ASSERT(hostnames.size() == 2); + CPPUNIT_ASSERT(hostnames[0] == "A_hostname"); + CPPUNIT_ASSERT(hostnames[1] == "C_hostname"); + + obj.update(xml_history_dump2); + + hostnames = obj["/VM_POOL/VM/HISTORY/HOSTNAME"]; + + CPPUNIT_ASSERT(hostnames.size() == 2); + CPPUNIT_ASSERT(hostnames[0] == "0_hostname"); + CPPUNIT_ASSERT(hostnames[1] == "1_hostname"); + } + catch(runtime_error& re) + { + cerr << re.what() << endl; + CPPUNIT_ASSERT(1 == 0); + } + }; + + + void requirements() + { + try + { + ObjectXML obj(host); + + char* err; + bool res; + int rc; + + // ----------------------------------------------------------------- + // REQUIREMENTS MATCHING + // ----------------------------------------------------------------- + string reqs[] = + { + "TOTALCPU = 800", // exact value matching + "TOTALCPU != 800", // Not equal + "TOTALCPU > 5", // Greater than expr. + "! (TOTALCPU > 5)", // Not exp. + + "HOSTNAME = \"ursa12\"", // Exact string matching + "HOSTNAME = \"ursa*\"", // Shell wildcard + "HOSTNAME = \"ursa\"", + + "HID = 1", + "ARCH = \"*64*\"", + "RUNNING_VMS < 100", + + /* + // Boolean operators + "HOSTNAME = \"ursa*\" & NETRX = \"13335836573\"", + // Operator precedence + "HOSTNAME = \"ursa*\" | HOSTNAME = \"no\" & HOSTNAME = \"no\"", + "( HOSTNAME = \"ursa*\" | HOSTNAME = \"no\" ) & HOSTNAME = \"no\"", + //*/ + + "END" + }; + + bool results[] = { true, false, true, false, + true, true, false, + true, true, true, + /* + true, true, false, + //*/ + }; + + int i = 0; + while( reqs[i] != "END" ) + { +// cout << endl << i << " - " << reqs[i]; + rc = obj.eval_bool( reqs[i], res, &err ); +// cout << "··· rc: " << rc << " result: " << res << " expected: " << results[i] << endl; + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( res == results[i] ); + + i++; + } + + // Non-existing attribute compared to string value + rc = obj.eval_bool( "FOO = \"BAR\"", res, &err ); + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( res == false ); + + // Non-existing attribute compared to numeric value + rc = obj.eval_bool( "FOO = 123", res, &err ); + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( res == false ); + + + // Existing string attribute compared to numeric value + rc = obj.eval_bool( "HOSTNAME = 123 ", res, &err ); + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( res == false ); + + // Existing numeric attribute compared to string value should work + rc = obj.eval_bool( "TOTALCPU = \"800\"", res, &err ); + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( res == true ); + + // Bad syntax + // TODO: Right now eval_bool returns 1 in case of error, and result + // is not set to false. + rc = obj.eval_bool( "TOTALCPU ^ * - = abc", res, &err ); + CPPUNIT_ASSERT( rc != 0 ); + // CPPUNIT_ASSERT( res == false ); + + if (err != 0) + { + free( err ); + } + } + catch(runtime_error& re) + { + cerr << re.what() << endl; + CPPUNIT_ASSERT(1 == 0); + } + }; + + + void rank() + { + try + { + ObjectXML obj(host); + + char* err; + int res; + int rc; + + // ----------------------------------------------------------------- + // RANK EXPRESSIONS + // ----------------------------------------------------------------- + string rank_exp[] = + { + "RUNNING_VMS", // Single attribute + "MAX_CPU + NETTX", // Simple operations + "RUNNING_VMS * 10", // Operations with fixed values + "- FREE_MEM", // Unary operator + "2 + 4 * 10", // Operator precedence + "(2 + 4) * 10", + "END" + }; + + int results[] = + { + 12, + 47959 + 800, + 12 * 10, + -7959232, + 2 + 4 * 10, + (2 + 4) * 10, + }; + + int i = 0; + while( rank_exp[i] != "END" ) + { +// cout << endl << i << " - " << rank_exp[i]; + rc = obj.eval_arith( rank_exp[i], res, &err ); +// cout << "··· rc: " << rc << " res: " << res << " expected: " << results[i] << endl; + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( res == results[i] ); + + i++; + } + + + // Non-existing attribute + rc = obj.eval_arith( "FOO", res, &err ); + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( res == 0 ); + + // Non-existing attribute and operators + rc = obj.eval_arith( "FOO + 10", res, &err ); + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( res == 10 ); + } + catch(runtime_error& re) + { + cerr << re.what() << endl; + CPPUNIT_ASSERT(1 == 0); + } + }; + + static const string xml_history_dump; + static const string xml_history_dump2; + static const string host; +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + CppUnit::TextUi::TestRunner runner; + + runner.addTest(ObjectXMLTest::suite()); + runner.run(); + + return 0; +} + +// ---------------------------------------------------------------------------- +const string ObjectXMLTest::xml_history_dump = + "00one_user_test" + "VM one01" + "000000000000" + "000" + "010" + "one_user_testSecond VM0" + "200000000000" + "000" + "000" + "A_hostname000" + "0000" + "0002" + "0one_user_testVM one" + "020" + "000000000000" + "0001" + "C_hostname200" + "0000" + "000" + ""; + +const string ObjectXMLTest::xml_history_dump2 = + "00one_user_test" + "VM one01" + "000000000000" + "000" + "010" + "one_user_testSecond VM0" + "200000000000" + "000" + "000" + "0_hostname000" + "0000" + "0002" + "0one_user_testVM one" + "020" + "000000000000" + "0001" + "1_hostname200" + "0000" + "000" + ""; + +const string ObjectXMLTest::host = + "" + "1" + "ursa12" + "2" + "im_kvm" + "vmm_kvm" + "tm_nfs" + "1273799044" + "" + " 1" + " 0" + " 0" + " 0" + " 0" + " 8194368" + " 800" + " 0" + " 7959232" + " 800" + " 0" + " 523080" + " 0" + " 12" + "" + "" + ""; diff --git a/src/scheduler/src/xml/test/SConstruct b/src/scheduler/src/xml/test/SConstruct new file mode 100644 index 0000000000..d05e73f0a3 --- /dev/null +++ b/src/scheduler/src/xml/test/SConstruct @@ -0,0 +1,88 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +import os +import sys +import shutil +sys.path.append("../../../../../share/scons") + +# This is the absolute path where the project is located +cwd=os.getcwd() + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Include dirs +main_env.Append(CPPPATH=[ + cwd+'/../../../include', + '/usr/include/cppunit/' +]) + +# Library dirs +main_env.Append(LIBPATH=[ + '../' +]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# Linking flags +main_env.Append(LDFLAGS=["-g"]) + +# Libraries +main_env.Append(LIBS=[ + 'cppunit', + 'scheduler_xml' +]) + +main_env.Program('test_xml','ObjectXMLTest.cc') + +################################################################################ +# EXTRA CONFIGURATION +################################################################################ + +#------------------------------------------------------------------------------- +# xmlrpc +#------------------------------------------------------------------------------- + +xmlrpc_dir=ARGUMENTS.get('xmlrpc', 'none') + +if xmlrpc_dir!='none': + main_env.Append(LIBPATH=[xmlrpc_dir+"/lib"]) + main_env.Append(CPPPATH=[xmlrpc_dir+"/include"]) + +main_env.ParseConfig('../../../../../share/scons/get_xmlrpc_config client') + +#------------------------------------------------------------------------------- +# build lex/bison +#------------------------------------------------------------------------------- + +build_parsers=ARGUMENTS.get('parsers', 'no') + +if build_parsers=='yes': + main_env.Append(parsers='yes') +else: + main_env.Append(parsers='no') + +#------------------------------------------------------------------------------- +# libxml2 +#------------------------------------------------------------------------------- + +main_env.ParseConfig('xml2-config --libs --cflags') diff --git a/src/sql/MySqlDB.cc b/src/sql/MySqlDB.cc new file mode 100644 index 0000000000..7e6ad4b257 --- /dev/null +++ b/src/sql/MySqlDB.cc @@ -0,0 +1,174 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 "MySqlDB.h" + +/********* + * Doc: http://dev.mysql.com/doc/refman/5.5/en/c-api-function-overview.html + ********/ + +/* -------------------------------------------------------------------------- */ + +MySqlDB::MySqlDB( + const string& server, + const string& user, + const string& password, + char * database) +{ + + // Initialize the MySQL library + mysql_library_init(0, NULL, NULL); + + // Initialize a connection handler + db = mysql_init(NULL); + + // Connect to the server + if (!mysql_real_connect(db, server.c_str(), user.c_str(), + password.c_str(), database, 0, NULL, 0)) + { + throw runtime_error("Could not open database."); + } + + pthread_mutex_init(&mutex,0); +} + +/* -------------------------------------------------------------------------- */ + +MySqlDB::~MySqlDB() +{ + // Close the connection to the MySQL server + mysql_close(db); + + // End use of the MySQL library + mysql_library_end(); + + pthread_mutex_destroy(&mutex); +} + +/* -------------------------------------------------------------------------- */ + +int MySqlDB::exec(ostringstream& cmd, Callbackable* obj) +{ + int rc; + + const char * c_str; + string str; + + + int (*callback)(void*,int,char**,char**); + void * arg; + + str = cmd.str(); + c_str = str.c_str(); + + callback = 0; + arg = 0; + + lock(); + + rc = mysql_query(db, c_str); + + if (rc != 0) + { + ostringstream oss; + const char * err_msg = mysql_error(db); + int err_num = mysql_errno(db); + + oss << "SQL command was: " << c_str; + oss << ", error " << err_num << " : " << err_msg; + + NebulaLog::log("ONE",Log::ERROR,oss); + + unlock(); + + return -1; + } + + + if ( (obj != 0) && (obj->isCallBackSet()) ) + { + + MYSQL_RES * result; + MYSQL_ROW row; + MYSQL_FIELD * fields; + unsigned int num_fields; + + // Retrieve the entire result set all at once + result = mysql_store_result(db); + + if (result == NULL) + { + ostringstream oss; + const char * err_msg = mysql_error(db); + int err_num = mysql_errno(db); + + oss << "SQL command was: " << c_str; + oss << ", error " << err_num << " : " << err_msg; + + NebulaLog::log("ONE",Log::ERROR,oss); + + unlock(); + + return -1; + } + + // Fetch the names of the fields + num_fields = mysql_num_fields(result); + fields = mysql_fetch_fields(result); + + char ** names = new char*[num_fields]; + + for(unsigned int i = 0; i < num_fields; i++) + { + names[i] = fields[i].name; + } + + // Fetch each row, and call-back the object waiting for them + while((row = mysql_fetch_row(result))) + { + obj->do_callback(num_fields, row, names); + } + + // Free the result object + mysql_free_result(result); + + delete[] names; + } + + unlock(); + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +char * MySqlDB::escape_str(const string& str) +{ + char * result = new char[str.size()*2+1]; + + mysql_real_escape_string(db, result, str.c_str(), str.size()); + + return result; +} + +/* -------------------------------------------------------------------------- */ + +void MySqlDB::free_str(char * str) +{ + delete[] str; +} + +/* -------------------------------------------------------------------------- */ diff --git a/src/sql/SConstruct b/src/sql/SConstruct new file mode 100644 index 0000000000..28532aed39 --- /dev/null +++ b/src/sql/SConstruct @@ -0,0 +1,33 @@ +# SConstruct for src/pool + +# -------------------------------------------------------------------------- # +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +Import('env') + +lib_name='nebula_sql' + +source_files=[] + +# Sources to generate the library +if env['sqlite']=='yes': + source_files.append('SqliteDB.cc') + +if env['mysql']=='yes': + source_files.append('MySqlDB.cc') + +# Build library +env.StaticLibrary(lib_name, source_files) \ No newline at end of file diff --git a/src/sql/SqliteDB.cc b/src/sql/SqliteDB.cc new file mode 100644 index 0000000000..43a3e0668d --- /dev/null +++ b/src/sql/SqliteDB.cc @@ -0,0 +1,149 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 "SqliteDB.h" + +using namespace std; + +/* -------------------------------------------------------------------------- */ + +extern "C" int sqlite_callback ( + void * _obj, + int num, + char ** values, + char ** names) +{ + Callbackable *obj; + + obj = static_cast(_obj); + + if (obj == 0) + { + return -1; + } + + return obj->do_callback(num,values,names); +}; + +/* -------------------------------------------------------------------------- */ + +SqliteDB::SqliteDB(string& db_name) +{ + int rc; + + pthread_mutex_init(&mutex,0); + + rc = sqlite3_open(db_name.c_str(), &db); + + if ( rc != SQLITE_OK ) + { + throw runtime_error("Could not open database."); + } +} + +/* -------------------------------------------------------------------------- */ + +SqliteDB::~SqliteDB() +{ + pthread_mutex_destroy(&mutex); + + sqlite3_close(db); +} + +/* -------------------------------------------------------------------------- */ + +int SqliteDB::exec(ostringstream& cmd, Callbackable* obj) +{ + int rc; + + const char * c_str; + string str; + + int counter = 0; + char * err_msg = 0; + + int (*callback)(void*,int,char**,char**); + void * arg; + + str = cmd.str(); + c_str = str.c_str(); + + callback = 0; + arg = 0; + + if ((obj != 0)&&(obj->isCallBackSet())) + { + callback = sqlite_callback; + arg = static_cast(obj); + } + + lock(); + + do + { + counter++; + + rc = sqlite3_exec(db, c_str, callback, arg, &err_msg); + + if (rc == SQLITE_BUSY || rc == SQLITE_IOERR_BLOCKED) + { + struct timeval timeout; + fd_set zero; + + FD_ZERO(&zero); + timeout.tv_sec = 0; + timeout.tv_usec = 250000; + + select(0, &zero, &zero, &zero, &timeout); + } + }while( (rc == SQLITE_BUSY || rc == SQLITE_IOERR_BLOCKED) && + (counter < 10)); + + unlock(); + + if (rc != SQLITE_OK) + { + if (err_msg != 0) + { + ostringstream oss; + + oss << "SQL command was: " << c_str << ", error: " << err_msg; + NebulaLog::log("ONE",Log::ERROR,oss); + + sqlite3_free(err_msg); + } + + return -1; + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +char * SqliteDB::escape_str(const string& str) +{ + return sqlite3_mprintf("%q",str.c_str()); +} + +/* -------------------------------------------------------------------------- */ + +void SqliteDB::free_str(char * str) +{ + sqlite3_free(str); +} + diff --git a/src/template/TemplateSQL.cc b/src/template/TemplateSQL.cc index e1ab343f0f..701cc7e0c1 100644 --- a/src/template/TemplateSQL.cc +++ b/src/template/TemplateSQL.cc @@ -1,90 +1,90 @@ -/* -------------------------------------------------------------------------- */ -/* Copyright 2002-2010, 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 +/* ------------------------------------------------------------------------ */ +/* Copyright 2002-2010, 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 "TemplateSQL.h" #include #include -/* ************************************************************************** */ -/* SQL Template */ -/* ************************************************************************** */ +/* ************************************************************************ */ +/* SQL Template */ +/* ************************************************************************ */ const char * TemplateSQL::db_names = "(id,name,type,value)"; -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -extern "C" +int TemplateSQL::insert_cb(void *nil, int num, char **values, char **names) { - static int insert_cb ( - void * _template_id, - int num, - char ** values, - char ** names) + if ( num<=0 ) { - int * template_id; + return -1; + } - template_id = static_cast(_template_id); + if ( values[0] == 0 ) + { + id = 0; + } + else + { + id = atoi(values[0]) + 1; + } - if ( (template_id == 0) || (num<=0) ) - { - return -1; - } - - if ( values[0] == 0 ) - { - *template_id = 0; - } - else - { - *template_id = atoi(values[0]) + 1; - } - - return 0; - }; + return 0; } -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ -int TemplateSQL::insert(SqliteDB * db) +int TemplateSQL::insert(SqlDB * db) { ostringstream oss; int rc; // Get next id from the DB table + set_callback( + static_cast(&TemplateSQL::insert_cb)); oss << "SELECT MAX(id) FROM " << table; - rc = db->exec(oss,insert_cb,(void *) &(this->id)); + rc = db->exec(oss,this); if ( rc != 0 ) { return -1; } - rc = update(db); + rc = insert_replace(db, false); return rc; } -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ -int TemplateSQL::update(SqliteDB * db) +int TemplateSQL::update(SqlDB * db) +{ + int rc; + + rc = insert_replace(db, true); + + return rc; +} + +/* ------------------------------------------------------------------------ */ + +int TemplateSQL::insert_replace(SqlDB *db, bool replace) { multimap::iterator it; ostringstream oss; @@ -93,7 +93,9 @@ int TemplateSQL::update(SqliteDB * db) char * sql_attr; Attribute::AttributeType atype; - for(it=attributes.begin(),oss.str("");it!=attributes.end();it++,oss.str("")) + for(it=attributes.begin(),oss.str(""); + it!=attributes.end(); + it++,oss.str("")) { if ( it->second == 0 ) { @@ -108,113 +110,112 @@ int TemplateSQL::update(SqliteDB * db) continue; } - sql_attr = sqlite3_mprintf("%q",(*attr).c_str()); + sql_attr = db->escape_str((*attr).c_str()); delete attr; - + if ( sql_attr == 0 ) { continue; } + + if(replace) + { + oss << "REPLACE"; + } + else + { + oss << "INSERT"; + } - oss << "INSERT OR REPLACE INTO " << table << " " << db_names + oss << " INTO " << table << " " << db_names << " VALUES (" << id << ",'" << it->first << "',"<< atype <<",'" << sql_attr << "')"; rc = db->exec(oss); - - sqlite3_free(sql_attr); - + + db->free_str(sql_attr); + if ( rc != 0 ) { - goto error_sqlite; + goto error_sql; } } return 0; -error_sqlite: +error_sql: drop(db); return -1; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -extern "C" +int TemplateSQL::select_cb(void *nil, int num, char **values, char **names) { - static int select_cb ( - void * _vmt, - int num, - char ** values, - char ** names) + Attribute * attr; + + string name; + string value; + int atype; + + if (num != 4) { - TemplateSQL * vmt; + return -1; + } - Attribute * attr; + if ( values[1] != 0 ) + { + name = values[1]; + } + else + { + return -1; + } - string name; - string value; - int atype; + if ( values[3] != 0 ) + { + value = values[3]; + } + else + { + return -1; + } - vmt = static_cast(_vmt); + if ( values[2] != 0 ) + { + atype = atoi(values[2]); - if ( (vmt == 0) || ( num != 4 ) ) + switch (atype) { + case Attribute::SIMPLE: + attr = new SingleAttribute(name); + break; + + case Attribute::VECTOR: + attr = new VectorAttribute(name); + break; + + default: return -1; - } + break; + }; + } - if ( values[1] != 0 ) - { - name = values[1]; - } - else - { - return -1; - } + attr->unmarshall(value); - if ( values[3] != 0 ) - { - value = values[3]; - } - else - { - return -1; - } + set(attr); - if ( values[2] != 0 ) - { - atype = atoi(values[2]); - - switch (atype) - { - case Attribute::SIMPLE: - attr = new SingleAttribute(name); - break; - - case Attribute::VECTOR: - attr = new VectorAttribute(name); - break; - - default: - return -1; - break; - }; - } - - attr->unmarshall(value); - - vmt->set(attr); - - return 0; - }; + return 0; } -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int TemplateSQL::select(SqliteDB * db) +int TemplateSQL::select(SqlDB * db) { ostringstream oss; int rc; @@ -224,17 +225,19 @@ int TemplateSQL::select(SqliteDB * db) return -1; } + set_callback(static_cast(&TemplateSQL::select_cb)); + oss << "SELECT * FROM " << table << " WHERE id=" << id; - rc = db->exec(oss,select_cb,(void *) this); + rc = db->exec(oss,this); return rc; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int TemplateSQL::drop(SqliteDB * db) +int TemplateSQL::drop(SqlDB * db) { ostringstream oss; @@ -248,10 +251,10 @@ int TemplateSQL::drop(SqliteDB * db) return db->exec(oss); } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int TemplateSQL::replace_attribute(SqliteDB * db, Attribute * attribute) +int TemplateSQL::replace_attribute(SqlDB * db, Attribute * attribute) { ostringstream oss; int rc; @@ -276,7 +279,7 @@ int TemplateSQL::replace_attribute(SqliteDB * db, Attribute * attribute) return -1; } - sql_attr = sqlite3_mprintf("%q",(*astr).c_str()); + sql_attr = db->escape_str((*astr).c_str()); delete astr; @@ -284,14 +287,14 @@ int TemplateSQL::replace_attribute(SqliteDB * db, Attribute * attribute) { return -1; } - + oss << "DELETE FROM " << table << " WHERE id=" << id << " AND name='" << attribute->name() << "' AND value='" << sql_attr << "'"; rc = db->exec(oss); - sqlite3_free(sql_attr); + db->free_str(sql_attr); if (rc != 0 ) { @@ -306,10 +309,10 @@ int TemplateSQL::replace_attribute(SqliteDB * db, Attribute * attribute) return insert_attribute(db,attribute); } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int TemplateSQL::insert_attribute(SqliteDB * db, Attribute * attribute) +int TemplateSQL::insert_attribute(SqlDB * db, Attribute * attribute) { ostringstream oss; int rc; @@ -331,10 +334,10 @@ int TemplateSQL::insert_attribute(SqliteDB * db, Attribute * attribute) return -1; } - sql_attr = sqlite3_mprintf("%q",(*astr).c_str()); + sql_attr = db->escape_str((*astr).c_str()); delete astr; - + if ( sql_attr == 0 ) { return -1; @@ -346,7 +349,7 @@ int TemplateSQL::insert_attribute(SqliteDB * db, Attribute * attribute) rc = db->exec(oss); - sqlite3_free(sql_attr); + db->free_str(sql_attr); if (rc == 0) { @@ -356,5 +359,5 @@ int TemplateSQL::insert_attribute(SqliteDB * db, Attribute * attribute) return rc; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ diff --git a/src/template/test/SConstruct b/src/template/test/SConstruct new file mode 100644 index 0000000000..ccad613e67 --- /dev/null +++ b/src/template/test/SConstruct @@ -0,0 +1,84 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad # +# Complutense de Madrid (dsa-research.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +import os +import sys +import shutil +sys.path.append("../../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located +cwd="../../../" + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) + +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include', + '/usr/include/cppunit/' +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd + '/src/common', + cwd + '/src/template', + cwd + '/src/nebula', + cwd + '/src/sql', + cwd + '/src/log', +]) + +main_env.Append(LIBS=[ + 'nebula_template', + 'nebula_common', + 'nebula_core', + 'nebula_sql', + 'nebula_log', + 'cppunit', + 'dl', + 'pthread' +]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# MYSQL +main_env.Append(LIBPATH=["/usr/lib/mysql"]) +main_env.Append(CPPPATH=["/usr/include/mysql"]) + +sqlite=ARGUMENTS.get('sqlite', 'yes') +if sqlite=='yes': + main_env.Append(CPPFLAGS=["-DSQLITE_DB"]) + main_env.Append(LIBS=[ 'sqlite3', ]) + +# MySQL +mysql=ARGUMENTS.get('mysql', 'no') +if mysql=='yes': + main_env.Append(CPPFLAGS=["-DMYSQL_DB"]) + main_env.Append(LIBS=[ 'mysqlclient', ]) + +main_env.Program('test','template.cc') +main_env.Program('test_sql','template_sql.cc') +# diff --git a/src/template/test/template.cc b/src/template/test/template.cc new file mode 100644 index 0000000000..bba056c88b --- /dev/null +++ b/src/template/test/template.cc @@ -0,0 +1,331 @@ +#include "Template.h" + +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +class TemplateTest : public CppUnit::TestFixture +{ +private: + Template *t, *tr, *t1; + + string test_ok; + string test_ok_marshall; + string test_ok_xml; + string test_ok_str; + +public: + + /* --------------------------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + TemplateTest() + { + test_ok = + "#This line is a comment\n" + " # Other comment\n" + "MEMORY=345 # more comments behind an attribute\n" + " CPU = 4\n" + "#------------------------------\n" + "#Comments in the middle\n" + "#------------------------------\n" + " empty_var = \n" + "REQUIREMENTS = \"HOSTNAME = \\\"host*.com\\\"\"\n" + " DISK= [file = path1, extra = \"disk attribute \"]\n" + "DISK =[ FILE = \"path2\", EXTRA = str, TYPE=disk]\n" + " graphics = [\n" + " VNC = \"127.0.0.1\",\n" + " PORT = 12\n" + " ]\n"; + + test_ok_marshall="CPU=4\nDISK=EXTRA=disk attribute @^_^@FILE=path1\n" + "DISK=EXTRA=str@^_^@FILE=path2@^_^@TYPE=disk\nEMPTY_VAR=\n" + "GRAPHICS=PORT=12@^_^@VNC=127.0.0.1\nMEMORY=345\n" + "REQUIREMENTS=HOSTNAME = \"host*.com\"\n"; + + test_ok_xml=""; + + test_ok_str= + "\n\tCPU=4" + "\n\tDISK=EXTRA=disk attribute ,FILE=path1" + "\n\tDISK=EXTRA=str,FILE=path2,TYPE=disk" + "\n\tEMPTY_VAR=" + "\n\tGRAPHICS=PORT=12,VNC=127.0.0.1" + "\n\tMEMORY=345" + "\n\tREQUIREMENTS=HOSTNAME = \"host*.com\""; + } + + ~TemplateTest(){}; + + /* --------------------------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + void setUp() + { + char *error = 0; + + t = new Template(); + + tr= new Template(true); + tr->parse(test_ok,&error); + + t1= new Template(); + t1->parse(test_ok,&error); + } + + void tearDown() + { + delete t; + delete tr; + delete t1; + } + + /* ********************************************************************* */ + /* ********************************************************************* */ + + void test_parser() + { + char * error = 0; + int rc; + string tmp; + + rc = t->parse(test_ok,&error); + + if ( error != 0 ) + { + cerr << error << endl; + free(error); + } + + CPPUNIT_ASSERT( rc == 0); + } + + /* --------------------------------------------------------------------- */ + + void test_marshall() + { + string tmp; + + t1->marshall(tmp); + + CPPUNIT_ASSERT(test_ok_marshall == tmp); + } + + /* --------------------------------------------------------------------- */ + + void test_xml() + { + string tmp; + + t1->to_xml(tmp); + + CPPUNIT_ASSERT(test_ok_xml == tmp); + } + + /* --------------------------------------------------------------------- */ + + void test_str() + { + string tmp; + + t1->to_str(tmp); + + CPPUNIT_ASSERT(test_ok_str == tmp); + } + + /* --------------------------------------------------------------------- */ + + void test_get() + { + vector attrs; + string *tmp; + + CPPUNIT_ASSERT(t1->get("DISK",attrs) == 2 ); + + CPPUNIT_ASSERT(attrs[0]->type() == Attribute::VECTOR); + + tmp = attrs[0]->to_xml(); + CPPUNIT_ASSERT( *tmp == + "" + ""); + delete tmp; + + CPPUNIT_ASSERT(attrs[1]->type() == Attribute::VECTOR); + + tmp = attrs[1]->to_xml(); + CPPUNIT_ASSERT( *tmp == + "" + ""); + delete tmp; + + CPPUNIT_ASSERT(t1->get("CPU",attrs) == 1 ); + + CPPUNIT_ASSERT(attrs[2]->type() == Attribute::SIMPLE); + + tmp = attrs[2]->to_xml(); + CPPUNIT_ASSERT( *tmp == ""); + delete tmp; + + string sval; + string sname = "REQUIREMENTS"; + + string iname = "MEMORY"; + int ival; + + t1->get(iname,ival); + t1->get(sname,sval); + + CPPUNIT_ASSERT ( ival == 345 ); + CPPUNIT_ASSERT ( sval == "HOSTNAME = \"host*.com\""); + + } + + /* --------------------------------------------------------------------- */ + + void test_remove() + { + vector attrs; + + string t1_xml; + string rm_xml=""; + + t1->remove("DISK",attrs); + t1->to_xml(t1_xml); + + CPPUNIT_ASSERT(t1_xml == rm_xml); + + delete attrs[0]; + delete attrs[1]; + } + + + /* --------------------------------------------------------------------- */ + + void test_set() + { + string t1_xml=""; + string xml; + + string nattr = "XTRA"; + string vattr = "44"; + + SingleAttribute *a = new SingleAttribute(nattr,vattr); + + t1->set(a); + t1->to_xml(xml); + + CPPUNIT_ASSERT(t1_xml == xml); + + nattr = "CPU"; + vattr = "5"; + + t1_xml=""; + SingleAttribute *b = new SingleAttribute(nattr,vattr); + + t1->set(b); + t1->to_xml(xml); + + CPPUNIT_ASSERT(t1_xml == xml); + + string tr_xml=""; + SingleAttribute *c = new SingleAttribute(nattr,vattr); + + tr->set(c); + tr->to_xml(xml); + + CPPUNIT_ASSERT(tr_xml == xml); + } + + /* ********************************************************************* */ + /* ********************************************************************* */ + + static CppUnit::TestSuite * suite() + { + CppUnit::TestSuite *ts=new CppUnit::TestSuite("Template Tests"); + + ts->addTest(new CppUnit::TestCaller( + "parse() Test", + &TemplateTest::test_parser)); + + ts->addTest(new CppUnit::TestCaller( + "marshall() Test", + &TemplateTest::test_marshall)); + + ts->addTest(new CppUnit::TestCaller( + "xml() Test", + &TemplateTest::test_xml)); + + ts->addTest(new CppUnit::TestCaller( + "str() Test", + &TemplateTest::test_str)); + + ts->addTest(new CppUnit::TestCaller( + "get() Test", + &TemplateTest::test_get)); + + ts->addTest(new CppUnit::TestCaller( + "remove() Test", + &TemplateTest::test_remove)); + + ts->addTest(new CppUnit::TestCaller( + "set() Test", + &TemplateTest::test_set)); + return ts; + } +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + CppUnit::TextUi::TestRunner tr; + + tr.addTest(TemplateTest::suite()); + tr.run(); + + return 0; +} diff --git a/src/template/test/template_sql.cc b/src/template/test/template_sql.cc new file mode 100644 index 0000000000..4947360a7b --- /dev/null +++ b/src/template/test/template_sql.cc @@ -0,0 +1,217 @@ +#include "TemplateSQL.h" +#include "SqliteDB.h" +#include "SqlDB.h" +#include "Log.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +/* --------------------------------------- */ +/* WRAPPER TO ACCESS TEMPLATESQL CLASS */ +/* --------------------------------------- */ + +class TSQL : public TemplateSQL +{ +public: + TSQL(const char * _table, + int template_id = -1, + bool replace = false, + const char separator = '=', + const char * xml_root = "TEMPLATE"): + TemplateSQL(_table,template_id,replace,separator,xml_root){} + + ~TSQL(){} + + /* --------------------------------------------------------------------- */ + int insert(SqlDB * db){return TemplateSQL::insert(db);} + int update(SqlDB * db){return TemplateSQL::update(db);} + int select(SqlDB * db){return TemplateSQL::select(db);} + int drop (SqlDB * db){return TemplateSQL::drop(db);} + + /* --------------------------------------------------------------------- */ + int replace_attribute(SqlDB * db, Attribute * attr) + {return TemplateSQL::replace_attribute(db,attr);} + int insert_attribute(SqlDB * db, Attribute * attr) + {return TemplateSQL::insert_attribute(db,attr);} + /* --------------------------------------------------------------------- */ + int id(){return TemplateSQL::id;}; +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +class TemplateSQLTest : public CppUnit::TestFixture +{ +private: + SqlDB *db; + + string filename; + + string template_ok; + string template_xml; + + static void log( + const char * module, + const Log::MessageType type, + const ostringstream& message, + const char * filename = 0, + Log::MessageType clevel = Log::ERROR) + { + cerr << message.str() << endl; + }; + +public: + /* --------------------------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + TemplateSQLTest() + { + filename = "template_sql.db"; + + template_ok = + "#This line is a comment\n" + " # Other comment\n" + "MEMORY=345 # more comments behind an attribute\n" + " CPU = 4\n" + "#------------------------------\n" + "#Comments in the middle\n" + "#------------------------------\n" + " empty_var = \n" + "REQUIREMENTS = \"HOSTNAME = \\\"host*.com\\\"\"\n" + " DISK= [file = path1, extra = \"disk attribute \"]\n" + "DISK =[ FILE = \"path2\", EXTRA = str, TYPE=disk]\n" + " graphics = [\n" + " VNC = \"127.0.0.1\",\n" + " PORT = 12\n" + " ]\n"; + + template_xml = + ""; + } + + ~TemplateSQLTest(){}; + + /* --------------------------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + void setUp() + { + ostringstream db_bs("CREATE TABLE template (id INTEGER, name TEXT," + " type INTEGER, value TEXT)"); + + db = new SqliteDB(filename); + CPPUNIT_ASSERT(db->exec(db_bs)== 0); + } + + void tearDown() + { + delete db; + unlink(filename.c_str()); + } + + /* ********************************************************************* */ + /* ********************************************************************* */ + + void test_insert() + { + char * error = 0; + int rc; + string tmp; + TSQL t("template"); + + rc = t.parse(template_ok,&error); + + if ( error != 0 ) + { + cerr << error << endl; + free(error); + } + + CPPUNIT_ASSERT( rc == 0); + + CPPUNIT_ASSERT( t.insert(db) == 0 ); + CPPUNIT_ASSERT( t.id() == 0 ); + + CPPUNIT_ASSERT( t.insert(db) == 0 ); + CPPUNIT_ASSERT( t.id() == 1 ); + + CPPUNIT_ASSERT( t.insert(db) == 0 ); + CPPUNIT_ASSERT( t.id() == 2 ); + } + + /* --------------------------------------------------------------------- */ + + void test_select() + { + char * error = 0; + + TSQL t("template"); + TSQL t2("template",0); + + string t2_xml; + + t.parse(template_ok,&error); + t.insert(db); + + if ( error != 0 ) + { + free(error); + } + + CPPUNIT_ASSERT( t2.select(db) == 0 ); + + t2.to_xml(t2_xml); + + CPPUNIT_ASSERT( t2_xml == template_xml ); + } + + /* ********************************************************************* */ + /* ********************************************************************* */ + + static CppUnit::TestSuite * suite() + { + CppUnit::TestSuite *ts=new CppUnit::TestSuite("TemplateSQL Tests"); + + ts->addTest(new CppUnit::TestCaller( + "bootstrap() Test", + &TemplateSQLTest::test_insert)); + + ts->addTest(new CppUnit::TestCaller( + "insert() Test", + &TemplateSQLTest::test_insert)); + + ts->addTest(new CppUnit::TestCaller( + "select() Test", + &TemplateSQLTest::test_select)); + + return ts; + } +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + CppUnit::TextUi::TestRunner tr; + + tr.addTest(TemplateSQLTest::suite()); + tr.run(); + + return 0; +} diff --git a/src/tm/TransferManager.cc b/src/tm/TransferManager.cc index f54b5c053e..4d26800ca1 100644 --- a/src/tm/TransferManager.cc +++ b/src/tm/TransferManager.cc @@ -15,6 +15,8 @@ /* -------------------------------------------------------------------------- */ #include "TransferManager.h" +#include "NebulaLog.h" + #include "Nebula.h" /* -------------------------------------------------------------------------- */ @@ -31,11 +33,11 @@ extern "C" void * tm_action_loop(void *arg) tm = static_cast(arg); - Nebula::log("TrM",Log::INFO,"Transfer Manager started."); + NebulaLog::log("TrM",Log::INFO,"Transfer Manager started."); tm->am.loop(0,0); - Nebula::log("TrM",Log::INFO,"Transfer Manager stopped."); + NebulaLog::log("TrM",Log::INFO,"Transfer Manager stopped."); return 0; } @@ -54,7 +56,7 @@ int TransferManager::start() return -1; } - Nebula::log("TrM",Log::INFO,"Starting Transfer Manager..."); + NebulaLog::log("TrM",Log::INFO,"Starting Transfer Manager..."); pthread_attr_init (&pattr); pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); @@ -178,7 +180,7 @@ void TransferManager::do_action(const string &action, void * arg) } else if (action == ACTION_FINALIZE) { - Nebula::log("TrM",Log::INFO,"Stopping Transfer Manager..."); + NebulaLog::log("TrM",Log::INFO,"Stopping Transfer Manager..."); MadManager::stop(); } @@ -187,7 +189,7 @@ void TransferManager::do_action(const string &action, void * arg) ostringstream oss; oss << "Unknown action name: " << action; - Nebula::log("TrM", Log::ERROR, oss); + NebulaLog::log("TrM", Log::ERROR, oss); } } @@ -1052,7 +1054,7 @@ void TransferManager::load_mads(int uid) oss << "Loading Transfer Manager drivers."; - Nebula::log("TM",Log::INFO,oss); + NebulaLog::log("TM",Log::INFO,oss); for(i=0,oss.str("");ivector_value("NAME"); oss << "\tLoading driver: " << name; - Nebula::log("VMM", Log::INFO, oss); + NebulaLog::log("VMM", Log::INFO, oss); tm_driver = new TransferManagerDriver( uid, @@ -1079,7 +1081,7 @@ void TransferManager::load_mads(int uid) oss.str(""); oss << "\tDriver " << name << " loaded."; - Nebula::log("TM",Log::INFO,oss); + NebulaLog::log("TM",Log::INFO,oss); } } } diff --git a/src/tm/TransferManagerDriver.cc b/src/tm/TransferManagerDriver.cc index 9a3aac29db..94a2828d58 100644 --- a/src/tm/TransferManagerDriver.cc +++ b/src/tm/TransferManagerDriver.cc @@ -15,8 +15,10 @@ /* -------------------------------------------------------------------------- */ #include "TransferManagerDriver.h" -#include "Nebula.h" +#include "NebulaLog.h" #include "LifeCycleManager.h" + +#include "Nebula.h" #include /* ************************************************************************** */ @@ -52,7 +54,7 @@ void TransferManagerDriver::protocol( VirtualMachine * vm; os << "Message received: " << message; - Nebula::log("TM", Log::DEBUG, os); + NebulaLog::log("TM", Log::DEBUG, os); // Parse the driver message if ( is.good() ) @@ -77,7 +79,7 @@ void TransferManagerDriver::protocol( is.clear(); getline(is,info); - Nebula::log("TM",Log::INFO, info.c_str()); + NebulaLog::log("TM",Log::INFO, info.c_str()); } return; @@ -192,5 +194,5 @@ error_state: void TransferManagerDriver::recover() { - Nebula::log("TM",Log::INFO,"Recovering TM drivers"); + NebulaLog::log("TM",Log::INFO,"Recovering TM drivers"); } diff --git a/src/um/User.cc b/src/um/User.cc index ea6f2ff1a6..fbf9768dbf 100644 --- a/src/um/User.cc +++ b/src/um/User.cc @@ -52,14 +52,14 @@ const char * User::table = "user_pool"; const char * User::db_names = "(oid,user_name,password,enabled)"; -const char * User::db_bootstrap = "CREATE TABLE user_pool (" - "oid INTEGER,user_name TEXT,password TEXT," - "enabled INTEGER, PRIMARY KEY(oid,user_name), UNIQUE(user_name))"; +const char * User::db_bootstrap = "CREATE TABLE IF NOT EXISTS user_pool (" + "oid INTEGER PRIMARY KEY, user_name VARCHAR(256), password TEXT," + "enabled INTEGER, UNIQUE(user_name))"; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int User::unmarshall(int num, char **names, char ** values) +int User::select_cb(void *nil, int num, char **values, char **names) { if ((!values[OID]) || (!values[USERNAME]) || @@ -74,45 +74,29 @@ int User::unmarshall(int num, char **names, char ** values) username = values[USERNAME]; password = values[PASSWORD]; enabled = (atoi(values[ENABLED])==0)?false:true; - + return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -extern "C" int user_select_cb ( - void * _user, - int num, - char ** values, - char ** names) -{ - User * user; - - user = static_cast(_user); - - if (user == 0) - { - return -1; - } - - return user->unmarshall(num,names,values); -}; - /* -------------------------------------------------------------------------- */ -int User::select(SqliteDB *db) +int User::select(SqlDB *db) { ostringstream oss; int rc; int boid; - + + set_callback(static_cast(&User::select_cb)); + oss << "SELECT * FROM " << table << " WHERE oid = " << oid; boid = oid; oid = -1; - rc = db->exec(oss, user_select_cb, (void *) this); + rc = db->exec(oss, this); if ((rc != 0) || (oid != boid )) { @@ -125,11 +109,11 @@ int User::select(SqliteDB *db) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int User::insert(SqliteDB *db) +int User::insert(SqlDB *db) { int rc; - - rc = update(db); + + rc = insert_replace(db, false); if ( rc != 0 ) { @@ -142,36 +126,61 @@ int User::insert(SqliteDB *db) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int User::update(SqliteDB *db) +int User::update(SqlDB *db) +{ + int rc; + + rc = insert_replace(db, true); + + if ( rc != 0 ) + { + return rc; + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int User::insert_replace(SqlDB *db, bool replace) { ostringstream oss; - + int rc; char * sql_username; char * sql_password; - + int str_enabled = enabled?1:0; - + // Update the User - - sql_username = sqlite3_mprintf("%q",username.c_str()); + + sql_username = db->escape_str(username.c_str()); if ( sql_username == 0 ) { goto error_username; } - - sql_password = sqlite3_mprintf("%q",password.c_str()); + + sql_password = db->escape_str(password.c_str()); if ( sql_password == 0 ) { goto error_password; } - - // Construct the SQL statement to Insert or Replace (effectively, update) - oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES (" + // Construct the SQL statement to Insert or Replace + if(replace) + { + oss << "REPLACE"; + } + else + { + oss << "INSERT"; + } + + oss << " INTO " << table << " "<< db_names <<" VALUES (" << oid << "," << "'" << sql_username << "'," << "'" << sql_password << "'," @@ -179,13 +188,13 @@ int User::update(SqliteDB *db) rc = db->exec(oss); - sqlite3_free(sql_username); - sqlite3_free(sql_password); + db->free_str(sql_username); + db->free_str(sql_password); return rc; - + error_password: - sqlite3_free(sql_username); + db->free_str(sql_username); error_username: return -1; } @@ -193,10 +202,7 @@ error_username: /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int User::unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values) +int User::dump(ostringstream& oss, int num, char **values, char **names) { if ((!values[OID]) || (!values[USERNAME]) || @@ -206,64 +212,24 @@ int User::unmarshall(ostringstream& oss, { return -1; } - + string str_enabled = (atoi(values[ENABLED])==0)?"Fase":"True"; oss << "" << - "" << values[OID] <<"" << - "" << values[USERNAME] <<"" << - "" << values[PASSWORD] <<"" << - "" << str_enabled <<"" << + "" << values[OID] <<"" << + "" << values[USERNAME]<<"" << + ""<< values[PASSWORD]<<""<< + "" << str_enabled <<"" << ""; return 0; - -} - -/* -------------------------------------------------------------------------- */ - -extern "C" int user_dump_cb ( - void * _oss, - int num, - char ** values, - char ** names) -{ - ostringstream * oss; - - oss = static_cast(_oss); - - if (oss == 0) - { - return -1; - } - - return User::unmarshall(*oss,num,names,values); -}; - -/* -------------------------------------------------------------------------- */ - -int User::dump(SqliteDB * db, ostringstream& oss, const string& where) -{ - int rc; - ostringstream cmd; - - cmd << "SELECT * FROM " << User::table; - - if ( !where.empty() ) - { - cmd << " WHERE " << where; - } - - rc = db->exec(cmd,user_dump_cb,(void *) &oss); - - return rc; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int User::drop(SqliteDB * db) +int User::drop(SqlDB * db) { ostringstream oss; int rc; @@ -286,10 +252,10 @@ int User::drop(SqliteDB * db) ostream& operator<<(ostream& os, User& user) { - string user_str; - - os << user.to_xml(user_str); - + string user_str; + + os << user.to_xml(user_str); + return os; }; @@ -300,11 +266,11 @@ ostream& operator<<(ostream& os, User& user) string& User::to_xml(string& xml) const { ostringstream oss; - + int enabled_int = enabled?1:0; - - oss << - "" + + oss << + "" "" << oid <<"" << "" << username <<"" << "" << password <<"" << @@ -325,14 +291,14 @@ string& User::to_str(string& str) const string enabled_str = enabled?"True":"False"; - os << - "ID = " << oid << endl << - "NAME = " << username << endl << - "PASSWORD = " << password << endl << + os << + "ID = " << oid << endl << + "NAME = " << username << endl << + "PASSWORD = " << password << endl << "ENABLED = " << enabled_str; str = os.str(); - + return str; } @@ -347,7 +313,7 @@ int User::authenticate(string _password) } else { - return -1; + return -1; } } @@ -362,13 +328,13 @@ int User::split_secret(const string secret, string& user, string& pass) pos=secret.find(":"); if (pos != string::npos) - { + { user = secret.substr(0,pos); pass = secret.substr(pos+1); rc = 0; } - + return rc; } @@ -381,7 +347,7 @@ string User::sha1_digest(const string& pass) unsigned char md_value[EVP_MAX_MD_SIZE]; unsigned int md_len; ostringstream oss; - + EVP_MD_CTX_init(&mdctx); EVP_DigestInit_ex(&mdctx, EVP_sha1(), NULL); diff --git a/src/um/UserPool.cc b/src/um/UserPool.cc index 68512eddd9..42b46dc6a6 100644 --- a/src/um/UserPool.cc +++ b/src/um/UserPool.cc @@ -19,52 +19,41 @@ /* ************************************************************************** */ #include "UserPool.h" -#include "Nebula.h" +#include "NebulaLog.h" #include #include #include +#include /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -extern "C" +int UserPool::init_cb(void *nil, int num, char **values, char **names) { - static int getuids_cb( - void * _known_users, - int num, - char ** values, - char ** names) + if ( num == 0 || values == 0 || values[0] == 0 ) { - map * known_users; - - known_users = static_cast *>(_known_users); - - if ( num == 0 || values == 0 || values[0] == 0 ) - { - return -1; - } - - known_users->insert(make_pair(values[1],atoi(values[0]))); - - return 0; + return -1; } + + known_users.insert(make_pair(values[1],atoi(values[0]))); + + return 0; } -/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -UserPool::UserPool(SqliteDB * db):PoolSQL(db,User::table) +UserPool::UserPool(SqlDB * db):PoolSQL(db,User::table) { - // The known_users table needs to be rebuilt - ostringstream sql; - + + set_callback(static_cast(&UserPool::init_cb)); + sql << "SELECT oid,user_name FROM " << User::table; - - db->exec(sql, getuids_cb, (void *) &known_users); - - if ((int) known_users.size() == 0) + + db->exec(sql, this); + + if ((int) known_users.size() == 0) { // User oneadmin needs to be added in the bootstrap int one_uid = -1; @@ -82,7 +71,7 @@ UserPool::UserPool(SqliteDB * db):PoolSQL(db,User::table) if (!one_auth) { struct passwd * pw_ent; - + pw_ent = getpwuid(getuid()); if ((pw_ent != NULL) && (pw_ent->pw_dir != NULL)) @@ -91,13 +80,13 @@ UserPool::UserPool(SqliteDB * db):PoolSQL(db,User::table) one_auth_file += "/.one/one_auth"; one_auth = one_auth_file.c_str(); - } + } else { oss << "Could not get one_auth file location"; } } - + file.open(one_auth); if (file.good()) @@ -127,10 +116,10 @@ UserPool::UserPool(SqliteDB * db):PoolSQL(db,User::table) } file.close(); - + if (one_uid != 0) { - Nebula::log("ONE",Log::ERROR,oss); + NebulaLog::log("ONE",Log::ERROR,oss); throw; } } @@ -157,11 +146,14 @@ int UserPool::allocate ( // Insert the Object in the pool *oid = PoolSQL::allocate(user); - - // Add the user to the map of known_users - known_users.insert(make_pair(username,*oid)); - return 0; + if (*oid != -1) + { + // Add the user to the map of known_users + known_users.insert(make_pair(username,*oid)); + } + + return *oid; } /* -------------------------------------------------------------------------- */ @@ -170,12 +162,12 @@ int UserPool::allocate ( int UserPool::authenticate(string& session) { map::iterator index; - + string username; string password; - - int user_id = -1; - + + int user_id = -1; + // session holds username:password if ( User::split_secret(session,username,password) == 0 ) @@ -188,6 +180,44 @@ int UserPool::authenticate(string& session) user_id = user->authenticate(password); } } - + return user_id; } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int UserPool::dump_cb(void * _oss, int num, char **values, char **names) +{ + ostringstream * oss; + + oss = static_cast(_oss); + + return User::dump(*oss, num, values, names); +} + +/* -------------------------------------------------------------------------- */ + +int UserPool::dump(ostringstream& oss, const string& where) +{ + int rc; + ostringstream cmd; + + oss << ""; + + set_callback(static_cast(&UserPool::dump_cb), + static_cast(&oss)); + + cmd << "SELECT * FROM " << User::table; + + if ( !where.empty() ) + { + cmd << " WHERE " << where; + } + + rc = db->exec(cmd, this); + + oss << ""; + + return rc; +} \ No newline at end of file diff --git a/src/um/test/SConstruct b/src/um/test/SConstruct new file mode 100644 index 0000000000..2b6eb98931 --- /dev/null +++ b/src/um/test/SConstruct @@ -0,0 +1,89 @@ +# -------------------------------------------------------------------------- +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# -------------------------------------------------------------------------- + +import os +import sys +import shutil +sys.path.append("../../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located +cwd="../../../" + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) + +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include', + cwd + '/include/test', + '/usr/include/cppunit/', +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd + '/src/common', + cwd + '/src/log', + cwd + '/src/nebula', + cwd + '/src/pool', + cwd + '/src/sql', + cwd + '/src/um', + '/usr/include/openssl/', +]) + +main_env.Append(LIBS=[ + 'nebula_um', + 'nebula_pool', + 'nebula_log', + 'nebula_common', + 'nebula_core', + 'nebula_sql', + 'cppunit', + 'dl', + 'pthread', + 'crypto' +]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# Linking flags +main_env.Append(LDFLAGS=["-g "]) +main_env.Program('test','UserPoolTest.cc') + +# MYSQL +main_env.Append(LIBPATH=["/usr/lib/mysql"]) +main_env.Append(CPPPATH=["/usr/include/mysql"]) + +sqlite=ARGUMENTS.get('sqlite', 'yes') +if sqlite=='yes': + main_env.Append(CPPFLAGS=["-DSQLITE_DB"]) + main_env.Append(LIBS=[ 'sqlite3', ]) + +# MySQL +mysql=ARGUMENTS.get('mysql', 'no') +if mysql=='yes': + main_env.Append(CPPFLAGS=["-DMYSQL_DB"]) + main_env.Append(LIBS=[ 'mysqlclient', ]) + diff --git a/src/um/test/UserPoolTest.cc b/src/um/test/UserPoolTest.cc new file mode 100644 index 0000000000..da41601c04 --- /dev/null +++ b/src/um/test/UserPoolTest.cc @@ -0,0 +1,328 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include +#include + +#include "UserPool.h" +#include "PoolTest.h" + +using namespace std; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +const string usernames[] = { "A user", "B user", "C user", "D user", "E user" }; +const string passwords[] = { "A pass", "B pass", "C pass", "D pass", "E pass" }; + +const string dump_result = + "0one_user_test" + "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" + "True1a" + "pTrue" + "2a namepass" + "True3a_name" + "passwordTrue" + "4another namesecret" + "True5user" + "1234True" + ""; + +const string dump_where_result = + "1a" + "pTrue" + "2a namepass" + "True3a_name" + "passwordTrue" + "4another namesecret" + "True"; + +class UserPoolTest : public PoolTest +{ + CPPUNIT_TEST_SUITE (UserPoolTest); + + // Not all tests from PoolTest can be used. Because + // of the initial user added to the DB, the oid_assignment would fail. + CPPUNIT_TEST (get_from_cache); + CPPUNIT_TEST (get_from_db); + CPPUNIT_TEST (wrong_get); + CPPUNIT_TEST (drop_and_get); + + CPPUNIT_TEST (sha1_digest); + CPPUNIT_TEST (split_secret); + CPPUNIT_TEST (initial_user); + CPPUNIT_TEST (authenticate); + CPPUNIT_TEST (get_using_name); + CPPUNIT_TEST (wrong_get_name); + CPPUNIT_TEST (update); + CPPUNIT_TEST (duplicates); + CPPUNIT_TEST (dump); + CPPUNIT_TEST (dump_where); + + CPPUNIT_TEST_SUITE_END (); + +protected: + + void bootstrap(SqlDB* db) + { + UserPool::bootstrap(db); + }; + + PoolSQL* create_pool(SqlDB* db) + { + return new UserPool(db); + }; + + int allocate(int index) + { + int oid; + return ((UserPool*)pool)->allocate(&oid, usernames[index], + passwords[index], true); + }; + + void check(int index, PoolObjectSQL* obj) + { + CPPUNIT_ASSERT( obj != 0 ); + + string name = ((User*)obj)->get_username(); + CPPUNIT_ASSERT( name == usernames[index] ); + CPPUNIT_ASSERT( ((User*)obj)->get_password() == passwords[index] ); + }; + +public: + + UserPoolTest() + { + // The UserPool constructor checks if the DB contains at least + // one user, and adds one automatically from the ONE_AUTH file. + // So the ONE_AUTH environment is forced to point to a test one_auth + // file. + ostringstream oss; + + oss << getenv("PWD") << "/one_auth"; + setenv("ONE_AUTH", oss.str().c_str(), 1); + }; + + ~UserPoolTest(){}; + + /* ********************************************************************* */ + /* ********************************************************************* */ + + void sha1_digest() + { + string st = "top_secret_string"; + string sha1 = "773260f433f7fd6f89c1f1bfc32e080fc0748478"; + + CPPUNIT_ASSERT( sha1 == User::sha1_digest(st) ); + } + + void split_secret() + { + string secret = "left_part-user.N AME:pass--word..SECRET?"; + string left = ""; + string right = ""; + + User::split_secret(secret, left, right); + + CPPUNIT_ASSERT( left == "left_part-user.N AME" ); + CPPUNIT_ASSERT( right == "pass--word..SECRET?" ); + } + + void initial_user() + { + // When creating a new pool, the constructor will check if the DB + // contains at least one user. + // If it doesn't, it adds one automatically from: + // * The $ONE_AUTH file. + // * The ~/.one/one_auth file. + + // The ONE_AUTH environment variable was forced to point to a prepared + // one_auth file at set-up, so the pool should contain the user + // one_user_test:password + + User* user = (User*) pool->get(0, false); + CPPUNIT_ASSERT(user != 0); + + CPPUNIT_ASSERT( user->get_uid() == 0 ); + CPPUNIT_ASSERT( user->get_username() == "one_user_test" ); + CPPUNIT_ASSERT( user->get_password() == User::sha1_digest("password") ); + } + + void authenticate() + { + UserPool* user_pool = (UserPool*) pool; + // There is an initial user, created with the one_auth file: + // one_user_test:password + string session="one_user_test:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"; + + int oid = user_pool->authenticate( session ); + CPPUNIT_ASSERT( oid == 0 ); + + session = "one_user_test:wrong_password"; + oid = user_pool->authenticate( session ); + CPPUNIT_ASSERT( oid == -1 ); + + session = "unknown_user:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"; + oid = user_pool->authenticate( session ); + CPPUNIT_ASSERT( oid == -1 ); + } + + void get_using_name() + { + int oid_0, oid_1; + + // Allocate two objects + oid_0 = allocate(0); + oid_1 = allocate(1); + + // --------------------------------- + // Get first object and check its integrity + obj = pool->get(oid_0, false); + CPPUNIT_ASSERT( obj != 0 ); + check(0, obj); + + // Get using its name + obj = ((UserPool*)pool)->get(usernames[1], true); + check(1, obj); + obj->unlock(); + + // --------------------------------- + // Clean the cache, forcing the pool to read the objects from the DB + pool->clean(); + + // Get first object and check its integrity + obj = pool->get(oid_0, false); + check(0, obj); + + // Get using its name + obj = ((UserPool*)pool)->get(usernames[1], true); + check(1, obj); + obj->unlock(); + }; + + void wrong_get_name() + { + // The pool is empty + // Non existing name + obj = ((UserPool*)pool)->get("Wrong name", true); + CPPUNIT_ASSERT( obj == 0 ); + + // Allocate an object + allocate(0); + + // Ask again for a non-existing name + obj = ((UserPool*)pool)->get("Non existing name", true); + CPPUNIT_ASSERT( obj == 0 ); + } + + void update() + { + int oid; + User* user; + + oid = allocate(2); + + user = ((UserPool*)pool)->get(oid, true); + + user->disable(); + pool->update(user); + + user->unlock(); + + // Check the cache + + user = ((UserPool*)pool)->get(oid,false); + CPPUNIT_ASSERT( user->isEnabled() == false ); + + //Now force access to DB + + pool->clean(); + user = ((UserPool*)pool)->get(oid,false); + + CPPUNIT_ASSERT( user != 0 ); + CPPUNIT_ASSERT( user->isEnabled() == false ); + }; + + void duplicates() + { + int rc, oid; + UserPool * up = static_cast(pool); + + // Allocate a user. + rc = up->allocate(&oid, usernames[0], passwords[0], true); + CPPUNIT_ASSERT( oid == 1 ); + CPPUNIT_ASSERT( oid == rc ); + + // Try to allocate twice the same user, should fail + rc = up->allocate(&oid, usernames[0], passwords[0], true); + CPPUNIT_ASSERT( rc == -1 ); + CPPUNIT_ASSERT( oid == rc ); + + // Try again, with different password + rc = up->allocate(&oid, usernames[0], passwords[1], true); + CPPUNIT_ASSERT( rc == -1 ); + CPPUNIT_ASSERT( oid == rc ); + } + + void dump() + { + string d_names[] = {"a", "a name", "a_name", "another name", "user"}; + string d_pass[] = {"p", "pass", "password", "secret", "1234"}; + + int oid; + + for(int i=0; i<5; i++) + { + ((UserPool*)pool)->allocate(&oid, d_names[i], d_pass[i], true); + } + + ostringstream oss; + ((UserPool*)pool)->dump(oss, ""); + + CPPUNIT_ASSERT( oss.str() == dump_result ); + } + + void dump_where() + { + string d_names[] = {"a", "a name", "a_name", "another name", "user"}; + string d_pass[] = {"p", "pass", "password", "secret", "1234"}; + + int oid; + + for(int i=0; i<5; i++) + { + ((UserPool*)pool)->allocate(&oid, d_names[i], d_pass[i], true); + } + + // Note: second parameter of dump is the WHERE constraint. The "order + // by" is a dirty fix (SQL injection, actually) because MySQL orders the + // results by user_name + ostringstream oss; + ((UserPool*)pool)->dump(oss, "user_name LIKE 'a%' ORDER BY oid"); + + CPPUNIT_ASSERT( oss.str() == dump_where_result ); + } +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + return PoolTest::main(argc, argv, UserPoolTest::suite()); +} diff --git a/src/um/test/one_auth b/src/um/test/one_auth new file mode 100644 index 0000000000..2f55c9c47b --- /dev/null +++ b/src/um/test/one_auth @@ -0,0 +1 @@ +one_user_test:password diff --git a/src/vm/History.cc b/src/vm/History.cc index 7cbf9c6c45..d73ab00927 100644 --- a/src/vm/History.cc +++ b/src/vm/History.cc @@ -28,11 +28,12 @@ const char * History::table = "history"; const char * History::db_names = "(vid,seq,host_name,vm_dir,hid,vm_mad,tm_mad,stime," "etime,pstime,petime,rstime,retime,estime,eetime,reason)"; -const char * History::db_bootstrap = "CREATE TABLE history (vid INTEGER," +const char * History::db_bootstrap = "CREATE TABLE IF NOT EXISTS " + "history (vid INTEGER," "seq INTEGER,host_name TEXT,vm_dir TEXT,hid INTEGER,vm_mad TEXT,tm_mad TEXT," "stime INTEGER,etime INTEGER,pstime INTEGER,petime INTEGER,rstime INTEGER," "retime INTEGER,estime INTEGER,eetime INTEGER,reason INTEGER," - "PRIMARY KEY(vid,seq))"; + "PRIMARY KEY(vid,seq))"; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -134,51 +135,84 @@ void History::non_persistent_data() /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int History::insert(SqliteDB * db) +int History::insert(SqlDB * db) +{ + int rc; + + rc = insert_replace(db, false); + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int History::update(SqlDB * db) +{ + int rc; + + rc = insert_replace(db, true); + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int History::insert_replace(SqlDB *db, bool replace) { ostringstream oss; - + int rc; char * sql_hostname; char * sql_vm_dir; char * sql_vmm_mad_name; char * sql_tm_mad_name; - + if (seq == -1) { return 0; } - - sql_hostname = sqlite3_mprintf("%q",hostname.c_str()); + + sql_hostname = db->escape_str(hostname.c_str()); if ( sql_hostname == 0 ) { goto error_hostname; } - sql_vm_dir = sqlite3_mprintf("%q",vm_dir.c_str()); + sql_vm_dir = db->escape_str(vm_dir.c_str()); if ( sql_vm_dir == 0 ) { goto error_vm_dir; } - - sql_vmm_mad_name = sqlite3_mprintf("%q",vmm_mad_name.c_str()); + + sql_vmm_mad_name = db->escape_str(vmm_mad_name.c_str()); if ( sql_vmm_mad_name == 0 ) { goto error_vmm; } - - sql_tm_mad_name = sqlite3_mprintf("%q",tm_mad_name.c_str()); + + sql_tm_mad_name = db->escape_str(tm_mad_name.c_str()); if ( sql_tm_mad_name == 0 ) { goto error_tm; } + + if(replace) + { + oss << "REPLACE"; + } + else + { + oss << "INSERT"; + } - oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES ("<< + oss << " INTO " << table << " "<< db_names <<" VALUES ("<< oid << "," << seq << "," << "'" << sql_hostname << "',"<< @@ -198,19 +232,19 @@ int History::insert(SqliteDB * db) rc = db->exec(oss); - sqlite3_free(sql_hostname); - sqlite3_free(sql_vm_dir); - sqlite3_free(sql_vmm_mad_name); - sqlite3_free(sql_tm_mad_name); - + db->free_str(sql_hostname); + db->free_str(sql_vm_dir); + db->free_str(sql_vmm_mad_name); + db->free_str(sql_tm_mad_name); + return rc; - + error_tm: - sqlite3_free(sql_vmm_mad_name); + db->free_str(sql_vmm_mad_name); error_vmm: - sqlite3_free(sql_vm_dir); + db->free_str(sql_vm_dir); error_vm_dir: - sqlite3_free(sql_hostname); + db->free_str(sql_hostname); error_hostname: return -1; } @@ -218,7 +252,7 @@ error_hostname: /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int History::unmarshall(int num, char **names, char ** values) +int History::select_cb(void *nil, int num, char **values, char **names) { if ((!values[VID]) || (!values[SEQ]) || @@ -243,10 +277,10 @@ int History::unmarshall(int num, char **names, char ** values) oid = atoi(values[VID]); seq = atoi(values[SEQ]); - + hostname = values[HOSTNAME]; vm_dir = values[VM_DIR]; - + hid = atoi(values[HID]); vmm_mad_name = values[VMMMAD]; @@ -272,12 +306,9 @@ int History::unmarshall(int num, char **names, char ** values) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int History::unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values) +int History::dump(ostringstream& oss, int num, char **values, char **names) { - if ((!values[VID])|| + if ((!values[VID])|| (!values[SEQ])|| (!values[HOSTNAME])|| (!values[HID])|| @@ -290,11 +321,11 @@ int History::unmarshall(ostringstream& oss, (!values[EPILOG_STIME])|| (!values[EPILOG_ETIME])|| (!values[REASON])|| - (num != LIMIT)) + (num != LIMIT)) { - return -1; - } - + return -1; + } + oss << "" << "" << values[SEQ] << "" << @@ -310,34 +341,13 @@ int History::unmarshall(ostringstream& oss, "" << values[EPILOG_ETIME] << "" << "" << values[REASON] << "" << ""; - - return 0; + + return 0; } -/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -extern "C" int history_select_cb ( - void * _history, - int num, - char ** values, - char ** names) -{ - History * history; - - history = static_cast(_history); - - if (history == 0) - { - return -1; - } - - return history->unmarshall(num,names,values); -}; - -/* -------------------------------------------------------------------------- */ - -int History::select(SqliteDB * db) +int History::select(SqlDB * db) { ostringstream oss; int rc; @@ -349,15 +359,17 @@ int History::select(SqliteDB * db) if ( seq == -1) { - oss << "SELECT * FROM history WHERE vid = "<< oid << - " AND seq=(SELECT MAX(seq) FROM history WHERE vid = " << oid << ")"; + oss << "SELECT * FROM history WHERE vid = "<< oid << + " AND seq=(SELECT MAX(seq) FROM history WHERE vid = " << oid << ")"; } else { - oss << "SELECT * FROM history WHERE vid = "<< oid <<" AND seq = "<< seq; + oss << "SELECT * FROM history WHERE vid = "<< oid <<" AND seq = "<< seq; } - rc = db->exec(oss,history_select_cb,(void *) this); + set_callback(static_cast(&History::select_cb)); + + rc = db->exec(oss,this); if ( rc == 0 ) // Regenerate non-persistent data { @@ -370,7 +382,7 @@ int History::select(SqliteDB * db) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int History::drop(SqliteDB * db) +int History::drop(SqlDB * db) { ostringstream oss; @@ -424,7 +436,7 @@ string& History::to_str(string& str) const string& History::to_xml(string& xml) const { ostringstream oss; - + oss << "" << "" << seq << "" << diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 22d5f11f64..97089edb89 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -25,6 +25,8 @@ #include "VirtualMachine.h" #include "VirtualNetworkPool.h" +#include "NebulaLog.h" + #include "Nebula.h" @@ -83,7 +85,8 @@ const char * VirtualMachine::db_names = "(oid,uid,name,last_poll,template_id,sta ",lcm_state,stime,etime,deploy_id" ",memory,cpu,net_tx,net_rx)"; -const char * VirtualMachine::db_bootstrap = "CREATE TABLE vm_pool (" +const char * VirtualMachine::db_bootstrap = "CREATE TABLE IF NOT EXISTS " + "vm_pool (" "oid INTEGER PRIMARY KEY,uid INTEGER,name TEXT," "last_poll INTEGER, template_id INTEGER,state INTEGER,lcm_state INTEGER," "stime INTEGER,etime INTEGER,deploy_id TEXT,memory INTEGER,cpu INTEGER," @@ -92,7 +95,7 @@ const char * VirtualMachine::db_bootstrap = "CREATE TABLE vm_pool (" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::unmarshall(int num, char **names, char ** values) +int VirtualMachine::select_cb(void *nil, int num, char **values, char **names) { if ((values[OID] == 0) || (values[UID] == 0) || @@ -139,30 +142,9 @@ int VirtualMachine::unmarshall(int num, char **names, char ** values) return 0; } -/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -extern "C" int vm_select_cb ( - void * _vm, - int num, - char ** values, - char ** names) -{ - VirtualMachine * vm; - - vm = static_cast(_vm); - - if (vm == 0) - { - return -1; - } - - return vm->unmarshall(num,names,values); -}; - -/* -------------------------------------------------------------------------- */ - -int VirtualMachine::select(SqliteDB * db) +int VirtualMachine::select(SqlDB * db) { ostringstream oss; ostringstream ose; @@ -171,15 +153,17 @@ int VirtualMachine::select(SqliteDB * db) int boid; string filename; - Nebula& nd = Nebula::instance(); + Nebula& nd = Nebula::instance(); + + set_callback( + static_cast(&VirtualMachine::select_cb)); oss << "SELECT * FROM " << table << " WHERE oid = " << oid; boid = oid; oid = -1; - rc = db->exec(oss,vm_select_cb,(void *) this); - + rc = db->exec(oss,this); if ((rc != 0) || (oid != boid )) { @@ -213,14 +197,14 @@ int VirtualMachine::select(SqliteDB * db) } else if (history->seq > 0) { - previous_history = new History(oid,history->seq - 1); + previous_history = new History(oid,history->seq - 1); - rc = previous_history->select(db); + rc = previous_history->select(db); - if ( rc != 0) - { - goto error_previous_history; - } + if ( rc != 0) + { + goto error_previous_history; + } } //Create support directory fo this VM @@ -235,15 +219,15 @@ int VirtualMachine::select(SqliteDB * db) try { - _log = new Log(nd.get_vm_log_filename(oid),Log::DEBUG); - } + _log = new FileLog(nd.get_vm_log_filename(oid),Log::DEBUG); + } catch(exception &e) { - ose << "Error creating log: " << e.what(); - Nebula::log("ONE",Log::ERROR, ose); + ose << "Error creating log: " << e.what(); + NebulaLog::log("ONE",Log::ERROR, ose); - _log = 0; - } + _log = 0; + } return 0; @@ -263,8 +247,8 @@ error_history: return -1; error_previous_history: - ose << "Can not get previous history record (seq:" << history->seq - << ") for VM id: " << oid; + ose << "Can not get previous history record (seq:" << history->seq + << ") for VM id: " << oid; log("ONE", Log::ERROR, ose); return -1; } @@ -272,7 +256,7 @@ error_previous_history: /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::insert(SqliteDB * db) +int VirtualMachine::insert(SqlDB * db) { int rc; string name; @@ -290,8 +274,8 @@ int VirtualMachine::insert(SqliteDB * db) attr = new SingleAttribute("VMID",value); vm_template.set(attr); - - + + get_template_attribute("NAME",name); if ( name.empty() == true ) @@ -328,7 +312,7 @@ int VirtualMachine::insert(SqliteDB * db) goto error_template; } - rc = update(db); + rc = insert_replace(db, false); if ( rc != 0 ) { @@ -338,25 +322,37 @@ int VirtualMachine::insert(SqliteDB * db) return 0; error_update: - Nebula::log("ONE",Log::ERROR, "Can not update VM in the database"); - vm_template.drop(db); - return -1; + NebulaLog::log("ONE",Log::ERROR, "Can not update VM in the database"); + vm_template.drop(db); + return -1; error_template: - Nebula::log("ONE",Log::ERROR, "Can not insert template in the database"); - release_network_leases(); - return -1; + NebulaLog::log("ONE",Log::ERROR, "Can not insert template in the database"); + release_network_leases(); + return -1; error_leases: - Nebula::log("ONE",Log::ERROR, "Could not get network lease for VM"); - release_network_leases(); - return -1; + NebulaLog::log("ONE",Log::ERROR, "Could not get network lease for VM"); + release_network_leases(); + return -1; } -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ -int VirtualMachine::update(SqliteDB * db) +int VirtualMachine::update(SqlDB * db) +{ + int rc; + + rc = insert_replace(db, true); + + return rc; +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int VirtualMachine::insert_replace(SqlDB *db, bool replace) { ostringstream oss; int rc; @@ -364,22 +360,31 @@ int VirtualMachine::update(SqliteDB * db) char * sql_deploy_id; char * sql_name; - sql_deploy_id = sqlite3_mprintf("%q",deploy_id.c_str()); + sql_deploy_id = db->escape_str(deploy_id.c_str()); if ( sql_deploy_id == 0 ) { return -1; } - sql_name = sqlite3_mprintf("%q",name.c_str()); + sql_name = db->escape_str(name.c_str()); if ( sql_name == 0 ) { - sqlite3_free(sql_deploy_id); + db->free_str(sql_deploy_id); return -1; } - - oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES ("<< + + if(replace) + { + oss << "REPLACE"; + } + else + { + oss << "INSERT"; + } + + oss << " INTO " << table << " "<< db_names <<" VALUES ("<< oid << "," << uid << "," << "'" << sql_name << "'," << @@ -395,8 +400,8 @@ int VirtualMachine::update(SqliteDB * db) net_tx << "," << net_rx << ")"; - sqlite3_free(sql_deploy_id); - sqlite3_free(sql_name); + db->free_str(sql_deploy_id); + db->free_str(sql_name); rc = db->exec(oss); @@ -406,10 +411,7 @@ int VirtualMachine::update(SqliteDB * db) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values) +int VirtualMachine::dump(ostringstream& oss,int num,char **values,char **names) { if ((!values[OID])|| (!values[UID])|| @@ -434,7 +436,7 @@ int VirtualMachine::unmarshall(ostringstream& oss, "" << values[OID] << "" << "" << values[UID] << "" << "" << values[LIMIT] << ""<< - "" << values[NAME] << "" << + "" << values[NAME] << "" << ""<< values[LAST_POLL]<< ""<< "" << values[STATE] << "" << ""<< values[LCM_STATE]<< ""<< @@ -446,67 +448,18 @@ int VirtualMachine::unmarshall(ostringstream& oss, "" << values[NET_TX] << "" << "" << values[NET_RX] << ""; - History::unmarshall(oss, num-LIMIT-2, names+LIMIT+1, values+LIMIT+1); - + History::dump(oss, num-LIMIT-2, values+LIMIT+1, names+LIMIT+1); + oss << ""; - return 0; -} - -/* -------------------------------------------------------------------------- */ - -extern "C" int vm_dump_cb ( - void * _oss, - int num, - char ** values, - char ** names) -{ - ostringstream * oss; - ostringstream dbg; - - oss = static_cast(_oss); - - if (oss == 0) - { - return -1; - } - - return VirtualMachine::unmarshall(*oss,num,names,values); -}; - -/* -------------------------------------------------------------------------- */ - -int VirtualMachine::dump(SqliteDB * db, ostringstream& oss, const string& where) -{ - int rc; - ostringstream cmd; - - cmd << "SELECT " << VirtualMachine::table << ".*, " - << "user_pool.user_name, " << History::table << ".* FROM " - << VirtualMachine::table - << " LEFT OUTER JOIN (SELECT *,MAX(seq) FROM " - << History::table << " GROUP BY vid) AS " << History::table - << " ON " << VirtualMachine::table << ".oid = " - << History::table << ".vid LEFT OUTER JOIN (SELECT oid,user_name FROM " - << "user_pool) AS user_pool ON " - << VirtualMachine::table << ".uid = user_pool.oid WHERE " - << VirtualMachine::table << ".state != " << VirtualMachine::DONE; - - if ( !where.empty() ) - { - cmd << " AND " << where; - } - - rc = db->exec(cmd,vm_dump_cb,(void *) &oss); - - return rc; + return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void VirtualMachine::add_history( - int hid, + int hid, string& hostname, string& vm_dir, string& vmm_mad, @@ -525,7 +478,7 @@ void VirtualMachine::add_history( if (previous_history != 0) { - delete previous_history; + delete previous_history; } previous_history = history; @@ -539,29 +492,29 @@ void VirtualMachine::add_history( void VirtualMachine::cp_history() { - History * htmp; + History * htmp; - if (history == 0) - { - return; - } + if (history == 0) + { + return; + } - htmp = new History(oid, - history->seq + 1, - history->hid, - history->hostname, - history->vm_dir, - history->vmm_mad_name, - history->tm_mad_name); + htmp = new History(oid, + history->seq + 1, + history->hid, + history->hostname, + history->vm_dir, + history->vmm_mad_name, + history->tm_mad_name); - if ( previous_history != 0 ) - { - delete previous_history; - } + if ( previous_history != 0 ) + { + delete previous_history; + } - previous_history = history; + previous_history = history; - history = htmp; + history = htmp; } /* -------------------------------------------------------------------------- */ @@ -569,26 +522,26 @@ void VirtualMachine::cp_history() void VirtualMachine::cp_previous_history() { - History * htmp; + History * htmp; - if ( previous_history == 0 || history == 0) - { - return; - } + if ( previous_history == 0 || history == 0) + { + return; + } - htmp = new History(oid, - history->seq + 1, - previous_history->hid, - previous_history->hostname, - previous_history->vm_dir, - previous_history->vmm_mad_name, - previous_history->tm_mad_name); + htmp = new History(oid, + history->seq + 1, + previous_history->hid, + previous_history->hostname, + previous_history->vm_dir, + previous_history->vmm_mad_name, + previous_history->tm_mad_name); - delete previous_history; + delete previous_history; - previous_history = history; + previous_history = history; - history = htmp; + history = htmp; } /* -------------------------------------------------------------------------- */ @@ -672,12 +625,12 @@ int VirtualMachine::get_network_leases() return -1; } - if ( vn->get_uid() != uid && vn->get_uid() != 0 && uid != 0) + if ( vn->get_uid() != uid && vn->get_uid() != 0 && uid != 0) { ostringstream ose; - ose << "Owner " << uid << " of the VM doesn't have ownership of Virtual Network " + ose << "Owner " << uid << " of the VM doesn't have ownership of Virtual Network " << vn->get_uid(); - Nebula::log("VMM", Log::ERROR, ose); + NebulaLog::log("VMM", Log::ERROR, ose); return -1; } @@ -712,7 +665,7 @@ int VirtualMachine::get_network_leases() if ( !model.empty() ) { - new_nic.insert(make_pair("MODEL",model)); + new_nic.insert(make_pair("MODEL",model)); } nic->replace(new_nic); @@ -743,7 +696,7 @@ void VirtualMachine::release_network_leases() for(int i=0; i(nics[i]); if ( nic == 0 ) @@ -843,17 +796,17 @@ int VirtualMachine::parse_template_attribute(const string& attribute, { int rc; char * err = 0; - + rc = parse_attribute(this,-1,attribute,parsed,&err); - + if ( rc != 0 && err != 0 ) { ostringstream oss; - + oss << "Error parsing: " << attribute << ". " << err; log("VM",Log::ERROR,oss); } - + return rc; } @@ -863,19 +816,19 @@ int VirtualMachine::parse_template_attribute(const string& attribute, pthread_mutex_t VirtualMachine::lex_mutex = PTHREAD_MUTEX_INITIALIZER; extern "C" -{ +{ typedef struct yy_buffer_state * YY_BUFFER_STATE; int vm_var_parse (VirtualMachine * vm, - int vm_id, + int vm_id, ostringstream * parsed, char ** errmsg); - + int vm_var_lex_destroy(); YY_BUFFER_STATE vm_var__scan_string(const char * str); - void vm_var__delete_buffer(YY_BUFFER_STATE); + void vm_var__delete_buffer(YY_BUFFER_STATE); } /* -------------------------------------------------------------------------- */ @@ -927,9 +880,9 @@ error_yy: ostream& operator<<(ostream& os, const VirtualMachine& vm) { string vm_str; - + os << vm.to_xml(vm_str); - + return os; }; @@ -939,9 +892,9 @@ string& VirtualMachine::to_xml(string& xml) const { string template_xml; string history_xml; - + ostringstream oss; - + oss << "" << "" << oid << "" << "" << uid << "" @@ -957,15 +910,15 @@ string& VirtualMachine::to_xml(string& xml) const << "" << net_tx << "" << "" << net_rx << "" << vm_template.to_xml(template_xml); - + if ( hasHistory() ) { oss << history->to_xml(history_xml); } oss << ""; - + xml = oss.str(); - + return xml; } @@ -975,9 +928,9 @@ string& VirtualMachine::to_str(string& str) const { string template_str; string history_str; - + ostringstream oss; - + oss<< "ID : " << oid << endl << "UID : " << uid << endl << "NAME : " << name << endl @@ -992,14 +945,14 @@ string& VirtualMachine::to_str(string& str) const << "NET TX : " << net_tx << endl << "NET RX : " << net_rx << endl << "Template" << endl << vm_template.to_str(template_str) << endl; - + if ( hasHistory() ) { oss << "Last History Record" << endl << history->to_str(history_str); - } - + } + str = oss.str(); - + return str; } diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index 4005d31053..a8f0831667 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -14,15 +14,17 @@ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ -#include "Nebula.h" #include "VirtualMachinePool.h" #include "VirtualMachineHook.h" + +#include "NebulaLog.h" + #include /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -VirtualMachinePool::VirtualMachinePool(SqliteDB * db, +VirtualMachinePool::VirtualMachinePool(SqlDB * db, vector hook_mads) : PoolSQL(db,VirtualMachine::table) { @@ -55,7 +57,7 @@ VirtualMachinePool::VirtualMachinePool(SqliteDB * db, oss << "Empty ON or COMMAND attribute in VM_HOOK. Hook " << "not registered!"; - Nebula::log("VM",Log::WARNING,oss); + NebulaLog::log("VM",Log::WARNING,oss); continue; } @@ -130,7 +132,7 @@ VirtualMachinePool::VirtualMachinePool(SqliteDB * db, ostringstream oss; oss << "Unkown VM_HOOK " << on << ". Hook not registered!"; - Nebula::log("VM",Log::WARNING,oss); + NebulaLog::log("VM",Log::WARNING,oss); } } @@ -187,9 +189,11 @@ int VirtualMachinePool::allocate ( ostringstream oss; oss << error_msg; - Nebula::log("ONE", Log::ERROR, oss); + NebulaLog::log("ONE", Log::ERROR, oss); free(error_msg); + delete vm; + return -2; } @@ -199,7 +203,7 @@ int VirtualMachinePool::allocate ( // ------------------------------------------------------------------------ // Insert the Object in the pool // ------------------------------------------------------------------------ - + *oid = PoolSQL::allocate(vm); if ( *oid == -1 ) @@ -210,7 +214,7 @@ int VirtualMachinePool::allocate ( // ------------------------------------------------------------------------ // Insert parsed context in the VM template and clean-up // ------------------------------------------------------------------------ - + if ((num_attr = (int) attrs.size()) > 0) { generate_context(*oid,attrs[0]); @@ -224,7 +228,7 @@ int VirtualMachinePool::allocate ( } } - return 0; + return *oid; } /* -------------------------------------------------------------------------- */ @@ -236,9 +240,9 @@ int VirtualMachinePool::get_running( ostringstream os; string where; - os << "state == " << VirtualMachine::ACTIVE - << " and ( lcm_state == " << VirtualMachine::RUNNING - << " or lcm_state == " << VirtualMachine::UNKNOWN << " )"; + os << "state = " << VirtualMachine::ACTIVE + << " and ( lcm_state = " << VirtualMachine::RUNNING + << " or lcm_state = " << VirtualMachine::UNKNOWN << " )"; where = os.str(); @@ -254,7 +258,7 @@ int VirtualMachinePool::get_pending( ostringstream os; string where; - os << "state == " << VirtualMachine::PENDING; + os << "state = " << VirtualMachine::PENDING; where = os.str(); @@ -302,7 +306,7 @@ void VirtualMachinePool::generate_context(int vm_id, Attribute * attr) oss << error_msg << ": " << *str; free(error_msg); - Nebula::log("ONE", Log::ERROR, oss); + NebulaLog::log("ONE", Log::ERROR, oss); } delete str; @@ -331,4 +335,52 @@ void VirtualMachinePool::generate_context(int vm_id, Attribute * attr) vm->unlock(); } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +int VirtualMachinePool::dump_cb(void * _oss,int num,char **values,char **names) +{ + ostringstream * oss; + + oss = static_cast(_oss); + + return VirtualMachine::dump(*oss, num, values, names); +} + +/* -------------------------------------------------------------------------- */ + +int VirtualMachinePool::dump(ostringstream& oss, const string& where) +{ + int rc; + ostringstream cmd; + + oss << ""; + + set_callback( + static_cast(&VirtualMachinePool::dump_cb), + static_cast(&oss)); + + cmd << "SELECT " << VirtualMachine::table << ".*, " + << "user_pool.user_name, " << History::table << ".* FROM " + << VirtualMachine::table + << " LEFT OUTER JOIN (" + << "SELECT *,seq AS max_seq FROM " << History::table << " h1 WHERE " + << "seq=(SELECT MAX(seq) FROM " << History::table << " h2 WHERE h1.vid=h2.vid)) " + << "AS " << History::table + << " ON " << VirtualMachine::table << ".oid = " + << History::table << ".vid LEFT OUTER JOIN (SELECT oid,user_name FROM " + << "user_pool) AS user_pool ON " + << VirtualMachine::table << ".uid = user_pool.oid WHERE " + << VirtualMachine::table << ".state <> " << VirtualMachine::DONE; + + if ( !where.empty() ) + { + cmd << " AND " << where; + } + + rc = db->exec(cmd,this); + + oss << ""; + + return rc; +} diff --git a/src/vm/VirtualMachineTemplate.cc b/src/vm/VirtualMachineTemplate.cc index 1c8375a95b..1612f03afb 100644 --- a/src/vm/VirtualMachineTemplate.cc +++ b/src/vm/VirtualMachineTemplate.cc @@ -18,6 +18,6 @@ const char * VirtualMachineTemplate::table = "vm_attributes"; -const char * VirtualMachineTemplate::db_bootstrap = "CREATE TABLE vm_attributes" - " (id INTEGER, name TEXT, type INTEGER, value TEXT)"; +const char * VirtualMachineTemplate::db_bootstrap = "CREATE TABLE IF NOT EXISTS" + " vm_attributes (id INTEGER, name TEXT, type INTEGER, value TEXT)"; diff --git a/src/vm/test/SConstruct b/src/vm/test/SConstruct new file mode 100644 index 0000000000..8f4943e4a6 --- /dev/null +++ b/src/vm/test/SConstruct @@ -0,0 +1,100 @@ +# -------------------------------------------------------------------------- +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# -------------------------------------------------------------------------- + +import os +import sys +import shutil +sys.path.append("../../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located +cwd="../../../" + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) + +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include', + cwd + '/include/test', + '/usr/include/cppunit/', +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd + '/src/common', + cwd + '/src/log', + cwd + '/src/nebula', + cwd + '/src/sql', + cwd + '/src/pool', + cwd + '/src/template', + cwd + '/src/vm', + cwd + '/src/hm', + cwd + '/src/mad', + cwd + '/src/vnm', + cwd + '/src/um', + '/usr/include/openssl/', +]) + +main_env.Append(LIBS=[ + 'nebula_um', + 'nebula_vm', + 'nebula_mad', + 'nebula_hm', + 'nebula_vnm', + 'nebula_template', + 'nebula_pool', + 'nebula_common', + 'nebula_log', + 'nebula_core', + 'nebula_sql', + 'cppunit', + 'dl', + 'pthread', + 'crypto', +]) + +# MYSQL +main_env.Append(LIBPATH=["/usr/lib/mysql"]) +main_env.Append(CPPPATH=["/usr/include/mysql"]) + +sqlite=ARGUMENTS.get('sqlite', 'yes') +if sqlite=='yes': + main_env.Append(CPPFLAGS=["-DSQLITE_DB"]) + main_env.Append(LIBS=[ 'sqlite3', ]) + +# MySQL +mysql=ARGUMENTS.get('mysql', 'no') +if mysql=='yes': + main_env.Append(CPPFLAGS=["-DMYSQL_DB"]) + main_env.Append(LIBS=[ 'mysqlclient', ]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# Linking flags +main_env.Append(LDFLAGS=["-g "]) + +main_env.Program('test','VirtualMachinePoolTest.cc') + diff --git a/src/vm/test/VirtualMachinePoolTest.cc b/src/vm/test/VirtualMachinePoolTest.cc new file mode 100644 index 0000000000..f575b70fe6 --- /dev/null +++ b/src/vm/test/VirtualMachinePoolTest.cc @@ -0,0 +1,454 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include +#include + +#include "VirtualMachinePool.h" +#include "PoolTest.h" + +using namespace std; + +const int uids[] = {123, 261, 123}; + +const string names[] = {"VM one", "Second VM", "VM one"}; + +const string templates[] = +{ + "NAME = \"VM one\"\n" + "MEMORY = 128\n" + "CPU = 1", + + "NAME = \"Second VM\"\n" + "MEMORY = 256\n" + "CPU = 2", + + "NAME = \"VM one\"\n" + "MEMORY = 1024\n" + "CPU = 1" +}; + + +const string xmls[] = +{ + "0123VM one010000000000000000", + + "1261Second VM0" + "1000000000000<" + "/ETIME>0000", + + "0123VM one010000000000000000" +}; + + +// This xml dump result has the STIMEs modified to 0000000000 +const string xml_dump = + "01A userVM one" + "01000000000000000012B userSecond VM0200000000000" + "00000"; + +const string xml_dump_where = + "01A userVM one" + "010000000000000000"; + +const string xml_history_dump = + "00one_user_test" + "VM one01" + "000000000000" + "000" + "010" + "one_user_testSecond VM0" + "200000000000" + "000" + "000" + "A_hostname000" + "0000" + "0002" + "0one_user_testVM one" + "020" + "000000000000" + "0001" + "C_hostname200" + "0000" + "000" + ""; + +const string replacement = "0000000000"; + + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class VirtualMachinePoolTest : public PoolTest +{ + CPPUNIT_TEST_SUITE (VirtualMachinePoolTest); + + // Not all PoolTest tests can be used. Drop method isn't defined for + // the VirtualMachinePool. + CPPUNIT_TEST (oid_assignment); + CPPUNIT_TEST (get_from_cache); + CPPUNIT_TEST (get_from_db); + CPPUNIT_TEST (wrong_get); + + CPPUNIT_TEST (update); + CPPUNIT_TEST (dump); + CPPUNIT_TEST (dump_where); + CPPUNIT_TEST (dump_history); + CPPUNIT_TEST (history); + + CPPUNIT_TEST_SUITE_END (); + +protected: + + void bootstrap(SqlDB* db) + { + VirtualMachinePool::bootstrap(db); + }; + + PoolSQL* create_pool(SqlDB* db) + { + // The VM pool needs a vector containing the vm hooks + vector vm_hooks; + return new VirtualMachinePool(db, vm_hooks); + }; + + int allocate(int index) + { + int oid; + return ((VirtualMachinePool*)pool)->allocate(uids[index], + templates[index], + &oid, false); + }; + + void check(int index, PoolObjectSQL* obj) + { + CPPUNIT_ASSERT( obj != 0 ); + + string xml_str = ""; + + // Get the xml and replace the STIME to 0, so we can compare it + ((VirtualMachine*)obj)->to_xml(xml_str); + xml_str.replace( xml_str.find("")+7, 10, replacement); + + CPPUNIT_ASSERT( ((VirtualMachine*)obj)->get_name() == names[index] ); + CPPUNIT_ASSERT( xml_str == xmls[index]); + }; + + void set_up_user_pool() + { + + // The UserPool constructor checks if the DB contains at least + // one user, and adds one automatically from the ONE_AUTH file. + // So the ONE_AUTH environment is forced to point to a test one_auth + // file. + ostringstream oss; + + oss << getenv("PWD") << "/one_auth"; + setenv("ONE_AUTH", oss.str().c_str(), 1); + + UserPool::bootstrap(db); + UserPool * user_pool = new UserPool(db); + int uid_1, uid_2; + + string username_1 = "A user"; + string username_2 = "B user"; + + string pass_1 = "A pass"; + string pass_2 = "B pass"; + + user_pool->allocate(&uid_1, username_1, pass_1, true); + user_pool->allocate(&uid_2, username_2, pass_2, true); + + delete user_pool; + }; + +public: + VirtualMachinePoolTest(){}; + + ~VirtualMachinePoolTest(){}; + + + /* ********************************************************************* */ + /* ********************************************************************* */ + + void update() + { + VirtualMachinePool * vmp = static_cast(pool); + VirtualMachine * vm; + int oid; + + string hostname = "hostname"; + string vm_dir = "vm_dir"; + string vmm_mad = "vm_mad"; + string tm_mad = "tm_mad"; + + // Allocate two VMs + oid = allocate(0); + CPPUNIT_ASSERT( oid != -1 ); + + // Get the first one, and change one of the templates attributes + vm = vmp->get(oid, true); + + CPPUNIT_ASSERT( vm != 0 ); + + string attribute = "MEMORY"; + string value = "1024"; + + vm->set_state(VirtualMachine::ACTIVE); + + // VirtualMachine object should be cached. Let's update the DB + vmp->update_template_attribute(vm, attribute, value); + + vmp->update(vm); + + //In memory (cache) check + string new_mem; + + vm->get_template_attribute("MEMORY",new_mem); + + CPPUNIT_ASSERT( new_mem == "1024" ); + CPPUNIT_ASSERT( vm->get_state() == VirtualMachine::ACTIVE ); + + vm->unlock(); + + //Now force access to DB + + pool->clean(); + vm = vmp->get(oid,false); + + new_mem.clear(); + + vm->get_template_attribute("MEMORY",new_mem); + + CPPUNIT_ASSERT( new_mem == "1024" ); + CPPUNIT_ASSERT( vm->get_state() == VirtualMachine::ACTIVE ); + }; + + void dump() + { + VirtualMachinePool * vmp = static_cast(pool); + + set_up_user_pool(); + + ostringstream oss; + int oid, rc; + + vmp->allocate(1, templates[0], &oid, false); + vmp->allocate(2, templates[1], &oid, true); + + rc = vmp->dump(oss, ""); + CPPUNIT_ASSERT(rc == 0); + + string result = oss.str(); + result.replace(152, 10, replacement); + result.replace(426, 10, replacement); + + CPPUNIT_ASSERT( result == xml_dump ); + } + + void dump_where() + { + VirtualMachinePool * vmp = static_cast(pool); + + set_up_user_pool(); + + int oid, rc; + ostringstream oss; + ostringstream where; + + vmp->allocate(1, templates[0], &oid, false); + vmp->allocate(2, templates[1], &oid, true); + + where << "uid < 2"; + rc = vmp->dump(oss, where.str()); + CPPUNIT_ASSERT(rc == 0); + + string result = oss.str(); + result.replace(152, 10, replacement); + CPPUNIT_ASSERT( result == xml_dump_where ); + } + + void dump_history() + { + VirtualMachinePool * vmp = static_cast(pool); + VirtualMachine* vm; + + string hostnames[] = {"A_hostname", "B_hostname", "C_hostname"}; + string vm_dirs[] = {"A_vm_dir", "B_vm_dir", "C_vm_dir"}; + string vmm_mads[] = {"A_vmm_mad", "B_vmm_mad", "C_vmm_mad"}; + string tm_mads[] = {"A_tm_mad", "B_tm_mad", "C_tm_mad"}; + + int oid, rc; + ostringstream oss; + ostringstream where; + + + set_up_user_pool(); + + // Allocate a VM + rc = vmp->allocate(0, templates[0], &oid, false); + CPPUNIT_ASSERT( rc == oid ); + CPPUNIT_ASSERT( oid >= 0 ); + //---------------------------------------------------------------------- + + // Allocate a VM with one history item + rc = vmp->allocate(0, templates[1], &oid, true); + CPPUNIT_ASSERT( rc == oid ); + CPPUNIT_ASSERT( oid >= 0 ); + + vm = vmp->get(oid, false); + CPPUNIT_ASSERT( vm != 0 ); + + // Add a history item + vm->add_history(0, hostnames[0], vm_dirs[0], vmm_mads[0], tm_mads[0]); + + rc = vmp->update_history(vm); + CPPUNIT_ASSERT( rc == 0 ); + //---------------------------------------------------------------------- + + // Allocate a VM with two history items + rc = vmp->allocate(0, templates[2], &oid, true); + CPPUNIT_ASSERT( rc == oid ); + CPPUNIT_ASSERT( oid >= 0 ); + + vm = vmp->get(oid, false); + CPPUNIT_ASSERT( vm != 0 ); + + // Add a history item + vm->add_history(1, hostnames[1], vm_dirs[1], vmm_mads[1], tm_mads[1]); + rc = vmp->update_history(vm); + CPPUNIT_ASSERT( rc == 0 ); + + // Add another history item + vm->add_history(2, hostnames[2], vm_dirs[2], vmm_mads[2], tm_mads[2]); + rc = vmp->update_history(vm); + CPPUNIT_ASSERT( rc == 0 ); + //---------------------------------------------------------------------- + + // Allocate a VM, will be set to DONE + rc = vmp->allocate(1, templates[0], &oid, false); + CPPUNIT_ASSERT( rc == oid ); + CPPUNIT_ASSERT( oid >= 0 ); + + vm = vmp->get(oid, false); + CPPUNIT_ASSERT( vm != 0 ); + + vm->set_state(VirtualMachine::DONE); + vmp->update(vm); + //---------------------------------------------------------------------- + + // Call dump. Should return: + // the first VM, with no history. + // the second VM, with the first and only history item + // the third VM, with only its last history item + + where << "uid < 2"; + rc = vmp->dump(oss, where.str()); + CPPUNIT_ASSERT(rc == 0); + + // Get the xml and replace the STIME to 0, so we can compare it + string result = oss.str(); + + result.replace(159, 10, replacement); + result.replace(440, 10, replacement); + result.replace(950, 10, replacement); + + CPPUNIT_ASSERT( result == xml_history_dump ); + } + + void history() + { + VirtualMachine * vm; + VirtualMachinePool * vmp = static_cast(pool); + + int rc, oid; + + string hostname = "hostname"; + string new_hostname = "new_hostname"; + string vm_dir = "vm_dir"; + string vmm_mad = "vm_mad"; + string tm_mad = "tm_mad"; + + // Allocate a VM + oid = allocate(0); + CPPUNIT_ASSERT( oid != -1 ); + + vm = vmp->get(oid, false); + CPPUNIT_ASSERT( vm != 0 ); + + // Add a history item + vm->add_history(0, hostname, vm_dir, vmm_mad, tm_mad); + + rc = vmp->update_history(vm); + CPPUNIT_ASSERT( rc == 0 ); + + vm->add_history(0, new_hostname, vm_dir, vmm_mad, tm_mad); + + vm->set_reason(History::USER); + vm->set_previous_reason(History::ERROR); + + rc = vmp->update_history(vm); + rc = vmp->update_previous_history(vm); + + CPPUNIT_ASSERT( rc == 0 ); + + // Clean the DB cache + pool->clean(); + + vm = vmp->get(oid, false); + + CPPUNIT_ASSERT( vm != 0 ); + CPPUNIT_ASSERT( vm->hasHistory() == true ); + CPPUNIT_ASSERT( vm->hasPreviousHistory() == true ); + + CPPUNIT_ASSERT( vm->get_hostname() == new_hostname ); + CPPUNIT_ASSERT( vm->get_previous_hostname() == hostname ); + + CPPUNIT_ASSERT( vm->get_vmm_mad() == vmm_mad ); + CPPUNIT_ASSERT( vm->get_previous_vmm_mad() == vmm_mad ); + + CPPUNIT_ASSERT( vm->get_previous_reason() == History::ERROR ); + } +}; + + +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + return PoolTest::main(argc, argv, VirtualMachinePoolTest::suite()); +} diff --git a/src/vm/test/one_auth b/src/vm/test/one_auth new file mode 100644 index 0000000000..2f55c9c47b --- /dev/null +++ b/src/vm/test/one_auth @@ -0,0 +1 @@ +one_user_test:password diff --git a/src/vmm/VirtualMachineManager.cc b/src/vmm/VirtualMachineManager.cc index 9da058cb1c..e28e15b44f 100644 --- a/src/vmm/VirtualMachineManager.cc +++ b/src/vmm/VirtualMachineManager.cc @@ -15,10 +15,13 @@ /* -------------------------------------------------------------------------- */ #include "VirtualMachineManager.h" -#include "Nebula.h" +#include "NebulaLog.h" #include "XenDriver.h" #include "XMLDriver.h" #include "LibVirtDriver.h" + +#include "Nebula.h" + #include /* ************************************************************************** */ @@ -55,11 +58,11 @@ extern "C" void * vmm_action_loop(void *arg) vmm = static_cast(arg); - Nebula::log("VMM",Log::INFO,"Virtual Machine Manager started."); + NebulaLog::log("VMM",Log::INFO,"Virtual Machine Manager started."); vmm->am.loop(vmm->timer_period,0); - Nebula::log("VMM",Log::INFO,"Virtual Machine Manager stopped."); + NebulaLog::log("VMM",Log::INFO,"Virtual Machine Manager stopped."); return 0; } @@ -78,7 +81,7 @@ int VirtualMachineManager::start() return -1; } - Nebula::log("VMM",Log::INFO,"Starting Virtual Machine Manager..."); + NebulaLog::log("VMM",Log::INFO,"Starting Virtual Machine Manager..."); pthread_attr_init (&pattr); pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); @@ -211,7 +214,7 @@ void VirtualMachineManager::do_action(const string &action, void * arg) } else if (action == ACTION_FINALIZE) { - Nebula::log("VMM",Log::INFO,"Stopping Virtual Machine Manager..."); + NebulaLog::log("VMM",Log::INFO,"Stopping Virtual Machine Manager..."); MadManager::stop(); } @@ -220,7 +223,7 @@ void VirtualMachineManager::do_action(const string &action, void * arg) ostringstream oss; oss << "Unknown action name: " << action; - Nebula::log("VMM", Log::ERROR, oss); + NebulaLog::log("VMM", Log::ERROR, oss); } } @@ -810,7 +813,7 @@ void VirtualMachineManager::timer_action() if ( mark >= 600 ) { - Nebula::log("VMM",Log::INFO,"--Mark--"); + NebulaLog::log("VMM",Log::INFO,"--Mark--"); mark = 0; } @@ -831,7 +834,7 @@ void VirtualMachineManager::timer_action() { os.str(""); os << "Monitoring VM " << *it << " but it has no history."; - Nebula::log("VMM", Log::ERROR, os); + NebulaLog::log("VMM", Log::ERROR, os); continue; } @@ -841,7 +844,7 @@ void VirtualMachineManager::timer_action() os.str(""); os << "Monitoring VM " << *it << "."; - Nebula::log("VMM", Log::INFO, os); + NebulaLog::log("VMM", Log::INFO, os); vm->set_last_poll(thetime); @@ -878,7 +881,7 @@ void VirtualMachineManager::load_mads(int uid) oss << "Loading Virtual Machine Manager drivers."; - Nebula::log("VMM",Log::INFO,oss); + NebulaLog::log("VMM",Log::INFO,oss); for(i=0,oss.str("");i VirtualMachineManagerDriver::VirtualMachineManagerDriver( @@ -66,7 +68,7 @@ VirtualMachineManagerDriver::VirtualMachineManagerDriver( oss << "Error loading driver configuration file " << cfile; } - Nebula::log("VMM", Log::ERROR, oss); + NebulaLog::log("VMM", Log::ERROR, oss); } } } @@ -238,7 +240,7 @@ void VirtualMachineManagerDriver::protocol( VirtualMachine * vm; os << "Message received: " << message; - Nebula::log("VMM", Log::DEBUG, os); + NebulaLog::log("VMM", Log::DEBUG, os); // Parse the driver message if ( is.good() ) @@ -263,7 +265,7 @@ void VirtualMachineManagerDriver::protocol( is.clear(); getline(is,info); - Nebula::log("VMM",Log::INFO, info.c_str()); + NebulaLog::log("VMM",Log::INFO, info.c_str()); } return; @@ -361,7 +363,7 @@ void VirtualMachineManagerDriver::protocol( } else { - string info; + string info; getline(is,info); @@ -602,6 +604,6 @@ void VirtualMachineManagerDriver::protocol( void VirtualMachineManagerDriver::recover() { - Nebula::log("VMM",Log::INFO,"Recovering VMM drivers"); + NebulaLog::log("VMM",Log::INFO,"Recovering VMM drivers"); } diff --git a/src/vnm/FixedLeases.cc b/src/vnm/FixedLeases.cc index ab3574f1b6..107b5af16b 100644 --- a/src/vnm/FixedLeases.cc +++ b/src/vnm/FixedLeases.cc @@ -16,33 +16,33 @@ #include "FixedLeases.h" -#include "Nebula.h" +#include "NebulaLog.h" FixedLeases::FixedLeases( - SqliteDB * db, - int _oid, - unsigned int _mac_prefix, - vector& vector_leases): - Leases(db,_oid,0),mac_prefix(_mac_prefix),current(leases.begin()) -{ + SqlDB * db, + int _oid, + unsigned int _mac_prefix, + vector& vector_leases): + Leases(db,_oid,0),mac_prefix(_mac_prefix),current(leases.begin()) +{ const VectorAttribute * single_attr_lease; string _mac; string _ip; - + size = vector_leases.size(); - + for (unsigned long i=0; i < size ;i++) { - single_attr_lease = dynamic_cast - (vector_leases[i]); - + single_attr_lease = dynamic_cast + (vector_leases[i]); + if( single_attr_lease ) { _ip = single_attr_lease->vector_value("IP"); _mac = single_attr_lease->vector_value("MAC"); - - add(_ip,_mac,-1,false); - } + + add(_ip,_mac,-1,false); + } } } @@ -54,25 +54,25 @@ int FixedLeases::add(const string& ip, const string& mac, int vid, bool used) ostringstream oss; unsigned int _ip; unsigned int _mac [2]; - + int rc; - + if ( Leases::Lease::ip_to_number(ip,_ip) ) { - goto error_ip; + goto error_ip; } - + if (mac.empty()) { - _mac[Lease::PREFIX] = mac_prefix; - _mac[Lease::SUFFIX] = _ip; + _mac[Lease::PREFIX] = mac_prefix; + _mac[Lease::SUFFIX] = _ip; } else if (Leases::Lease::mac_to_number(mac,_mac)) { - goto error_mac; + goto error_mac; } - - oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES (" << + + oss << "INSERT INTO " << table << " "<< db_names <<" VALUES (" << oid << "," << _ip << "," << _mac[Lease::PREFIX] << "," << @@ -81,25 +81,25 @@ int FixedLeases::add(const string& ip, const string& mac, int vid, bool used) used << ")"; rc = db->exec(oss); - + if ( rc == 0 ) { - leases.insert(make_pair(_ip,new Lease(_ip,_mac,vid,used))); + leases.insert(make_pair(_ip,new Lease(_ip,_mac,vid,used))); } - + return rc; error_mac: oss.str(""); oss << "Error inserting lease, MAC = " << mac; goto error_common; - + error_ip: oss.str(""); oss << "Error inserting lease, IP = " << ip; error_common: - Nebula::log("VNM", Log::ERROR, oss); + NebulaLog::log("VNM", Log::ERROR, oss); return -1; } @@ -108,33 +108,33 @@ error_common: int FixedLeases::del(const string& ip) { - unsigned int _ip; + unsigned int _ip; ostringstream oss; - + map::iterator it_ip; - + // Remove lease from leases map - + if ( Leases::Lease::ip_to_number(ip,_ip) ) { - return 0; //Wrong format, not leased + return 0; //Wrong format, not leased } - + it_ip = leases.find(_ip); - + if (it_ip == leases.end()) { - return 0; //Not in the map, not leased + return 0; //Not in the map, not leased } // Flip used flag to false - + it_ip->second->used = false; it_ip->second->vid = -1; - - oss << "UPDATE " << table << " SET used='0', vid='-1' " - << " WHERE ip='" << _ip <<"'"; - + + oss << "UPDATE " << table << " SET used='0', vid='-1' " + << " WHERE oid=" << oid << " AND ip='" << _ip <<"'"; + return db->exec(oss); } @@ -142,45 +142,46 @@ int FixedLeases::del(const string& ip) /* -------------------------------------------------------------------------- */ int FixedLeases::get(int vid, string& ip, string& mac) -{ - int rc = -1; - - if (leases.empty()) - { - return -1; - } - - for(unsigned int i=0 ;isecond->used == false) - { - ostringstream oss; - - oss << "UPDATE " << table << " SET used='1', vid='" << vid - << "' WHERE ip='" << current->second->ip <<"'"; + if (leases.empty()) + { + return -1; + } - rc = db->exec(oss); - - if ( rc == 0 ) - { - current->second->used = true; - current->second->vid = vid; - - current->second->to_string(ip,mac); - - current++; - } - - break; - } - } - - return rc; + for(unsigned int i=0 ;isecond->used == false) + { + ostringstream oss; + + oss << "UPDATE " << table << " SET used='1', vid='" << vid + << "' WHERE oid=" << oid + << " AND ip='" << current->second->ip <<"'"; + + rc = db->exec(oss); + + if ( rc == 0 ) + { + current->second->used = true; + current->second->vid = vid; + + current->second->to_string(ip,mac); + + current++; + } + + break; + } + } + + return rc; } /* -------------------------------------------------------------------------- */ @@ -188,45 +189,45 @@ int FixedLeases::get(int vid, string& ip, string& mac) int FixedLeases::set(int vid, const string& ip, string& mac) { - map::iterator it; - - ostringstream oss; - unsigned int num_ip; - int rc; - - rc = Leases::Lease::ip_to_number(ip,num_ip); - - if (rc != 0) - { - return -1; - } - + map::iterator it; + + ostringstream oss; + unsigned int num_ip; + int rc; + + rc = Leases::Lease::ip_to_number(ip,num_ip); + + if (rc != 0) + { + return -1; + } + it=leases.find(num_ip); - if (it == leases.end()) //it does not exists in the net + if (it == leases.end()) //it does not exist in the net { - return -1; + return -1; } else if (it->second->used) //it is in use { - return -1; + return -1; } - - oss << "UPDATE " << table << " SET used='1', vid='" << vid - << "' WHERE ip='" << it->second->ip <<"'"; + + oss << "UPDATE " << table << " SET used='1', vid='" << vid << "'" + << " WHERE oid=" << oid << " AND ip='" << it->second->ip <<"'"; rc = db->exec(oss); - + if ( rc != 0 ) { - return -1; + return -1; } it->second->used = true; it->second->vid = vid; - + Leases::Lease::mac_to_string(it->second->mac,mac); - + return 0; } diff --git a/src/vnm/Leases.cc b/src/vnm/Leases.cc index a74c1e0025..d2478b3ecf 100644 --- a/src/vnm/Leases.cc +++ b/src/vnm/Leases.cc @@ -16,7 +16,7 @@ #include "Leases.h" -#include "Nebula.h" +#include "NebulaLog.h" /* ************************************************************************** */ /* ************************************************************************** */ @@ -187,31 +187,31 @@ ostream& operator<<(ostream& os, Leases::Lease& _lease) string xml; os << _lease.to_xml(xml); - + return os; } string& Leases::Lease::to_str(string& str) const { - string ip; - string mac; - + string ip; + string mac; + ostringstream os; to_string(ip,mac); - + ip = "IP = " + ip; mac = "MAC = " + mac; - + os.width(20); os << left << ip; - + os.width(24); os << left << mac; - - os << left << " USED = " << used; + + os << left << " USED = " << used; os << left << " VID = " << vid; - + str = os.str(); return str; @@ -220,14 +220,14 @@ string& Leases::Lease::to_str(string& str) const string& Leases::Lease::to_xml(string& str) const { - string ip; - string mac; - + string ip; + string mac; + ostringstream os; to_string(ip,mac); - - os << + + os << "" << ""<< ip << "" << "" << mac << "" << @@ -250,14 +250,14 @@ const char * Leases::table = "leases"; const char * Leases::db_names = "(oid,ip,mac_prefix,mac_suffix,vid,used)"; -const char * Leases::db_bootstrap = "CREATE TABLE leases (" - "oid INTEGER,ip INTEGER, mac_prefix INTEGER,mac_suffix INTEGER," +const char * Leases::db_bootstrap = "CREATE TABLE IF NOT EXISTS leases (" + "oid INTEGER,ip BIGINT, mac_prefix INTEGER,mac_suffix INTEGER," "vid INTEGER, used INTEGER, PRIMARY KEY(oid,ip))"; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int Leases::unmarshall(int num, char **names, char ** values) +int Leases::select_cb(void *nil, int num, char **values, char **names) { if ( (values[OID] == 0) || (values[IP] == 0) || @@ -274,65 +274,45 @@ int Leases::unmarshall(int num, char **names, char ** values) unsigned int ip; int vid; bool used; - + istringstream iss; - + iss.str(values[IP]); iss >> ip; - + iss.clear(); iss.str(values[MAC_PREFIX]); iss >> mac[Lease::PREFIX]; - + iss.clear(); iss.str(values[MAC_SUFFIX]); iss >> mac[Lease::SUFFIX]; - + iss.clear(); iss.str(values[VID]); iss >> vid; - + iss.clear(); iss.str(values[USED]); iss >> used; leases.insert(make_pair(ip,new Lease(ip,mac,vid,used))); - + return 0; } -/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -extern "C" int leases_select_cb ( - void * _leases, - int num, - char ** values, - char ** names) -{ - Leases * leases; - - leases = static_cast(_leases); - - if (leases == 0) - { - return -1; - } - - return leases->unmarshall(num,names,values); -}; - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int Leases::select(SqliteDB * db) +int Leases::select(SqlDB * db) { ostringstream oss; int rc; + set_callback(static_cast(&Leases::select_cb)); + oss << "SELECT * FROM " << table << " WHERE oid = " << oid; - rc = db->exec(oss,leases_select_cb,(void *) this); + rc = db->exec(oss,this); if (rc != 0) { @@ -342,21 +322,21 @@ int Leases::select(SqliteDB * db) return 0; error_id: - oss.str(""); + oss.str(""); oss << "Error getting leases for network nid: " << oid; - - Nebula::log("VNM", Log::ERROR, oss); + + NebulaLog::log("VNM", Log::ERROR, oss); return -1; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int Leases::drop(SqliteDB * db) +int Leases::drop(SqlDB * db) { ostringstream oss; - - // Drop all the leases + + // Drop all the leases oss << "DELETE FROM " << table << " WHERE oid=" << oid; return db->exec(oss); @@ -365,18 +345,18 @@ int Leases::drop(SqliteDB * db) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int Leases::insert(SqliteDB * db) +int Leases::insert(SqlDB * db) { - Nebula::log("VNM", Log::ERROR, "Should not access to Leases.insert()"); + NebulaLog::log("VNM", Log::ERROR, "Should not access to Leases.insert()"); return -1; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int Leases::update(SqliteDB * db) +int Leases::update(SqlDB * db) { - Nebula::log("VNM", Log::ERROR, "Should not access to Leases.update()"); + NebulaLog::log("VNM", Log::ERROR, "Should not access to Leases.update()"); return -1; } @@ -461,7 +441,7 @@ string& Leases::to_str(string& str) const { os << it->second->to_str(lease_str) << endl; } - + str = os.str(); return str; diff --git a/src/vnm/RangedLeases.cc b/src/vnm/RangedLeases.cc index ac19d3fe99..0e2a49ce18 100644 --- a/src/vnm/RangedLeases.cc +++ b/src/vnm/RangedLeases.cc @@ -24,7 +24,7 @@ /* ************************************************************************** */ RangedLeases::RangedLeases( - SqliteDB * db, + SqlDB * db, int _oid, unsigned long _size, unsigned int _mac_prefix, @@ -32,12 +32,12 @@ RangedLeases::RangedLeases( Leases(db,_oid,_size),mac_prefix(_mac_prefix),current(0) { unsigned int net_addr; - + Leases::Lease::ip_to_number(_network_address,net_addr); - + //size is the number of hosts in the network size = _size + 2; - + network_address = 0xFFFFFFFF << (int) ceil(log(size)/log(2)); network_address &= net_addr; @@ -49,33 +49,33 @@ RangedLeases::RangedLeases( int RangedLeases::get(int vid, string& ip, string& mac) { - unsigned int num_ip; - int rc = -1; - - for (unsigned int i=0; iexec(oss); - + if ( rc == 0 ) { leases.insert(make_pair(ip,new Lease(ip,mac,vid,used))); @@ -161,7 +161,7 @@ int RangedLeases::del(const string& ip) { unsigned int _ip; ostringstream oss; - int rc; + int rc; map::iterator it_ip; // Remove lease from leases map diff --git a/src/vnm/VirtualNetwork.cc b/src/vnm/VirtualNetwork.cc index 5c38882290..9b9efeb734 100644 --- a/src/vnm/VirtualNetwork.cc +++ b/src/vnm/VirtualNetwork.cc @@ -16,7 +16,7 @@ #include "VirtualNetwork.h" -#include "Nebula.h" +#include "NebulaLog.h" #include "RangedLeases.h" #include "FixedLeases.h" @@ -24,7 +24,7 @@ /* Virtual Network :: Constructor/Destructor */ /* ************************************************************************** */ -VirtualNetwork::VirtualNetwork(unsigned int mp, int ds): +VirtualNetwork::VirtualNetwork(unsigned int mp, int ds): PoolObjectSQL(-1), name(""), uid(-1), @@ -32,19 +32,17 @@ VirtualNetwork::VirtualNetwork(unsigned int mp, int ds): type(UNINITIALIZED), leases(0), mac_prefix(mp), - default_size(ds) -{ -} + default_size(ds){}; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ VirtualNetwork::~VirtualNetwork() -{ +{ if (leases != 0) { delete leases; - } + } } /* ************************************************************************** */ @@ -55,19 +53,21 @@ const char * VirtualNetwork::table = "network_pool"; const char * VirtualNetwork::db_names = "(oid,uid,name,type,bridge)"; -const char * VirtualNetwork::db_bootstrap = "CREATE TABLE network_pool (" - "oid INTEGER,uid INTEGER, name TEXT PRIMARY KEY,type INTEGER, bridge TEXT)"; +const char * VirtualNetwork::db_bootstrap = "CREATE TABLE IF NOT EXISTS" + " network_pool (" + "oid INTEGER PRIMARY KEY, uid INTEGER, name VARCHAR(256), type INTEGER, " + "bridge TEXT, UNIQUE(name))"; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualNetwork::unmarshall(int num, char **names, char ** values) +int VirtualNetwork::select_cb(void * nil, int num, char **values, char **names) { if ((!values[OID]) || (!values[UID]) || (!values[NAME]) || (!values[TYPE]) || - (!values[BRIDGE]) || + (!values[BRIDGE]) || (num != LIMIT )) { return -1; @@ -75,14 +75,14 @@ int VirtualNetwork::unmarshall(int num, char **names, char ** values) oid = atoi(values[OID]); uid = atoi(values[UID]); - + name = values[NAME]; - + type = (NetworkType)atoi(values[TYPE]); - + bridge = values[BRIDGE]; - - // Virtual Network template ID is the Network ID + + // Virtual Network template ID is the Network ID vn_template.id = oid; return 0; @@ -91,48 +91,31 @@ int VirtualNetwork::unmarshall(int num, char **names, char ** values) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -extern "C" int vn_select_cb ( - void * _vn, - int num, - char ** values, - char ** names) -{ - VirtualNetwork * vn; - - vn = static_cast(_vn); - - if (vn == 0) - { - return -1; - } - - return vn->unmarshall(num,names,values); -}; - -/* -------------------------------------------------------------------------- */ - -int VirtualNetwork::select(SqliteDB * db) +int VirtualNetwork::select(SqlDB * db) { ostringstream oss; ostringstream ose; - + int rc; int boid; string network_address; - + + set_callback( + static_cast(&VirtualNetwork::select_cb)); + oss << "SELECT * FROM " << table << " WHERE oid = " << oid; boid = oid; oid = -1; - rc = db->exec(oss,vn_select_cb,(void *) this); + rc = db->exec(oss, this); if ((rc != 0) || (oid != boid )) { goto error_id; } - + //Get the template rc = vn_template.select(db); @@ -144,99 +127,99 @@ int VirtualNetwork::select(SqliteDB * db) //Get the leases if (type == RANGED) { - string nclass = ""; - int size = 0; - + string nclass = ""; + int size = 0; + // retrieve specific information from template get_template_attribute("NETWORK_ADDRESS",network_address); - + if (network_address.empty()) { - goto error_addr; + goto error_addr; } - + get_template_attribute("NETWORK_SIZE",nclass); - - if ( nclass == "B" ) + + if ( nclass == "B" || nclass == "b" ) { - size = 65534; + size = 65534; } - else if ( nclass == "C" ) + else if ( nclass == "C" || nclass == "c" ) { - size = 254; + size = 254; } else if (!nclass.empty()) //Assume its a number { - istringstream iss(nclass); - iss >> size; + istringstream iss(nclass); + iss >> size; } - + if (size == 0) { - size = default_size; + size = default_size; } - - leases = new RangedLeases::RangedLeases(db, - oid, - size, - mac_prefix, - network_address); + + leases = new RangedLeases(db, + oid, + size, + mac_prefix, + network_address); } else if(type == FIXED) { - leases = new FixedLeases(db, + leases = new FixedLeases(db, oid, - mac_prefix); + mac_prefix); } else { - goto error_type; + goto error_type; } - + if (leases == 0) { goto error_leases; } - + return leases->select(db); error_id: ose << "Error getting Virtual Network nid: " << oid; - goto error_common; + goto error_common; error_template: ose << "Can not get template for Virtual Network nid: " << oid; - goto error_common; - + goto error_common; + error_leases: ose << "Error getting Virtual Network leases nid: " << oid; - goto error_common; + goto error_common; error_type: - ose << "Wrong type of Virtual Network: " << type; + ose << "Wrong type of Virtual Network: " << type; goto error_common; - + error_addr: - ose << "Network address is not defined nid: " << oid; - + ose << "Network address is not defined nid: " << oid; + error_common: - Nebula::log("VNM", Log::ERROR, ose); - return -1; + NebulaLog::log("VNM", Log::ERROR, ose); + return -1; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualNetwork::unmarshall(ostringstream& oss, - int num, - char ** names, - char ** values) +int VirtualNetwork::dump(ostringstream& oss, + int num, + char ** values, + char ** names) { if ((!values[OID]) || (!values[UID]) || (!values[NAME]) || (!values[TYPE]) || - (!values[BRIDGE])|| + (!values[BRIDGE])|| (!values[LIMIT]) || (num != LIMIT + 2 )) { @@ -258,69 +241,20 @@ int VirtualNetwork::unmarshall(ostringstream& oss, } /* -------------------------------------------------------------------------- */ - -extern "C" int vn_dump_cb ( - void * _oss, - int num, - char ** values, - char ** names) -{ - ostringstream * oss; - - oss = static_cast(_oss); - - if (oss == 0) - { - return -1; - } - - return VirtualNetwork::unmarshall(*oss,num,names,values); -}; - /* -------------------------------------------------------------------------- */ -int VirtualNetwork::dump(SqliteDB * db, ostringstream& oss, const string& where) -{ - int rc; - ostringstream cmd; - - cmd << "SELECT " << VirtualNetwork::table << ".*,COUNT(" - << Leases::table << ".used), user_pool.user_name FROM " - << VirtualNetwork::table - << " LEFT OUTER JOIN " << Leases::table << " ON " - << VirtualNetwork::table << ".oid = " << Leases::table << ".oid" - << " AND " << Leases::table << ".used = 1" - << " LEFT OUTER JOIN (SELECT oid,user_name FROM user_pool) " - << " AS user_pool ON "<< VirtualNetwork::table << ".uid = user_pool.oid"; - - if ( !where.empty() ) - { - cmd << " WHERE " << where; - } - - cmd << " GROUP BY " << VirtualNetwork::table << ".oid"; - - rc = db->exec(cmd,vn_dump_cb,(void *) &oss); - - return rc; -} - - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -int VirtualNetwork::insert(SqliteDB * db) +int VirtualNetwork::insert(SqlDB * db) { ostringstream ose; int rc; - + if ( vn_template.id == -1 ) { vn_template.id = oid; } // Insert the template first - rc = vn_template.update(db); + rc = vn_template.insert(db); if ( rc != 0 ) { @@ -328,94 +262,94 @@ int VirtualNetwork::insert(SqliteDB * db) } // Insert the Virtual Network - rc = update(db); + rc = insert_replace(db, false); if ( rc != 0 ) { - goto error_update; + goto error_update; } - - //Get the leases - if (type == VirtualNetwork::RANGED) - { - string nclass = ""; - string naddr = ""; - int size = 0; - - // retrieve specific information from template - get_template_attribute("NETWORK_ADDRESS",naddr); - if (naddr.empty()) - { - goto error_addr; - } - - get_template_attribute("NETWORK_SIZE",nclass); - - if ( nclass == "B" ) - { - size = 65534; - } - else if ( nclass == "C" ) - { - size = 254; - } - else if (!nclass.empty())//Assume its a number - { - istringstream iss(nclass); - - iss >> size; - } - - if (size == 0) - { - size = default_size; - } - - leases = new RangedLeases::RangedLeases(db, - oid, - size, - mac_prefix, - naddr); - } - else if(type == VirtualNetwork::FIXED) - { - vector vector_leases; - - get_template_attribute("LEASES",vector_leases); + //Get the leases + if (type == VirtualNetwork::RANGED) + { + string nclass = ""; + string naddr = ""; + int size = 0; - leases = new FixedLeases::FixedLeases(db, - oid, - mac_prefix, - vector_leases); - } - else - { - goto error_type; - } - - if (leases == 0) - { - goto error_null_leases; - } - - return 0; + // retrieve specific information from template + get_template_attribute("NETWORK_ADDRESS",naddr); + + if (naddr.empty()) + { + goto error_addr; + } + + get_template_attribute("NETWORK_SIZE",nclass); + + if ( nclass == "B" || nclass == "b" ) + { + size = 65534; + } + else if ( nclass == "C" || nclass == "c" ) + { + size = 254; + } + else if (!nclass.empty())//Assume its a number + { + istringstream iss(nclass); + + iss >> size; + } + + if (size == 0) + { + size = default_size; + } + + leases = new RangedLeases(db, + oid, + size, + mac_prefix, + naddr); + } + else if(type == VirtualNetwork::FIXED) + { + vector vector_leases; + + get_template_attribute("LEASES",vector_leases); + + leases = new FixedLeases(db, + oid, + mac_prefix, + vector_leases); + } + else + { + goto error_type; + } + + if (leases == 0) + { + goto error_null_leases; + } + + return 0; error_template: - ose << "Can not insert in DB template for Virtual Network id " << oid; + ose << "Can not insert in DB template for Virtual Network id " << oid; goto error_common; error_update: - ose << "Can not update Virtual Network id " << oid; - vn_template.drop(db); - goto error_common; + ose << "Can not update Virtual Network id " << oid; + vn_template.drop(db); + goto error_common; error_type: - ose << "Wrong type of Virtual Network: " << type; + ose << "Wrong type of Virtual Network: " << type; goto error_leases; error_addr: - ose << "Network address is not defined nid: " << oid; + ose << "Network address is not defined nid: " << oid; goto error_leases; error_null_leases: @@ -425,62 +359,88 @@ error_leases: vn_drop(db); error_common: - Nebula::log("VNM", Log::ERROR, ose); + NebulaLog::log("VNM", Log::ERROR, ose); return -1; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualNetwork::update(SqliteDB * db) + +int VirtualNetwork::update(SqlDB * db) +{ + int rc; + + // Update the template first + rc = vn_template.update(db); + + if ( rc == 0 ) + { + rc = insert_replace(db, true); + } + + return rc; +} + +int VirtualNetwork::insert_replace(SqlDB *db, bool replace) { ostringstream oss; int rc; - - char * sql_name = sqlite3_mprintf("%q",name.c_str()); + + char * sql_name = db->escape_str(name.c_str()); if ( sql_name == 0 ) { return -1; } - char * sql_bridge = sqlite3_mprintf("%q",bridge.c_str()); + char * sql_bridge = db->escape_str(bridge.c_str()); if ( sql_bridge == 0 ) { - sqlite3_free(sql_name); + db->free_str(sql_name); return -1; } - oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES ("<< + // Construct the SQL statement to Insert or Replace + if(replace) + { + oss << "REPLACE"; + } + else + { + oss << "INSERT"; + } + + oss << " INTO " << table << " "<< db_names <<" VALUES ("<< oid << "," << uid << "," << "'" << sql_name << "'," << type << "," << "'" << sql_bridge << "')"; - + rc = db->exec(oss); - sqlite3_free(sql_name); - sqlite3_free(sql_bridge); - + db->free_str(sql_name); + db->free_str(sql_bridge); + return rc; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualNetwork::vn_drop(SqliteDB * db) +int VirtualNetwork::vn_drop(SqlDB * db) { ostringstream oss; int rc; - vn_template.drop(db); + vn_template.drop(db); leases->drop(db); oss << "DELETE FROM " << table << " WHERE OID=" << oid; - + rc = db->exec(oss); if ( rc == 0 ) @@ -488,7 +448,7 @@ int VirtualNetwork::vn_drop(SqliteDB * db) set_valid(false); } - return rc; + return rc; } @@ -501,8 +461,8 @@ ostream& operator<<(ostream& os, VirtualNetwork& vn) { string vnet_xml; - os << vn.to_xml(vnet_xml); - + os << vn.to_xml(vnet_xml); + return os; }; @@ -516,7 +476,7 @@ string& VirtualNetwork::to_xml(string& xml) const string template_xml; string leases_xml; - os << + os << "" << "" << oid << "" << "" << uid << "" << @@ -527,7 +487,7 @@ string& VirtualNetwork::to_xml(string& xml) const if (leases) os << leases->to_xml(leases_xml); os << ""; - + xml = os.str(); return xml; @@ -542,7 +502,7 @@ string& VirtualNetwork::to_str(string& str) const string template_str; string leases_str; - + os << "ID : " << oid << endl; os << "UID : " << uid << endl; os << "NAME : " << name << endl; @@ -555,16 +515,16 @@ string& VirtualNetwork::to_str(string& str) const { os << "Fixed" << endl; } - + os << "Bridge : " << bridge << endl << endl; os << "....: Template :...." << vn_template.to_str(template_str) << endl << endl; - + if (leases) { os << "....: Leases :...." << endl << leases->to_str(leases_str) << endl; } - + str = os.str(); return str; @@ -572,4 +532,3 @@ string& VirtualNetwork::to_str(string& str) const /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ - diff --git a/src/vnm/VirtualNetworkPool.cc b/src/vnm/VirtualNetworkPool.cc index f7178386cf..a52e3b6b0e 100644 --- a/src/vnm/VirtualNetworkPool.cc +++ b/src/vnm/VirtualNetworkPool.cc @@ -14,16 +14,19 @@ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ -#include "Nebula.h" #include "VirtualNetworkPool.h" -#include +#include "NebulaLog.h" -VirtualNetworkPool::VirtualNetworkPool(SqliteDB * db, - const string& prefix, - int _default_size): - PoolSQL(db,VirtualNetwork::table), - mac_prefix(0), - default_size(_default_size) +#include +#include + + +VirtualNetworkPool::VirtualNetworkPool(SqlDB * db, + const string& prefix, + int _default_size): + PoolSQL(db,VirtualNetwork::table), + mac_prefix(0), + default_size(_default_size) { istringstream iss; size_t pos = 0; @@ -34,16 +37,17 @@ VirtualNetworkPool::VirtualNetworkPool(SqliteDB * db, while ( (pos = mac.find(':')) != string::npos ) { - mac.replace(pos,1," "); - count++; + mac.replace(pos,1," "); + count++; } if (count != 1) { - Nebula::log("VNM",Log::ERROR,"Wrong MAC prefix format, using default"); - mac_prefix = 1; //"00:01" - - return; + NebulaLog::log("VNM",Log::ERROR, + "Wrong MAC prefix format, using default"); + mac_prefix = 1; //"00:01" + + return; } iss.str(mac); @@ -55,92 +59,92 @@ VirtualNetworkPool::VirtualNetworkPool(SqliteDB * db, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ - + int VirtualNetworkPool::allocate ( int uid, const string& stemplate, int * oid) { - VirtualNetwork * vn; - char * error_msg; + VirtualNetwork * vn; + char * error_msg; int rc; - ostringstream oss; + ostringstream oss; string name; string bridge; - - string str_type; - + + string s_type; + // Build a new Virtual Network object vn = new VirtualNetwork(mac_prefix, default_size); - + vn->uid = uid; - + rc = vn->vn_template.parse(stemplate,&error_msg); - + if ( rc != 0 ) { - oss << error_msg; - Nebula::log("VNM", Log::ERROR, oss); + oss << error_msg; + NebulaLog::log("VNM", Log::ERROR, oss); free(error_msg); - return -1; + delete vn; + + return -2; } - + // Information about the VN needs to be extracted from the template - vn->get_template_attribute("TYPE",str_type); - - if ( str_type == "RANGED") + vn->get_template_attribute("TYPE",s_type); + + transform(s_type.begin(),s_type.end(),s_type.begin(),(int(*)(int))toupper); + + if (s_type == "RANGED") { vn->type = VirtualNetwork::RANGED; } - else + else if ( s_type == "FIXED") { vn->type = VirtualNetwork::FIXED; } + else + { + NebulaLog::log("VNM", Log::ERROR, "Wrong type for VirtualNetwork " + "template"); + delete vn; + + return -3; + } vn->get_template_attribute("NAME",name); vn->name = name; - + vn->get_template_attribute("BRIDGE",bridge); vn->bridge = bridge; - + // Insert the VN in the pool so we have a valid OID *oid = PoolSQL::allocate(vn); - - if ( *oid == -1 ) - { - return -1; - } - - return 0; + + return *oid; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -extern "C" +int VirtualNetworkPool::get_cb(void * _oid, int num, char **values,char **names) { -static int select_name_cb( - void * _value, - int num, - char ** values, - char ** names) -{ - int * oid; - - oid = static_cast(_value); - + int * oid; + + oid = static_cast(_oid); + if ( oid == 0 || values == 0 || values[0] == 0 ) { return -1; } - + *oid = atoi(values[0]); - - return 0; -} + + return 0; } /* -------------------------------------------------------------------------- */ @@ -149,25 +153,29 @@ static int select_name_cb( VirtualNetwork * VirtualNetworkPool::get(const string& name, bool lock) { ostringstream oss; - - int oid; - int rc; - char * sql_name = sqlite3_mprintf("%q",name.c_str()); + int oid = -1; + int rc; + + char * sql_name = db->escape_str(name.c_str()); if ( sql_name == 0 ) { return 0; } - - oss << "SELECT oid FROM " << VirtualNetwork::table << " WHERE name = '" + + set_callback( + static_cast(&VirtualNetworkPool::get_cb), + static_cast(&oid)); + + oss << "SELECT oid FROM " << VirtualNetwork::table << " WHERE name = '" << sql_name << "'"; - - rc = db->exec(oss, select_name_cb, (void *) (&oid)); - sqlite3_free(sql_name); + rc = db->exec(oss, this); - if (rc != 0) + db->free_str(sql_name); + + if (rc != 0 || oid == -1) { return 0; } @@ -178,4 +186,51 @@ VirtualNetwork * VirtualNetworkPool::get(const string& name, bool lock) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +int VirtualNetworkPool::dump_cb(void * _oss, + int num, + char ** values, + char ** names) +{ + ostringstream * oss; + oss = static_cast(_oss); + + return VirtualNetwork::dump(*oss, num, values, names); +} + +/* -------------------------------------------------------------------------- */ + +int VirtualNetworkPool::dump(ostringstream& oss, const string& where) +{ + int rc; + ostringstream cmd; + + oss << ""; + + set_callback( + static_cast(&VirtualNetworkPool::dump_cb), + static_cast(&oss)); + + cmd << "SELECT " << VirtualNetwork::table << ".*,COUNT(" + << Leases::table << ".used), user_pool.user_name FROM " + << VirtualNetwork::table + << " LEFT OUTER JOIN " << Leases::table << " ON " + << VirtualNetwork::table << ".oid = " << Leases::table << ".oid" + << " AND " << Leases::table << ".used = 1" + << " LEFT OUTER JOIN (SELECT oid,user_name FROM user_pool) " + << " AS user_pool ON "<< VirtualNetwork::table + << ".uid = user_pool.oid"; + + if ( !where.empty() ) + { + cmd << " WHERE " << where; + } + + cmd << " GROUP BY " << VirtualNetwork::table << ".oid"; + + rc = db->exec(cmd,this); + + oss << ""; + + return rc; +} \ No newline at end of file diff --git a/src/vnm/VirtualNetworkTemplate.cc b/src/vnm/VirtualNetworkTemplate.cc index 63622f9995..790de8eebf 100644 --- a/src/vnm/VirtualNetworkTemplate.cc +++ b/src/vnm/VirtualNetworkTemplate.cc @@ -18,6 +18,6 @@ const char * VirtualNetworkTemplate::table = "vn_template"; -const char * VirtualNetworkTemplate::db_bootstrap = "CREATE TABLE vn_template" - " (id INTEGER, name TEXT, type INTEGER, value TEXT)"; +const char * VirtualNetworkTemplate::db_bootstrap = "CREATE TABLE IF NOT EXISTS" + " vn_template (id INTEGER, name TEXT, type INTEGER, value TEXT)"; diff --git a/src/vnm/test/SConstruct b/src/vnm/test/SConstruct new file mode 100644 index 0000000000..221228318e --- /dev/null +++ b/src/vnm/test/SConstruct @@ -0,0 +1,93 @@ +# -------------------------------------------------------------------------- +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# -------------------------------------------------------------------------- + +import os +import sys +import shutil +sys.path.append("../../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located +cwd="../../../" + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) + +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include', + cwd + '/include/test', + '/usr/include/cppunit/', +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd + '/src/common', + cwd + '/src/nebula', + cwd + '/src/sql', + cwd + '/src/log', + cwd + '/src/pool', + cwd + '/src/template', + cwd + '/src/um', + cwd + '/src/vnm', +]) + +main_env.Append(LIBS=[ + 'nebula_log', + 'nebula_um', + 'nebula_vnm', + 'nebula_template', + 'nebula_pool', + 'nebula_common', + 'nebula_core', + 'nebula_sql', + 'cppunit', + 'dl', + 'pthread', + 'crypto', +]) + +# MYSQL +main_env.Append(LIBPATH=["/usr/lib/mysql"]) +main_env.Append(CPPPATH=["/usr/include/mysql"]) + +sqlite=ARGUMENTS.get('sqlite', 'yes') +if sqlite=='yes': + main_env.Append(CPPFLAGS=["-DSQLITE_DB"]) + main_env.Append(LIBS=[ 'sqlite3', ]) + +# MySQL +mysql=ARGUMENTS.get('mysql', 'no') +if mysql=='yes': + main_env.Append(CPPFLAGS=["-DMYSQL_DB"]) + main_env.Append(LIBS=[ 'mysqlclient', ]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# Linking flags +main_env.Append(LDFLAGS=["-g "]) + +main_env.Program('test','VirtualNetworkPoolTest.cc') + diff --git a/src/vnm/test/VirtualNetworkPoolTest.cc b/src/vnm/test/VirtualNetworkPoolTest.cc new file mode 100644 index 0000000000..aa569139c8 --- /dev/null +++ b/src/vnm/test/VirtualNetworkPoolTest.cc @@ -0,0 +1,831 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, 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 +#include +#include + +#include "VirtualNetworkPool.h" +#include "PoolTest.h" + +using namespace std; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +const int uids[] = {123, 261, 133}; + +const string names[] = {"Net number one", "A virtual network","Net number two"}; + +const string templates[] = +{ + "NAME = \"Net number one\"\n" + "TYPE = FIXED\n" + "BRIDGE = br1\n" + "LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]", + + "NAME = \"A virtual network\"\n" + "TYPE = RANGED\n" + "BRIDGE = br0\n" + "NETWORK_SIZE = C\n" + "NETWORK_ADDRESS = 192.168.0.0\n", + + "NAME = \"Net number two\"\n" + "TYPE = fixed\n" + "BRIDGE = br1\n" + "LEASES = [IP=130.10.2.1, MAC=50:20:20:20:20:20]", + + "NAME = \"Net number three\"\n" + "TYPE = not_a_type\n" + "BRIDGE = br1\n" + "LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]", + + "NAME = = \n" + "TYPE = not_a_type\n" + "BRIDGE = br1\n" + "LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]", +}; + +const string xmls[] = +{ + "0123Net number one" + "1br1" + "130.10.0.150:20:20:20:20:20" + "0-1", + + "1261A virtual network" + "0br0" + "", + + "0133Net number two" + "1br1" + "130.10.2.1" + "50:20:20:20:20:200-1" + "" +}; + +const string xml_dump = + "01A userNe" + "t number one1br1012B userA virtual network0br00"; + +const string xml_dump_where = + "12B userA virtual network0br00"; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class VirtualNetworkPoolTest : public PoolTest +{ + CPPUNIT_TEST_SUITE (VirtualNetworkPoolTest); + + ALL_POOLTEST_CPPUNIT_TESTS(); + CPPUNIT_TEST (allocate_rcs); + CPPUNIT_TEST (get_using_name); + CPPUNIT_TEST (wrong_get_name); + CPPUNIT_TEST (update); + CPPUNIT_TEST (size); + CPPUNIT_TEST (duplicates); + CPPUNIT_TEST (dump); + CPPUNIT_TEST (dump_where); + CPPUNIT_TEST (fixed_leases); + CPPUNIT_TEST (ranged_leases); + CPPUNIT_TEST (wrong_leases); + CPPUNIT_TEST (overlapping_leases_ff); + CPPUNIT_TEST (overlapping_leases_fr); + CPPUNIT_TEST (overlapping_leases_rf); + CPPUNIT_TEST (overlapping_leases_rr); + CPPUNIT_TEST (drop_leases); + + CPPUNIT_TEST_SUITE_END (); + +protected: + + void bootstrap(SqlDB* db) + { + VirtualNetworkPool::bootstrap(db); + }; + + PoolSQL* create_pool(SqlDB* db) + { + // VNet pool constructor needs DB, default mac prefix, + // and default network size + return new VirtualNetworkPool(db, "00:01", 126); + }; + + int allocate(int index) + { + int oid; + return ((VirtualNetworkPool*)pool)->allocate(uids[index], + templates[index], &oid); + }; + + void check(int index, PoolObjectSQL* obj) + { + CPPUNIT_ASSERT( obj != 0 ); + + string xml_str = ""; + + CPPUNIT_ASSERT( ((VirtualNetwork*)obj)->get_uid() == uids[index] ); + CPPUNIT_ASSERT( ((VirtualNetwork*)obj)->to_xml(xml_str) == xmls[index] ); + }; + + void set_up_user_pool() + { + + // The UserPool constructor checks if the DB contains at least + // one user, and adds one automatically from the ONE_AUTH file. + // So the ONE_AUTH environment is forced to point to a test one_auth + // file. + ostringstream oss; + + oss << getenv("PWD") << "/one_auth"; + setenv("ONE_AUTH", oss.str().c_str(), 1); + + UserPool::bootstrap(db); + UserPool * user_pool = new UserPool(db); + int uid_1, uid_2; + + string username_1 = "A user"; + string username_2 = "B user"; + + string pass_1 = "A pass"; + string pass_2 = "B pass"; + + user_pool->allocate(&uid_1, username_1, pass_1, true); + user_pool->allocate(&uid_2, username_2, pass_2, true); + + delete user_pool; + }; + + + +public: + VirtualNetworkPoolTest(){}; + + ~VirtualNetworkPoolTest(){}; + + /* ********************************************************************* */ + /* ********************************************************************* */ + + void allocate_rcs() + { + VirtualNetworkPool * vnpool = static_cast(pool); + VirtualNetwork * vn; + int rc; + + // Check case + rc = allocate(2); + CPPUNIT_ASSERT( rc >= 0 ); + vn = vnpool->get(rc, false); + check(2,vn); + + // Check template attribute + rc = allocate(3); + CPPUNIT_ASSERT( rc == -3 ); + + // Parser error for Vnet template + //TODO: Check memory leak for allocating strings in template parser + rc = allocate(4); + CPPUNIT_ASSERT( rc == -2 ); + } + + void get_using_name() + { + VirtualNetworkPool * vnpool = static_cast(pool); + VirtualNetwork * vn; + int oid; + + // Allocate two objects + oid = allocate(0); + CPPUNIT_ASSERT( oid >= 0 ); + + oid = allocate(1); + CPPUNIT_ASSERT( oid >= 0 ); + + // Get using its name + vn = vnpool->get(names[1], true); + CPPUNIT_ASSERT(vn != 0); + vn->unlock(); + + check(1, vn); + vn->unlock(); + + vnpool->clean(); + + // Get using its name + vn = vnpool->get(names[1], false); + check(1, vn); + }; + + void wrong_get_name() + { + VirtualNetworkPool * vnpool = static_cast(pool); + VirtualNetwork * vn; + + // Empty Pool + vn = vnpool->get("Wrong name", true); + CPPUNIT_ASSERT( vn == 0 ); + + // Allocate an object + allocate(0); + + // Ask again for a non-existing name + vn = vnpool->get("Non existing name", true); + CPPUNIT_ASSERT( vn == 0 ); + } + + void update() + { + // TODO + }; + + void size() + { + VirtualNetworkPool * vnpool = static_cast(pool); + + int rc; + VirtualNetwork* vnet; + + string templ[] = { + // Fixed, 1 lease + "NAME = \"Net number one\"\n" + "TYPE = FIXED\n" + "BRIDGE = br1\n" + "LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]", + + // Fixed, 3 leases + "NAME = \"Net A\"\n" + "TYPE = FIXED\n" + "BRIDGE = br1\n" + "LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]" + "LEASES = [IP=130.10.0.2, MAC=50:20:20:20:20:21]" + "LEASES = [IP=130.10.0.3, MAC=50:20:20:20:20:22]", + + // Ranged, size "C" + "NAME = \"A virtual network\"\n" + "TYPE = RANGED\n" + "BRIDGE = br0\n" + "NETWORK_SIZE = C\n" + "NETWORK_ADDRESS = 192.168.10.0\n", + + // Ranged, size "c" + "NAME = \"Another virtual network\"\n" + "TYPE = RANGED\n" + "BRIDGE = br0\n" + "NETWORK_SIZE = c\n" + "NETWORK_ADDRESS = 192.168.10.0\n", + + // Size is "B" + "NAME = \"Net C\"\n" + "TYPE = RANGED\n" + "BRIDGE = br0\n" + "NETWORK_SIZE = B\n" + "NETWORK_ADDRESS = 192.168.1.0\n", + + // Size "X", defaults to 128 + "NAME = \"Net D\"\n" + "TYPE = RANGED\n" + "BRIDGE = br0\n" + "NETWORK_SIZE = X\n" + "NETWORK_ADDRESS = 192.168.1.0\n", + + // Size 32 + "NAME = \"Net E\"\n" + "TYPE = RANGED\n" + "BRIDGE = br0\n" + "NETWORK_SIZE = 30\n" + "NETWORK_ADDRESS = 192.168.1.0\n" + }; + + unsigned int sizes[7]={1,3,256,256,65536,128,32}; + int oid[7]; + + for (int i = 0 ; i < 7 ; i++) + { + rc = vnpool->allocate(uids[0], templ[i], &oid[i]); + CPPUNIT_ASSERT( rc >= 0 ); + + vnet = vnpool->get(oid[i], false); + CPPUNIT_ASSERT( vnet != 0 ); + CPPUNIT_ASSERT( vnet->get_size() == sizes[i] ); + } + + vnpool->clean(); + + for (int i = 0 ; i < 7 ; i++) + { + vnet = vnpool->get(oid[i], false); + CPPUNIT_ASSERT( vnet != 0 ); + CPPUNIT_ASSERT( vnet->get_size() == sizes[i] ); + } + } + + void duplicates() + { + int rc, oid_0, oid_1; + VirtualNetworkPool * vnpool = static_cast(pool); + VirtualNetwork * vnet; + + // Allocate a vnet + rc = vnpool->allocate(uids[0], templates[0], &oid_0); + CPPUNIT_ASSERT( rc == oid_0 ); + CPPUNIT_ASSERT( rc == 0 ); + + // Allocate the same vnet twice, with the same user ID + rc = vnpool->allocate(uids[0], templates[0], &oid_1); + CPPUNIT_ASSERT( rc == oid_1 ); + CPPUNIT_ASSERT( rc == -1 ); + + // With different user ID + rc = vnpool->allocate(uids[1], templates[0], &oid_1); + CPPUNIT_ASSERT( rc == oid_1 ); + CPPUNIT_ASSERT( rc == -1 ); + + // Insert a different template, with the same user ID + rc = vnpool->allocate(uids[1], templates[1], &oid_1); + CPPUNIT_ASSERT( rc == oid_1 ); + CPPUNIT_ASSERT( rc == 1 ); + + + // Make sure the table contains only one vnet with name[0] + vector results; + int ret; + const char * table = "network_pool"; + + string where = "name = '" + names[0] + "'"; + + ret = pool->search(results, table, where); + CPPUNIT_ASSERT(ret == 0); + CPPUNIT_ASSERT(results.size() == 1); + CPPUNIT_ASSERT(results.at(0) == oid_0); + + // Get the vnet and check it, to make sure the user id was not rewritten + vnet = vnpool->get(oid_0, false); + check(0, vnet); + } + + void dump() + { + VirtualNetworkPool * vnpool = static_cast(pool); + int oid, rc; + ostringstream oss; + + set_up_user_pool(); + + vnpool->allocate(1, templates[0], &oid); + vnpool->allocate(2, templates[1], &oid); + + rc = pool->dump(oss, ""); + + CPPUNIT_ASSERT(rc == 0); + + string result = oss.str(); + CPPUNIT_ASSERT( result == xml_dump ); + }; + + void dump_where() + { + VirtualNetworkPool * vnpool = static_cast(pool); + int oid, rc; + ostringstream oss; + + set_up_user_pool(); + + vnpool->allocate(1, templates[0], &oid); + vnpool->allocate(2, templates[1], &oid); + + string where = "uid > 1"; + rc = pool->dump(oss, where); + + CPPUNIT_ASSERT(rc == 0); + + string result = oss.str(); + CPPUNIT_ASSERT( result == xml_dump_where ); + }; + + void fixed_leases() + { + int rc, oid; + VirtualNetwork *vn; + + string ip = ""; + string mac = ""; + string bridge = ""; + + + // First VNet template is a fixed network with only one IP + oid = allocate(0); + CPPUNIT_ASSERT( oid != -1 ); + + vn = ((VirtualNetworkPool*)pool)->get(oid, false); + CPPUNIT_ASSERT( vn != 0 ); + + // Ask for an IP + vn->lock(); + rc = vn->get_lease(33, ip, mac, bridge); + vn->unlock(); + + // Check the only available IP was granted + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( ip == "130.10.0.1" ); + CPPUNIT_ASSERT( mac == "50:20:20:20:20:20" ); + CPPUNIT_ASSERT( bridge == "br1" ); + + + // Clean the cache + pool->clean(); + + // Read the Vnet from the DB + vn = ((VirtualNetworkPool*)pool)->get(oid, false); + CPPUNIT_ASSERT( vn != 0 ); + + // Ask for another IP + vn->lock(); + rc = vn->get_lease(77, ip, mac, bridge); + vn->unlock(); + + // Check that the only IP available is in use + CPPUNIT_ASSERT( rc != 0 ); + + + // Instead of asking for a free IP, lets request the specific IP that + // we know is in use + vn->lock(); + rc = vn->set_lease(77, ip, mac, bridge); + vn->unlock(); + CPPUNIT_ASSERT( rc != 0 ); + + + // Release the lease + vn->lock(); + vn->release_lease(ip); + vn->unlock(); + + // Clean the mac and bridge strings, to make sure they are correctly + // assigned + mac = ""; + bridge = ""; + + // Now that the lease is free, ask for it again + vn->lock(); + rc = vn->set_lease(77, ip, mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( ip == "130.10.0.1" ); + CPPUNIT_ASSERT( mac == "50:20:20:20:20:20" ); + CPPUNIT_ASSERT( bridge == "br1" ); + } + + void ranged_leases() + { + int rc, oid; + VirtualNetwork *vn; + + string ip = ""; + string mac = ""; + string bridge = ""; + + string tmpl = + "NAME = \"A ranged network\"\n" + "TYPE = RANGED\n" + "BRIDGE = bridge0\n" + "NETWORK_SIZE = 3\n" + "NETWORK_ADDRESS = 192.168.50.0\n"; + + + ((VirtualNetworkPool*)pool)->allocate(45, tmpl, &oid); + CPPUNIT_ASSERT( oid != -1 ); + + vn = ((VirtualNetworkPool*)pool)->get(oid, false); + CPPUNIT_ASSERT( vn != 0 ); + + // Ask for an IP + vn->lock(); + rc = vn->get_lease(33, ip, mac, bridge); + vn->unlock(); + + // Check that it is valid IP + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( ip == "192.168.50.1" ); + CPPUNIT_ASSERT( mac == "00:01:c0:a8:32:01" ); + CPPUNIT_ASSERT( bridge == "bridge0" ); + + // Clean the cache + pool->clean(); + + // Read the Vnet from the DB + vn = ((VirtualNetworkPool*)pool)->get(oid, false); + CPPUNIT_ASSERT( vn != 0 ); + + // Ask for the IP already in use + vn->lock(); + rc = vn->set_lease(77, ip, mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc != 0 ); + + + // Ask for two more IPs + vn->lock(); + rc = vn->get_lease(123, ip, mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc == 0 ); + + vn->lock(); + rc = vn->get_lease(456, ip, mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc == 0 ); + + + // All IPs are now used + vn->lock(); + rc = vn->get_lease(789, ip, mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc != 0 ); + + // Release one of the 3 IPs + vn->lock(); + vn->release_lease("192.168.50.2"); + vn->unlock(); + + + // Clean the mac and bridge strings, to make sure they are correctly + // assigned + mac = ""; + bridge = ""; + + // Now that the lease is free, ask for it again + vn->lock(); + rc = vn->get_lease(77, ip, mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc == 0 ); + CPPUNIT_ASSERT( ip == "192.168.50.2" ); + CPPUNIT_ASSERT( mac == "00:01:c0:a8:32:02" ); + CPPUNIT_ASSERT( bridge == "bridge0" ); + } + + void wrong_leases() + { + int rc, oid_0, oid_1; + VirtualNetwork *vn; + + string ip = ""; + string mac = ""; + string bridge = ""; + + + // First VNet template is a fixed network with only one IP + oid_0 = allocate(0); + CPPUNIT_ASSERT( oid_0 != -1 ); + + vn = ((VirtualNetworkPool*)pool)->get(oid_0, false); + CPPUNIT_ASSERT( vn != 0 ); + + // Ask for a non-defined IP + vn->lock(); + ip = "130.10.0.17"; + rc = vn->set_lease(33, ip, mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc == -1 ); + + // Allocate a ranged VNet + oid_1 = allocate(1); + CPPUNIT_ASSERT( oid_1 != -1 ); + + vn = ((VirtualNetworkPool*)pool)->get(oid_1, false); + CPPUNIT_ASSERT( vn != 0 ); + + // Ask for an out of range IP + vn->lock(); + ip = "130.10.0.17"; + rc = vn->set_lease(33, ip, mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc == -1 ); + + // Ask the second Vnet for a lease defined by the first one + vn->lock(); + rc = vn->set_lease(1234, "130.10.0.1", mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc == -1 ); + } + + void overlapping_leases_ff() + { + // It is a different Vnet from #0: different user, name, and bridge. + // But both of them use the IP 130.10.0.1 + string tmpl_B = + "NAME = \"New Network\"\n" + "TYPE = FIXED\n" + "BRIDGE = br9\n" + "LEASES = [IP=130.10.0.5, MAC=50:20:20:20:20:21]\n" + "LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:22]\n"; + + overlapping_leases(templates[0], tmpl_B); + } + + void overlapping_leases_fr() + { + // Now use a ranged network, also containig the IP 130.10.0.1 + string tmpl_B = + "NAME = \"New Network\"\n" + "TYPE = RANGED\n" + "BRIDGE = br9\n" + "NETWORK_SIZE = 3\n" + "NETWORK_ADDRESS = 130.10.0.0\n"; + + overlapping_leases(templates[0], tmpl_B); + } + + void overlapping_leases_rf() + { + // It is a different Vnet from #0: different user, name, and bridge. + // But both of them use the IP 130.10.0.1 + string tmpl_A = + "NAME = \"New Network\"\n" + "TYPE = RANGED\n" + "BRIDGE = br9\n" + "NETWORK_SIZE = 3\n" + "NETWORK_ADDRESS = 130.10.0.0\n"; + + overlapping_leases(tmpl_A, templates[0]); + } + + void overlapping_leases_rr() + { + // It is a different Vnet from #0: different user, name, and bridge. + // But both of them use the IP 130.10.0.1 + string tmpl_A = + "NAME = \"Network A\"\n" + "TYPE = RANGED\n" + "BRIDGE = br9\n" + "NETWORK_SIZE = 3\n" + "NETWORK_ADDRESS = 130.10.0.0\n"; + + string tmpl_B = + "NAME = \"Network B\"\n" + "TYPE = RANGED\n" + "BRIDGE = br7\n" + "NETWORK_SIZE = 9\n" + "NETWORK_ADDRESS = 130.10.0.0\n"; + + overlapping_leases(tmpl_A, tmpl_B); + } + + + // Runs a test using the given templates + void overlapping_leases(string tmpl_A, string tmpl_B) + { + int rc, oid_0, oid_new; + VirtualNetwork *vn; + + string ip = ""; + string mac = ""; + string bridge = ""; + + vector results; + + + // First VNet template + ((VirtualNetworkPool*)pool)->allocate(13, tmpl_A, &oid_0); + CPPUNIT_ASSERT( oid_0 != -1 ); + + // Second VNet + ((VirtualNetworkPool*)pool)->allocate(45, tmpl_B, &oid_new); + CPPUNIT_ASSERT( oid_new != -1 ); + + // Get this second VNet + vn = ((VirtualNetworkPool*)pool)->get(oid_new, false); + CPPUNIT_ASSERT( vn != 0 ); + + // Set a lease. Ask for the IP that both Vnets have + vn->lock(); + rc = vn->set_lease(1234, "130.10.0.1", mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc == 0 ); + + + // The IP ...1 should be tagged as used only in the second Vnet + + const char * table = "leases"; + string where = "used = 1 AND vid = 1234"; + + rc = pool->search(results, table, where); + CPPUNIT_ASSERT(rc == 0); + CPPUNIT_ASSERT(results.size() == 1); + + + // Now check that the first VNet has that IP available + vn = ((VirtualNetworkPool*)pool)->get(oid_0, false); + CPPUNIT_ASSERT( vn != 0 ); + + // Ask the first VNet for the IP that both Vnets have + vn->lock(); + rc = vn->set_lease(5678, "130.10.0.1", mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc == 0 ); + + // Release the lease on first Vnet + vn->lock(); + vn->release_lease("130.10.0.1"); + vn->unlock(); + + + // Get again the second VNet + vn = ((VirtualNetworkPool*)pool)->get(oid_new, false); + CPPUNIT_ASSERT( vn != 0 ); + + // Ask for the IP, should be still used + vn->lock(); + rc = vn->set_lease(1234, "130.10.0.1", mac, bridge); + vn->unlock(); + + CPPUNIT_ASSERT( rc != 0 ); + + // Check that in the DB, only one lease is used + where = "used = 1"; + // Clean the reults + results.resize(0); + rc = pool->search(results, table, where); + CPPUNIT_ASSERT(rc == 0); + CPPUNIT_ASSERT(results.size() == 1); + } + + void drop_leases() + { + int rc, oid; + VirtualNetwork *vn; + + string ip = ""; + string mac = ""; + string bridge = ""; + + vector results; + + // Allocate a VNet + oid = allocate(0); + CPPUNIT_ASSERT( oid != -1 ); + + vn = ((VirtualNetworkPool*)pool)->get(oid, false); + CPPUNIT_ASSERT( vn != 0 ); + + // Drop the VNet + pool->drop(vn); + + // Check that the leases were also dropped + const char * table = "leases"; + string where = "oid > -1"; + + rc = pool->search(results, table, where); + CPPUNIT_ASSERT(rc == 0); + CPPUNIT_ASSERT(results.size() == 0); + } +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + return PoolTest::main(argc, argv, VirtualNetworkPoolTest::suite()); +} diff --git a/src/vnm/test/one_auth b/src/vnm/test/one_auth new file mode 100644 index 0000000000..2f55c9c47b --- /dev/null +++ b/src/vnm/test/one_auth @@ -0,0 +1 @@ +one_user_test:password