diff --git a/SConstruct b/SConstruct index 1c3203d935..3bf25cec2b 100644 --- a/SConstruct +++ b/SConstruct @@ -63,6 +63,7 @@ main_env.Append(LIBPATH=[ cwd+'/src/pool', cwd+'/src/template', cwd+'/src/vm', + cwd+'/src/vm_template', cwd+'/src/vmm', cwd+'/src/lcm', cwd+'/src/tm', @@ -127,15 +128,27 @@ else: main_env.Append(parsers='no') if not main_env.GetOption('clean'): + try: + if mysql=='yes': + main_env.ParseConfig('mysql_config --cflags --libs') + except Exception, e: + print "" + print "mysql_config was not found in the path" + print "" + print "Check that mysql development package is installed and" + print "mysql_config is in the path. If your mysql config tool" + print "is called mysql5_config make a symlink as mysql_config" + print "to a directory in the path." + print "" + exit(-1) + + try: main_env.ParseConfig(("LDFLAGS='%s' share/scons/get_xmlrpc_config"+ " server") % (os.environ['LDFLAGS'],)) main_env.ParseConfig(("LDFLAGS='%s' share/scons/get_xmlrpc_config"+ " client") % (os.environ['LDFLAGS'],)) - if mysql=='yes': - main_env.ParseConfig('mysql_config --cflags --libs') - except Exception, e: print "" print "Error searching for xmlrpc-c libraries. Please check this"+\ @@ -178,6 +191,7 @@ build_scripts=[ 'src/nebula/SConstruct', 'src/pool/SConstruct', 'src/vm/SConstruct', + 'src/vm_template/SConstruct', 'src/vmm/SConstruct', 'src/lcm/SConstruct', 'src/rm/SConstruct', @@ -228,6 +242,7 @@ if testing=='yes': 'src/vm/test/SConstruct', 'src/vnm/test/SConstruct', 'src/xml/test/SConstruct', + 'src/vm_template/test/SConstruct', ]) else: main_env.Append(testing='no') diff --git a/include/Attribute.h b/include/Attribute.h index dcaa05d765..d390e92ee7 100644 --- a/include/Attribute.h +++ b/include/Attribute.h @@ -39,6 +39,17 @@ public: attribute_name.end(), attribute_name.begin(), (int(*)(int))toupper); + + // FIX Attribute name if it does not conform XML element + // naming conventions + + int size = attribute_name.size(); + + if ((size >0 && !isalpha(aname[0]))|| + (size >=3 && (aname[0]=='X' && aname[1]=='M' && aname[2]=='L'))) + { + attribute_name.insert(0,"ONE_"); + } }; virtual ~Attribute(){}; @@ -82,8 +93,12 @@ public: */ virtual AttributeType type() = 0; -private: + /** + * Clones the current attribute + */ + virtual Attribute* clone() const = 0; +protected: /** * The attribute name. */ @@ -107,6 +122,11 @@ public: SingleAttribute(const string& name, const string& value): Attribute(name),attribute_value(value){}; + SingleAttribute(const SingleAttribute& sa):Attribute(sa.attribute_name) + { + attribute_value = sa.attribute_value; + }; + ~SingleAttribute(){}; /** @@ -173,6 +193,14 @@ public: return SIMPLE; }; + /** + * Clones the current attribute + */ + Attribute* clone() const + { + return new SingleAttribute(*this); + }; + private: string attribute_value; @@ -195,6 +223,11 @@ public: VectorAttribute(const string& name,const map& value): Attribute(name),attribute_value(value){}; + VectorAttribute(const VectorAttribute& va):Attribute(va.attribute_name) + { + attribute_value = va.attribute_value; + }; + ~VectorAttribute(){}; /** @@ -256,6 +289,14 @@ public: return VECTOR; }; + /** + * Clones the current attribute + */ + Attribute* clone() const + { + return new VectorAttribute(*this); + }; + private: static const char * magic_sep; diff --git a/include/AuthManager.h b/include/AuthManager.h index 307ebc29e1..e456f02fee 100644 --- a/include/AuthManager.h +++ b/include/AuthManager.h @@ -276,11 +276,12 @@ public: */ enum Operation { - CREATE, /** Authorization to create an object (host, vm, net, image)*/ - DELETE, /** Authorization to delete an object */ - USE, /** Authorization to use an object */ - MANAGE, /** Authorization to manage an object */ - INFO /** Authorization to view an object */ + CREATE, /** Authorization to create an object */ + DELETE, /** Authorization to delete an object */ + USE, /** Authorization to use an object */ + MANAGE, /** Authorization to manage an object */ + INFO, /** Authorization to view an object */ + INSTANTIATE /** Authorization to instantiate a VM from a TEMPLATE */ }; /** @@ -293,7 +294,8 @@ public: NET, IMAGE, USER, - CLUSTER + CLUSTER, + TEMPLATE }; /** diff --git a/include/Host.h b/include/Host.h index 6f7982413f..26726c35ae 100644 --- a/include/Host.h +++ b/include/Host.h @@ -181,63 +181,6 @@ public: return 0; }; - // ------------------------------------------------------------------------ - // Template - // ------------------------------------------------------------------------ - - /** - * Gets the values of a template attribute - * @param name of the attribute - * @param values of the attribute - * @return the number of values - */ - int get_template_attribute( - string& name, - vector& values) const - { - return host_template.get(name,values); - }; - - /** - * Gets the values of a template attribute - * @param name of the attribute - * @param values of the attribute - * @return the number of values - */ - int get_template_attribute( - const char *name, - vector& values) const - { - 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 - */ - void get_template_attribute( - const char * name, - string& value) const - { - string str=name; - 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 - */ - void get_template_attribute( - const char * name, - int& value) const - { - string str=name; - host_template.get(str,value); - } - // ------------------------------------------------------------------------ // Share functions // ------------------------------------------------------------------------ @@ -394,12 +337,6 @@ private: // ------------------------------------------------------------------------- // Host Attributes // ------------------------------------------------------------------------- - - /** - * The Host template, holds the Host attributes. - */ - HostTemplate host_template; - /** * The Share represents the logical capacity associated with the host */ diff --git a/include/Image.h b/include/Image.h index 90b4a116ee..1ce8c795c8 100644 --- a/include/Image.h +++ b/include/Image.h @@ -47,7 +47,9 @@ public: INIT = 0, /** < Initialization state */ READY = 1, /** < Image ready to use */ USED = 2, /** < Image in use */ - DISABLED = 3 /** < Image can not be instantiated by a VM */ + DISABLED = 3, /** < Image can not be instantiated by a VM */ + LOCKED = 4, /** < FS operation for the Image in process */ + ERROR = 5 /** < Error state the operation FAILED*/ }; /** @@ -92,6 +94,74 @@ public: return (persistent_img == 1); }; + /** + * Returns the source path of the image + * @return source of image + */ + const string& get_source() + { + return source; + } + + /** + * Returns the source path of the image + * @return source of image + */ + void set_source(const string& _source) + { + source = _source; + } + + /** + * Returns the type of the image + * @return type + */ + ImageType get_type() + { + return type; + } + /** + * Returns the image state + * @return state of image + */ + ImageState get_state() + { + return state; + } + + /** + * Sets the image state + * @param state of image + */ + void set_state(ImageState _state) + { + state = _state; + } + + /** + * + */ + int dec_running () + { + return --running_vms; + } + + /** + * + */ + int inc_running() + { + return ++running_vms; + } + + /** + * + */ + int get_running() + { + return running_vms; + } + /** * Set enum type * @return 0 on success, -1 otherwise @@ -120,47 +190,6 @@ public: return rc; } - /** - * Get an image to be used in a VM, and updates its state. - * @return 0 if success - */ - int acquire_image(); - - - /** - * Releases an image being used by a VM - * @return true if the image needs to be updated - */ - bool release_image(); - - /** - * Enables the image - * @param to_enable true will enable the image. - * @return 0 on success - */ - int enable(bool to_enable) - { - int rc = 0; - - if ( to_enable == true ) - { - if(state == DISABLED) - { - state = READY; - } - } - else if (state != USED) // to_enable == false - { - state = DISABLED; - } - else - { - rc = -1; - } - - return rc; - } - /** * Publish or unpublish an image * @param pub true to publish the image @@ -230,93 +259,6 @@ public: */ int disk_attribute(VectorAttribute * disk, int* index, ImageType* img_type); - // ------------------------------------------------------------------------ - // Template - // ------------------------------------------------------------------------ - - /** - * Gets the values of a template attribute - * @param name of the attribute - * @param values of the attribute - * @return the number of values - */ - int get_template_attribute( - string& name, - vector& values) const - { - return image_template->get(name,values); - }; - - /** - * Gets the values of a template attribute - * @param name of the attribute - * @param values of the attribute - * @return the number of values - */ - int get_template_attribute( - const char *name, - vector& values) const - { - string str=name; - return image_template->get(str,values); - }; - - /** - * Gets a string based Image attribute - * @param name of the attribute - * @param value of the attribute (a string), will be "" if not defined - */ - void get_template_attribute( - const char * name, - string& value) const - { - string str=name; - image_template->get(str,value); - } - - /** - * Gets a string based Image attribute - * @param name of the attribute - * @param value of the attribute (an int), will be 0 if not defined - */ - void get_template_attribute( - const char * name, - int& value) const - { - string str=name; - image_template->get(str,value); - } - - /** - * Removes an Image attribute - * @param name of the attribute - */ - int remove_template_attribute(const string& name) - { - return image_template->erase(name); - } - - /** - * Adds a new attribute to the template (replacing it if - * already defined), the image's mutex SHOULD be locked - * @param name of the new attribute - * @param value of the new attribute - * @return 0 on success - */ - int replace_template_attribute( - const string& name, - const string& value) - { - SingleAttribute * sattr; - - image_template->erase(name); - - sattr = new SingleAttribute(name,value); - image_template->set(sattr); - - return 0; - } - private: // ------------------------------------------------------------------------- @@ -369,16 +311,6 @@ private: */ int running_vms; - // ------------------------------------------------------------------------- - // Image Attributes - // ------------------------------------------------------------------------- - - /** - * The Image template, holds the Image attributes. - */ - ImageTemplate * image_template; - - // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* @@ -401,13 +333,12 @@ private: db->exec(oss_image); }; - /** * "Encrypts" the password with SHA1 digest * @param password * @return sha1 encrypted password */ - string sha1_digest(const string& pass); + static string sha1_digest(const string& pass); protected: diff --git a/include/ImageManager.h b/include/ImageManager.h new file mode 100644 index 0000000000..7ba9299606 --- /dev/null +++ b/include/ImageManager.h @@ -0,0 +1,204 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, 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 IMAGE_MANAGER_H_ +#define IMAGE_MANAGER_H_ + +#include "MadManager.h" +#include "ActionManager.h" +#include "ImageManagerDriver.h" + +using namespace std; + +extern "C" void * image_action_loop(void *arg); + +class Image; + +class ImageManager : public MadManager, public ActionListener +{ +public: + + ImageManager(ImagePool * _ipool, vector& _mads): + MadManager(_mads), ipool(_ipool) + { + am.addListener(this); + }; + + ~ImageManager(){}; + + /** + * This functions starts the associated listener thread, and creates a + * new thread for the Information Manager. This thread will wait in + * an action loop till it receives ACTION_FINALIZE. + * @return 0 on success. + */ + int start(); + + /** + * Loads the Image Driver defined in configuration file + * @param uid of the user executing the driver. When uid is 0 the nebula + * identity will be used. Otherwise the Mad will be loaded through the + * sudo application. + */ + void load_mads(int uid=0); + + /** + * Gets the thread identification. + * @return pthread_t for the manager thread (that in the action loop). + */ + pthread_t get_thread_id() const + { + return imagem_thread; + }; + + /** + * Finalizes the Image Manager + */ + void finalize() + { + am.trigger(ACTION_FINALIZE,0); + }; + + /**************************************************************************/ + /* Image Manager Actions */ + /* Operates in a semi-sinchronous mode. Operations will be granted or not */ + /* , when needed the image repository drivers will be used to perform FS */ + /* operations in the background. */ + /**************************************************************************/ + + /** + * Try to acquire an image from the repository for a VM. + * @param image_id id of image + * @return pointer to the image or 0 if could not be acquired + */ + Image * acquire_image(int image_id); + + /** + * Try to acquire an image from the repository for a VM. + * @param name of the image + * @param id of owner + * @return pointer to the image or 0 if could not be acquired + */ + Image * acquire_image(const string& name, int uid); + + /** + * Releases an image and triggers any needed operations in the repo + * @param iid image id of the image to be released + * @param disk_path base path for disk location + * @param disk number for this image in the VM + * @param saveid id of image to save the current image + */ + void release_image(const string& iid, + const string& disk_path, + int disk_num, + const string& saveid); + + /** + * Moves a VM disk to the Image Repository + * @param disk_path base path for disk location + * @param disk number for this image in the VM + * @param saveid id of image to save the current image + */ + void disk_to_image(const string& disk_path, + int disk_num, + const string& save_id); + + /** + * Enables the image + * @param to_enable true will enable the image. + * @return 0 on success + */ + int enable_image(int iid, bool to_enable); + + /** + * Adds a new image to the repository copying or creating it as needed + * @param iid id of image + * @return 0 on success + */ + int register_image(int iid); + + /** + * Deletes an image from the repository and the DB + * @param iid id of image + * @return 0 on success + */ + int delete_image(int iid); + +private: + /** + * Generic name for the Image driver + */ + static const char * image_driver_name; + + /** + * Thread id for the Transfer Manager + */ + pthread_t imagem_thread; + + /** + * Pointer to the Image Pool to access VMs + */ + ImagePool * ipool; + + /** + * Action engine for the Manager + */ + ActionManager am; + + /** + * Returns a pointer to the Image Manager Driver used for the Repository + * @return the Image Manager driver or 0 in not found + */ + const ImageManagerDriver * get() + { + string name("NAME"); + + return static_cast + (MadManager::get(0,name,image_driver_name)); + }; + + /** + * Function to execute the Manager action loop method within a new pthread + * (requires C linkage) + */ + friend void * image_action_loop(void *arg); + + /** + * The action function executed when an action is triggered. + * @param action the name of the action + * @param arg arguments for the action function + */ + void do_action( + const string & action, + void * arg); + + /** + * Acquires an image updating its state. + * @param image pointer to image, it should be locked + * @return 0 on success + */ + int acquire_image(Image *img); + + /** + * Moves a file to an image in the repository + * @param image to be updated (it's source attribute) + * @param source path of the disk file + */ + void move_image(Image *img, const string& source); +}; + +#endif /*IMAGE_MANAGER_H*/ + diff --git a/include/ImageManagerDriver.h b/include/ImageManagerDriver.h new file mode 100644 index 0000000000..7a07c73350 --- /dev/null +++ b/include/ImageManagerDriver.h @@ -0,0 +1,105 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, 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 IMAGE_MANAGER_DRIVER_H_ +#define IMAGE_MANAGER_DRIVER_H_ + +#include +#include +#include + +#include "Mad.h" + +using namespace std; + +//Forward definition of related classes +class ImagePool; +class ImageManager; + +/** + * ImageManagerDriver represents the basic abstraction for Image Repository + * drivers. It implements the protocol and recover functions from the Mad + * interface. + */ +class ImageManagerDriver : public Mad +{ +public: + + ImageManagerDriver(int userid, + const map& attrs, + bool sudo, + ImagePool* _ipool): + Mad(userid,attrs,sudo),ipool(_ipool){}; + + virtual ~ImageManagerDriver(){}; + + /** + * Implements the Image Manager driver protocol. + * @param message the string read from the driver + */ + void protocol(string& message); + + /** + * TODO: What do we need here? Check on-going xfr? + */ + void recover(); + +private: + friend class ImageManager; + + /** + * Reference to the ImagePool + */ + ImagePool * ipool; + + /** + * Configuration file for the driver + */ + //Template driver_conf; + + void cp(int oid, const string& source) const; + + /** + * Sends a move request to the MAD: "MV IMAGE_ID SRC_PATH DST_PATH" + * @param oid the image id. + * @param destination is a driver specific location or "-" if not + * initialized + * @param size_mb of the image to be created + */ + void mv(int oid, const string& source, const string& destination) const; + + /** + * Sends a make filesystem request to the MAD: "MKFS IMAGE_ID PATH SIZE_MB" + * @param oid the image id. + * @param fs type + * @param size_mb of the image to be created + */ + void mkfs(int oid, + const string& fs, + const string& size_mb) const; + /** + * Sends a delete request to the MAD: "DELETE IMAGE_ID PATH" + * @param oid the image id. + * @param destination is the path to the image to be removed + */ + void rm(int oid, const string& destination) const; +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +#endif /*IMAGE_MANAGER_DRIVER_H_*/ + diff --git a/include/ImagePool.h b/include/ImagePool.h index d319ff1dda..9dae46d2ed 100644 --- a/include/ImagePool.h +++ b/include/ImagePool.h @@ -39,7 +39,6 @@ class ImagePool : public PoolSQL public: ImagePool(SqlDB * db, - const string& _source_prefix, const string& _default_type, const string& _default_dev_prefix); @@ -146,11 +145,6 @@ public: */ void authorize_disk(VectorAttribute * disk, int uid, AuthRequest * ar); - static const string& source_prefix() - { - return _source_prefix; - }; - static const string& default_type() { return _default_type; @@ -165,10 +159,6 @@ private: //-------------------------------------------------------------------------- // Configuration Attributes for Images // ------------------------------------------------------------------------- - /** - * Path to the image repository - **/ - static string _source_prefix; /** * Default image type diff --git a/include/Mad.h b/include/Mad.h index 70ae7ffe21..789df4ac0f 100644 --- a/include/Mad.h +++ b/include/Mad.h @@ -26,6 +26,8 @@ #include +#include "Log.h" + using namespace std; /** @@ -68,12 +70,11 @@ protected: { string str; const char * cstr; - size_t retval; str = os.str(); cstr = str.c_str(); - retval = ::write(nebula_mad_pipe, cstr, str.size()); + ::write(nebula_mad_pipe, cstr, str.size()); }; /** @@ -89,6 +90,32 @@ protected: write(os); }; + /** + * Sets the log message type as specify by the driver. + * @param first character of the type string + * @return the message type + */ + Log::MessageType log_type(const char r) + { + Log::MessageType lt; + + switch (r) + { + case 'E': + lt = Log::ERROR; + break; + case 'I': + lt = Log::INFO; + break; + case 'D': + lt = Log::DEBUG; + break; + default: + lt = Log::INFO; + } + + return lt; + } private: friend class MadManager; @@ -141,7 +168,7 @@ private: * @return 0 on success */ int reload(); - + /** * Implements the driver specific protocol, this function should trigger * actions on the associated manager. diff --git a/include/MySqlDB.h b/include/MySqlDB.h index b733020de2..a32cd03c31 100644 --- a/include/MySqlDB.h +++ b/include/MySqlDB.h @@ -43,11 +43,11 @@ class MySqlDB : public SqlDB { public: - MySqlDB(const string& server, - int port, - const string& user, - const string& password, - const char * database); + MySqlDB(const string& _server, + int _port, + const string& _user, + const string& _password, + const string& _database); ~MySqlDB(); @@ -81,6 +81,19 @@ private: */ MYSQL * db; + /** + * MySQL Connection parameters + */ + string server; + + int port; + + string user; + + string password; + + string database; + /** * Fine-grain mutex for DB access */ @@ -113,7 +126,7 @@ public: int port, string user, string password, - const char * database) + string database) { throw runtime_error("Aborting oned, MySQL support not compiled!"); }; diff --git a/include/Nebula.h b/include/Nebula.h index 9019ae8ddb..a677815583 100644 --- a/include/Nebula.h +++ b/include/Nebula.h @@ -25,6 +25,7 @@ #include "VirtualNetworkPool.h" #include "HostPool.h" #include "UserPool.h" +#include "VMTemplatePool.h" #include "VirtualMachineManager.h" #include "LifeCycleManager.h" @@ -34,6 +35,7 @@ #include "RequestManager.h" #include "HookManager.h" #include "AuthManager.h" +#include "ImageManager.h" class Nebula { @@ -80,6 +82,11 @@ public: return cpool; }; + VMTemplatePool * get_tpool() + { + return tpool; + }; + // -------------------------------------------------------------- // Manager Accessors // -------------------------------------------------------------- @@ -114,12 +121,16 @@ public: return hm; }; - AuthManager * get_authm() { return authm; }; + ImageManager * get_imagem() + { + return imagem; + }; + // -------------------------------------------------------------- // Environment & Configuration // -------------------------------------------------------------- @@ -228,8 +239,9 @@ 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), - ipool(0),cpool(0),lcm(0),vmm(0),im(0),tm(0),dm(0),rm(0),hm(0),authm(0) + Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0), + upool(0),ipool(0),cpool(0),tpool(0),lcm(0),vmm(0),im(0),tm(0),dm(0), + rm(0),hm(0),authm(0),imagem(0) { const char * nl = getenv("ONE_LOCATION"); @@ -294,6 +306,11 @@ private: delete cpool; } + if ( tpool != 0) + { + delete tpool; + } + if ( vmm != 0) { delete vmm; @@ -334,6 +351,11 @@ private: delete authm; } + if ( imagem != 0) + { + delete imagem; + } + if ( nebula_configuration != 0) { delete nebula_configuration; @@ -381,6 +403,7 @@ private: UserPool * upool; ImagePool * ipool; ClusterPool * cpool; + VMTemplatePool * tpool; // --------------------------------------------------------------- // Nebula Managers @@ -394,6 +417,7 @@ private: RequestManager * rm; HookManager * hm; AuthManager * authm; + ImageManager * imagem; // --------------------------------------------------------------- // Implementation functions diff --git a/include/PoolObjectSQL.h b/include/PoolObjectSQL.h index fc8727004c..2709d66a49 100644 --- a/include/PoolObjectSQL.h +++ b/include/PoolObjectSQL.h @@ -19,6 +19,7 @@ #include "ObjectSQL.h" #include "ObjectXML.h" +#include "Template.h" #include #include @@ -32,14 +33,13 @@ using namespace std; * implementation assumes that the mutex IS LOCKED when the class destructor * is called. */ - class PoolObjectSQL : public ObjectSQL, public ObjectXML { public: PoolObjectSQL(int id, const string& _name, int _uid,const char *_table) :ObjectSQL(),ObjectXML(),oid(id),name(_name),uid(_uid), - valid(true),table(_table) + valid(true),obj_template(0),table(_table) { pthread_mutex_init(&mutex,0); }; @@ -119,6 +119,110 @@ public: */ virtual int from_xml(const string &xml_str) = 0; + // ------------------------------------------------------------------------ + // Template + // ------------------------------------------------------------------------ + + /** + * Gets the values of a template attribute + * @param name of the attribute + * @param values of the attribute + * @return the number of values + */ + int get_template_attribute( + string& name, + vector& values) const + { + return obj_template->get(name,values); + }; + + /** + * Gets the values of a template attribute + * @param name of the attribute + * @param values of the attribute + * @return the number of values + */ + int get_template_attribute( + const char *name, + vector& values) const + { + string str=name; + return obj_template->get(str,values); + }; + + /** + * Gets a string based attribute (single) + * @param name of the attribute + * @param value of the attribute (a string), will be "" if not defined or + * not a single attribute + */ + void get_template_attribute( + const char * name, + string& value) const + { + string str=name; + obj_template->get(str,value); + } + + /** + * Gets an int based 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 + */ + void get_template_attribute( + const char * name, + int& value) const + { + string str=name; + obj_template->get(str,value); + } + + /** + * Adds a new attribute to the template (replacing it if + * already defined), the object's mutex SHOULD be locked + * @param name of the new attribute + * @param value of the new attribute + * @return 0 on success + */ + int replace_template_attribute( + const string& name, + const string& value) + { + SingleAttribute * sattr = new SingleAttribute(name,value); + + obj_template->erase(sattr->name()); + + obj_template->set(sattr); + + return 0; + } + + /** + * Generates a XML string for the template of the Object + * @param xml the string to store the XML description. + */ + void template_to_xml(string &xml) const + { + obj_template->to_xml(xml); + } + + /** + * Removes an Image attribute + * @param name of the attribute + */ + int remove_template_attribute(const string& name) + { + return obj_template->erase(name); + } + + /** + * Sets an error message for the VM in the template + * @param message + * @return 0 on success + */ + void set_template_error_message(const string& message); + protected: /** @@ -198,6 +302,11 @@ protected: */ bool valid; + /** + * Template for this object, will be allocated if needed + */ + Template * obj_template; + private: /** @@ -215,6 +324,11 @@ private: * Pointer to the SQL table for the PoolObjectSQL */ const char * table; + + /** + * Name for the error messages attribute + */ + static const char * error_attribute_name; }; #endif /*POOL_OBJECT_SQL_H_*/ diff --git a/include/RequestManager.h b/include/RequestManager.h index 4128b20784..e604581e30 100644 --- a/include/RequestManager.h +++ b/include/RequestManager.h @@ -24,6 +24,7 @@ #include "VirtualNetworkPool.h" #include "ImagePool.h" #include "ClusterPool.h" +#include "VMTemplatePool.h" #include #include @@ -46,10 +47,11 @@ public: UserPool * _upool, ImagePool * _ipool, ClusterPool * _cpool, + VMTemplatePool * _tpool, int _port, string _xml_log_file) :vmpool(_vmpool),hpool(_hpool),vnpool(_vnpool),upool(_upool), - ipool(_ipool),cpool(_cpool),port(_port),socket_fd(-1), + ipool(_ipool),cpool(_cpool),tpool(_tpool),port(_port),socket_fd(-1), xml_log_file(_xml_log_file) { am.addListener(this); @@ -130,10 +132,15 @@ private: ImagePool * ipool; /** - * Pointer to the Image Pool, to access images + * Pointer to the Cluster Pool, to access clusters */ ClusterPool * cpool; + /** + * Pointer to the Template Pool, to access templates + */ + VMTemplatePool * tpool; + /** * Port number where the connection will be open */ @@ -314,10 +321,12 @@ private: VirtualMachinePool * _vmpool, VirtualNetworkPool * _vnpool, ImagePool * _ipool, + VMTemplatePool * _tpool, UserPool * _upool): vmpool(_vmpool), vnpool(_vnpool), ipool(_ipool), + tpool(_tpool), upool(_upool) { _signature="A:ss"; @@ -333,6 +342,7 @@ private: VirtualMachinePool * vmpool; VirtualNetworkPool * vnpool; ImagePool * ipool; + VMTemplatePool * tpool; UserPool * upool; }; @@ -459,8 +469,9 @@ private: upool(_upool), ipool(_ipool) { - _signature="A:siii"; - _help="Sets the disk to be saved in the given image."; + _signature="A:siis"; + _help = "Sets the disk to be saved in a new Image with the given " + "name."; }; ~VirtualMachineSaveDisk(){}; @@ -501,6 +512,185 @@ private: UserPool * upool; }; + /* ---------------------------------------------------------------------- */ + /* Template Interface */ + /* ---------------------------------------------------------------------- */ + + class TemplateAllocate: public xmlrpc_c::method + { + public: + TemplateAllocate( + VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:ss"; + _help="Allocates a template in the pool"; + }; + + ~TemplateAllocate(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplateDelete: public xmlrpc_c::method + { + public: + TemplateDelete(VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:si"; + _help="Deletes a Template"; + }; + + ~TemplateDelete(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplateInfo: public xmlrpc_c::method + { + public: + TemplateInfo(VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:si"; + _help="Returns information for a Template"; + }; + + ~TemplateInfo(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplateUpdate: public xmlrpc_c::method + { + public: + TemplateUpdate(VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:siss"; + _help="Modifies Template attribute"; + }; + + ~TemplateUpdate(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplateRemoveAttribute: public xmlrpc_c::method + { + public: + TemplateRemoveAttribute(VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:sis"; + _help="Removes Template attribute"; + }; + + ~TemplateRemoveAttribute(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplatePublish: public xmlrpc_c::method + { + public: + TemplatePublish(VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:sib"; + _help="Publish/Unpublish the Template"; + }; + + ~TemplatePublish(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplatePoolInfo: public xmlrpc_c::method + { + public: + TemplatePoolInfo( + VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:sii"; + _help="Returns the template pool"; + }; + + ~TemplatePoolInfo(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + /* ---------------------------------------------------------------------- */ /* Host Interface */ /* ---------------------------------------------------------------------- */ diff --git a/include/Template.h b/include/Template.h index d81cf4b8c2..2c623ffb42 100644 --- a/include/Template.h +++ b/include/Template.h @@ -47,6 +47,20 @@ public: separator(_separator), xml_root(_xml_root){}; + Template(const Template& t) + { + multimap::const_iterator it; + + replace_mode = t.replace_mode; + separator = t.separator; + xml_root = t.xml_root; + + for (it = t.attributes.begin() ; it != t.attributes.end() ; it++) + { + attributes.insert(make_pair(it->first,(it->second)->clone())); + } + } + /** * The class destructor frees all the attributes conforming the template */ @@ -161,8 +175,10 @@ public: * @param name the attribute name. * @param value the attribute value, an int, 0 if the attribute is not * defined or not Single + * + * @returns True if the Single attribute was found */ - virtual void get( + virtual bool get( string& name, int& value) const; diff --git a/include/User.h b/include/User.h index c2437bc617..be2acaecae 100644 --- a/include/User.h +++ b/include/User.h @@ -134,15 +134,6 @@ private: */ int insert_replace(SqlDB *db, bool replace); - /** - * 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 - */ - int select_cb(void *nil, int num, char **values, char **names); - /** * Bootstraps the database table(s) associated to the User */ diff --git a/include/VMTemplate.h b/include/VMTemplate.h new file mode 100644 index 0000000000..7a92818bda --- /dev/null +++ b/include/VMTemplate.h @@ -0,0 +1,190 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, 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 VMTEMPLATE_H_ +#define VMTEMPLATE_H_ + +#include "PoolObjectSQL.h" +#include "VirtualMachineTemplate.h" + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +/** + * The VMTemplate class. + */ +class VMTemplate : public PoolObjectSQL +{ +public: + + /** + * Function to write a VMTemplate on an output stream + */ + friend ostream& operator<<(ostream& os, VMTemplate& u); + + /** + * Function to print the VMTemplate 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; + + /** + * Returns true if the object is public + * @return true if the Virtual Network is public + */ + bool isPublic() + { + return (public_template == 1); + }; + + /** + * Publish or unpublish an object + * @param pub true to publish the object + * @return 0 on success + */ + bool publish(bool pub) + { + if (pub == true) + { + public_template = 1; + } + else + { + public_template = 0; + } + + return true; + }; + + // ------------------------------------------------------------------------ + // Template Contents + // ------------------------------------------------------------------------ + + /** + * Returns a copy of the VirtualMachineTemplate + * @return A copy of the VirtualMachineTemplate + */ + VirtualMachineTemplate * clone_template() const + { + return new VirtualMachineTemplate( + *(static_cast(obj_template))); + + // TODO: Check if there is a more efficient way to do this copy. + /*string xml_str; + VirtualMachineTemplate * new_template = new VirtualMachineTemplate(); + + obj_template->to_xml(xml_str); + new_template->from_xml(xml_str); + + return new_template;*/ + }; + +private: + // ------------------------------------------------------------------------- + // Friends + // ------------------------------------------------------------------------- + + friend class VMTemplatePool; + + // ------------------------------------------------------------------------- + // VMTemplate Attributes + // ------------------------------------------------------------------------- + + /** + * Owner's name + */ + string user_name; + + /** + * Public scope of the VMTemplate + */ + int public_template; + + /** + * Registration time + */ + time_t regtime; + + // ************************************************************************* + // 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 one success + */ + int insert_replace(SqlDB *db, bool replace); + + /** + * Bootstraps the database table(s) associated to the VMTemplate + */ + static void bootstrap(SqlDB * db) + { + ostringstream oss(VMTemplate::db_bootstrap); + + db->exec(oss); + }; + + /** + * Rebuilds the object from an xml formatted string + * @param xml_str The xml-formatted string + * + * @return 0 on success, -1 otherwise + */ + int from_xml(const string &xml_str); + +protected: + + // ************************************************************************* + // Constructor + // ************************************************************************* + VMTemplate(int id, int uid, string _user_name, + VirtualMachineTemplate * _template_contents); + + ~VMTemplate(); + + // ************************************************************************* + // DataBase implementation + // ************************************************************************* + + static const char * db_names; + + static const char * db_bootstrap; + + static const char * table; + + /** + * Writes the VMTemplate in the database. + * @param db pointer to the db + * @return 0 on success + */ + int insert(SqlDB *db, string& error_str); + + /** + * Writes/updates the VMTemplate data fields in the database. + * @param db pointer to the db + * @return 0 on success + */ + int update(SqlDB *db) + { + return insert_replace(db, true); + }; +}; + +#endif /*VMTEMPLATE_H_*/ diff --git a/include/VMTemplatePool.h b/include/VMTemplatePool.h new file mode 100644 index 0000000000..92660f6226 --- /dev/null +++ b/include/VMTemplatePool.h @@ -0,0 +1,146 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, 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 VMTEMPLATE_POOL_H_ +#define VMTEMPLATE_POOL_H_ + +#include "PoolSQL.h" +#include "VMTemplate.h" + +/** + * The VMTemplate Pool class. + */ +class VMTemplatePool : public PoolSQL +{ +public: + + VMTemplatePool(SqlDB * db) : PoolSQL(db, VMTemplate::table){}; + + ~VMTemplatePool(){}; + + /** + * Allocates a new object, writting it in the pool database. No memory is + * allocated for the object. + * @param uid user id (the owner of the Template) + * @param user_name Owner's user name + * @param template_contents a VM Template object + * @param oid the id assigned to the Template + * @param error_str Returns the error reason, if any + * + * @return the oid assigned to the object, -1 in case of failure + */ + int allocate(int uid, + string user_name, + VirtualMachineTemplate * template_contents, + int * oid, + string& error_str); + + /** + * 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 + */ + VMTemplate * get(int oid, bool lock) + { + return static_cast(PoolSQL::get(oid,lock)); + }; + + /** + * Gets an object from the pool (if needed the object is loaded from the + * database). + * @param name of the object + * @param uid id of owner + * @param lock locks the object if true + * + * @return a pointer to the object, 0 in case of failure + */ + VMTemplate * get(const string& name, int uid, bool lock) + { + return static_cast(PoolSQL::get(name,uid,lock)); + }; + + /** + * 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. + */ + int update(VMTemplate * vm_template) + { + return vm_template->update(db); + }; + + /** + * 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. + */ + int drop(VMTemplate * vm_template) + { + return PoolSQL::drop(vm_template); + }; + + /** + * 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 + */ + int dump(ostringstream& oss, const string& where) + { + return PoolSQL::dump(oss, "VMTEMPLATE_POOL",VMTemplate::table,where); + }; + + /** + * Bootstraps the database table(s) associated to the pool + */ + static void bootstrap(SqlDB *_db) + { + VMTemplate::bootstrap(_db); + }; + +private: + //-------------------------------------------------------------------------- + // Configuration Attributes for Images + // ------------------------------------------------------------------------- + + // TODO + + //-------------------------------------------------------------------------- + // Pool Attributes + // ------------------------------------------------------------------------- + + // TODO + + + /** + * Factory method to produce Image objects + * @return a pointer to the new Image + */ + PoolObjectSQL * create() + { + return new VMTemplate(-1,-1,"", 0); + }; +}; + +#endif /*VMTEMPLATE_POOL_H_*/ diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 970a0ae22f..6295b100ca 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -532,93 +532,6 @@ public: // ------------------------------------------------------------------------ // Template // ------------------------------------------------------------------------ - - /** - * Gets the values of a template attribute - * @param name of the attribute - * @param values of the attribute - * @return the number of values - */ - int get_template_attribute( - string& name, - vector& values) const - { - return vm_template->get(name,values); - }; - - /** - * Gets the values of a template attribute - * @param name of the attribute - * @param values of the attribute - * @return the number of values - */ - int get_template_attribute( - const char *name, - vector& values) const - { - string str=name; - return vm_template->get(str,values); - }; - - /** - * 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 - */ - void get_template_attribute( - const char * name, - string& value) const - { - string str=name; - 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 - */ - void get_template_attribute( - const char * name, - int& value) const - { - string str=name; - vm_template->get(str,value); - } - - /** - * Adds a new attribute to the template (replacing it if - * already defined), the vm's mutex SHOULD be locked - * @param name of the new attribute - * @param value of the new attribute - * @return 0 on success - */ - int replace_template_attribute( - string& name, - string& value) - { - SingleAttribute * sattr; - - vm_template->erase(name); - - sattr = new SingleAttribute(name,value); - vm_template->set(sattr); - - return 0; - } - - - /** - * 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); - } - /** * Parse a string and substitute variables (e.g. $NAME) using the VM * template values: @@ -626,12 +539,11 @@ public: * @param parsed, the resulting parsed string * @return 0 on success. */ - int parse_template_attribute(const string& attribute, - string& parsed); + int parse_template_attribute(const string& attribute, string& parsed); + // ------------------------------------------------------------------------ // States // ------------------------------------------------------------------------ - /** * Returns the VM state (Dispatch Manager) * @return the VM state @@ -743,7 +655,7 @@ public: * @param img_id ID of the image this disk will be saved to. * @return 0 if success */ - int save_disk(int disk_id, int img_id); + int save_disk(int disk_id, int img_id, string& error_str); private: @@ -775,14 +687,6 @@ private: // ------------------------------------------------------------------------- // Virtual Machine Description // ------------------------------------------------------------------------- - - /** - * The Virtual Machine template, holds the VM attributes. - */ - VirtualMachineTemplate* vm_template; - - // Dynamic state of the Virtual Machine - /** * The state of the virtual machine. */ @@ -914,7 +818,6 @@ private: return -1; }; - // ------------------------------------------------------------------------- // Attribute Parser // ------------------------------------------------------------------------- diff --git a/include/VirtualMachinePool.h b/include/VirtualMachinePool.h index c069357f61..cedf998473 100644 --- a/include/VirtualMachinePool.h +++ b/include/VirtualMachinePool.h @@ -41,8 +41,10 @@ public: /** * Function to allocate a new VM object * @param uid user id (the owner of the VM) + * @param user_name Owner's user name * @param vm_template a VM Template object describing the VM * @param oid the id assigned to the VM (output) + * @param error_str Returns the error reason, if any * @param on_hold flag to submit on hold * @return oid on success, -1 error inserting in DB or -2 error parsing * the template diff --git a/include/VirtualMachineTemplate.h b/include/VirtualMachineTemplate.h index a8c76404b6..c19fbdf171 100644 --- a/include/VirtualMachineTemplate.h +++ b/include/VirtualMachineTemplate.h @@ -19,6 +19,8 @@ #include "Template.h" +#include + using namespace std; /** @@ -32,6 +34,8 @@ public: ~VirtualMachineTemplate(){}; + VirtualMachineTemplate(VirtualMachineTemplate& vmt):Template(vmt){}; + private: friend class VirtualMachine; }; diff --git a/include/VirtualNetwork.h b/include/VirtualNetwork.h index daf20f5d62..5df5114888 100644 --- a/include/VirtualNetwork.h +++ b/include/VirtualNetwork.h @@ -19,7 +19,6 @@ #include "PoolSQL.h" -#include "VirtualNetworkTemplate.h" #include "Leases.h" #include @@ -33,10 +32,11 @@ using namespace std; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +class VirtualNetworkTemplate; /** - * The Virtual Network class. It represents a Virtual Network at manages its leases. - * One lease is formed by one IP and one MAC address. + * The Virtual Network class. It represents a Virtual Network at manages its + * leases. One lease is formed by one IP and one MAC address. * MAC address are derived from IP addresses. */ class VirtualNetwork : public PoolObjectSQL @@ -176,63 +176,6 @@ public: */ int nic_attribute(VectorAttribute * nic, int vid); - //------------------------------------------------------------------------ - // Template - // ------------------------------------------------------------------------ - - /** - * Gets the values of a template attribute - * @param name of the attribute - * @param values of the attribute - * @return the number of values - */ - int get_template_attribute( - string& name, - vector& values) const - { - return vn_template->get(name,values); - }; - - /** - * Gets the values of a template attribute - * @param name of the attribute - * @param values of the attribute - * @return the number of values - */ - int get_template_attribute( - const char *name, - vector& values) const - { - 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 - */ - void get_template_attribute( - const char * name, - string& value) const - { - string str=name; - 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 - */ - void get_template_attribute( - const char * name, - int& value) const - { - string str=name; - vn_template->get(str,value); - } - private: // ------------------------------------------------------------------------- @@ -280,11 +223,6 @@ private: */ Leases * leases; - /** - * The Virtual Network template, holds the VNW attributes. - */ - VirtualNetworkTemplate * vn_template; - // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* diff --git a/include/test/NebulaTest.h b/include/test/NebulaTest.h index 18589b0da4..52c551799d 100644 --- a/include/test/NebulaTest.h +++ b/include/test/NebulaTest.h @@ -26,6 +26,7 @@ #include "HostPool.h" #include "UserPool.h" #include "ClusterPool.h" +#include "VMTemplatePool.h" #include "VirtualMachineManager.h" #include "LifeCycleManager.h" @@ -35,6 +36,7 @@ #include "RequestManager.h" #include "HookManager.h" #include "AuthManager.h" +#include "ImageManager.h" class NebulaTest { @@ -42,7 +44,8 @@ protected: NebulaTest():mysql(false), need_host_pool(false), need_vm_pool(false), need_vnet_pool(false), need_image_pool(false), - need_user_pool(false), need_cluster_pool(false),need_vmm(false), + need_user_pool(false), need_cluster_pool(false), + need_template_pool(false),need_vmm(false), need_im(false), need_tm(false), need_lcm(false), need_dm(false), need_rm(false), need_hm(false), @@ -62,6 +65,7 @@ public: bool need_image_pool; bool need_user_pool; bool need_cluster_pool; + bool need_template_pool; bool need_vmm; bool need_im; @@ -71,6 +75,7 @@ public: bool need_rm; bool need_hm; bool need_authm; + bool need_imagem; static NebulaTest * instance() { @@ -92,12 +97,13 @@ public: virtual UserPool* create_upool(SqlDB* db); virtual ImagePool* create_ipool( SqlDB* db, - string repository_path, string default_image_type, string default_device_prefix); virtual ClusterPool* create_cpool(SqlDB* db); + virtual VMTemplatePool* create_tpool(SqlDB* db); + // ------------------------------------------------------------------------ // Managers // ------------------------------------------------------------------------ @@ -127,11 +133,14 @@ public: UserPool * upool, ImagePool * ipool, ClusterPool * cpool, + VMTemplatePool * tpool, string log_file); virtual HookManager* create_hm(VirtualMachinePool * vmpool); virtual AuthManager* create_authm(time_t timer_period); + + virtual ImageManager* create_imagem(ImagePool * ipool); }; #endif /*NEBULA_TEST_H_*/ diff --git a/include/test/OneUnitTest.h b/include/test/OneUnitTest.h index e3a4823438..ff07a79775 100644 --- a/include/test/OneUnitTest.h +++ b/include/test/OneUnitTest.h @@ -57,7 +57,7 @@ public: if (mysql) { db = new MySqlDB( "localhost",0, - "oneadmin","oneadmin",NULL); + "oneadmin","oneadmin",db_name); ostringstream oss1; oss1 << "DROP DATABASE IF EXISTS " << db_name; diff --git a/install.sh b/install.sh index c7b090f721..716a499a42 100755 --- a/install.sh +++ b/install.sh @@ -193,7 +193,10 @@ LIB_DIRS="$LIB_LOCATION/ruby \ $LIB_LOCATION/remotes/im/xen.d \ $LIB_LOCATION/remotes/im/ganglia.d \ $LIB_LOCATION/remotes/vmm/xen \ - $LIB_LOCATION/remotes/vmm/kvm" + $LIB_LOCATION/remotes/vmm/kvm \ + $LIB_LOCATION/remotes/image \ + $LIB_LOCATION/remotes/image/fs \ + $LIB_LOCATION/sh" VAR_DIRS="$VAR_LOCATION/remotes \ $VAR_LOCATION/remotes/im \ @@ -201,7 +204,9 @@ VAR_DIRS="$VAR_LOCATION/remotes \ $VAR_LOCATION/remotes/im/xen.d \ $VAR_LOCATION/remotes/im/ganglia.d \ $VAR_LOCATION/remotes/vmm/xen \ - $VAR_LOCATION/remotes/vmm/kvm" + $VAR_LOCATION/remotes/vmm/kvm \ + $VAR_LOCATION/remotes/image \ + $VAR_LOCATION/remotes/image/fs" SUNSTONE_DIRS="$SUNSTONE_LOCATION/models \ $SUNSTONE_LOCATION/models/OpenNebulaJSON \ @@ -253,6 +258,12 @@ INSTALL_FILES=( LIB_FILES:$LIB_LOCATION RUBY_LIB_FILES:$LIB_LOCATION/ruby RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/OpenNebula + MAD_RUBY_LIB_FILES:$LIB_LOCATION/ruby + MAD_RUBY_LIB_FILES:$LIB_LOCATION/remotes + MAD_RUBY_LIB_FILES:$VAR_LOCATION/remotes + MAD_SH_LIB_FILES:$LIB_LOCATION/sh + MAD_SH_LIB_FILES:$LIB_LOCATION/remotes + MAD_SH_LIB_FILES:$VAR_LOCATION/remotes MADS_LIB_FILES:$LIB_LOCATION/mads IM_PROBES_FILES:$VAR_LOCATION/remotes/im IM_PROBES_KVM_FILES:$VAR_LOCATION/remotes/im/kvm.d @@ -278,6 +289,8 @@ INSTALL_FILES=( SSH_TM_COMMANDS_LIB_FILES:$LIB_LOCATION/tm_commands/ssh DUMMY_TM_COMMANDS_LIB_FILES:$LIB_LOCATION/tm_commands/dummy LVM_TM_COMMANDS_LIB_FILES:$LIB_LOCATION/tm_commands/lvm + IMAGE_DRIVER_FS_SCRIPTS:$LIB_LOCATION/remotes/image/fs + IMAGE_DRIVER_FS_SCRIPTS:$VAR_LOCATION/remotes/image/fs EXAMPLE_SHARE_FILES:$SHARE_LOCATION/examples TM_EXAMPLE_SHARE_FILES:$SHARE_LOCATION/examples/tm HOOK_SHARE_FILES:$SHARE_LOCATION/hooks @@ -354,6 +367,7 @@ BIN_FILES="src/nebula/oned \ src/cli/oneuser \ src/cli/oneimage \ src/cli/onecluster \ + src/cli/onetemplate \ share/scripts/one \ src/authm_mad/oneauth" @@ -396,11 +410,21 @@ RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/OpenNebula/Host.rb \ src/oca/ruby/OpenNebula/VirtualNetworkPool.rb \ src/oca/ruby/OpenNebula/Image.rb \ src/oca/ruby/OpenNebula/ImagePool.rb \ - src/oca/ruby/OpenNebula/ImageRepository.rb \ src/oca/ruby/OpenNebula/Cluster.rb \ src/oca/ruby/OpenNebula/ClusterPool.rb \ + src/oca/ruby/OpenNebula/Template.rb \ + src/oca/ruby/OpenNebula/TemplatePool.rb \ src/oca/ruby/OpenNebula/XMLUtils.rb" + +#----------------------------------------------------------------------------- +# MAD Script library files, to be installed under $LIB_LOCATION/ + diff --git a/src/template/Template.cc b/src/template/Template.cc index 75a2b9f712..f880cf78c2 100644 --- a/src/template/Template.cc +++ b/src/template/Template.cc @@ -14,8 +14,6 @@ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ -#include - #include "Template.h" #include "template_syntax.h" @@ -309,7 +307,7 @@ void Template::get( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -void Template::get( +bool Template::get( string& name, int& value) const { @@ -320,12 +318,13 @@ void Template::get( if ( sval == "" ) { value = 0; - return; + return false; } istringstream iss(sval); iss >> value; + return true; } /* -------------------------------------------------------------------------- */ diff --git a/src/test/Nebula.cc b/src/test/Nebula.cc index 7fbf0642b3..0c07de18cf 100644 --- a/src/test/Nebula.cc +++ b/src/test/Nebula.cc @@ -82,6 +82,11 @@ void Nebula::start() delete cpool; } + if ( tpool != 0) + { + delete tpool; + } + if ( vmm != 0) { delete vmm; @@ -178,7 +183,6 @@ void Nebula::start() { string mac_prefix = "00:00"; int size = 1; - string repository_path; string default_image_type; string default_device_prefix; @@ -205,7 +209,6 @@ void Nebula::start() if (tester->need_image_pool) { ipool = tester->create_ipool(db, - repository_path, default_image_type, default_device_prefix); } @@ -214,6 +217,11 @@ void Nebula::start() { cpool = tester->create_cpool(db); } + + if (tester->need_template_pool) + { + tpool = tester->create_tpool(db); + } } catch (exception&) { @@ -358,7 +366,7 @@ void Nebula::start() { try { - rm = tester->create_rm(vmpool,hpool,vnpool,upool,ipool,cpool, + rm = tester->create_rm(vmpool,hpool,vnpool,upool,ipool,cpool,tpool, log_location + "one_xmlrpc.log"); } catch (bad_alloc&) @@ -424,6 +432,29 @@ void Nebula::start() } } + // ---- Auth Manager ---- + if (tester->need_imagem) + { + try + { + imagem = tester->create_imagem(ipool); + } + catch (bad_alloc&) + { + throw; + } + + if (imagem != 0) + { + rc = imagem->start(); + + if ( rc != 0 ) + { + throw runtime_error("Could not start the Image Manager"); + } + } + } + // ----------------------------------------------------------- // Load mads // ----------------------------------------------------------- diff --git a/src/test/NebulaTest.cc b/src/test/NebulaTest.cc index d953962b5e..c0a6b04808 100644 --- a/src/test/NebulaTest.cc +++ b/src/test/NebulaTest.cc @@ -41,12 +41,10 @@ UserPool* NebulaTest::create_upool(SqlDB* db) } ImagePool* NebulaTest::create_ipool( SqlDB* db, - string repository_path, string default_image_type, string default_device_prefix) { - return new ImagePool(db,repository_path,default_image_type, - default_device_prefix); + return new ImagePool(db,default_image_type,default_device_prefix); } ClusterPool* NebulaTest::create_cpool(SqlDB* db) @@ -54,6 +52,11 @@ ClusterPool* NebulaTest::create_cpool(SqlDB* db) return new ClusterPool(db); } +VMTemplatePool* NebulaTest::create_tpool(SqlDB* db) +{ + return new VMTemplatePool(db); +} + // ----------------------------------------------------------- // Managers // ----------------------------------------------------------- @@ -112,6 +115,7 @@ RequestManager* NebulaTest::create_rm( UserPool * upool, ImagePool * ipool, ClusterPool * cpool, + VMTemplatePool * tpool, string log_file) { int rm_port = 2633; @@ -122,6 +126,7 @@ RequestManager* NebulaTest::create_rm( upool, ipool, cpool, + tpool, rm_port, log_file); } @@ -145,3 +150,18 @@ AuthManager* NebulaTest::create_authm(time_t timer_period) { return 0; } + +ImageManager* NebulaTest::create_imagem(ImagePool * ipool) +{ + map mad_value; + VectorAttribute * mad; + + vector im_mads; + + mad_value.insert(make_pair("executable","one_image")); + + mad = new VectorAttribute("HM_MAD",mad_value); + im_mads.push_back(mad); + + return new ImageManager(ipool,im_mads); +} diff --git a/src/tm/TransferManagerDriver.cc b/src/tm/TransferManagerDriver.cc index 86dd932759..29cefc49b1 100644 --- a/src/tm/TransferManagerDriver.cc +++ b/src/tm/TransferManagerDriver.cc @@ -79,7 +79,7 @@ void TransferManagerDriver::protocol( is.clear(); getline(is,info); - NebulaLog::log("TM",Log::INFO, info.c_str()); + NebulaLog::log("TM",log_type(result[0]), info.c_str()); } return; @@ -142,8 +142,16 @@ void TransferManagerDriver::protocol( getline(is,info); os.str(""); - os << "Error excuting image transfer script: " << info; + os << "Error excuting image transfer script"; + + if (!info.empty() && info[0] != '-') + { + os << ": " << info; + vm->set_template_error_message(os.str()); + vmpool->update(vm); + } + vm->log("TM",Log::ERROR,os); switch (vm->get_lcm_state()) @@ -171,7 +179,7 @@ void TransferManagerDriver::protocol( string info; getline(is,info); - vm->log("TM",Log::INFO,info.c_str()); + vm->log("TM",log_type(result[0]),info.c_str()); } vm->unlock(); diff --git a/src/tm_mad/TMScript.rb b/src/tm_mad/TMScript.rb index 1d3b7bb085..be9decb1e7 100644 --- a/src/tm_mad/TMScript.rb +++ b/src/tm_mad/TMScript.rb @@ -27,18 +27,7 @@ are the names of the commands (uppercase) and contain the path of the script that will be executed for that command. It also contains some methods to execute the scripts, get the output -of the script (success/failure, error and log messages). The protocol -for scripts to do so is as follows: - -* Log messages will be sent to STDOUT -* The script will return 0 if it succeded or any other value - if there was a failure -* In case of failure the cause of the error will be written to STDERR - wrapped by start and end marks as follows: - - ERROR MESSAGE --8<------ - error message for the failure - ERROR MESSAGE ------>8-- +of the script (success/failure, error and log messages). =end class TMPlugin < Hash @@ -150,7 +139,7 @@ class TMScript if res.code == 0 res = [true, ""] else - res = [false, get_error_message(res.stderr)] + res = [false, res.get_error_message] end end @@ -176,13 +165,6 @@ class TMScript @lines<< command } end - - # Parses error message from +stderr+ output - def get_error_message(str) - tmp=str.scan(/^ERROR MESSAGE --8<------\n(.*?)ERROR MESSAGE ------>8--$/m) - return "Error message not available" if !tmp[0] - tmp[0][0].strip - end end diff --git a/src/tm_mad/nfs/tm_clone.sh b/src/tm_mad/nfs/tm_clone.sh index b54c826517..62c33fc2e8 100755 --- a/src/tm_mad/nfs/tm_clone.sh +++ b/src/tm_mad/nfs/tm_clone.sh @@ -34,8 +34,8 @@ DST_PATH=`arg_path $DST` fix_paths -log "$1 $2" -log "DST: $DST_PATH" +log_debug "$1 $2" +log_debug "DST: $DST_PATH" DST_DIR=`dirname $DST_PATH` @@ -46,12 +46,14 @@ exec_and_log "chmod a+w $DST_DIR" case $SRC in http://*) log "Downloading $SRC" - exec_and_log "$WGET -O $DST_PATH $SRC" + exec_and_log "$WGET -O $DST_PATH $SRC" \ + "Error downloading $SRC" ;; *) log "Cloning $SRC_PATH" - exec_and_log "cp -r $SRC_PATH $DST_PATH" + exec_and_log "cp -r $SRC_PATH $DST_PATH" \ + "Error copying $SRC to $DST" ;; esac diff --git a/src/tm_mad/nfs/tm_context.sh b/src/tm_mad/nfs/tm_context.sh index b079622054..f211024f3d 100755 --- a/src/tm_mad/nfs/tm_context.sh +++ b/src/tm_mad/nfs/tm_context.sh @@ -48,16 +48,19 @@ exec_and_log "mkdir -p $ISO_DIR" for f in $SRC; do case $f in http://*) - exec_and_log "$WGET -O $ISO_DIR $f" + exec_and_log "$WGET -O $ISO_DIR $f" \ + "Error downloading $f" ;; *) - exec_and_log "cp -R $f $ISO_DIR" + exec_and_log "cp -R $f $ISO_DIR" \ + "Error copying $f to $ISO_DIR" ;; esac done -exec_and_log "$MKISOFS -o $DST_PATH -J -R $ISO_DIR" +exec_and_log "$MKISOFS -o $DST_PATH -J -R $ISO_DIR" \ + "Error creating iso fs" exec_and_log "rm -rf $ISO_DIR" diff --git a/src/tm_mad/nfs/tm_delete.sh b/src/tm_mad/nfs/tm_delete.sh index cf1ff88742..942e0678cf 100755 --- a/src/tm_mad/nfs/tm_delete.sh +++ b/src/tm_mad/nfs/tm_delete.sh @@ -34,4 +34,5 @@ SRC_PATH=`arg_path $SRC` fix_src_path log "Deleting $SRC_PATH" -exec_and_log "rm -rf $SRC_PATH" +exec_and_log "rm -rf $SRC_PATH" \ + "Error deleting $SRC_PATH" diff --git a/src/tm_mad/nfs/tm_ln.sh b/src/tm_mad/nfs/tm_ln.sh index 33b4a2a21c..1a3578e7b6 100755 --- a/src/tm_mad/nfs/tm_ln.sh +++ b/src/tm_mad/nfs/tm_ln.sh @@ -37,7 +37,8 @@ fix_dst_path DST_DIR=`dirname $DST_PATH` log "Creating directory $DST_DIR" -exec_and_log "mkdir -p $DST_DIR" +exec_and_log "mkdir -p $DST_DIR" \ + "Could not create directory $DST_DIR" exec_and_log "chmod a+w $DST_DIR" log "Link $SRC_PATH" diff --git a/src/tm_mad/nfs/tm_mkimage.sh b/src/tm_mad/nfs/tm_mkimage.sh index ddafb405ec..b30c0ff327 100755 --- a/src/tm_mad/nfs/tm_mkimage.sh +++ b/src/tm_mad/nfs/tm_mkimage.sh @@ -36,8 +36,11 @@ fix_dst_path DST_DIR=`dirname $DST_PATH` -exec_and_log "mkdir -p $DST_DIR" -exec_and_log "$DD if=/dev/zero of=$DST_PATH bs=1 count=1 seek=${SIZE}M" -exec_and_log "$MKFS -t $FSTYPE -F $DST_PATH" +exec_and_log "mkdir -p $DST_DIR" \ + "Error creating directory $DST_DIR" +exec_and_log "$DD if=/dev/zero of=$DST_PATH bs=1 count=1 seek=${SIZE}M" \ + "Could not create image $DST_PATH" +exec_and_log "$MKFS -t $FSTYPE -F $DST_PATH" \ + "Unable to create filesystem $FSTYPE in $DST_PATH" exec_and_log "chmod a+rw $DST_PATH" diff --git a/src/tm_mad/nfs/tm_mkswap.sh b/src/tm_mad/nfs/tm_mkswap.sh index af78a59087..58b1e286fb 100755 --- a/src/tm_mad/nfs/tm_mkswap.sh +++ b/src/tm_mad/nfs/tm_mkswap.sh @@ -35,15 +35,17 @@ fix_dst_path DST_DIR=`dirname $DST_PATH` -log "Creating directory $DST_DIR" +log_debug "Creating directory $DST_DIR" exec_and_log "mkdir -p $DST_DIR" exec_and_log "chmod a+w $DST_DIR" -log "Creating ${SIZE}Mb image in $DST_PATH" -exec_and_log "$DD if=/dev/zero of=$DST_PATH bs=1 count=1 seek=${SIZE}M" +log_debug "Creating ${SIZE}Mb image in $DST_PATH" +exec_and_log "$DD if=/dev/zero of=$DST_PATH bs=1 count=1 seek=${SIZE}M" \ + "Could not create image file $DST_PATH" -log "Initializing swap space" -exec_and_log "$MKSWAP $DST_PATH" +log_debug "Initializing swap space" +exec_and_log "$MKSWAP $DST_PATH" \ + "Could not create swap on $DST_PATH" exec_and_log "chmod a+w $DST_PATH" diff --git a/src/tm_mad/nfs/tm_mv.sh b/src/tm_mad/nfs/tm_mv.sh index 68902f969b..23483b6655 100755 --- a/src/tm_mad/nfs/tm_mv.sh +++ b/src/tm_mad/nfs/tm_mv.sh @@ -43,7 +43,8 @@ else log "Will not move, is not saving image" else log "Moving $SRC_PATH" - exec_and_log "mv $SRC_PATH $DST_PATH" + exec_and_log "mv $SRC_PATH $DST_PATH" \ + "Could not move $SRC_PATH to $DST_PATH" fi fi diff --git a/src/tm_mad/ssh/tm_clone.sh b/src/tm_mad/ssh/tm_clone.sh index 8507c43e0a..71800d1874 100755 --- a/src/tm_mad/ssh/tm_clone.sh +++ b/src/tm_mad/ssh/tm_clone.sh @@ -34,23 +34,26 @@ SRC_HOST=`arg_host $SRC` DST_HOST=`arg_host $DST` -log "$1 $2" -log "DST: $DST_PATH" +log_debug "$1 $2" +log_debug "DST: $DST_PATH" DST_DIR=`dirname $DST_PATH` log "Creating directory $DST_DIR" -exec_and_log "$SSH $DST_HOST mkdir -p $DST_DIR" +exec_and_log "$SSH $DST_HOST mkdir -p $DST_DIR" \ + "Error creating directory $DST_DIR" case $SRC in http://*) log "Downloading $SRC" - exec_and_log "$SSH $DST_HOST $WGET -O $DST_PATH $SRC" + exec_and_log "$SSH $DST_HOST $WGET -O $DST_PATH $SRC" \ + "Error downloading $SRC" ;; *) log "Cloning $SRC" - exec_and_log "$SCP $SRC $DST" + exec_and_log "$SCP $SRC $DST" \ + "Error copying $SRC to $DST" ;; esac diff --git a/src/tm_mad/ssh/tm_context.sh b/src/tm_mad/ssh/tm_context.sh index ee7fd40603..322ebdaf1b 100755 --- a/src/tm_mad/ssh/tm_context.sh +++ b/src/tm_mad/ssh/tm_context.sh @@ -47,21 +47,27 @@ fi ISO_DIR="$TMP_DIR/isofiles" -exec_and_log "mkdir -p $ISO_DIR" +exec_and_log "mkdir -p $ISO_DIR" \ + "Error creating directory $ISO_DIR" for f in $SRC; do case $f in http://*) - exec_and_log "$WGET -O $ISO_DIR $f" + exec_and_log "$WGET -O $ISO_DIR $f" \ + "Error downloading $f" ;; *) - exec_and_log "cp -R $f $ISO_DIR" + exec_and_log "cp -R $f $ISO_DIR" \ + "Error copying $f to $ISO_DIR" ;; esac done -exec_and_log "$MKISOFS -o $TMP_DIR/$DST_FILE -J -R $ISO_DIR" -exec_and_log "$SCP $TMP_DIR/$DST_FILE $DST" -exec_and_log "rm -rf $TMP_DIR" +exec_and_log "$MKISOFS -o $TMP_DIR/$DST_FILE -J -R $ISO_DIR" \ + "Error creating iso fs" +exec_and_log "$SCP $TMP_DIR/$DST_FILE $DST" \ + "Error copying $TMP_DIR/$DST_FILE to $DST" +exec_and_log "rm -rf $TMP_DIR" \ + "Error deleting $TMP_DIR" diff --git a/src/tm_mad/ssh/tm_delete.sh b/src/tm_mad/ssh/tm_delete.sh index f0c7205a43..0824634ebd 100755 --- a/src/tm_mad/ssh/tm_delete.sh +++ b/src/tm_mad/ssh/tm_delete.sh @@ -31,4 +31,5 @@ SRC_PATH=`arg_path $SRC` SRC_HOST=`arg_host $SRC` log "Deleting $SRC_PATH" -exec_and_log "$SSH $SRC_HOST rm -rf $SRC_PATH" +exec_and_log "$SSH $SRC_HOST rm -rf $SRC_PATH" \ + "Error deleting $SRC_PATH" diff --git a/src/tm_mad/ssh/tm_mkimage.sh b/src/tm_mad/ssh/tm_mkimage.sh index d092a8b9b2..81ff20f32c 100755 --- a/src/tm_mad/ssh/tm_mkimage.sh +++ b/src/tm_mad/ssh/tm_mkimage.sh @@ -32,7 +32,10 @@ DST_PATH=`arg_path $DST` DST_HOST=`arg_host $DST` DST_DIR=`dirname $DST_PATH` -exec_and_log "$SSH $DST_HOST mkdir -p $DST_DIR" -exec_and_log "$SSH $DST_HOST $DD if=/dev/zero of=$DST_PATH bs=1 count=1 seek=${SIZE}M" -exec_and_log "$SSH $DST_HOST $MKFS -t $FSTYPE -F $DST_PATH" -exec_and_log "$SSH $DST_HOST chmod a+rw $DST_PATH" +exec_and_log "$SSH $DST_HOST mkdir -p $DST_DIR" \ + "Error creating directory $DST_DIR" +exec_and_log "$SSH $DST_HOST $DD if=/dev/zero of=$DST_PATH bs=1 count=1 seek=${SIZE}M" \ + "Could not create image $DST_PATH" +exec_and_log "$SSH $DST_HOST $MKFS -t $FSTYPE -F $DST_PATH" \ + "Unable to create filesystem $FSTYPE in $DST_PATH" +exec_and_log "$SSH $DST_HOST chmod a+rw $DST_PATH" \ No newline at end of file diff --git a/src/tm_mad/ssh/tm_mkswap.sh b/src/tm_mad/ssh/tm_mkswap.sh index 046a277bbc..60705134aa 100755 --- a/src/tm_mad/ssh/tm_mkswap.sh +++ b/src/tm_mad/ssh/tm_mkswap.sh @@ -34,10 +34,12 @@ DST_DIR=`dirname $DST_PATH` log "Creating ${SIZE}Mb image in $DST_PATH" exec_and_log "$SSH $DST_HOST mkdir -p $DST_DIR" -exec_and_log "$SSH $DST_HOST $DD if=/dev/zero of=$DST_PATH bs=1 count=1 seek=${SIZE}M" +exec_and_log "$SSH $DST_HOST $DD if=/dev/zero of=$DST_PATH bs=1 count=1 seek=${SIZE}M" \ + "Could not create image file $DST_PATH" log "Initializing swap space" -exec_and_log "$SSH $DST_HOST $MKSWAP $DST_PATH" +exec_and_log "$SSH $DST_HOST $MKSWAP $DST_PATH" \ + "Could not create swap on $DST_PATH" exec_and_log "$SSH $DST_HOST chmod a+w $DST_PATH" diff --git a/src/tm_mad/ssh/tm_mv.sh b/src/tm_mad/ssh/tm_mv.sh index 6d3ff82065..3f10354e8b 100755 --- a/src/tm_mad/ssh/tm_mv.sh +++ b/src/tm_mad/ssh/tm_mv.sh @@ -36,6 +36,8 @@ DST_HOST=`arg_host $DST` DST_DIR=`dirname $DST_PATH` log "Moving $SRC_PATH" -exec_and_log "$SSH $DST_HOST mkdir -p $DST_DIR" -exec_and_log "$SCP -r $SRC $DST" +exec_and_log "$SSH $DST_HOST mkdir -p $DST_DIR" \ + "Unable to create directory $DST_DIR" +exec_and_log "$SCP -r $SRC $DST" \ + "Could not copy $SRC to $DST" exec_and_log "$SSH $SRC_HOST rm -rf $SRC_PATH" diff --git a/src/tm_mad/tm_common.sh b/src/tm_mad/tm_common.sh index afcea79c46..00ad3fb18a 100644 --- a/src/tm_mad/tm_common.sh +++ b/src/tm_mad/tm_common.sh @@ -18,28 +18,17 @@ export LANG=C if [ -z "$ONE_LOCATION" ]; then ONE_LOCAL_VAR=/var/lib/one + ONE_LIB=/usr/lib/one else ONE_LOCAL_VAR=$ONE_LOCATION/var + ONE_LIB=$ONE_LOCATION/lib fi -# Paths for utilities -AWK=awk -BASH=/bin/bash -CUT=cut -DATE=/bin/date -DD=/bin/dd -LVCREATE=/sbin/lvcreate -LVREMOVE=/sbin/lvremove -LVS=/sbin/lvs -MD5SUM=/usr/bin/md5sum -MKFS=/sbin/mkfs -MKISOFS=/usr/bin/mkisofs -MKSWAP=/sbin/mkswap -SCP=/usr/bin/scp -SED=/bin/sed -SSH=/usr/bin/ssh -SUDO=/usr/bin/sudo -WGET=/usr/bin/wget +ONE_SH=$ONE_LIB/sh + +. $ONE_SH/scripts_common.sh + + if [ "x$(uname -s)" = "xLinux" ]; then SED="$SED -r" @@ -92,37 +81,6 @@ function fix_dst_path fi } -# Used for log messages -SCRIPT_NAME=`basename $0` - -# Formats date for logs -function log_date -{ - $DATE +"%a %b %d %T %Y" -} - -# Logs a message -function log -{ - echo "$SCRIPT_NAME: $1" -} - -# Logs an error message -function log_error -{ - log "ERROR: $1" -} - -# This function is used to pass error message to the mad -function error_message -{ - ( - echo "ERROR MESSAGE --8<------" - echo "$1" - echo "ERROR MESSAGE ------>8--" - ) 1>&2 -} - # Gets the host from an argument function arg_host { @@ -135,57 +93,5 @@ function arg_path echo $1 | $SED 's/^[^:]*:(.*)$/\1/' } -# Executes a command, if it fails return error message and exits -function exec_and_log -{ - output=`$1 2>&1 1>/dev/null` - code=$? - if [ "x$code" != "x0" ]; then - log_error "Command \"$1\" failed." - log_error "$output" - error_message "$output" - exit $code - fi - log "Executed \"$1\"." -} -# Like exec_and_log but the first argument is the number of seconds -# before here is timeout and kills the command -# -# NOTE: if the command is killed because a timeout the exit code -# will be 143 = 128+15 (SIGHUP) -function timeout_exec_and_log -{ - TIMEOUT=$1 - shift - - CMD="$1" - - exec_and_log "$CMD" & - CMD_PID=$! - - # timeout process - ( - sleep $TIMEOUT - kill $CMD_PID 2>/dev/null - log_error "Timeout executing $CMD" - error_message "Timeout executing $CMD" - exit -1 - ) & - TIMEOUT_PID=$! - - # stops the execution until the command finalizes - wait $CMD_PID 2>/dev/null - CMD_CODE=$? - - # if the script reaches here the command finished before it - # consumes timeout seconds so we can kill timeout process - kill $TIMEOUT_PID 2>/dev/null 1>/dev/null - wait $TIMEOUT_PID 2>/dev/null - - # checks the exit code of the command and exits if it is not 0 - if [ "x$CMD_CODE" != "x0" ]; then - exit $CMD_CODE - fi -} diff --git a/src/um/test/UserPoolTest.cc b/src/um/test/UserPoolTest.cc index fd41e94811..9815c3d111 100644 --- a/src/um/test/UserPoolTest.cc +++ b/src/um/test/UserPoolTest.cc @@ -175,11 +175,11 @@ public: void get_using_name() { - int oid_0, oid_1; + int oid_0; // Allocate two objects oid_0 = allocate(0); - oid_1 = allocate(1); + allocate(1); // --------------------------------- // Get first object and check its integrity diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 300fec15fc..83b0af12d2 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -58,11 +58,11 @@ VirtualMachine::VirtualMachine(int id, { if (_vm_template != 0) { - vm_template = _vm_template; + obj_template = _vm_template; } else { - vm_template = new VirtualMachineTemplate; + obj_template = new VirtualMachineTemplate; } } @@ -83,9 +83,9 @@ VirtualMachine::~VirtualMachine() delete _log; } - if ( vm_template != 0 ) + if ( obj_template != 0 ) { - delete vm_template; + delete obj_template; } } @@ -123,7 +123,7 @@ int VirtualMachine::select(SqlDB * db) return rc; } - //Get History Records. Current history is record is built in from_xml() (if any). + //Get History Records. Current history is built in from_xml() (if any). if( hasHistory() ) { last_seq = history->seq; @@ -191,7 +191,7 @@ int VirtualMachine::insert(SqlDB * db, string& error_str) attr = new SingleAttribute("VMID",value); - vm_template->set(attr); + obj_template->set(attr); get_template_attribute("NAME",name); @@ -202,7 +202,7 @@ int VirtualMachine::insert(SqlDB * db, string& error_str) name = oss.str(); attr = new SingleAttribute("NAME",name); - vm_template->set(attr); + obj_template->set(attr); } this->name = name; @@ -301,7 +301,7 @@ int VirtualMachine::parse_context(string& error_str) string * str; string parsed; - num = vm_template->remove("CONTEXT", array_context); + num = obj_template->remove("CONTEXT", array_context); if ( num == 0 ) { @@ -352,7 +352,7 @@ int VirtualMachine::parse_context(string& error_str) context_parsed->replace("TARGET", dev_prefix); } - vm_template->set(context_parsed); + obj_template->set(context_parsed); } /* --- Delete old context attributes --- */ @@ -378,7 +378,7 @@ void VirtualMachine::parse_graphics() vector array_graphics; VectorAttribute * graphics; - num = vm_template->get("GRAPHICS", array_graphics); + num = obj_template->get("GRAPHICS", array_graphics); if ( num == 0 ) { @@ -425,7 +425,7 @@ int VirtualMachine::parse_requirements(string& error_str) string parsed; - num = vm_template->remove("REQUIREMENTS", array_reqs); + num = obj_template->remove("REQUIREMENTS", array_reqs); if ( num == 0 ) { @@ -452,7 +452,7 @@ int VirtualMachine::parse_requirements(string& error_str) SingleAttribute * reqs_parsed; reqs_parsed = new SingleAttribute("REQUIREMENTS",parsed); - vm_template->set(reqs_parsed); + obj_template->set(reqs_parsed); } /* --- Delete old requirements attributes --- */ @@ -677,7 +677,7 @@ int VirtualMachine::get_disk_images(string& error_str) Nebula& nd = Nebula::instance(); ipool = nd.get_ipool(); - num_disks = vm_template->get("DISK",disks); + num_disks = obj_template->get("DISK",disks); for(int i=0, index=0; i disks; - Image * img; - ImagePool * ipool; + ImageManager * imagem; + + string disk_base_path = ""; Nebula& nd = Nebula::instance(); - ipool = nd.get_ipool(); + imagem = nd.get_imagem(); num_disks = get_template_attribute("DISK",disks); + if (hasHistory() != 0) + { + disk_base_path = get_local_dir(); + } + for(int i=0; ivector_value("IMAGE_ID"); + iid = disk->vector_value("IMAGE_ID"); + saveas = disk->vector_value("SAVE_AS"); if ( iid.empty() ) { - continue; + if (!saveas.empty()) + { + imagem->disk_to_image(disk_base_path,i,saveas); + } } - - img = ipool->get(atoi(iid.c_str()),true); - - if ( img == 0 ) + else { - continue; + imagem->release_image(iid,disk_base_path,i,saveas); } - - img->release_image(); - - saveas = disk->vector_value("SAVE_AS"); - - if ( !saveas.empty() && saveas == iid ) - { - img->enable(false); - } - - ipool->update(img); - - img->unlock(); } } @@ -820,7 +814,7 @@ int VirtualMachine::get_network_leases() Nebula& nd = Nebula::instance(); vnpool = nd.get_vnpool(); - num_nics = vm_template->get("NIC",nics); + num_nics = obj_template->get("NIC",nics); for(int i=0; i disks; @@ -970,7 +964,7 @@ int VirtualMachine::save_disk(int disk_id, int img_id) istringstream iss; - num_disks = vm_template->get("DISK",disks); + num_disks = obj_template->get("DISK",disks); for(int i=0; i> tmp_disk_id; - if( tmp_disk_id == disk_id ) + if ( tmp_disk_id == disk_id ) { + if(!((disk->vector_value("SAVE_AS")).empty())) + { + goto error_saved; + } + disk->replace("SAVE", "YES"); oss << (img_id); @@ -997,6 +996,19 @@ int VirtualMachine::save_disk(int disk_id, int img_id) } } + goto error_not_found; + +error_saved: + oss << "The DISK " << disk_id << " is already suppossed to be saved."; + goto error_common; + +error_not_found: + oss << "The DISK " << disk_id << " does not exist for VM " << oid << "."; + +error_common: + NebulaLog::log("VM",Log::ERROR, oss); + error_str = oss.str(); + return -1; } @@ -1106,7 +1118,7 @@ string& VirtualMachine::to_xml(string& xml) const << "" << cpu << "" << "" << net_tx << "" << "" << net_rx << "" - << vm_template->to_xml(template_xml); + << obj_template->to_xml(template_xml); if ( hasHistory() ) { @@ -1162,7 +1174,7 @@ int VirtualMachine::from_xml(const string &xml_str) } // Virtual Machine template - rc += vm_template->from_xml_node(content[0]); + rc += obj_template->from_xml_node(content[0]); // Last history entry content.clear(); diff --git a/src/vm_template/SConstruct b/src/vm_template/SConstruct new file mode 100644 index 0000000000..7705f4e7ff --- /dev/null +++ b/src/vm_template/SConstruct @@ -0,0 +1,30 @@ +# SConstruct for src/vm + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, 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_vmtemplate' + +# Sources to generate the library +source_files=[ + 'VMTemplate.cc', + 'VMTemplatePool.cc' +] + +# Build library +env.StaticLibrary(lib_name, source_files) diff --git a/src/vm_template/VMTemplate.cc b/src/vm_template/VMTemplate.cc new file mode 100644 index 0000000000..ac626f94f0 --- /dev/null +++ b/src/vm_template/VMTemplate.cc @@ -0,0 +1,246 @@ +/* ------------------------------------------------------------------------ */ +/* Copyright 2002-2011, 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 "VMTemplate.h" + +#define TO_UPPER(S) transform(S.begin(),S.end(),S.begin(),(int(*)(int))toupper) + + +/* ************************************************************************ */ +/* VMTemplate :: Constructor/Destructor */ +/* ************************************************************************ */ + +VMTemplate::VMTemplate(int id, + int _uid, + string _user_name, + VirtualMachineTemplate * _template_contents): + PoolObjectSQL(id,"",_uid,table), + user_name(_user_name), + regtime(time(0)) +{ + if (_template_contents != 0) + { + obj_template = _template_contents; + } + else + { + obj_template = new VirtualMachineTemplate; + } +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +VMTemplate::~VMTemplate() +{ + if ( obj_template != 0 ) + { + delete obj_template; + } +} + +/* ************************************************************************ */ +/* VMTemplate :: Database Access Functions */ +/* ************************************************************************ */ + +const char * VMTemplate::table = "template_pool"; + +const char * VMTemplate::db_names = "oid, name, body, uid, public"; + +const char * VMTemplate::db_bootstrap = + "CREATE TABLE IF NOT EXISTS template_pool (oid INTEGER PRIMARY KEY, " + "name VARCHAR(256), body TEXT, uid INTEGER, public INTEGER)"; + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int VMTemplate::insert(SqlDB *db, string& error_str) +{ + int rc; + ostringstream oss; + string public_attr; + + + // --------------------------------------------------------------------- + // Check default attributes + // --------------------------------------------------------------------- + + // ------------ NAME -------------------- + get_template_attribute("NAME", name); + + if ( name.empty() == true ) + { + oss.str(""); + oss << "template-" << oid; + name = oss.str(); + } + + // ------------ PUBLIC -------------------- + get_template_attribute("PUBLIC", public_attr); + + obj_template->erase("PUBLIC"); + + TO_UPPER(public_attr); + + public_template = (public_attr == "YES"); + + // ------------------------------------------------------------------------ + // Insert the Template + // ------------------------------------------------------------------------ + + rc = insert_replace(db, false); + + if ( rc != 0 ) + { + error_str = "Error inserting Template in DB."; + } + + return rc; +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int VMTemplate::insert_replace(SqlDB *db, bool replace) +{ + ostringstream oss; + + int rc; + string xml_body; + + char * sql_name; + char * sql_xml; + + // Update the Object + + sql_name = db->escape_str(name.c_str()); + + if ( sql_name == 0 ) + { + goto error_name; + } + + sql_xml = db->escape_str(to_xml(xml_body).c_str()); + + if ( sql_xml == 0 ) + { + goto error_body; + } + + if(replace) + { + oss << "REPLACE"; + } + else + { + oss << "INSERT"; + } + + // Construct the SQL statement to Insert or Replace + + oss <<" INTO "<exec(oss); + + db->free_str(sql_name); + db->free_str(sql_xml); + + return rc; + +error_body: + db->free_str(sql_name); +error_name: + return -1; +} + +/* ************************************************************************ */ +/* VMTemplate :: Misc */ +/* ************************************************************************ */ + +ostream& operator<<(ostream& os, VMTemplate& vmTemplate) +{ + string xml_str; + + os << vmTemplate.to_xml(xml_str); + + return os; +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +string& VMTemplate::to_xml(string& xml) const +{ + ostringstream oss; + string template_xml; + + oss << "" + << "" << oid << "" + << "" << uid << "" + << "" << user_name << "" + << "" << name << "" + << "" << public_template << "" + << "" << regtime << "" + << obj_template->to_xml(template_xml) + << ""; + + xml = oss.str(); + + return xml; +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int VMTemplate::from_xml(const string& xml) +{ + vector content; + int rc = 0; + + // Initialize the internal XML object + update_from_str(xml); + + // Get class base attributes + rc += xpath(oid, "/VMTEMPLATE/ID", -1); + rc += xpath(uid, "/VMTEMPLATE/UID", -1); + rc += xpath(user_name, "/VMTEMPLATE/USERNAME", "not_found"); + rc += xpath(name, "/VMTEMPLATE/NAME", "not_found"); + rc += xpath(public_template,"/VMTEMPLATE/PUBLIC", 0); + rc += xpath(regtime, "/VMTEMPLATE/REGTIME", 0); + + // Get associated classes + ObjectXML::get_nodes("/VMTEMPLATE/TEMPLATE", content); + + if( content.size() < 1 ) + { + return -1; + } + + // Template contents + rc += obj_template->from_xml_node(content[0]); + + if (rc != 0) + { + return -1; + } + + return 0; +} diff --git a/src/vm_template/VMTemplatePool.cc b/src/vm_template/VMTemplatePool.cc new file mode 100644 index 0000000000..a8ebe75179 --- /dev/null +++ b/src/vm_template/VMTemplatePool.cc @@ -0,0 +1,76 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, 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. */ +/* -------------------------------------------------------------------------- */ + +/* ************************************************************************** */ +/* Template Pool */ +/* ************************************************************************** */ + +#include "VMTemplatePool.h" + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VMTemplatePool::allocate ( + int uid, + string user_name, + VirtualMachineTemplate * template_contents, + int * oid, + string& error_str) +{ + VMTemplate * vm_template; + VMTemplate * vm_template_aux = 0; + string name; + ostringstream oss; + + // ------------------------------------------------------------------------ + // Build a new VMTemplate object + // ------------------------------------------------------------------------ + vm_template = new VMTemplate(-1, uid, user_name, template_contents); + + // Check name + vm_template->get_template_attribute("NAME", name); + + if ( !name.empty() ) + { + // Check for duplicates + vm_template_aux = get(name,uid,false); + + if( vm_template_aux != 0 ) + { + goto error_duplicated; + } + } + + // ------------------------------------------------------------------------ + // Insert the Object in the pool + // ------------------------------------------------------------------------ + + *oid = PoolSQL::allocate(vm_template, error_str); + + return *oid; + + +error_duplicated: + oss << "NAME is already taken by TEMPLATE " + << vm_template_aux->get_oid() << "."; + + delete vm_template; + + *oid = -1; + error_str = oss.str(); + + return *oid; +} diff --git a/src/vm_template/test/SConstruct b/src/vm_template/test/SConstruct new file mode 100644 index 0000000000..6ab70ef56e --- /dev/null +++ b/src/vm_template/test/SConstruct @@ -0,0 +1,39 @@ +# -------------------------------------------------------------------------- +# Copyright 2002-2011, 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') + +env.Prepend(LIBS=[ + 'nebula_image', + 'nebula_um', + 'nebula_vm', + 'nebula_vmtemplate', + 'nebula_hm', + 'nebula_vnm', + 'nebula_authm', + 'nebula_template', + 'nebula_pool', + 'nebula_mad', + 'nebula_common', + 'nebula_core', + 'nebula_sql', + 'nebula_log', + 'nebula_xml', + 'crypto' +]) + +env.Program('test','VMTemplatePoolTest.cc') + diff --git a/src/vm_template/test/VMTemplatePoolTest.cc b/src/vm_template/test/VMTemplatePoolTest.cc new file mode 100644 index 0000000000..8648f410b9 --- /dev/null +++ b/src/vm_template/test/VMTemplatePoolTest.cc @@ -0,0 +1,553 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, 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 "VMTemplatePool.h" +#include "PoolTest.h" + +using namespace std; + +const int uids[] = {0,1,2}; +const string user_names[] = {"A user","B user","C user"}; + +const string names[] = {"Template one", "Second Template", "Third Template"}; + +const string templates[] = +{ + "NAME = \"Template one\"\n" + "MEMORY = 128\n" + "CPU = 1", + + "NAME = \"Second Template\"\n" + "MEMORY = 256\n" + "CPU = 2", + + "NAME = \"Third Template\"\n" + "MEMORY = 1024\n" + "CPU = 3" +}; + + +const string xmls[] = +{ + "00A userTemplate one00000000000", + + "11B userSecond Template00000000000", + + "22C userThird Template00000000000" +}; + + +// This xml dump result has the STIMEs modified to 0000000000 +const string xml_dump = + "00A userTemplate one0000000000011B userSecond Template0000000000022C userThird Template00000000000"; +const string xml_dump_where = + "00A userTemplate one0000000000011B userSecond Template00000000000"; + +const string replacement = "0000000000"; + +class VMTemplatePoolFriend : public VMTemplatePool +{ +public: + VMTemplatePoolFriend(SqlDB * db) : VMTemplatePool(db){}; + + int allocate(int uid, + const string& stemplate, + int * oid) + { + VirtualMachineTemplate * template_contents; + char * error_msg = 0; + int rc; + string err; + + template_contents = new VirtualMachineTemplate(); + rc = template_contents->parse(stemplate,&error_msg); + + if( rc == 0 ) + { + return VMTemplatePool::allocate(uid, user_names[uid], template_contents, oid, err); + } + else + { + if (error_msg != 0 ) + { + free(error_msg); + } + + delete template_contents; + return -2; + } + }; +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class VMTemplatePoolTest : public PoolTest +{ + CPPUNIT_TEST_SUITE (VMTemplatePoolTest); + + ALL_POOLTEST_CPPUNIT_TESTS(); + + CPPUNIT_TEST ( names_initialization ); + CPPUNIT_TEST ( clone_template ); + CPPUNIT_TEST ( update ); + CPPUNIT_TEST ( get_using_name ); + CPPUNIT_TEST ( wrong_get_name ); + CPPUNIT_TEST ( duplicates ); + CPPUNIT_TEST ( public_attribute ); + CPPUNIT_TEST ( dump ); + CPPUNIT_TEST ( dump_where ); + + CPPUNIT_TEST_SUITE_END (); + +protected: + + void bootstrap(SqlDB* db) + { + VMTemplatePool::bootstrap(db); + }; + + PoolSQL* create_pool(SqlDB* db) + { + return new VMTemplatePoolFriend(db); + }; + + int allocate(int index) + { + int oid; + return ((VMTemplatePoolFriend*)pool)->allocate(uids[index], + templates[index], + &oid); + + }; + + void check(int index, PoolObjectSQL* obj) + { + CPPUNIT_ASSERT( obj != 0 ); + + string xml_str = ""; + + // Get the xml and replace the REGTIME to 0, so we can compare + // it. + ((VMTemplate*)obj)->to_xml(xml_str); + xml_str.replace( xml_str.find("")+9, 10, replacement); + +/* + if( xml_str != xmls[index] ) + { + cout << endl << xml_str << endl << xmls[index] << endl; + } +//*/ + + CPPUNIT_ASSERT( obj->get_name() == names[index] ); + CPPUNIT_ASSERT( xml_str == xmls[index]); + }; + +public: + VMTemplatePoolTest(){xmlInitParser();}; + + ~VMTemplatePoolTest(){xmlCleanupParser();}; + + + /* ********************************************************************* */ + + void names_initialization() + { + VMTemplatePoolFriend * tpool; + VMTemplate * temp; + + // Allocate 2 Templates, so they are written to the DB. + allocate(0); + allocate(2); + + // Create a new pool, using the same DB. This new pool should read the + // allocated Templates. + tpool = new VMTemplatePoolFriend(db); + + temp = tpool->get(names[0], uids[0], false); + CPPUNIT_ASSERT( temp != 0 ); + + temp = tpool->get(names[1], uids[1], false); + CPPUNIT_ASSERT( temp == 0 ); + + temp = tpool->get(names[2], uids[2], false); + CPPUNIT_ASSERT( temp != 0 ); + + + delete tpool; + } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + + void clone_template() + { + string attr_temp; + string attr_vmt; + + string name1 = "NAME"; + string name2 = "MEMORY"; + + VMTemplatePoolFriend * tpool; + VMTemplate * temp; + VirtualMachineTemplate * vmt; + + int oid_1; + + tpool = static_cast(pool); + oid_1 = allocate(0); + + temp = tpool->get(oid_1, true); + CPPUNIT_ASSERT( temp != 0 ); + + vmt = temp->clone_template(); + + vmt->get(name1,attr_vmt); + CPPUNIT_ASSERT( attr_vmt == "Template one"); + + temp->get_template_attribute(name1.c_str(), attr_temp); + CPPUNIT_ASSERT( attr_temp == "Template one"); + + temp->replace_template_attribute(name2.c_str(), "1024"); + + vmt->get(name2,attr_vmt); + CPPUNIT_ASSERT( attr_vmt == "128"); + + temp->get_template_attribute(name2.c_str(), attr_temp); + CPPUNIT_ASSERT( attr_temp == "1024"); + + delete vmt; + + temp->get_template_attribute(name2.c_str(), attr_temp); + CPPUNIT_ASSERT( attr_temp == "1024"); + + tpool->update(temp); + + temp->unlock(); + }; +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + + void update() + { + string description_name = "DESCRIPTION"; + string description_val = ""; + string new_description = "A new description"; + + string attr_name = "NEW_ATTRIBUTE"; + string attr_val = ""; + string new_attr_value = "New value"; + + string no_value = "Some random value"; + + VMTemplatePoolFriend * tpool; + VMTemplate * temp; + int oid_1; + + tpool = static_cast(pool); + oid_1 = allocate(0); + + temp = tpool->get(oid_1, true); + CPPUNIT_ASSERT( temp != 0 ); + + // Object should be cached. Let's change some template attributes + temp->replace_template_attribute(description_name, new_description); + temp->replace_template_attribute(attr_name, new_attr_value); + temp->remove_template_attribute("ORIGINAL_PATH"); + + tpool->update(temp); + + temp->unlock(); + + temp = tpool->get(oid_1,false); + CPPUNIT_ASSERT( temp != 0 ); + + + temp->get_template_attribute("DESCRIPTION", description_val); + temp->get_template_attribute("NEW_ATTRIBUTE", attr_val); + temp->get_template_attribute("ORIGINAL_PATH", no_value); + + CPPUNIT_ASSERT( description_val == new_description ); + CPPUNIT_ASSERT( attr_val == new_attr_value ); + CPPUNIT_ASSERT( no_value == "" ); + + //Now force access to DB + + pool->clean(); + temp = tpool->get(oid_1,false); + + CPPUNIT_ASSERT( temp != 0 ); + + description_val = ""; + attr_val = ""; + no_value = "Random value"; + temp->get_template_attribute("DESCRIPTION", description_val); + temp->get_template_attribute("NEW_ATTRIBUTE", attr_val); + temp->get_template_attribute("ORIGINAL_PATH", no_value); + + CPPUNIT_ASSERT( description_val == new_description ); + CPPUNIT_ASSERT( attr_val == new_attr_value ); + CPPUNIT_ASSERT( no_value == "" ); + }; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + + 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 = pool->get(names[1], uids[1], true); + CPPUNIT_ASSERT( obj != 0 ); + obj->unlock(); + + check(1, obj); + + + // --------------------------------- + // 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(names[0], uids[0], false); + check(0, obj); + + // Get using its name + obj = pool->get(oid_1, false); + check(1, obj); + }; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + + void wrong_get_name() + { + // The pool is empty + // Non existing name + obj = pool->get("Wrong name", 0, true); + CPPUNIT_ASSERT( obj == 0 ); + + // Allocate an object + allocate(0); + + // Ask again for a non-existing name + obj = pool->get("Non existing name",uids[0], true); + CPPUNIT_ASSERT( obj == 0 ); + } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + + void duplicates() + { + int rc, oid; + VMTemplatePoolFriend * tpool = static_cast(pool); + + // Allocate a template + rc = tpool->allocate(uids[0], templates[0], &oid); + CPPUNIT_ASSERT( oid == 0 ); + CPPUNIT_ASSERT( oid == rc ); + + // Try to allocate twice the same template, should fail + rc = tpool->allocate(uids[0], templates[0], &oid); + CPPUNIT_ASSERT( rc == -1 ); + CPPUNIT_ASSERT( oid == rc ); + + // Try again, this time with different uid. Should be allowed + rc = tpool->allocate(uids[1], templates[0], &oid); + CPPUNIT_ASSERT( rc >= 0 ); + CPPUNIT_ASSERT( oid == rc ); + } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + + void public_attribute() + { + int oid; + VMTemplatePoolFriend * tpool = static_cast(pool); + VMTemplate * temp; + + string templates[] = + { + // false + "NAME = \"name A\"\n", + + // true + "NAME = \"name B\"\n" + "PUBLIC = YES", + + // false + "NAME = \"name C\"\n" + "PUBLIC = NO", + + // false + "NAME = \"name D\"\n" + "PUBLIC = 1", + + // true + "NAME = \"name E\"\n" + "PUBLIC = Yes", + + // false + "NAME = \"name F\"\n" + "PUBLIC = TRUE", + + // true + "NAME = \"name G\"\n" + "PUBLIC = yes", + + // false + "NAME = \"name H\"\n" + "PUBLIC = 'YES'", + + // true + "NAME = \"name I\"\n" + "PUBLIC = \"YES\"", + + "END" + }; + + bool results[] = { false, true, false, false, + true, false, true, false, true }; + + int i = 0; + while( templates[i] != "END" ) + { + + tpool->allocate(0, templates[i], &oid); + + CPPUNIT_ASSERT( oid >= 0 ); + + temp = tpool->get( oid, false ); + CPPUNIT_ASSERT( temp != 0 ); +//cout << endl << i << " : exp. " << results[i] << " got " << temp->is_public(); + + CPPUNIT_ASSERT( temp->isPublic() == results[i] ); + + i++; + } + + bool success; + + // temp 0 is not public. + temp = tpool->get( 0, false ); + CPPUNIT_ASSERT( temp != 0 ); + + success = temp->publish(false); + CPPUNIT_ASSERT( success == true ); + CPPUNIT_ASSERT( temp->isPublic() == false ); + + success = temp->publish(true); + CPPUNIT_ASSERT( success == true ); + CPPUNIT_ASSERT( temp->isPublic() == true ); + } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + + void dump() + { + VMTemplatePool * tpool = static_cast(pool); + + ostringstream oss; + int rc; + string nan; + + allocate(0); + allocate(1); + allocate(2); + + rc = tpool->dump(oss,nan); + CPPUNIT_ASSERT(rc == 0); + + string result = oss.str(); + + result.replace(130, 10, replacement); + result.replace(393, 10, replacement); + result.replace(658, 10, replacement); + +/* + if( result != xml_dump ) + { + cout << endl << result << endl << xml_dump << endl; + } +//*/ + + CPPUNIT_ASSERT( result == xml_dump ); + } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + + void dump_where() + { + VMTemplatePool * tpool = static_cast(pool); + + int rc; + ostringstream oss; + ostringstream where; + + allocate(0); + allocate(1); + allocate(2); + + where << "uid < 2"; + + rc = tpool->dump(oss, where.str()); + CPPUNIT_ASSERT(rc == 0); + + string result = oss.str(); + + result.replace(130, 10, replacement); + result.replace(393, 10, replacement); + +/* + if( result != xml_dump_where ) + { + cout << endl << result << endl << xml_dump_where << endl; + } +//*/ + + CPPUNIT_ASSERT( result == xml_dump_where ); + } + + /* ********************************************************************* */ + +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + return PoolTest::main(argc, argv, VMTemplatePoolTest::suite()); +} diff --git a/src/vmm/LibVirtDriverKVM.cc b/src/vmm/LibVirtDriverKVM.cc index ce71f4e658..a3baa9d5bb 100644 --- a/src/vmm/LibVirtDriverKVM.cc +++ b/src/vmm/LibVirtDriverKVM.cc @@ -53,7 +53,9 @@ int LibVirtDriver::deployment_description_kvm( string bus = ""; string ro = ""; string driver = ""; - string default_driver = ""; + string cache = ""; + string default_driver = ""; + string default_driver_cache = ""; bool readonly; const VectorAttribute * nic; @@ -62,6 +64,9 @@ int LibVirtDriver::deployment_description_kvm( string bridge = ""; string script = ""; string model = ""; + string ip = ""; + string filter = ""; + string default_filter = ""; const VectorAttribute * graphics; @@ -251,9 +256,8 @@ int LibVirtDriver::deployment_description_kvm( attrs.clear(); // ------------------------------------------------------------------------ - // Disks + // DEVICES SECTION // ------------------------------------------------------------------------ - file << "\t" << endl; if (emulator == "kvm") @@ -268,6 +272,9 @@ int LibVirtDriver::deployment_description_kvm( file << "\t\t" << emulator_path << "" << endl; } + // ------------------------------------------------------------------------ + // Disks + // ------------------------------------------------------------------------ get_default("DISK","DRIVER",default_driver); if (default_driver.empty()) @@ -275,6 +282,15 @@ int LibVirtDriver::deployment_description_kvm( default_driver = "raw"; } + get_default("DISK","CACHE",default_driver_cache); + + if (default_driver_cache.empty()) + { + default_driver_cache = "default"; + } + + // ------------------------------------------------------------------------ + num = vm->get_template_attribute("DISK",attrs); for (int i=0; i < num ;i++) @@ -291,6 +307,7 @@ int LibVirtDriver::deployment_description_kvm( ro = disk->vector_value("READONLY"); bus = disk->vector_value("BUS"); driver = disk->vector_value("DRIVER"); + cache = disk->vector_value("CACHE"); if (target.empty()) { @@ -363,11 +380,22 @@ int LibVirtDriver::deployment_description_kvm( if ( !driver.empty() ) { - file << driver << "'/>" << endl; + file << driver; } else { - file << default_driver << "'/>" << endl; + file << default_driver; + } + + file << "' cache='"; + + if ( !cache.empty() ) + { + file << cache << "'/>" << endl; + } + else + { + file << default_driver_cache << "'/>" << endl; } file << "\t\t" << endl; @@ -419,6 +447,8 @@ int LibVirtDriver::deployment_description_kvm( // Network interfaces // ------------------------------------------------------------------------ + get_default("NIC","FILTER",default_filter); + num = vm->get_template_attribute("NIC",attrs); for(int i=0; ivector_value("TARGET"); script = nic->vector_value("SCRIPT"); model = nic->vector_value("MODEL"); + ip = nic->vector_value("IP"); + filter = nic->vector_value("FILTER"); if ( bridge.empty() ) { @@ -466,8 +498,29 @@ int LibVirtDriver::deployment_description_kvm( file << "\t\t\t" << endl; } - file << "\t\t" << endl; + if (!ip.empty() ) + { + string * the_filter = 0; + if (!filter.empty()) + { + the_filter = &filter; + } + else if (!default_filter.empty()) + { + the_filter = &default_filter; + } + + if ( the_filter != 0 ) + { + file <<"\t\t\t"<" << endl; + file << "\t\t\t" << endl; + } + } + + file << "\t\t" << endl; } attrs.clear(); diff --git a/src/vmm/LibVirtDriverVMware.cc b/src/vmm/LibVirtDriverVMware.cc index d5144b9309..ade02db1b5 100644 --- a/src/vmm/LibVirtDriverVMware.cc +++ b/src/vmm/LibVirtDriverVMware.cc @@ -278,7 +278,7 @@ int LibVirtDriver::deployment_description_vmware( { file << "\t\t" << endl; file << "\t\t\t" << endl; + << "/disk." << num << ".iso'/>" << endl; file << "\t\t\t" << endl; file << "\t\t\t" << endl; file << "\t\t" << endl; diff --git a/src/vmm/VirtualMachineManagerDriver.cc b/src/vmm/VirtualMachineManagerDriver.cc index 3d278bd6fe..4b58f06f2f 100644 --- a/src/vmm/VirtualMachineManagerDriver.cc +++ b/src/vmm/VirtualMachineManagerDriver.cc @@ -227,17 +227,46 @@ void VirtualMachineManagerDriver::poll ( /* MAD Interface */ /* ************************************************************************** */ +/* -------------------------------------------------------------------------- */ +/* Helpers for the protocol function */ +/* -------------------------------------------------------------------------- */ + +static void log_error(VirtualMachine* vm, + ostringstream& os, + istringstream& is, + const char * msg) +{ + string info; + + getline(is,info); + + os.str(""); + os << msg; + + if (!info.empty() && info[0] != '-') + { + os << ": " << info; + vm->set_template_error_message(os.str()); + } + + vm->log("VMM",Log::ERROR,os); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + void VirtualMachineManagerDriver::protocol( string& message) { - istringstream is(message); - ostringstream os; + istringstream is(message); + ostringstream os; - string action; - string result; + string action; + string result; + + int id; + VirtualMachine * vm; - int id; - VirtualMachine * vm; os << "Message received: " << message; NebulaLog::log("VMM", Log::DEBUG, os); @@ -265,7 +294,7 @@ void VirtualMachineManagerDriver::protocol( is.clear(); getline(is,info); - NebulaLog::log("VMM",Log::INFO, info.c_str()); + NebulaLog::log("VMM", log_type(result[0]), info.c_str()); } return; @@ -316,17 +345,8 @@ void VirtualMachineManagerDriver::protocol( } else { - string info; - - getline(is,info); - - os.str(""); - os << "Error deploying virtual machine"; - - if (info[0] != '-') - os << ": " << info; - - vm->log("VMM",Log::ERROR,os); + log_error(vm,os,is,"Error deploying virtual machine"); + vmpool->update(vm); lcm->trigger(LifeCycleManager::DEPLOY_FAILURE, id); } @@ -342,14 +362,8 @@ void VirtualMachineManagerDriver::protocol( } else { - string info; - - getline(is,info); - - os.str(""); - os << "Error shuting down VM, " << info; - - vm->log("VMM",Log::ERROR,os); + log_error(vm,os,is,"Error shuting down VM"); + vmpool->update(vm); lcm->trigger(LifeCycleManager::SHUTDOWN_FAILURE, id); } @@ -365,14 +379,8 @@ void VirtualMachineManagerDriver::protocol( } else { - string info; - - getline(is,info); - - os.str(""); - os << "Error canceling VM, " << info; - - vm->log("VMM",Log::ERROR,os); + log_error(vm,os,is,"Error canceling VM"); + vmpool->update(vm); lcm->trigger(LifeCycleManager::CANCEL_FAILURE, id); } @@ -388,14 +396,8 @@ void VirtualMachineManagerDriver::protocol( } else { - string info; - - getline(is,info); - - os.str(""); - os << "Error saving VM state, " << info; - - vm->log("VMM",Log::ERROR,os); + log_error(vm,os,is,"Error saving VM state"); + vmpool->update(vm); lcm->trigger(LifeCycleManager::SAVE_FAILURE, id); } @@ -411,14 +413,8 @@ void VirtualMachineManagerDriver::protocol( } else { - string info; - - getline(is,info); - - os.str(""); - os << "Error restoring VM, " << info; - - vm->log("VMM",Log::ERROR,os); + log_error(vm,os,is,"Error restoring VM"); + vmpool->update(vm); lcm->trigger(LifeCycleManager::DEPLOY_FAILURE, id); } @@ -434,14 +430,8 @@ void VirtualMachineManagerDriver::protocol( } else { - string info; - - getline(is,info); - - os.str(""); - os << "Error live-migrating VM, " << info; - - vm->log("VMM",Log::ERROR,os); + log_error(vm,os,is,"Error live migrating VM"); + vmpool->update(vm); lcm->trigger(LifeCycleManager::DEPLOY_FAILURE, id); } @@ -463,6 +453,9 @@ void VirtualMachineManagerDriver::protocol( int net_rx = -1; char state = '-'; + string monitor_str = is.str(); + bool parse_error = false; + while(is.good()) { is >> tmp >> ws; @@ -471,12 +464,8 @@ void VirtualMachineManagerDriver::protocol( if ( pos == string::npos ) { - os.str(""); - os << "Error parsing monitoring attribute: " << tmp; - - vm->log("VMM",Log::ERROR,os); - - break; + parse_error = true; + continue; } tmp.replace(pos,1," "); @@ -485,7 +474,13 @@ void VirtualMachineManagerDriver::protocol( tiss.str(tmp); - tiss >> var; + tiss >> var >> ws; + + if (!tiss.good()) + { + parse_error = true; + continue; + } if (var == "USEDMEMORY") { @@ -507,13 +502,12 @@ void VirtualMachineManagerDriver::protocol( { tiss >> state; } - else + else if (!var.empty()) { string val; os.str(""); - os << "Unknown monitoring attribute (adding/updating" - << " template): " << tmp; + os << "Adding custom monitoring attribute: " << tmp; vm->log("VMM",Log::WARNING,os); @@ -523,6 +517,20 @@ void VirtualMachineManagerDriver::protocol( } } + if (parse_error) + { + os.str(""); + os << "Error parsing monitoring str:\"" << monitor_str <<"\""; + + vm->log("VMM",Log::ERROR,os); + + vm->set_template_error_message(os.str()); + vmpool->update(vm); + + vm->unlock(); + return; + } + vm->update_info(memory,cpu,net_tx,net_rx); vmpool->update(vm); @@ -580,12 +588,8 @@ void VirtualMachineManagerDriver::protocol( } else { - string info; - - getline(is,info); - - os.str(""); - os << "Error monitoring VM, " << info; + log_error(vm,os,is,"Error monitoring VM"); + vmpool->update(vm); vm->log("VMM",Log::ERROR,os); } @@ -595,7 +599,7 @@ void VirtualMachineManagerDriver::protocol( string info; getline(is,info); - vm->log("VMM",Log::INFO,info.c_str()); + vm->log("VMM",log_type(result[0]),info.c_str()); } vm->unlock(); diff --git a/src/vmm_mad/remotes/kvm/cancel b/src/vmm_mad/remotes/kvm/cancel index 11bbffe5db..cbcdad3eb7 100755 --- a/src/vmm_mad/remotes/kvm/cancel +++ b/src/vmm_mad/remotes/kvm/cancel @@ -17,7 +17,9 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/kvmrc +source $(dirname $0)/../../scripts_common.sh deploy_id=$1 -virsh --connect $LIBVIRT_URI destroy $deploy_id +exec_and_log "virsh --connect $LIBVIRT_URI destroy $deploy_id" \ + "Could not destroy $deploy_id" diff --git a/src/vmm_mad/remotes/kvm/deploy b/src/vmm_mad/remotes/kvm/deploy index fe611ce7d0..dd39ead402 100755 --- a/src/vmm_mad/remotes/kvm/deploy +++ b/src/vmm_mad/remotes/kvm/deploy @@ -17,6 +17,7 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/kvmrc +source $(dirname $0)/../../scripts_common.sh domain=$1 @@ -28,5 +29,6 @@ data=`virsh --connect $LIBVIRT_URI create $domain` if [ "x$?" = "x0" ]; then echo $data | sed 's/Domain //' | sed 's/ created from .*$//' else + error_message "Could not create domain from $domain" exit -1 fi diff --git a/src/vmm_mad/remotes/kvm/kvmrc b/src/vmm_mad/remotes/kvm/kvmrc index ecb4c7e22b..15b72df854 100644 --- a/src/vmm_mad/remotes/kvm/kvmrc +++ b/src/vmm_mad/remotes/kvm/kvmrc @@ -18,4 +18,4 @@ export LANG=C export LIBVIRT_URI=qemu:///system -export QEMU_PROTOCOL=qemu +export QEMU_PROTOCOL=qemu+ssh diff --git a/src/vmm_mad/remotes/kvm/migrate b/src/vmm_mad/remotes/kvm/migrate index 1f95602bc4..2dbdf8a521 100755 --- a/src/vmm_mad/remotes/kvm/migrate +++ b/src/vmm_mad/remotes/kvm/migrate @@ -17,8 +17,10 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/kvmrc +source $(dirname $0)/../../scripts_common.sh deploy_id=$1 dest_host=$2 -virsh --connect $LIBVIRT_URI migrate --live $deploy_id $QEMU_PROTOCOL://$dest_host/system +exec_and_log "virsh --connect $LIBVIRT_URI migrate --live $deploy_id $QEMU_PROTOCOL://$dest_host/system" \ + "Could not migrate $deploy_id to $dest_host" diff --git a/src/vmm_mad/remotes/kvm/restore b/src/vmm_mad/remotes/kvm/restore index 8a83fc92b5..761a82227a 100755 --- a/src/vmm_mad/remotes/kvm/restore +++ b/src/vmm_mad/remotes/kvm/restore @@ -17,7 +17,9 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/kvmrc +source $(dirname $0)/../../scripts_common.sh file=$1 -virsh --connect $LIBVIRT_URI restore $file +exec_and_log "virsh --connect $LIBVIRT_URI restore $file" \ + "Could not restore from $file" diff --git a/src/vmm_mad/remotes/kvm/save b/src/vmm_mad/remotes/kvm/save index b51735188f..4b09cf7fc4 100755 --- a/src/vmm_mad/remotes/kvm/save +++ b/src/vmm_mad/remotes/kvm/save @@ -17,6 +17,7 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/kvmrc +source $(dirname $0)/../../scripts_common.sh deploy_id=$1 file=$2 @@ -26,4 +27,5 @@ if [ ! -f $file ]; then chmod 666 $file fi -virsh --connect $LIBVIRT_URI save $deploy_id $file +exec_and_log "virsh --connect $LIBVIRT_URI save $deploy_id $file" \ + "Could not save $deploy_id to $file" diff --git a/src/vmm_mad/remotes/kvm/shutdown b/src/vmm_mad/remotes/kvm/shutdown index e7d4c8d7a4..bd2491ab2f 100755 --- a/src/vmm_mad/remotes/kvm/shutdown +++ b/src/vmm_mad/remotes/kvm/shutdown @@ -17,6 +17,7 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/kvmrc +source $(dirname $0)/../../scripts_common.sh #------------------------------------------------------------------------------ # Wait the VM to shutdown TIMEOUT (xPOLL_INTERVAL) seconds. @@ -32,6 +33,7 @@ virsh --connect $LIBVIRT_URI shutdown $deploy_id exit_code=$? if [ "$exit_code" != "0" ]; then + error_message "Could not shutdown $deploy_id" exit $exit_code fi @@ -41,6 +43,7 @@ do sleep $POLL_INTERVAL if [ "$count" -gt "$TIMEOUT" ] then + error_message "Timeout reached and VM $deploy_id is still alive" echo "Timeout reached" >&2 exit 1 fi diff --git a/src/vmm_mad/remotes/poll_xen_kvm.rb b/src/vmm_mad/remotes/poll_xen_kvm.rb index 6a2521bbef..00e0f6dfec 100755 --- a/src/vmm_mad/remotes/poll_xen_kvm.rb +++ b/src/vmm_mad/remotes/poll_xen_kvm.rb @@ -118,7 +118,7 @@ private lines=text.split(/\n/)[2..-1] lines.map do |line| - line.split(/\s+/)[1] + line.split(/\s+/).delete_if {|d| d.empty? }[1] end end diff --git a/src/vmm_mad/remotes/xen/cancel b/src/vmm_mad/remotes/xen/cancel index b8c0a484c2..4beab6b21c 100755 --- a/src/vmm_mad/remotes/xen/cancel +++ b/src/vmm_mad/remotes/xen/cancel @@ -17,7 +17,9 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/xenrc +source $(dirname $0)/../../scripts_common.sh deploy_id=$1 -$XM_CANCEL $deploy_id +exec_and_log "$XM_CANCEL $deploy_id" \ + "Could not destroy $deploy_id" diff --git a/src/vmm_mad/remotes/xen/deploy b/src/vmm_mad/remotes/xen/deploy index 99c771c6fe..b91569c1cc 100755 --- a/src/vmm_mad/remotes/xen/deploy +++ b/src/vmm_mad/remotes/xen/deploy @@ -17,10 +17,13 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/xenrc +source $(dirname $0)/../../scripts_common.sh function error_exit() { exit_code=$1 + message=$2 if [ "x$exit_code" != "x0" ]; then + error_message $message exit $exit_code fi } @@ -32,7 +35,7 @@ cat > $domain output=`$XM_CREATE $domain` -error_exit $? +error_exit $? "Unable to create domain" domain_name=`echo $output | grep 'Started domain' | sed 's/^.*Started domain //' | tr -d '\n'` @@ -41,11 +44,13 @@ out=`grep -e '^\#O CPU_CREDITS =' < $domain` if [ "x$?" = "x0" ]; then credits=`echo $out | cut -d= -f2 | tr -d ' '` + log_debug "Credits set to $credits" + name=`grep -e '^name =' < $domain | cut -d= -f2 | tr -d ' ' | tr -d "\'"` $XM_CREDITS -d $name -w $credits - error_exit $? + error_exit $? "Unable to set VM credits" fi echo $domain_name diff --git a/src/vmm_mad/remotes/xen/migrate b/src/vmm_mad/remotes/xen/migrate index bd5c074799..6458d3b542 100755 --- a/src/vmm_mad/remotes/xen/migrate +++ b/src/vmm_mad/remotes/xen/migrate @@ -17,8 +17,10 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/xenrc +source $(dirname $0)/../../scripts_common.sh deploy_id=$1 dest_host=$2 -$XM_MIGRATE $deploy_id $dest_host +exec_and_log "$XM_MIGRATE $deploy_id $dest_host" \ + "Could not migrate $deploy_id to $dest_host" diff --git a/src/vmm_mad/remotes/xen/restore b/src/vmm_mad/remotes/xen/restore index c92cb1e1ec..aa4bc0402b 100755 --- a/src/vmm_mad/remotes/xen/restore +++ b/src/vmm_mad/remotes/xen/restore @@ -17,8 +17,10 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/xenrc +source $(dirname $0)/../../scripts_common.sh file=$1 -$XM_RESTORE $file +exec_and_log "$XM_RESTORE $file" \ + "Could not restore from $file" diff --git a/src/vmm_mad/remotes/xen/save b/src/vmm_mad/remotes/xen/save index fc653c569f..7be9ce93cc 100755 --- a/src/vmm_mad/remotes/xen/save +++ b/src/vmm_mad/remotes/xen/save @@ -17,9 +17,10 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/xenrc +source $(dirname $0)/../../scripts_common.sh deploy_id=$1 file=$2 -$XM_SAVE $deploy_id $file - +exec_and_log "$XM_SAVE $deploy_id $file" \ + "Could not save $deploy_id to $file" diff --git a/src/vmm_mad/remotes/xen/shutdown b/src/vmm_mad/remotes/xen/shutdown index 9d3ca25367..d6b240672c 100755 --- a/src/vmm_mad/remotes/xen/shutdown +++ b/src/vmm_mad/remotes/xen/shutdown @@ -17,6 +17,7 @@ #--------------------------------------------------------------------------- # source $(dirname $0)/xenrc +source $(dirname $0)/../../scripts_common.sh deploy_id=$1 @@ -24,7 +25,8 @@ function gdm { $XM_LIST | grep "$deploy_id " } -$XM_SHUTDOWN $deploy_id || exit -1 +exec_and_log "$XM_SHUTDOWN $deploy_id" \ + "Could not shutdown $deploy_id" OUT=$(gdm) diff --git a/src/vmm_mad/ssh/vmm_ssh_kvm.conf b/src/vmm_mad/ssh/vmm_ssh_kvm.conf index af6920d24e..72d862cf20 100644 --- a/src/vmm_mad/ssh/vmm_ssh_kvm.conf +++ b/src/vmm_mad/ssh/vmm_ssh_kvm.conf @@ -23,7 +23,8 @@ # - cpu # - vcpu # - features [acpi, pae] -# - disk [driver ]A +# - disk [driver, cache] +# - nic [filter] #EMULATOR = /usr/libexec/qemu-kvm @@ -33,4 +34,6 @@ OS = [ boot = "hd", arch = "i686" ] FEATURES = [ PAE = "no", ACPI = "yes" ] -DISK = [ driver = "raw" ] +DISK = [ driver = "raw" , cache = "default"] + +NIC = [ filter = "clean-traffic" ] diff --git a/src/vmm_mad/ssh/vmm_sshrc b/src/vmm_mad/ssh/vmm_sshrc index b039809d7b..744f2b4d68 100644 --- a/src/vmm_mad/ssh/vmm_sshrc +++ b/src/vmm_mad/ssh/vmm_sshrc @@ -15,6 +15,6 @@ #--------------------------------------------------------------------------- # # To change the directory where the VMM scripts are copied on the remote node -# uncomment and change the path of VMMM_REMOTE_DIR +# uncomment and change the path of VMM_REMOTE_DIR # #VMM_REMOTE_DIR=/tmp/ne_im_scripts diff --git a/src/vnm/VirtualNetwork.cc b/src/vnm/VirtualNetwork.cc index 8d885b670f..bc5279b4eb 100644 --- a/src/vnm/VirtualNetwork.cc +++ b/src/vnm/VirtualNetwork.cc @@ -17,6 +17,7 @@ #include "VirtualNetwork.h" #include "VirtualNetworkPool.h" +#include "VirtualNetworkTemplate.h" #include "NebulaLog.h" #include "RangedLeases.h" @@ -40,11 +41,11 @@ VirtualNetwork::VirtualNetwork(int uid, { if (_vn_template != 0) { - vn_template = _vn_template; + obj_template = _vn_template; } else { - vn_template = new VirtualNetworkTemplate; + obj_template = new VirtualNetworkTemplate; } }; @@ -58,9 +59,9 @@ VirtualNetwork::~VirtualNetwork() delete leases; } - if (vn_template != 0) + if (obj_template != 0) { - delete vn_template; + delete obj_template; } } @@ -70,11 +71,11 @@ VirtualNetwork::~VirtualNetwork() const char * VirtualNetwork::table = "network_pool"; -const char * VirtualNetwork::db_names = "oid, name, body, uid"; +const char * VirtualNetwork::db_names = "oid, name, body, uid, public"; const char * VirtualNetwork::db_bootstrap = "CREATE TABLE IF NOT EXISTS" - " network_pool (oid INTEGER PRIMARY KEY, name VARCHAR(256)," - " body TEXT, uid INTEGER, UNIQUE(name,uid))"; + " network_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128)," + " body TEXT, uid INTEGER, public INTEGER, UNIQUE(name,uid))"; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -263,7 +264,7 @@ int VirtualNetwork::insert(SqlDB * db, string& error_str) public_vnet = (pub == "YES"); - vn_template->erase("PUBLIC"); + obj_template->erase("PUBLIC"); //-------------------------------------------------------------------------- // Get the leases @@ -307,7 +308,7 @@ int VirtualNetwork::insert(SqlDB * db, string& error_str) oss << default_size; attribute = new SingleAttribute("NETWORK_SIZE",oss.str()); - vn_template->set(attribute); + obj_template->set(attribute); size = default_size; } @@ -423,7 +424,8 @@ int VirtualNetwork::insert_replace(SqlDB *db, bool replace) << oid << "," << "'" << sql_name << "'," << "'" << sql_xml << "'," - << uid << ")"; + << uid << "," + << public_vnet << ")"; rc = db->exec(oss); @@ -505,7 +507,7 @@ string& VirtualNetwork::to_xml_extended(string& xml, bool extended) const "" << bridge << "" << "" << public_vnet << "" << ""<< total_leases << ""<< - vn_template->to_xml(template_xml); + obj_template->to_xml(template_xml); if (extended && leases != 0) { @@ -552,7 +554,7 @@ int VirtualNetwork::from_xml(const string &xml_str) } // Virtual Network template - rc += vn_template->from_xml_node( content[0] ); + rc += obj_template->from_xml_node( content[0] ); if (rc != 0) { @@ -569,15 +571,11 @@ int VirtualNetwork::nic_attribute(VectorAttribute *nic, int vid) { int rc; - string model; string ip; string mac; ostringstream vnid; - map new_nic; - - model = nic->vector_value("MODEL"); ip = nic->vector_value("IP"); vnid << oid; @@ -603,18 +601,11 @@ int VirtualNetwork::nic_attribute(VectorAttribute *nic, int vid) // NEW NIC ATTRIBUTES //-------------------------------------------------------------------------- - new_nic.insert(make_pair("NETWORK" ,name)); - new_nic.insert(make_pair("MAC" ,mac)); - new_nic.insert(make_pair("BRIDGE" ,bridge)); - new_nic.insert(make_pair("NETWORK_ID",vnid.str())); - new_nic.insert(make_pair("IP" ,ip)); - - if (!model.empty()) - { - new_nic.insert(make_pair("MODEL",model)); - } - - nic->replace(new_nic); + nic->replace("NETWORK" ,name); + nic->replace("NETWORK_ID",vnid.str()); + nic->replace("BRIDGE" ,bridge); + nic->replace("MAC" ,mac); + nic->replace("IP" ,ip); return 0; } diff --git a/src/vnm/test/VirtualNetworkPoolTest.cc b/src/vnm/test/VirtualNetworkPoolTest.cc index c059dd1213..43f96c0d07 100644 --- a/src/vnm/test/VirtualNetworkPoolTest.cc +++ b/src/vnm/test/VirtualNetworkPoolTest.cc @@ -19,6 +19,7 @@ #include #include "VirtualNetworkPool.h" +#include "VirtualNetworkTemplate.h" #include "PoolTest.h" #include "ObjectXML.h"