diff --git a/include/Attribute.h b/include/Attribute.h index 1689765d27..62adb851e6 100644 --- a/include/Attribute.h +++ b/include/Attribute.h @@ -21,13 +21,13 @@ #include #include #include -#include +#include using namespace std; /** * Attribute base class for name-value pairs. This class provides a generic - * interface to implement + * interface to implement */ class Attribute { @@ -45,11 +45,11 @@ public: Attribute(const char * aname) { ostringstream name; - + name << uppercase << aname; attribute_name = name.str(); }; - + virtual ~Attribute(){}; enum AttributeType @@ -57,7 +57,7 @@ public: SIMPLE = 0, VECTOR = 1 }; - + /** * Gets the name of the attribute. * @return the attribute name @@ -72,8 +72,8 @@ public: * by the calling function. * @return a string (allocated in the heap) holding the attribute value. */ - virtual string * marshall(const char * _sep = 0) = 0; - + virtual string * marshall(const char * _sep = 0) const = 0; + /** * Write the attribute using a simple XML format. The string MUST be freed * by the calling function. @@ -84,8 +84,8 @@ public: /** * Builds a new attribute from a string. */ - virtual void unmarshall(const string& sattr) = 0; - + virtual void unmarshall(const string& sattr, const char * _sep = 0) = 0; + /** * Returns the attribute type */ @@ -103,8 +103,8 @@ private: /* -------------------------------------------------------------------------- */ /** - * The SingleAttribute class represents a simple attribute in the form - * NAME = VALUE. + * The SingleAttribute class represents a simple attribute in the form + * NAME = VALUE. */ class SingleAttribute : public Attribute @@ -115,12 +115,12 @@ public: SingleAttribute(const string& name, const string& value): Attribute(name),attribute_value(value){}; - + SingleAttribute(const char * name, const string& value): Attribute(name),attribute_value(value){}; ~SingleAttribute(){}; - + /** * Returns the attribute value, a string. */ @@ -128,43 +128,43 @@ public: { return attribute_value; }; - + /** * Marshall the attribute in a single string. The string MUST be freed * by the calling function. * @return a string (allocated in the heap) holding the attribute value. - */ - string * marshall(const char * _sep = 0) + */ + string * marshall(const char * _sep = 0) const { string * rs = new string; - + *rs = attribute_value; - - return rs; + + return rs; }; - + /** * Write the attribute using a simple XML format: - * - * attribute_value - * + * + * attribute_value + * * The string MUST be freed by the calling function. * @return a string (allocated in the heap) holding the attribute value. */ string * to_xml() const { string * xml = new string; - + *xml = "<" + name() + ">" + attribute_value + ""; - + return xml; } - + /** * Builds a new attribute from a string. - */ - void unmarshall(const string& sattr) + */ + void unmarshall(const string& sattr, const char * _sep = 0) { attribute_value = sattr; }; @@ -179,23 +179,23 @@ public: /** * Returns the attribute type - */ + */ AttributeType type() { return SIMPLE; }; - + private: - string attribute_value; + string attribute_value; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** - * The VectorAttribute class represents an array attribute in the form - * NAME = [ VAL_NAME_1=VAL_VALUE_1,...,VAL_NAME_N=VAL_VALUE_N]. + * The VectorAttribute class represents an array attribute in the form + * NAME = [ VAL_NAME_1=VAL_VALUE_1,...,VAL_NAME_N=VAL_VALUE_N]. */ class VectorAttribute : public Attribute @@ -208,7 +208,7 @@ public: Attribute(name),attribute_value(value){}; ~VectorAttribute(){}; - + /** * Returns the attribute value, a string. */ @@ -216,29 +216,29 @@ public: { return attribute_value; }; - + /** * */ string vector_value(const char *name) const; - + /** * Marshall the attribute in a single string. The string MUST be freed - * by the calling function. The string is in the form: + * by the calling function. The string is in the form: * "VAL_NAME_1=VAL_VALUE_1,...,VAL_NAME_N=VAL_VALUE_N". * @return a string (allocated in the heap) holding the attribute value. - */ - string * marshall(const char * _sep = 0); - + */ + string * marshall(const char * _sep = 0) const; + /** * Write the attribute using a simple XML format: - * + * * * val_value_1 * ... * val_value_n - * - * + * + * * The string MUST be freed by the calling function. * @return a string (allocated in the heap) holding the attribute value. */ @@ -247,8 +247,8 @@ public: /** * Builds a new attribute from a string of the form: * "VAL_NAME_1=VAL_VALUE_1,...,VAL_NAME_N=VAL_VALUE_N". - */ - void unmarshall(const string& sattr); + */ + void unmarshall(const string& sattr, const char * _sep = 0); /** * Replace the value of the given attribute with the provided map @@ -258,19 +258,19 @@ public: /** * Returns the attribute type - */ + */ AttributeType type() { return VECTOR; }; private: - + static const char * magic_sep; - + static const int magic_sep_size; - map attribute_value; + map attribute_value; }; #endif /*ATTRIBUTE_H_*/ diff --git a/include/History.h b/include/History.h index 94852de755..f8c232b0e4 100644 --- a/include/History.h +++ b/include/History.h @@ -28,7 +28,7 @@ extern "C" int history_select_cb ( int num, char ** values, char ** names); - + /** * The History class, it represents an execution record of a Virtual Machine. */ @@ -60,7 +60,7 @@ public: private: friend class VirtualMachine; - + // ---------------------------------------- // DataBase implementation variables // ---------------------------------------- @@ -88,17 +88,17 @@ private: static const char * table; static const char * db_names; - + static const char * db_bootstrap; void non_persistent_data(); - + static string column_name(const ColNames column) { switch (column) { case HID: - return "hid"; + return "hid"; case ETIME: return "etime"; case RUNNING_ETIME: @@ -116,7 +116,7 @@ private: string hostname; string vm_dir; - + int hid; string vmm_mad_name; @@ -140,17 +140,18 @@ private: string vm_lhome; string transfer_file; string deployment_file; - + string context_file; + string vm_rhome; 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. @@ -172,14 +173,14 @@ private: */ int drop(SqliteDB * db); - + /** * Updates the history record * @param db pointer to the database. * @return 0 on success. - */ + */ int update(SqliteDB * db) - { + { return insert(db); } @@ -199,7 +200,7 @@ private: { return ObjectSQL::select_column(db,table,column,where,value); } - + /** * Sets the value of a column in the pool for a given object * @param db pointer to Database @@ -216,7 +217,7 @@ private: { return ObjectSQL::update_column(db,table,column,where,value); } - + /** * Function to unmarshall a history object diff --git a/include/Template.h b/include/Template.h index 8b3330ef41..e33c6642b1 100644 --- a/include/Template.h +++ b/include/Template.h @@ -107,6 +107,17 @@ public: attributes.insert(make_pair(attr->name(),attr)); }; + /** + * Removes an attribute from the template. The attributes are returned. The + * attributes MUST be freed by the calling funtion + * @param name of the attribute + * @param values a vector containing a pointer to the attributes + * @returns the number of attributes removed + */ + virtual int remove( + const string& name, + vector& values); + /** * Gets all the attributes with the given name. * @param name the attribute name. diff --git a/include/TemplateSQL.h b/include/TemplateSQL.h index f4cb668382..94e06f0892 100644 --- a/include/TemplateSQL.h +++ b/include/TemplateSQL.h @@ -44,29 +44,29 @@ public: {}; virtual ~TemplateSQL(){}; - + protected: //Database implementation variables - + const char * table; static const char * db_names; - + //Template attributes - + /** * Template unique identification. */ int id; - + /** * Writes the template in the DB * @param db pointer to the database. * @return 0 on success. */ int insert(SqliteDB * db); - + /** * Updates the template in the DB * @param db pointer to the database. @@ -88,13 +88,21 @@ protected: int drop(SqliteDB *db); /** - * Removes a template attribute from the DB (ONLY SINGLE ATTRIBUTES) + * 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. * @param db pointer to the database. - * @param name of the attribute. - * @param value of the new attribute. + * @param attribute pointer to the new attribute. */ - int replace_attribute(SqliteDB * db, const string& name, const string& value); - + int replace_attribute(SqliteDB * db, Attribute * attribute); + + /** + * Insert a given attribute (MUST be allocated in the heap) in the template + * and updates the DB. + * @param db pointer to the database. + * @param attribute pointer to the new attribute + */ + int insert_attribute(SqliteDB * db, Attribute * attribute); }; /* -------------------------------------------------------------------------- */ diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 2bea91ee32..347c829477 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -41,7 +41,7 @@ class VirtualMachine : public PoolObjectSQL public: // ------------------------------------------------------------------------- // VM States - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- /** * Global Virtual Machine state @@ -59,7 +59,7 @@ public: }; /** - * Virtual Machine state associated to the Life-cycle Manager + * Virtual Machine state associated to the Life-cycle Manager */ enum LcmState { @@ -81,11 +81,11 @@ public: // ------------------------------------------------------------------------- // Log & Print - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- /** * writes a log message in vm.log. The class lock should be locked and - * the VM MUST BE obtained through the VirtualMachinePool get() method. + * the VM MUST BE obtained through the VirtualMachinePool get() method. */ void log( const char * module, @@ -97,22 +97,22 @@ public: _log->log(module,type,message); } }; - + /** * writes a log message in vm.log. The class lock should be locked and - * the VM MUST BE obtained through the VirtualMachinePool get() method. + * the VM MUST BE obtained through the VirtualMachinePool get() method. */ void log( const char * module, const Log::MessageType type, - const char * message) const + const char * message) const { if (_log != 0) { _log->log(module,type,message); } }; - + /** * Function to write a Virtual Machine in an output stream */ @@ -120,7 +120,7 @@ public: // ------------------------------------------------------------------------ // Dynamic Info - // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ /** * Updates VM dynamic information (id). @@ -186,7 +186,7 @@ public: // ------------------------------------------------------------------------ // History - // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ /** * Adds a new history record an writes it in the database. */ @@ -215,7 +215,7 @@ public: * Checks if the VM has a valid history record. This function * MUST be called before using any history related function. * @return true if the VM has a record - */ + */ bool hasHistory() const { return (history!=0); @@ -225,7 +225,7 @@ public: * Checks if the VM has a valid previous history record. This function * MUST be called before using any previous_history related function. * @return true if the VM has a previous record - */ + */ bool hasPreviousHistory() const { return (previous_history!=0); @@ -234,7 +234,7 @@ public: * Returns the VMM driver name for the current host. The hasHistory() * function MUST be called before this one. * @return the VMM mad name - */ + */ const string & get_vmm_mad() const { return history->vmm_mad_name; @@ -244,20 +244,20 @@ public: * Returns the TM driver name for the current host. The hasHistory() * function MUST be called before this one. * @return the TM mad name - */ + */ const string & get_tm_mad() const { return history->tm_mad_name; }; /** - * Returns the transfer filename. The transfer file is in the form: + * Returns the transfer filename. The transfer file is in the form: * $ONE_LOCATION/var/$VM_ID/transfer.$SEQ * or, in case that OpenNebula is installed in root - * /var/lib/one/$VM_ID/transfer.$SEQ + * /var/lib/one/$VM_ID/transfer.$SEQ * The hasHistory() function MUST be called before this one. * @return the transfer filename - */ + */ const string & get_transfer_file() const { return history->transfer_file; @@ -270,79 +270,92 @@ public: * /var/lib/one/$VM_ID/deployment.$SEQ * The hasHistory() function MUST be called before this one. * @return the deployment filename - */ + */ const string & get_deployment_file() const { return history->deployment_file; }; - + /** - * Returns the remote deployment filename. The file is in the form: - * $VM_DIR/$VM_ID/images/deployment.$SEQ + * Returns the context filename. The context file is in the form: + * $ONE_LOCATION/var/$VM_ID/context.sh + * or, in case that OpenNebula is installed in root + * /var/lib/one/$VM_ID/context.sh * The hasHistory() function MUST be called before this one. * @return the deployment filename - */ + */ + const string & get_context_file() const + { + return history->context_file; + } + + /** + * Returns the remote deployment filename. The file is in the form: + * $VM_DIR/$VM_ID/images/deployment.$SEQ + * The hasHistory() function MUST be called before this one. + * @return the deployment filename + */ const string & get_remote_deployment_file() const { return history->rdeployment_file; - }; - + }; + /** - * Returns the checkpoint filename for the current host. The checkpoint file - * is in the form: - * $VM_DIR/$VM_ID/images/checkpoint + * Returns the checkpoint filename for the current host. The checkpoint file + * is in the form: + * $VM_DIR/$VM_ID/images/checkpoint * The hasHistory() function MUST be called before this one. * @return the checkpoint filename - */ + */ const string & get_checkpoint_file() const { return history->checkpoint_file; }; - + /** - * Returns the remote VM directory. The VM remote dir is in the form: + * Returns the remote VM directory. The VM remote dir is in the form: * $VM_DIR/$VM_ID/ * or, in case that OpenNebula is installed in root * /var/lib/one/$VM_ID/ * The hasHistory() function MUST be called before this one. * @return the remote directory - */ + */ const string & get_remote_dir() const { return history->vm_rhome; }; - + /** - * Returns the local VM directory. The VM local dir is in the form: - * $ONE_LOCATION/var/$VM_ID/ + * Returns the local VM directory. The VM local dir is in the form: + * $ONE_LOCATION/var/$VM_ID/ * The hasHistory() function MUST be called before this one. * @return the remote directory - */ + */ const string & get_local_dir() const { return history->vm_lhome; - }; + }; /** * Returns the hostname for the current host. The hasHistory() * function MUST be called before this one. * @return the hostname - */ + */ const string & get_hostname() const { return history->hostname; }; - + /** * Returns the hostname for the previous host. The hasPreviousHistory() * function MUST be called before this one. * @return the hostname - */ + */ const string & get_previous_hostname() const { return previous_history->hostname; }; - + /** * Returns the reason that originated the VM migration in the previous host * @return the migration reason to leave this host @@ -350,8 +363,8 @@ public: const History::MigrationReason get_previous_reason() const { return previous_history->reason; - }; - + }; + /** * Get host id where the VM is or is going to execute. The hasHistory() * function MUST be called before this one. @@ -369,7 +382,7 @@ public: { return previous_history->hid; } - + /** * Sets start time of a VM. * @param _stime time when the VM started @@ -396,7 +409,7 @@ public: { previous_history->etime=_etime; }; - + /** * Sets start time of VM prolog. * @param _stime time when the prolog started @@ -441,7 +454,7 @@ public: { previous_history->running_etime=_etime; }; - + /** * Sets start time of VM epilog. * @param _stime time when the epilog started @@ -468,7 +481,7 @@ public: { history->reason=_reason; }; - + /** * Sets the reason that originated the VM migration in the previous host * @param _reason migration reason to leave this host @@ -476,11 +489,11 @@ public: void set_previous_reason(History::MigrationReason _reason) { previous_history->reason=_reason; - }; + }; // ------------------------------------------------------------------------ // Template - // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ /** * Gets the values of a template attribute @@ -489,7 +502,7 @@ public: * @return the number of values */ int get_template_attribute( - string& name, + string& name, vector& values) const { return vm_template.get(name,values); @@ -513,42 +526,42 @@ public: * Gets a string based VM attribute (single) * @param name of the attribute * @param value of the attribute (a string), will be "" if not defined or - * not a single attribute + * not a single attribute */ void get_template_attribute( - const char * name, + const char * name, string& value) const { string str=name; - vm_template.get(str,value); - } - + vm_template.get(str,value); + } + /** * Gets an int based VM attribute (single) * @param name of the attribute * @param value of the attribute (an int), will be 0 if not defined or - * not a single attribute + * not a single attribute */ void get_template_attribute( - const char * name, + const char * name, int& value) const { string str=name; - vm_template.get(str,value); + vm_template.get(str,value); } - + /** * Generates a XML string for the template of the VM * @param xml the string to store the XML description. */ void template_to_xml(string &xml) const { - vm_template.to_xml(xml); + vm_template.to_xml(xml); } - + // ------------------------------------------------------------------------ // States - // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ /** * Returns the VM state (Dispatch Manager) @@ -585,7 +598,7 @@ public: { lcm_state = s; }; - + /** * Gets the user id of the owner of this VM * @return the VM uid @@ -594,11 +607,11 @@ public: { return uid; }; - + // ------------------------------------------------------------------------ // Timers - // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ /** * Gets time from last information polling. * @return time of last poll (epoch) or 0 if never polled @@ -607,7 +620,7 @@ public: { return last_poll; }; - + /** * Sets time of last information polling. * @param poll time in epoch, normally time(0) @@ -616,15 +629,15 @@ public: { last_poll = poll; }; - + /** * Get the VM physical requirements for the host. * @param cpu * @param memory - * @param disk + * @param disk */ void get_requirements (int& cpu, int& memory, int& disk); - + // ------------------------------------------------------------------------ // Leases // ------------------------------------------------------------------------ @@ -633,12 +646,18 @@ public: * @return 0 if success */ int get_leases(); - + /** * Releases all network leases taken by this Virtual Machine */ void release_leases(); - + + /** + * Writes the context file for this VM. + * @return 0 if success + */ + int write_context(); + private: // ------------------------------------------------------------------------- @@ -655,11 +674,11 @@ private: // ************************************************************************* // Virtual Machine Attributes // ************************************************************************* - + // ------------------------------------------------------------------------- // Identification variables // ------------------------------------------------------------------------- - + /** * User (owner) id */ @@ -667,12 +686,12 @@ private: // ------------------------------------------------------------------------- // VM Scheduling & Managing Information - // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- /** * Last time (in epoch) that the VM was polled to get its status */ time_t last_poll; - + // ------------------------------------------------------------------------- // Virtual Machine Description // ------------------------------------------------------------------------- @@ -737,7 +756,7 @@ private: * History record, for the previous host */ History * previous_history; - + // ------------------------------------------------------------------------- // Logging // ------------------------------------------------------------------------- @@ -749,7 +768,7 @@ private: * /var/log/one/$VM_ID.log */ Log * _log; - + // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* @@ -765,7 +784,7 @@ private: db->exec(History::db_bootstrap); }; - + /** * Function to unmarshall a VM object, an associated classes. * @param num the number of columns read from the DB @@ -774,11 +793,11 @@ private: * @return 0 on success */ int unmarshall(int num, char **names, char ** values); - + /** * Updates the VM history record * @param db pointer to the db - * @return 0 on success + * @return 0 on success */ int update_history(SqliteDB * db) { @@ -793,7 +812,7 @@ private: /** * Updates the previous history record * @param db pointer to the db - * @return 0 on success + * @return 0 on success */ int update_previous_history(SqliteDB * db) { @@ -804,11 +823,11 @@ private: else return -1; }; - + /** - * Updates the template of a VM, adding a new attribute (replacing it if + * Updates the template of a VM, adding a new attribute (replacing it if * already defined), the vm's mutex SHOULD be locked - * @param vm pointer to the virtual machine object + * @param db pointer to the database * @param name of the new attribute * @param value of the new attribute * @return 0 on success @@ -818,19 +837,41 @@ private: string& name, string& value) { - return vm_template.replace_attribute(db,name,value); - } - + SingleAttribute * sattr; + int rc; + + sattr = new SingleAttribute(name,value); + rc = vm_template.replace_attribute(db,sattr); + + if (rc != 0) + delete sattr; + + return rc; + } + + /** + * Inserts a new attribute in the template of a VM, also the DB is + * updated. The vm's mutex SHOULD be locked + * @param db pointer to the database + * @param attribute the new attribute for the template + * @return 0 on success + */ + int insert_template_attribute(SqliteDB * db, Attribute * attribute) + { + return vm_template.insert_attribute(db,attribute); + } + + protected: - + //************************************************************************** // Constructor //************************************************************************** - + VirtualMachine(int id=-1); virtual ~VirtualMachine(); - + // ************************************************************************* // DataBase implementation // ************************************************************************* @@ -858,7 +899,7 @@ protected: static const char * db_names; static const char * db_bootstrap; - + /** * Reads the Virtual Machine (identified with its OID) from the database. * @param db pointer to the db @@ -879,7 +920,7 @@ protected: * @return 0 on success */ virtual int update(SqliteDB * db); - + /** * Deletes a VM from the database and all its associated information: * - History records @@ -888,16 +929,16 @@ protected: * @return 0 on success */ virtual int drop(SqliteDB * db) - { + { int rc; - + rc = vm_template.drop(db); - + if ( history != 0 ) { rc += history->drop(db); } - + return rc; } }; diff --git a/include/VirtualMachinePool.h b/include/VirtualMachinePool.h index 0b703fa883..bf5f9da805 100644 --- a/include/VirtualMachinePool.h +++ b/include/VirtualMachinePool.h @@ -43,7 +43,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 0 on success, -1 error inserting in DB or -2 error parsing * the template */ int allocate ( @@ -85,9 +85,9 @@ public: //-------------------------------------------------------------------------- // Virtual Machine DB access functions //-------------------------------------------------------------------------- - + /** - * Updates the template of a VM, adding a new attribute (replacing it if + * Updates the template of a VM, adding a new attribute (replacing it if * already defined), the vm's mutex SHOULD be locked * @param vm pointer to the virtual machine object * @param name of the new attribute @@ -101,7 +101,7 @@ public: { return vm->update_template_attribute(db,name,value); } - + /** * Updates the history record of a VM, the vm's mutex SHOULD be locked * @param vm pointer to the virtual machine object @@ -123,7 +123,21 @@ public: { return vm->update_previous_history(db); } - + + /** + * Parse a string and substitute variables (e.g. $NAME) using template + * values: + * @param vm_id, ID of the VM used to substitute the variables + * @param attribute, the string to be parsed + * @param parsed, the resulting parsed string + * @param error_msg, string describing the syntax error + * @return 0 on success. + */ + int parse_attribute(int vm_id, + string &attribute, + string &parsed, + char ** error_msg); + /** * Bootstraps the database table(s) associated to the VirtualMachine pool */ @@ -131,8 +145,20 @@ public: { VirtualMachine::bootstrap(db); }; - + private: + /** + * Mutex to perform just one attribute parse at a time + */ + static pthread_mutex_t lex_mutex; + + /** + * Generate context file to be sourced upon VM booting + * @param vm_id, ID of the VM to generate context for + * @param attrs, the template CONTEXT attributes (only the first one will + * be used) + */ + void generate_context(int vm_id, vector attrs); /** * Factory method to produce VM objects @@ -143,5 +169,5 @@ private: return new VirtualMachine; }; }; - + #endif /*VIRTUAL_MACHINE_POOL_H_*/ diff --git a/include/VirtualNetwork.h b/include/VirtualNetwork.h index 9358ef72ca..538cbf009c 100644 --- a/include/VirtualNetwork.h +++ b/include/VirtualNetwork.h @@ -45,18 +45,18 @@ extern "C" int vn_select_cb (void * _vn, int num,char ** values, char ** names); class VirtualNetwork : public PoolObjectSQL { public: - + /** * Possible types of networks - */ - + */ + enum NetworkType { UNINITIALIZED = -1, RANGED = 0, FIXED = 1, }; - + // ************************************************************************* // Virtual Network Public Methods // ************************************************************************* @@ -65,7 +65,7 @@ public: * @param vid VM identifier * @param _ip pointer to string for IP to be stored into * @param _mac pointer to string for MAC to be stored into - * @param _bridge name of the physical bridge this VN binds to + * @param _bridge name of the physical bridge this VN binds to * @return 0 if success */ int get_lease(int vid, string& _ip, string& _mac, string& _bridge) @@ -79,7 +79,7 @@ public: * @param vid VM identifier * @param _ip the ip of the requested lease * @param _mac pointer to string for MAC to be stored into - * @param _bridge name of the physical bridge this VN binds to + * @param _bridge name of the physical bridge this VN binds to * @return 0 if success */ int set_lease(int vid, const string& _ip, string& _mac, string& _bridge) @@ -87,7 +87,7 @@ public: _bridge = bridge; return leases->set(vid,_ip,_mac); }; - + /** * Release previously given lease * @param _ip IP identifying the lease @@ -97,7 +97,7 @@ public: { return leases->release(ip); }; - + /** * Gets size of the network (used + free) * @return number of hosts that can be fitted in this network @@ -106,12 +106,12 @@ public: { return leases->size; }; - + /** * Function to write a Virtual Network in an output stream */ friend ostream& operator<<(ostream& os, VirtualNetwork& vn); - + private: // ------------------------------------------------------------------------- @@ -136,7 +136,7 @@ private: * Name of the Virtual Network */ string name; - + /** * Owner of the Virtual Network */ @@ -145,7 +145,7 @@ private: // ------------------------------------------------------------------------- // Binded physical attributes // ------------------------------------------------------------------------- - + /** * Name of the bridge this VNW binds to */ @@ -158,27 +158,27 @@ private: * Holds the type of this network */ 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. */ VirtualNetworkTemplate vn_template; - + // ************************************************************************* // Non persistent data members from Nebula.conf // ************************************************************************* - + /** * MAC prefix for this OpenNebula site */ unsigned int mac_prefix; - + /** * Default size for virtual networks */ @@ -194,12 +194,12 @@ private: static void bootstrap(SqliteDB * db) { db->exec(VirtualNetwork::db_bootstrap); - + db->exec(VirtualNetworkTemplate::db_bootstrap); - + db->exec(Leases::db_bootstrap); }; - + /** * Function to unmarshall a VNW object, and associated classes. * @param num the number of columns read from the DB @@ -208,7 +208,7 @@ private: * @return 0 on success */ int unmarshall(int num, char **names, char ** values); - + /** * Function to drop VN entry in vn_pool * @return 0 on success @@ -217,7 +217,7 @@ private: // ------------------------------------------------------------------------ // Template - // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ /** * Gets the values of a template attribute @@ -226,7 +226,7 @@ private: * @return the number of values */ int get_template_attribute( - string& name, + string& name, vector& values) const { return vn_template.get(name,values); @@ -245,35 +245,35 @@ private: string str=name; return vn_template.get(str,values); }; - + /** * Gets a string based VN 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; - vn_template.get(str,value); - } - + vn_template.get(str,value); + } + /** * Gets a string based VN 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; - vn_template.get(str,value); + vn_template.get(str,value); } - + /** - * Updates the template of a VNW, adding a new attribute (replacing it if + * 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 name of the new attribute @@ -285,19 +285,28 @@ private: string& name, string& value) { - return vn_template.replace_attribute(db,name,value); - } - + SingleAttribute * sattr; + int rc; + + sattr = new SingleAttribute(name,value); + rc = vn_template.replace_attribute(db,sattr); + + if (rc != 0) + delete sattr; + + return rc; + } + protected: - + //************************************************************************** // Constructor //************************************************************************** - + VirtualNetwork(unsigned int _mac_prefix, int _default_size); ~VirtualNetwork(); - + // ************************************************************************* // DataBase implementation // ************************************************************************* @@ -317,7 +326,7 @@ protected: static const char * db_names; static const char * db_bootstrap; - + /** * Reads the Virtual Network (identified with its OID) from the database. * @param db pointer to the db @@ -338,7 +347,7 @@ protected: * @return 0 on success */ int update(SqliteDB * db); - + /** * Deletes a VNW from the database and all its associated information: * - VNW template @@ -347,15 +356,15 @@ protected: * @return 0 on success */ int drop(SqliteDB * db) - { + { int rc; - + rc = vn_template.drop(db); - + rc += leases->drop(db); - + rc += vn_drop(db); - + return rc; } }; diff --git a/src/common/Attribute.cc b/src/common/Attribute.cc index ae6fb08b9e..452ec2cd94 100644 --- a/src/common/Attribute.cc +++ b/src/common/Attribute.cc @@ -17,6 +17,7 @@ #include #include +#include #include "Attribute.h" @@ -24,13 +25,14 @@ const char * VectorAttribute::magic_sep = "@^_^@"; const int VectorAttribute::magic_sep_size = 5; -string * VectorAttribute::marshall(const char * _sep) +string * VectorAttribute::marshall(const char * _sep) const { - ostringstream os; - map::iterator it; - string * rs; - const char * my_sep; - + ostringstream os; + string * rs; + const char * my_sep; + + map::const_iterator it; + if ( _sep == 0 ) { my_sep = magic_sep; @@ -39,7 +41,7 @@ string * VectorAttribute::marshall(const char * _sep) { my_sep = _sep; } - + if ( attribute_value.size() == 0 ) { return 0; @@ -69,38 +71,52 @@ string * VectorAttribute::to_xml() const map::const_iterator it; ostringstream oss; string * xml; - + oss << "<" << name() << ">"; - + for (it=attribute_value.begin();it!=attribute_value.end();it++) { - oss << "<" << it->first << ">" << it->second + oss << "<" << it->first << ">" << it->second << "first << ">"; } - + oss << ""; - + xml = new string; - + *xml = oss.str(); - + return xml; -} +} /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void VectorAttribute::unmarshall(const string& sattr) +void VectorAttribute::unmarshall(const string& sattr, const char * _sep) { - size_t bpos=0,epos,mpos; + size_t bpos=0,epos,mpos; string tmp; - bool cont = true; - + bool cont = true; + + const char * my_sep; + int my_sep_size; + + if ( _sep == 0 ) + { + my_sep = magic_sep; + my_sep_size = magic_sep_size; + } + else + { + my_sep = _sep; + my_sep_size = strlen(_sep); + } + while(cont) { - epos=sattr.find(magic_sep,bpos); - + epos=sattr.find(my_sep,bpos); + if (epos == string::npos) { tmp = sattr.substr(bpos); @@ -109,16 +125,16 @@ void VectorAttribute::unmarshall(const string& sattr) else { tmp = sattr.substr(bpos,epos-bpos); - bpos = epos + magic_sep_size; + bpos = epos + my_sep_size; } - + mpos = tmp.find('='); - + if (mpos == string::npos) { continue; } - + attribute_value.insert(make_pair(tmp.substr(0,mpos), tmp.substr(mpos+1))); } diff --git a/src/template/TemplateSQL.cc b/src/template/TemplateSQL.cc index d8ae20b486..4e3a1ff8a2 100644 --- a/src/template/TemplateSQL.cc +++ b/src/template/TemplateSQL.cc @@ -242,62 +242,84 @@ int TemplateSQL::drop(SqliteDB * db) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int TemplateSQL::replace_attribute( - SqliteDB * db, - const string& name, - const string& value) +int TemplateSQL::replace_attribute(SqliteDB * db, Attribute * attribute) { - ostringstream oss; - int rc; - - multimap::const_iterator i; - Attribute * attribute; - - if ( id == -1 || name.empty() || value.empty() ) + ostringstream oss; + int rc; + string * astr; + + multimap::iterator i; + + if ( id == -1 || attribute == 0) { return -1; } - - i = attributes.find(name); - - if ( i != attributes.end() ) //attribute exists + + i = attributes.find(attribute->name()); + + if ( i != attributes.end() ) { - string * attr = i->second->marshall(); - - if ( attr != 0 ) - { - oss << "DELETE FROM " << table << " WHERE id=" << id - << " AND name='" << name << "' AND value='" << *attr << "'"; - - delete attr; - } - else - { - oss << "DELETE FROM " << table << " WHERE id=" << id - << " AND name='" << name << "'"; - } - - rc = db->exec(oss); - - if ( rc != 0 ) - { - return rc; - } - - attributes.erase(name); + astr = i->second->marshall(); + + if ( astr == 0 ) + { + return -1; + } + + oss << "DELETE FROM " << table << " WHERE id=" << id + << " AND name='" << attribute->name() << "' AND value='" + << *astr << "'"; + + delete astr; + + if ((rc = db->exec(oss)) != 0 ) + { + return rc; + } + + delete i->second; + + attributes.erase(i); } - attribute = new SingleAttribute(name,value); - - attributes.insert(make_pair(attribute->name(),attribute)); - - oss.str(""); - - oss << "INSERT INTO " << table << " " << db_names - << " VALUES (" << id << ",'" << name << "'," << - Attribute::SIMPLE <<",'" << value << "')"; - - return db->exec(oss); + return insert_attribute(db,attribute); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int TemplateSQL::insert_attribute(SqliteDB * db, Attribute * attribute) +{ + ostringstream oss; + int rc; + string * astr; + int atype; + + if ( id == -1 || attribute == 0) + { + return -1; + } + + astr = attribute->marshall(); + atype = attribute->type(); + + if ( astr == 0 ) + { + return -1; + } + + oss << "INSERT INTO " << table << " " << db_names + << " VALUES (" << id << ",'" << attribute->name() << "'," << atype + << ",'" << *astr << "')"; + + delete astr; + + if ((rc = db->exec(oss)) == 0) + { + attributes.insert(make_pair(attribute->name(),attribute)); + } + + return rc; } /* -------------------------------------------------------------------------- */ diff --git a/src/vm/History.cc b/src/vm/History.cc index 2d5aa790fa..d8e75086a1 100644 --- a/src/vm/History.cc +++ b/src/vm/History.cc @@ -95,35 +95,40 @@ void History::non_persistent_data() { ostringstream os; Nebula& nd = Nebula::instance(); - + // ----------- Local Locations ------------ os.str(""); - os << nd.get_var_location() << oid; - + os << nd.get_var_location() << oid; + vm_lhome = os.str(); - + os << "/deployment." << seq; - + deployment_file = os.str(); - + os.str(""); os << vm_lhome << "/transfer." << seq; - + transfer_file = os.str(); - + + os.str(""); + os << vm_lhome << "/context.sh"; + + context_file = os.str(); + // ----------- Remote Locations ------------ os.str(""); os << vm_dir << "/" << oid << "/images"; - + vm_rhome = os.str(); - + os << "/checkpoint"; - + checkpoint_file = os.str(); - + os.str(""); os << vm_rhome << "/deployment." << seq; - + rdeployment_file = os.str(); } @@ -194,7 +199,7 @@ int History::unmarshall(int num, char **names, char ** values) hostname = values[HOSTNAME]; vm_dir = values[VM_DIR]; - + hid = atoi(values[HID]); vmm_mad_name = values[VMMMAD]; @@ -257,7 +262,7 @@ int History::select(SqliteDB * db) } 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); @@ -277,7 +282,7 @@ int History::drop(SqliteDB * db) { ostringstream oss; - oss << "DELETE FROM " << table << " WHERE vid= "<< oid; + oss << "DELETE FROM " << table << " WHERE vid= "<< oid; return db->exec(oss); } diff --git a/src/vm/SConstruct b/src/vm/SConstruct index 6f1cc54783..a7da1cd539 100644 --- a/src/vm/SConstruct +++ b/src/vm/SConstruct @@ -21,12 +21,27 @@ Import('env') lib_name='nebula_vm' +if env['parsers']=='yes': + # LEX + parser=env.Lex( + source='vm_var_parser.l' + ) + env.NoClean(parser) + + # BISON + parser=env.Bison( + source='vm_var_syntax.y' + ) + env.NoClean(parser) + # Sources to generate the library source_files=[ 'History.cc', 'VirtualMachine.cc', + 'vm_var_parser.c', + 'vm_var_syntax.cc', 'VirtualMachinePool.cc', - 'VirtualMachineTemplate.cc', + 'VirtualMachineTemplate.cc' ] # Build library diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 3acd790077..bc91c0368b 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -18,8 +18,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -158,13 +158,13 @@ int VirtualMachine::select(SqliteDB * db) { ostringstream oss; ostringstream ose; - + int rc; int boid; - + string filename; Nebula& nd = Nebula::instance(); - + oss << "SELECT * FROM " << table << " WHERE oid = " << oid; boid = oid; @@ -206,26 +206,26 @@ int VirtualMachine::select(SqliteDB * db) else if (history->seq > 0) { previous_history = new History(oid,history->seq - 1); - + rc = previous_history->select(db); - + if ( rc != 0) { - goto error_previous_history; + goto error_previous_history; } } - + //Create support directory fo this VM - + oss.str(""); oss << nd.get_var_location() << oid; - + mkdir(oss.str().c_str(), 0777); chmod(oss.str().c_str(), 0777); - + //Create Log support fo this VM - - try + + try { _log = new Log(nd.get_vm_log_filename(oid),Log::DEBUG); } @@ -233,7 +233,7 @@ int VirtualMachine::select(SqliteDB * db) { ose << "Error creating log: " << e.what(); Nebula::log("ONE",Log::ERROR, ose); - + _log = 0; } @@ -253,60 +253,78 @@ error_history: ose << "Can not get history for VM id: " << oid; log("ONE", Log::ERROR, ose); return -1; - + error_previous_history: - ose << "Can not get previous history record (seq:" << history->seq + ose << "Can not get previous history record (seq:" << history->seq << ") for VM id: " << oid; log("ONE", Log::ERROR, ose); - return -1; + return -1; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int VirtualMachine::insert(SqliteDB * db) -{ - int rc; - string name; - - //Set a name if the VM has not got one - +{ + int rc; + string name; + + SingleAttribute * attr; + string value; + ostringstream oss; + + // ------------------------------------------------------------------------ + // Set a name if the VM has not got one and VM_ID + // ------------------------------------------------------------------------ + get_template_attribute("NAME",name); - + if ( name.empty() == true ) { - SingleAttribute * name_attr; - ostringstream default_name; - - default_name << "one-" << oid; - name = default_name.str(); - - name_attr = new SingleAttribute("NAME",name); - - vm_template.set(name_attr); - } - + oss << "one-" << oid; + value = oss.str(); + + attr = new SingleAttribute("NAME",value); + + vm_template.set(attr); + } + + oss.str(""); + + oss << oid; + value = oss.str(); + + attr = new SingleAttribute("VM_ID",value); + + vm_template.set(attr); + + // ------------------------------------------------------------------------ + // Get network leases + // ------------------------------------------------------------------------ + rc = get_leases(); - + if ( rc != 0 ) { goto error_leases; } - // Insert the template first, so we get a valid template ID + // ------------------------------------------------------------------------ + // Insert the template first, so we get a valid template ID. Then the VM + // ------------------------------------------------------------------------ + rc = vm_template.insert(db); if ( rc != 0 ) { - goto error_template; + goto error_template; } - //Insert the VM rc = update(db); if ( rc != 0 ) { - goto error_update; + goto error_update; } return 0; @@ -375,7 +393,7 @@ void VirtualMachine::add_history( else { seq = history->seq + 1; - + if (previous_history != 0) { delete previous_history; @@ -389,16 +407,16 @@ void VirtualMachine::add_history( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ - + void VirtualMachine::cp_history() { History * htmp; - + if (history == 0) { return; } - + htmp = new History(oid, history->seq + 1, history->hid, @@ -406,20 +424,20 @@ void VirtualMachine::cp_history() history->vm_dir, history->vmm_mad_name, history->tm_mad_name); - + if ( previous_history != 0 ) { delete previous_history; } - + previous_history = history; - history = htmp; + history = htmp; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ - + void VirtualMachine::cp_previous_history() { History * htmp; @@ -428,7 +446,7 @@ void VirtualMachine::cp_previous_history() { return; } - + htmp = new History(oid, history->seq + 1, previous_history->hid, @@ -436,12 +454,12 @@ void VirtualMachine::cp_previous_history() previous_history->vm_dir, previous_history->vmm_mad_name, previous_history->tm_mad_name); - + delete previous_history; - + previous_history = history; - - history = htmp; + + history = htmp; } /* -------------------------------------------------------------------------- */ @@ -452,7 +470,7 @@ void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk) string scpu; istringstream iss; float fcpu; - + get_template_attribute("MEMORY",memory); get_template_attribute("CPU",scpu); @@ -461,7 +479,7 @@ void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk) cpu = 0; memory = 0; disk = 0; - + return; } @@ -482,11 +500,11 @@ int VirtualMachine::get_leases() { int num_nics, rc; vector nics; - VirtualNetworkPool * vnpool; + VirtualNetworkPool * vnpool; VirtualNetwork * vn; VectorAttribute * nic; map new_nic; - + string ip; string mac; string bridge; @@ -495,37 +513,37 @@ int VirtualMachine::get_leases() ostringstream vnid; // Set the networking attributes. - + Nebula& nd = Nebula::instance(); vnpool = nd.get_vnpool(); - + num_nics = vm_template.get("NIC",nics); - + for(int i=0; i(nics[i]); if ( nic == 0 ) { continue; } - + network = nic->vector_value("NETWORK"); - + if ( network.empty() ) { continue; } - + vn = vnpool->get(network,true); - + if ( vn == 0 ) { - continue; + return -1; } - + ip = nic->vector_value("IP"); - + if (ip.empty()) { rc = vn->get_lease(oid, ip, mac, bridge); @@ -534,9 +552,9 @@ int VirtualMachine::get_leases() { rc = vn->set_lease(oid, ip, mac, bridge); } - - vn->unlock(); - + + vn->unlock(); + if ( rc != 0 ) { return -1; @@ -549,12 +567,12 @@ int VirtualMachine::get_leases() new_nic.insert(make_pair("BRIDGE" ,bridge)); new_nic.insert(make_pair("VNID" ,vnid.str())); new_nic.insert(make_pair("IP" ,ip)); - + nic->replace(new_nic); - + new_nic.erase(new_nic.begin(),new_nic.end()); } - + return 0; } @@ -564,7 +582,7 @@ int VirtualMachine::get_leases() void VirtualMachine::release_leases() { Nebula& nd = Nebula::instance(); - + VirtualNetworkPool * vnpool = nd.get_vnpool(); string vnid; @@ -572,7 +590,7 @@ void VirtualMachine::release_leases() int num_nics; vector nics; - VirtualNetwork * vn; + VirtualNetwork * vn; num_nics = get_template_attribute("NIC",nics); @@ -591,26 +609,80 @@ void VirtualMachine::release_leases() { continue; } - + ip = nic->vector_value("IP"); if ( ip.empty() ) { continue; } - + vn = vnpool->get(atoi(vnid.c_str()),true); - + if ( vn == 0 ) { continue; } - vn->release_lease(ip); - vn->unlock(); + vn->release_lease(ip); + vn->unlock(); } } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachine::write_context() +{ + ofstream file; + + vector attrs; + const VectorAttribute * context; + + map::const_iterator it; + + if ( history == 0 ) + return -1; + + if ( get_template_attribute("CONTEXT",attrs) != 1 ) + { + log("VM", Log::INFO, "Virtual Machine has no context"); + return 0; + } + + file.open(history->context_file.c_str(),ios::out); + + if (file.fail() == true) + { + ostringstream oss; + + oss << "Could not open context file: " << history->context_file; + log("VM", Log::ERROR, oss); + return -1; + } + + context = dynamic_cast(attrs[0]); + + if (context == 0) + { + file.close(); + return -1; + } + + const map values = context->value(); + + file << "# Context variables generated by OpenNebula\n"; + + for (it=values.begin(); it != values.end(); it++ ) + { + file << it->first <<"=\""<< it->second << "\"" << endl; + } + + file.close(); + + return 0; +} + /* ************************************************************************** */ /* Virtual Machine :: Misc */ /* ************************************************************************** */ @@ -622,15 +694,15 @@ ostream& operator<<(ostream& os, VirtualMachine& vm) os << "STATE : " << vm.state << endl; os << "LCM STATE : " << vm.lcm_state << endl; os << "DEPLOY ID : " << vm.deploy_id << endl; - os << "MEMORY : " << vm.memory << endl; + os << "MEMORY : " << vm.memory << endl; os << "CPU : " << vm.cpu << endl; - os << "LAST POLL : " << vm.last_poll << endl; - os << "START TIME : " << vm.stime << endl; - os << "STOP TIME : " << vm.etime << endl; - os << "NET TX : " << vm.net_tx << endl; + os << "LAST POLL : " << vm.last_poll << endl; + os << "START TIME : " << vm.stime << endl; + os << "STOP TIME : " << vm.etime << endl; + os << "NET TX : " << vm.net_tx << endl; os << "NET RX : " << vm.net_rx << endl; os << "Template" << endl << vm.vm_template << endl; - + return os; }; diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index 064f508116..93ba657637 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -17,6 +17,11 @@ #include "Nebula.h" #include "VirtualMachinePool.h" +#include "vm_var_syntax.h" +extern "C" +{ + #include "vm_var_parser.h" +} #include int VirtualMachinePool::allocate ( @@ -25,15 +30,17 @@ int VirtualMachinePool::allocate ( int * oid, bool on_hold) { - VirtualMachine * vm; - - char * error_msg; - int rc; - + VirtualMachine * vm; + + char * error_msg; + int rc; + + vector attrs; + // Build a new Virtual Machine object vm = new VirtualMachine; - + if (on_hold == true) { vm->state = VirtualMachine::HOLD; @@ -50,23 +57,33 @@ int VirtualMachinePool::allocate ( if ( rc != 0 ) { ostringstream oss; - - oss << error_msg; + + oss << error_msg; Nebula::log("ONE", Log::ERROR, oss); free(error_msg); return -2; } + vm->vm_template.remove("CONTEXT",attrs); + // Insert the Object in the pool *oid = PoolSQL::allocate(vm); - + if ( *oid == -1 ) { return -1; } + generate_context(*oid,attrs); + + for (int i = 0; i < attrs.size() ; i++) + { + if (attrs[i] != 0) + delete attrs[i]; + } + return 0; } @@ -102,3 +119,150 @@ int VirtualMachinePool::get_pending( return PoolSQL::search(oids,VirtualMachine::table,where); }; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachinePool::generate_context(int vm_id, vector attrs) +{ + VirtualMachine * vm; + VectorAttribute * context_parsed; + VectorAttribute * context; + + string * str; + string parsed; + + int rc; + + char * error_msg; + + if ( attrs.size() == 0 ) + { + return; + } + + context = dynamic_cast(attrs[0]); + + if (context == 0) + { + return; + } + + str = context->marshall(" @^_^@ "); + + if (str == 0) + { + return; + } + + rc = parse_attribute(vm_id,*str,parsed,&error_msg); + + if ( rc != 0 ) + { + if (error_msg != 0) + { + ostringstream oss; + + oss << error_msg << ": " << *str; + free(error_msg); + + Nebula::log("ONE", Log::ERROR, oss); + } + + delete str; + + return; + } + + delete str; + + context_parsed = new VectorAttribute("CONTEXT"); + context_parsed->unmarshall(parsed," @^_^@ "); + + vm = get(vm_id,true); + + if ( vm == 0 ) + { + return; + } + + vm->insert_template_attribute(db,context_parsed); + + vm->unlock(); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +pthread_mutex_t VirtualMachinePool::lex_mutex = PTHREAD_MUTEX_INITIALIZER; + +extern "C" +{ + int vm_var_parse (VirtualMachinePool * vmpool, + ostringstream * parsed, + VirtualMachine * vm, + 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); +} + + +int VirtualMachinePool::parse_attribute(int vm_id, + string &attribute, + string &parsed, + char ** error_msg) +{ + YY_BUFFER_STATE str_buffer; + const char * str; + int rc; + VirtualMachine * vm; + ostringstream oss_parsed; + + *error_msg = 0; + + pthread_mutex_lock(&lex_mutex); + + vm = get(vm_id,true); + + if ( vm == 0 ) + { + goto error_vm; + } + + str = attribute.c_str(); + str_buffer = vm_var__scan_string(str); + + if (str_buffer == 0) + { + goto error_yy; + } + + rc = vm_var_parse(this,&oss_parsed,vm,error_msg); + + vm_var__delete_buffer(str_buffer); + + vm_var_lex_destroy(); + + vm->unlock(); + + pthread_mutex_unlock(&lex_mutex); + + parsed = oss_parsed.str(); + + return rc; + +error_vm: + *error_msg=strdup("Could not find virtual machine!"); + goto error_common; + +error_yy: + *error_msg=strdup("Error setting scan buffer"); + vm->unlock(); +error_common: + pthread_mutex_unlock(&lex_mutex); + return -1; +}