diff --git a/SConstruct b/SConstruct index 1c3203d935..ac58affdd1 100644 --- a/SConstruct +++ b/SConstruct @@ -127,15 +127,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"+\ 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..6e72bc0fb2 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,65 @@ public: return (persistent_img == 1); }; + /** + * Returns the source path of the image + * @return source of image + */ + const string& get_source() + { + return 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 +181,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,92 +250,13 @@ 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 + * Generates the source path for the repository. + * @param uid of the image owner + * @param name of the image + * @return source for the image */ - 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; - } + static string generate_source(int uid, const string& name); private: @@ -369,16 +310,6 @@ private: */ int running_vms; - // ------------------------------------------------------------------------- - // Image Attributes - // ------------------------------------------------------------------------- - - /** - * The Image template, holds the Image attributes. - */ - ImageTemplate * image_template; - - // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* @@ -401,13 +332,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..4844a3b68d --- /dev/null +++ b/include/ImageManagerDriver.h @@ -0,0 +1,106 @@ +/* -------------------------------------------------------------------------- */ +/* 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 string& destination) const; + + /** + * Sends a move request to the MAD: "MV IMAGE_ID SRC_PATH DST_PATH" + * @param oid the image id. + * @param destination is the path to the image to be created + * @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 destination is the path to the image to be created + * @param fs type + * @param size_mb of the image to be created + */ + void mkfs(int oid, + const string& destination, + 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/Nebula.h b/include/Nebula.h index 9019ae8ddb..e7be3edca4 100644 --- a/include/Nebula.h +++ b/include/Nebula.h @@ -34,6 +34,7 @@ #include "RequestManager.h" #include "HookManager.h" #include "AuthManager.h" +#include "ImageManager.h" class Nebula { @@ -114,12 +115,16 @@ public: return hm; }; - AuthManager * get_authm() { return authm; }; + ImageManager * get_imagem() + { + return imagem; + }; + // -------------------------------------------------------------- // Environment & Configuration // -------------------------------------------------------------- @@ -229,7 +234,8 @@ private: // ----------------------------------------------------------------------- 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) + ipool(0),cpool(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"); @@ -334,6 +340,11 @@ private: delete authm; } + if ( imagem != 0) + { + delete imagem; + } + if ( nebula_configuration != 0) { delete nebula_configuration; @@ -394,6 +405,7 @@ private: RequestManager * rm; HookManager * hm; AuthManager * authm; + ImageManager * imagem; // --------------------------------------------------------------- // Implementation functions diff --git a/include/PoolObjectSQL.h b/include/PoolObjectSQL.h index fc8727004c..83d1f4a614 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,104 @@ 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; + + obj_template->erase(name); + + sattr = new SingleAttribute(name,value); + 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); + } + protected: /** @@ -198,6 +296,11 @@ protected: */ bool valid; + /** + * Template for this object, will be allocated if needed + */ + Template * obj_template; + private: /** diff --git a/include/RequestManager.h b/include/RequestManager.h index ca45567335..7c84223380 100644 --- a/include/RequestManager.h +++ b/include/RequestManager.h @@ -459,8 +459,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(){}; @@ -1048,27 +1049,6 @@ private: /* ---------------------------------------------------------------------- */ - class UserAuthenticate: public xmlrpc_c::method - { - public: - UserAuthenticate(UserPool * _upool):upool(_upool) - { - _signature="A:s"; - _help="Authenticates the user."; - }; - - ~UserAuthenticate(){}; - - void execute( - xmlrpc_c::paramList const& paramList, - xmlrpc_c::value * const retvalP); - - private: - UserPool * upool; - }; - - /* ---------------------------------------------------------------------- */ - class UserInfo: public xmlrpc_c::method { public: diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 970a0ae22f..9c510d831f 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,8 +539,8 @@ 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 // ------------------------------------------------------------------------ @@ -743,7 +656,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 +688,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. */ 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..a60b93141e 100644 --- a/include/test/NebulaTest.h +++ b/include/test/NebulaTest.h @@ -35,6 +35,7 @@ #include "RequestManager.h" #include "HookManager.h" #include "AuthManager.h" +#include "ImageManager.h" class NebulaTest { @@ -71,6 +72,7 @@ public: bool need_rm; bool need_hm; bool need_authm; + bool need_imagem; static NebulaTest * instance() { @@ -132,6 +134,8 @@ public: 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/install.sh b/install.sh index 277d835e6f..f9dd157f59 100755 --- a/install.sh +++ b/install.sh @@ -193,7 +193,9 @@ 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" VAR_DIRS="$VAR_LOCATION/remotes \ $VAR_LOCATION/remotes/im \ @@ -201,12 +203,15 @@ 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 \ $SUNSTONE_LOCATION/public \ $SUNSTONE_LOCATION/public/js \ + $SUNSTONE_LOCATION/public/js/plugins \ $SUNSTONE_LOCATION/public/css \ $SUNSTONE_LOCATION/public/vendor \ $SUNSTONE_LOCATION/public/vendor/jQueryLayout \ @@ -277,6 +282,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 @@ -313,6 +320,7 @@ INSTALL_SUNSTONE_FILES=( SUNSTONE_MODELS_JSON_FILES:$SUNSTONE_LOCATION/models/OpenNebulaJSON SUNSTONE_TEMPLATE_FILES:$SUNSTONE_LOCATION/templates SUNSTONE_PUBLIC_JS_FILES:$SUNSTONE_LOCATION/public/js + SUNSTONE_PUBLIC_JS_PLUGINS_FILES:$SUNSTONE_LOCATION/public/js/plugins SUNSTONE_PUBLIC_CSS_FILES:$SUNSTONE_LOCATION/public/css SUNSTONE_PUBLIC_VENDOR_DATATABLES:$SUNSTONE_LOCATION/public/vendor/dataTables SUNSTONE_PUBLIC_VENDOR_JGROWL:$SUNSTONE_LOCATION/public/vendor/jGrowl @@ -394,7 +402,6 @@ 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/XMLUtils.rb" @@ -426,7 +433,9 @@ MADS_LIB_FILES="src/mad/sh/madcommon.sh \ src/hm_mad/one_hm.rb \ src/hm_mad/one_hm \ src/authm_mad/one_auth_mad.rb \ - src/authm_mad/one_auth_mad" + src/authm_mad/one_auth_mad \ + src/image_mad/one_image.rb \ + src/image_mad/one_image" #------------------------------------------------------------------------------- # VMM SH Driver KVM scripts, to be installed under $REMOTES_LOCATION/vmm/kvm @@ -512,6 +521,15 @@ LVM_TM_COMMANDS_LIB_FILES="src/tm_mad/lvm/tm_clone.sh \ src/tm_mad/lvm/tm_mv.sh \ src/tm_mad/lvm/tm_context.sh" +#------------------------------------------------------------------------------- +# Image Repository drivers, to be installed under $REMOTES_LOCTION/image +# - FS based Image Repository, $REMOTES_LOCATION/image/fs +#------------------------------------------------------------------------------- +IMAGE_DRIVER_FS_SCRIPTS="src/image_mad/remotes/fs/cp \ + src/image_mad/remotes/fs/mkfs \ + src/image_mad/remotes/fs/mv \ + src/image_mad/remotes/fs/rm" + #------------------------------------------------------------------------------- # Configuration files for OpenNebula, to be installed under $ETC_LOCATION #------------------------------------------------------------------------------- @@ -726,10 +744,18 @@ SUNSTONE_TEMPLATE_FILES="src/sunstone/templates/index.html \ SUNSTONE_PUBLIC_JS_FILES="src/sunstone/public/js/layout.js \ src/sunstone/public/js/login.js \ - src/sunstone/public/js/one-ui_views.js \ - src/sunstone/public/js/one-ui_views.templates.js \ + src/sunstone/public/js/sunstone.js \ + src/sunstone/public/js/sunstone-util.js \ src/sunstone/public/js/opennebula.js" +SUNSTONE_PUBLIC_JS_PLUGINS_FILES="\ + src/sunstone/public/js/plugins/dashboard-tab.js \ + src/sunstone/public/js/plugins/hosts-tab.js \ + src/sunstone/public/js/plugins/images-tab.js \ + src/sunstone/public/js/plugins/users-tab.js \ + src/sunstone/public/js/plugins/vms-tab.js \ + src/sunstone/public/js/plugins/vnets-tab.js" + SUNSTONE_PUBLIC_CSS_FILES="src/sunstone/public/css/application.css \ src/sunstone/public/css/layout.css \ src/sunstone/public/css/login.css" diff --git a/share/etc/oned.conf b/share/etc/oned.conf index 9d2bfc2c08..a0fa2ffb9b 100644 --- a/share/etc/oned.conf +++ b/share/etc/oned.conf @@ -285,6 +285,25 @@ TM_MAD = [ # arguments = "tm_lvm/tm_lvm.conf" ] #------------------------------------------------------------------------------- +#******************************************************************************* +# Image Manager Driver Configuration +#******************************************************************************* +# Drivers to manage the image repository, specialized for the storage backend +# executable: path of the transfer driver executable, can be an +# absolute path or relative to $ONE_LOCATION/lib/mads (or +# /usr/lib/one/mads/ if OpenNebula was installed in /) +# +# arguments : for the driver executable +#******************************************************************************* +#------------------------------------------------------------------------------- +# FS based Image Manager Driver Configuration +# -t number of threads, i.e. number of repo operations at the same time +#------------------------------------------------------------------------------- +IMAGE_MAD = [ + executable = "one_image", + arguments = "fs -t 15" ] +#------------------------------------------------------------------------------- + #******************************************************************************* # Hook Manager Configuration #******************************************************************************* @@ -339,16 +358,6 @@ TM_MAD = [ HM_MAD = [ executable = "one_hm" ] -#-------------------------------- Image Hook ----------------------------------- -# This hook is used to handle image saving and overwriting when virtual machines -# reach the DONE state after being shutdown. - -VM_HOOK = [ - name = "image", - on = "DONE", - command = "image.rb", - arguments = "$VMID" ] - #------------------------------------------------------------------------------- #------------------------------ Fault Tolerance Hooks -------------------------- diff --git a/share/scripts/ganglia/push_ganglia b/share/scripts/ganglia/push_ganglia new file mode 100755 index 0000000000..6f8e56dc8a --- /dev/null +++ b/share/scripts/ganglia/push_ganglia @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby + +# -------------------------------------------------------------------------- # +# 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. # +#--------------------------------------------------------------------------- # + +data=STDIN.read.strip + +data.each_line do |line| + next if !/^([^=]+?)=(.*)$/.match line + + var_name="OPENNEBULA_#{$1}" + var_data=$2 + + var_type=/^\d+$/.match(var_data) ? 'uint32' : 'string' + + command="gmetric -n #{var_name} -v \"#{var_data}\" -t #{var_type}" + + system command +end + + diff --git a/src/cli/oneimage b/src/cli/oneimage index 13c6185bb3..09cd59fd64 100755 --- a/src/cli/oneimage +++ b/src/cli/oneimage @@ -321,8 +321,6 @@ result=[false, "Unknown error"] command=ARGV.shift -img_repo = OpenNebula::ImageRepository.new - case command when "register", "create", "add" check_parameters("register", 1) @@ -330,7 +328,7 @@ when "register", "create", "add" image = OpenNebula::Image.new(OpenNebula::Image.build_xml, get_one_client) - result = img_repo.create(image, template) + result = image.allocate(template) if is_successful?(result) puts "ID: " + image.id.to_s if ops[:verbose] end @@ -506,7 +504,7 @@ when "delete" OpenNebula::Image.build_xml(image_id), get_one_client) - result = img_repo.delete(image) + result = image.delete if is_successful?(result) puts "Image correctly deleted" if ops[:verbose] end diff --git a/src/cli/onevm b/src/cli/onevm index 10de4f0e38..0c81b07caa 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -785,56 +785,17 @@ when "saveas" exit -1 end - if ops[:type] - image_type = ops[:type] - else - image_id = vm["TEMPLATE/DISK[DISK_ID=\"#{disk_id}\"]/IMAGE_ID"] - - if (image_id != nil) - if vm["TEMPLATE/DISK[DISK_ID=\"#{disk_id}\"]/SAVE_AS"] - puts "Error: The disk #{disk_id} is already" << - " suppossed to be saved" - exit -1 - end - - # Get the image type - image = OpenNebula::Image.new( - OpenNebula::Image.build_xml(image_id), - get_one_client) - - result = image.info - if !is_successful?(result) - puts result.message - exit -1 - end - - image_type = image.type_str - end - end - - # Build the template and allocate the new Image - template = "NAME=\"#{image_name}\"\n" - template << "TYPE=#{image_type}\n" if image_type - - - image = OpenNebula::Image.new( - OpenNebula::Image.build_xml, - get_one_client) - - result = image.allocate(template) - if !is_successful?(result) - puts result.message + if vm["TEMPLATE/DISK[DISK_ID=\"#{disk_id}\"]/SAVE_AS"] + puts "Error: The disk #{disk_id} is already" << + " suppossed to be saved" exit -1 end - - result = vm.save_as(disk_id.to_i, image.id) + + result = vm.save_as(disk_id.to_i, image_name) if is_successful?(result) puts "VM disk with ID #{disk_id} is prepared to be" << " saved" if ops[:verbose] - else - image.delete end - when "show" check_parameters("get_info", 1) diff --git a/src/cloud/common/CloudServer.rb b/src/cloud/common/CloudServer.rb index 0955c2e84e..e05757ee07 100755 --- a/src/cloud/common/CloudServer.rb +++ b/src/cloud/common/CloudServer.rb @@ -62,8 +62,6 @@ class CloudServer @one_client = Client.new(nil,@config[:one_xmlrpc]) @user_pool = UserPool.new(@one_client) - - @img_repo = OpenNebula::ImageRepository.new end # @@ -103,39 +101,6 @@ class CloudServer return @user_pool["USER[NAME=\"#{name}\"]/PASSWORD"] end - ########################################################################### - # Repository Methods - ########################################################################### - - # Adds a new image to the repository and deletes the temp_file - # uid:: _Integer_ owner of the image - # path:: _String_ path of the tmp file - # metadata:: Additional metadata for the file - # [return] _Image_ Newly created image object - def add_image(image, file=nil) - template = image.to_one_template - - if file - if file[:tempfile] - file_path = file[:tempfile].path - template << "\nPATH = #{file_path}" - else - error_msg = "Image not present, aborting." - error = OpenNebula::Error.new(error_msg) - return error - end - end - - rc = @img_repo.create(image, template) - - file[:tempfile].unlink if file - - if OpenNebula.is_error?(rc) - return rc - end - - return nil - end # Finds out if a port is available on ip # ip:: _String_ IP address where the port to check is diff --git a/src/cloud/ec2/lib/EC2QueryClient.rb b/src/cloud/ec2/lib/EC2QueryClient.rb index d98b5c2b27..0cbc7fdb54 100644 --- a/src/cloud/ec2/lib/EC2QueryClient.rb +++ b/src/cloud/ec2/lib/EC2QueryClient.rb @@ -140,7 +140,7 @@ module EC2QueryClient def upload_image(file_name, curb=true) params = { "Action" => "UploadImage", "SignatureVersion" => "2", - "SignatureMethod" => 'HmacSHA1', + "SignatureMethod" => 'HmacSHA256', "AWSAccessKeyId" => @access_key_id, "Version" => API_VERSION, "Timestamp" => Time.now.getutc.iso8601 } diff --git a/src/cloud/ec2/lib/EC2QueryServer.rb b/src/cloud/ec2/lib/EC2QueryServer.rb index 75a86f06d7..e93e06b66e 100644 --- a/src/cloud/ec2/lib/EC2QueryServer.rb +++ b/src/cloud/ec2/lib/EC2QueryServer.rb @@ -122,11 +122,16 @@ class EC2QueryServer < CloudServer ########################################################################### def upload_image(params, one_client) - image = ImageEC2.new(Image.build_xml, one_client) + image = ImageEC2.new(Image.build_xml, one_client, params['file']) - rc = add_image(image, params['file']) + template = image.to_one_template + if OpenNebula.is_error?(template) + return OpenNebula::Error.new('Unsupported'), 400 + end + + rc = image.allocate(template) if OpenNebula.is_error?(rc) - return OpenNebula::Error.new('Unsupported'),400 + return OpenNebula::Error.new('Unsupported'), 400 end erb_version = params['Version'] diff --git a/src/cloud/ec2/lib/ImageEC2.rb b/src/cloud/ec2/lib/ImageEC2.rb index b1745330eb..e34da8127d 100644 --- a/src/cloud/ec2/lib/ImageEC2.rb +++ b/src/cloud/ec2/lib/ImageEC2.rb @@ -24,8 +24,21 @@ class ImageEC2 < Image ONE_IMAGE = %q{ NAME = "ec2-<%= uuid %>" TYPE = OS + <% if @image_file != nil %> + PATH = "<%= @image_file %>" + <% end %> }.gsub(/^ /, '') - + + def initialize(xml, client, file=nil) + super(xml, client) + @image_info = nil + @image_file = file + + if file && file[:tempfile] + @image_file = file[:tempfile].path + end + end + def to_one_template() uuid = UUID.generate diff --git a/src/cloud/ec2/lib/views/describe_images.erb b/src/cloud/ec2/lib/views/describe_images.erb index d4a787e005..5ef277ad1a 100644 --- a/src/cloud/ec2/lib/views/describe_images.erb +++ b/src/cloud/ec2/lib/views/describe_images.erb @@ -1,25 +1,27 @@ - + <% impool.each do |im| %> <% im.info %> - + ami-<%= sprintf('%08i', im.id) %> <%= im['SOURCE'].split('/').last %> - <% if im['STATE'] == '3' %> - deregistered + <% if im['STATE'] == '3' || im['STATE'] == '5' %> + failed <% elsif im['STATE'] == '1' || im['STATE'] == '2' %> - available + available + <% elsif im['STATE'] == '4'%> + pending <% end %> - <%= erb_user_name %> + <%= erb_user_name %> <% if im['PUBLIC'] == '0' %> - false + false <% elsif im['PUBLIC'] == '1' %> - true + true <% end %> - i386 - machine - + i386 + machine + <% end %> - - + + diff --git a/src/cloud/occi/lib/ImageOCCI.rb b/src/cloud/occi/lib/ImageOCCI.rb index 0ee1f97c33..77a6150349 100755 --- a/src/cloud/occi/lib/ImageOCCI.rb +++ b/src/cloud/occi/lib/ImageOCCI.rb @@ -46,6 +46,9 @@ class ImageOCCI < Image <% if @image_info['DESCRIPTION'] != nil %> DESCRIPTION = "<%= @image_info['DESCRIPTION'] %>" <% end %> + <% if @image_file != nil %> + PATH = "<%= @image_file %>" + <% end %> <% if @image_info['PUBLIC'] != nil %> PUBLIC = "<%= @image_info['PUBLIC'] %>" <% end %> @@ -64,9 +67,14 @@ class ImageOCCI < Image }.gsub(/^ /, '') # Class constructor - def initialize(xml, client, xml_info=nil) + def initialize(xml, client, xml_info=nil, file=nil) super(xml, client) @image_info = nil + @image_file = file + + if file && file[:tempfile] + @image_file = file[:tempfile].path + end if xml_info != nil xmldoc = XMLElement.build_xml(xml_info, 'STORAGE') diff --git a/src/cloud/occi/lib/OCCIClient.rb b/src/cloud/occi/lib/OCCIClient.rb index 29bf1f7279..6c7041f22a 100755 --- a/src/cloud/occi/lib/OCCIClient.rb +++ b/src/cloud/occi/lib/OCCIClient.rb @@ -170,18 +170,18 @@ module OCCIClient return error end - if image_info.elements['URL'] == nil + if image_info.elements['URL'] + file_path = image_info.elements['URL'].text + + m = file_path.match(/^\w+:\/\/(.*)$/) + + if m + file_path="/"+m[1] + end + elsif !image_info.elements['TYPE'] == "DATABLOCK" return CloudClient::Error.new("Can not find URL") end - file_path = image_info.elements['URL'].text - - m = file_path.match(/^\w+:\/\/(.*)$/) - - if m - file_path="/"+m[1] - end - if curb if !CURL_LOADED error_msg = "curb gem not loaded" @@ -197,10 +197,14 @@ module OCCIClient curl.multipart_form_post = true begin - curl.http_post( - Curl::PostField.content('occixml', xml), - Curl::PostField.file('file', file_path) - ) + postfields = Array.new + postfields << Curl::PostField.content('occixml', xml) + + if file_path + postfields << Curl::PostField.file('file', file_path) + end + + curl.http_post(*postfields) rescue Exception => e return CloudClient::Error.new(e.message) end @@ -213,11 +217,13 @@ module OCCIClient return error end - file=File.open(file_path) - params=Hash.new - params["file"]=UploadIO.new(file, - 'application/octet-stream', file_path) + + if file_path + file=File.open(file_path) + params["file"]=UploadIO.new(file, + 'application/octet-stream', file_path) + end params['occixml'] = xml @@ -231,8 +237,8 @@ module OCCIClient http.request(req) end - file.close - pp res + file.close if file_path + if CloudClient::is_error?(res) return res else diff --git a/src/cloud/occi/lib/OCCIServer.rb b/src/cloud/occi/lib/OCCIServer.rb index 1c3afb198a..da8db35353 100755 --- a/src/cloud/occi/lib/OCCIServer.rb +++ b/src/cloud/occi/lib/OCCIServer.rb @@ -401,16 +401,18 @@ class OCCIServer < CloudServer image = ImageOCCI.new( Image.build_xml, get_client(request.env), - occixml) + occixml, + request.params['file']) - rc = add_image(image, request.params['file']) - return rc, 500 if OpenNebula.is_error?(rc) + # --- Generate the template and Allocate the new Instance --- + template = image.to_one_template + return template, 500 if OpenNebula.is_error?(template) - # --- Enable the new Image --- - rc = image.enable + rc = image.allocate(template) return rc, 500 if OpenNebula.is_error?(rc) # --- Prepare XML Response --- + image.info return to_occi_xml(image, 201) end diff --git a/src/host/Host.cc b/src/host/Host.cc index f8095c24c5..43e1cf74c6 100644 --- a/src/host/Host.cc +++ b/src/host/Host.cc @@ -40,11 +40,18 @@ Host::Host( vmm_mad_name(_vmm_mad_name), tm_mad_name(_tm_mad_name), last_monitored(0), - cluster(_cluster), - host_template() - {} + cluster(_cluster) +{ + obj_template = new HostTemplate; +} -Host::~Host(){} +Host::~Host() +{ + if ( obj_template != 0 ) + { + delete obj_template; + } +} /* ************************************************************************ */ /* Host :: Database Access Functions */ @@ -167,7 +174,7 @@ int Host::update_info(string &parse_str) char * error_msg; int rc; - rc = host_template.parse(parse_str, &error_msg); + rc = obj_template->parse(parse_str, &error_msg); if ( rc != 0 ) { @@ -222,7 +229,7 @@ string& Host::to_xml(string& xml) const "" << last_monitored << "" << "" << cluster << "" << host_share.to_xml(share_xml) << - host_template.to_xml(template_xml) << + obj_template->to_xml(template_xml) << ""; xml = oss.str(); @@ -276,7 +283,7 @@ int Host::from_xml(const string& xml) return -1; } - rc += host_template.from_xml_node( content[0] ); + rc += obj_template->from_xml_node( content[0] ); if (rc != 0) { diff --git a/src/image/Image.cc b/src/image/Image.cc index a261558507..accc84eae6 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -47,19 +47,19 @@ Image::Image(int _uid, { if (_image_template != 0) { - image_template = _image_template; + obj_template = _image_template; } else { - image_template = new ImageTemplate; + obj_template = new ImageTemplate; } } Image::~Image() { - if (image_template != 0) + if (obj_template != 0) { - delete image_template; + delete obj_template; } } @@ -78,6 +78,22 @@ const char * Image::db_bootstrap = "CREATE TABLE IF NOT EXISTS image_pool (" /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ +string Image::generate_source(int uid, const string& name) +{ + ostringstream tmp_hashstream; + ostringstream tmp_sourcestream; + + tmp_hashstream << uid << ":" << name; + + tmp_sourcestream << ImagePool::source_prefix() << "/"; + tmp_sourcestream << sha1_digest(tmp_hashstream.str()); + + return tmp_sourcestream.str(); +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + int Image::insert(SqlDB *db, string& error_str) { int rc; @@ -116,7 +132,7 @@ int Image::insert(SqlDB *db, string& error_str) get_template_attribute("PUBLIC", public_attr); - image_template->erase("PUBLIC"); + obj_template->erase("PUBLIC"); TO_UPPER(public_attr); @@ -126,7 +142,7 @@ int Image::insert(SqlDB *db, string& error_str) get_template_attribute("PERSISTENT", persistent_attr); - image_template->erase("PERSISTENT"); + obj_template->erase("PERSISTENT"); TO_UPPER(persistent_attr); @@ -147,14 +163,12 @@ int Image::insert(SqlDB *db, string& error_str) { SingleAttribute * dev_att = new SingleAttribute("DEV_PREFIX", ImagePool::default_dev_prefix()); - - image_template->set(dev_att); + obj_template->set(dev_att); } - // ------------ PATH -------------------- - get_template_attribute("PATH", path_attr); + // ------------ PATH & SOURCE -------------------- - // ------------ SOURCE (path to store the image) -------------------- + get_template_attribute("PATH", path_attr); get_template_attribute("SOURCE", source); // The template should contain PATH or SOURCE @@ -163,14 +177,26 @@ int Image::insert(SqlDB *db, string& error_str) string size_attr; string fstype_attr; + istringstream iss; + int size_mb; + get_template_attribute("SIZE", size_attr); get_template_attribute("FSTYPE", fstype_attr); - // It could be an empty DATABLOCK image, if it declares SIZE and FSTYPE - if ( type_att != "DATABLOCK" || size_attr.empty() || fstype_attr.empty() ) + // DATABLOCK image needs SIZE and FSTYPE + if (type != DATABLOCK || size_attr.empty() || fstype_attr.empty()) { goto error_no_path; } + + iss.str(size_attr); + + iss >> size_mb; + + if (iss.fail() == true) + { + goto error_size_format; + } } else if ( !source.empty() && !path_attr.empty() ) { @@ -179,18 +205,10 @@ int Image::insert(SqlDB *db, string& error_str) if (source.empty()) { - ostringstream tmp_hashstream; - ostringstream tmp_sourcestream; - - tmp_hashstream << uid << ":" << name; - - tmp_sourcestream << ImagePool::source_prefix() << "/"; - tmp_sourcestream << sha1_digest(tmp_hashstream.str()); - - source = tmp_sourcestream.str(); + source = Image::generate_source(uid,name); } - state = DISABLED; + state = LOCKED; //LOCKED till the ImageManager copies it to the Repository //-------------------------------------------------------------------------- // Insert the Image @@ -214,7 +232,7 @@ error_public_and_persistent: goto error_common; error_no_path: - if ( type_att == "DATABLOCK" ) + if ( type == DATABLOCK ) { error_str = "A DATABLOCK type IMAGE has to declare a PATH, or both " "SIZE and FSTYPE."; @@ -225,6 +243,10 @@ error_no_path: } goto error_common; +error_size_format: + error_str = "Wrong number in SIZE."; + goto error_common; + error_path_and_source: error_str = "Template malformed, PATH and SOURCE are mutuallly exclusive."; goto error_common; @@ -337,7 +359,7 @@ string& Image::to_xml(string& xml) const "" << source << "" << "" << state << "" << "" << running_vms << "" << - image_template->to_xml(template_xml) << + obj_template->to_xml(template_xml) << ""; xml = oss.str(); @@ -384,7 +406,7 @@ int Image::from_xml(const string& xml) return -1; } - rc += image_template->from_xml_node(content[0]); + rc += obj_template->from_xml_node(content[0]); if (rc != 0) { @@ -397,70 +419,6 @@ int Image::from_xml(const string& xml) /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ -int Image::acquire_image() -{ - int rc = 0; - - - switch (state) - { - case READY: - running_vms++; - state = USED; - break; - - case USED: - if (persistent_img) - { - rc = -1; - } - else - { - running_vms++; - } - break; - - case DISABLED: - default: - rc = -1; - break; - } - - return rc; -} - -/* ------------------------------------------------------------------------ */ -/* ------------------------------------------------------------------------ */ - -bool Image::release_image() -{ - bool dirty = false; - - switch (state) - { - case USED: - running_vms--; - - if ( running_vms == 0) - { - state = READY; - } - - dirty = true; - break; - - case DISABLED: - case READY: - default: - break; - } - - return dirty; -} - -/* ------------------------------------------------------------------------ */ -/* ------------------------------------------------------------------------ */ - int Image::disk_attribute( VectorAttribute * disk, int * index, ImageType* img_type) @@ -488,15 +446,6 @@ int Image::disk_attribute( VectorAttribute * disk, get_template_attribute("DEV_PREFIX", prefix); - //-------------------------------------------------------------------------- - // Acquire the image - //-------------------------------------------------------------------------- - - if ( acquire_image() != 0 ) - { - return -1; - } - //--------------------------------------------------------------------------- // NEW DISK ATTRIBUTES //--------------------------------------------------------------------------- @@ -533,8 +482,6 @@ int Image::disk_attribute( VectorAttribute * disk, { new_disk.insert(make_pair("CLONE","NO")); new_disk.insert(make_pair("SAVE","YES")); - - new_disk.insert(make_pair("SAVE_AS", iid.str())); // Tells the hook to overwrite } else { diff --git a/src/image/ImageManager.cc b/src/image/ImageManager.cc new file mode 100644 index 0000000000..4272b36715 --- /dev/null +++ b/src/image/ImageManager.cc @@ -0,0 +1,126 @@ +/* -------------------------------------------------------------------------- */ +/* 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 "ImageManager.h" +#include "NebulaLog.h" +#include "ImagePool.h" + +const char * ImageManager::image_driver_name = "image_exe"; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +extern "C" void * image_action_loop(void *arg) +{ + ImageManager * im; + + if ( arg == 0 ) + { + return 0; + } + + NebulaLog::log("ImM",Log::INFO,"Image Manager started."); + + im = static_cast(arg); + + im->am.loop(0,0); + + NebulaLog::log("ImM",Log::INFO,"Image Manager stopped."); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void ImageManager::load_mads(int uid) +{ + ImageManagerDriver * imagem_mad; + ostringstream oss; + const VectorAttribute * vattr; + int rc; + + NebulaLog::log("ImM",Log::INFO,"Loading Image Manager driver."); + + vattr = static_cast(mad_conf[0]); + + if ( vattr == 0 ) + { + NebulaLog::log("ImM",Log::INFO,"Failed to load Image Manager driver."); + return; + } + + VectorAttribute image_conf("IMAGE_MAD",vattr->value()); + + image_conf.replace("NAME",image_driver_name); + + imagem_mad = new ImageManagerDriver(0,image_conf.value(),false,ipool); + + rc = add(imagem_mad); + + if ( rc == 0 ) + { + oss.str(""); + oss << "\tImage Manager loaded"; + + NebulaLog::log("ImM",Log::INFO,oss); + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int ImageManager::start() +{ + int rc; + pthread_attr_t pattr; + + rc = MadManager::start(); + + if ( rc != 0 ) + { + return -1; + } + + NebulaLog::log("ImM",Log::INFO,"Starting Image Manager..."); + + pthread_attr_init (&pattr); + pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); + + rc = pthread_create(&imagem_thread,&pattr,image_action_loop,(void *) this); + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void ImageManager::do_action(const string &action, void * arg) +{ + if (action == ACTION_FINALIZE) + { + NebulaLog::log("ImM",Log::INFO,"Stopping Image Manager..."); + MadManager::stop(); + } + else + { + ostringstream oss; + oss << "Unknown action name: " << action; + + NebulaLog::log("ImM", Log::ERROR, oss); + } +} + diff --git a/src/image/ImageManagerActions.cc b/src/image/ImageManagerActions.cc new file mode 100644 index 0000000000..13df8d592b --- /dev/null +++ b/src/image/ImageManagerActions.cc @@ -0,0 +1,433 @@ +/* -------------------------------------------------------------------------- */ +/* 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 "ImageManager.h" +#include "NebulaLog.h" +#include "ImagePool.h" + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +Image * ImageManager::acquire_image(int image_id) +{ + Image * img; + int rc; + + img = ipool->get(image_id,true); + + if ( img == 0 ) + { + return 0; + } + + rc = acquire_image(img); + + if ( rc != 0 ) + { + img->unlock(); + img = 0; + } + + return img; +} + +/* -------------------------------------------------------------------------- */ + +Image * ImageManager::acquire_image(const string& name, int uid) +{ + Image * img; + int rc; + + img = ipool->get(name,uid,true); + + if ( img == 0 ) + { + return 0; + } + + rc = acquire_image(img); + + if ( rc != 0 ) + { + img->unlock(); + img = 0; + } + + return img; +} + +/* -------------------------------------------------------------------------- */ + +int ImageManager::acquire_image(Image *img) +{ + int rc = 0; + + switch (img->get_state()) + { + case Image::READY: + img->inc_running(); + img->set_state(Image::USED); + ipool->update(img); + break; + + case Image::USED: + if (img->isPersistent()) + { + rc = -1; + } + else + { + img->inc_running(); + ipool->update(img); + } + break; + + case Image::DISABLED: + case Image::LOCKED: + case Image::ERROR: + default: + rc = -1; + break; + } + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void ImageManager::move_image(Image *img, const string& source) +{ + const ImageManagerDriver* imd = get(); + ostringstream oss; + + if ( imd == 0 ) + { + NebulaLog::log("ImM",Log::ERROR, + "Could not get driver to update repository"); + return; + } + + oss << "Moving disk " << source << " to repository image " + << img->get_oid() << " as " << img->get_source(); + + imd->mv(img->get_oid(),source,img->get_source()); + + NebulaLog::log("ImM",Log::INFO,oss); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void ImageManager::disk_to_image(const string& disk_path, + int disk_num, + const string& save_id) +{ + int sid; + + istringstream iss; + Image * img; + + ostringstream disk_file; + + iss.str(save_id); + + iss >> sid; + + img = ipool->get(sid,true); + + if ( img == 0 ) + { + NebulaLog::log("ImM",Log::ERROR,"Could not get image to saveas disk."); + } + else + { + disk_file << disk_path << "/disk." << disk_num; + + move_image(img,disk_file.str()); + } + + img->unlock(); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void ImageManager::release_image(const string& image_id, + const string& disk_path, + int disk_num, + const string& save_id) +{ + int rvms; + + int iid; + int sid = -1; + + istringstream iss; + Image * img; + + ostringstream disk_file; + + iss.str(image_id); + + iss >> iid; + + if ( save_id.empty() == false ) + { + iss.clear(); + iss.str(save_id); + + iss >> sid; + } + + img = ipool->get(iid,true); + + if ( img == 0 ) + { + return; + } + + switch (img->get_state()) + { + case Image::USED: + rvms = img->dec_running(); + + if ( img->isPersistent() ) + { + disk_file << disk_path << "/disk." << disk_num; + + img->set_state(Image::LOCKED); + + move_image(img,disk_file.str()); + + ipool->update(img); + + img->unlock(); + } + else + { + if ( rvms == 0) + { + img->set_state(Image::READY); + } + + ipool->update(img); + + img->unlock(); + + if ( sid != -1 ) + { + img = ipool->get(sid,true); + + if ( img == 0 ) + { + NebulaLog::log("ImM",Log::ERROR, + "Could not get image to saveas disk."); + } + else + { + disk_file << disk_path << "/disk." << disk_num; + + move_image(img,disk_file.str()); + } + + img->unlock(); + } + } + break; + + case Image::DISABLED: + case Image::READY: + case Image::ERROR: + case Image::LOCKED: + NebulaLog::log("ImM",Log::ERROR, + "Trying to release image in wrong state."); + default: + img->unlock(); + break; + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int ImageManager::enable_image(int iid, bool to_enable) +{ + int rc = 0; + Image * img; + + img = ipool->get(iid,true); + + if ( img == 0 ) + { + return -1; + } + + if ( to_enable == true ) + { + switch (img->get_state()) + { + case Image::DISABLED: + case Image::ERROR: + img->set_state(Image::READY); + ipool->update(img); + case Image::READY: + break; + default: + rc = -1; + break; + } + } + else + { + switch (img->get_state()) + { + case Image::READY: + case Image::ERROR: + img->set_state(Image::DISABLED); + ipool->update(img); + case Image::DISABLED: + break; + default: + rc = -1; + break; + } + } + + img->unlock(); + + return rc; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int ImageManager::delete_image(int iid) +{ + Image * img; + + img = ipool->get(iid,true); + + if ( img == 0 ) + { + return -1; + } + + switch(img->get_state()) + { + case Image::READY: + if ( img->get_running() != 0 ) + { + img->unlock(); + return -1; //Can not remove images in use + } + break; + + case Image::USED: + img->unlock(); + return -1; //Can not remove images in use + break; + + case Image::INIT: + case Image::DISABLED: + case Image::LOCKED: + case Image::ERROR: + break; + } + + const ImageManagerDriver* imd = get(); + + if ( imd == 0 ) + { + return -1; + } + + imd->rm(img->get_oid(),img->get_source()); + + img->unlock(); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int ImageManager::register_image(int iid) +{ + const ImageManagerDriver* imd = get(); + ostringstream oss; + + string path; + Image* img; + + if ( imd == 0 ) + { + NebulaLog::log("ImM",Log::ERROR, + "Could not get driver to update repository"); + return -1; + } + + img = ipool->get(iid,true); + + if (img == 0) + { + return -1; + } + + img->get_template_attribute("PATH",path); + + if ( path.empty() == true ) //NO PATH -> USE SOURCE OR MKFS FOR DATABLOCK + { + string fs; + string size; + + img->get_template_attribute("SIZE", size); + img->get_template_attribute("FSTYPE", fs); + + if ( img->get_type() == Image::DATABLOCK && + !size.empty() && !fs.empty() ) + { + imd->mkfs(img->get_oid(), img->get_source(), fs, size); + + oss << "Creating disk at " << img->get_source() << " of " + << size << "Mb with format " << fs; + } + else + { + img->set_state(Image::READY); + ipool->update(img); + + oss << "Using source " << img->get_source() + << " from template for image " << img->get_name(); + } + } + else //PATH -> COPY TO REPOSITORY AS SOURCE + { + imd->cp(img->get_oid(), path, img->get_source()); + oss << "Copying image " << path + << " to repository as " << img->get_source(); + } + + NebulaLog::log("ImM",Log::INFO,oss); + + img->unlock(); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + diff --git a/src/image/ImageManagerDriver.cc b/src/image/ImageManagerDriver.cc new file mode 100644 index 0000000000..3ca30af29c --- /dev/null +++ b/src/image/ImageManagerDriver.cc @@ -0,0 +1,268 @@ +/* -------------------------------------------------------------------------- */ +/* 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 "ImageManagerDriver.h" +#include "ImagePool.h" + +#include "NebulaLog.h" + +#include "Nebula.h" +#include + +/* ************************************************************************** */ +/* Driver ASCII Protocol Implementation */ +/* ************************************************************************** */ + +void ImageManagerDriver::cp(int oid, + const string& source, + const string& destination) const +{ + ostringstream os; + + os << "CP " << oid << " " << source << " " << destination << endl; + + write(os); +} + +/* -------------------------------------------------------------------------- */ + +void ImageManagerDriver::mv(int oid, + const string& source, + const string& destination) const +{ + ostringstream os; + + os << "MV " << oid << " " << source << " " << destination << endl; + + write(os); +} + +/* -------------------------------------------------------------------------- */ + +void ImageManagerDriver::mkfs(int oid, + const string& destination, + const string& fs, + const string& size_mb) const +{ + ostringstream os; + + os << "MKFS " << oid << " " << destination << " " << + fs << " " << size_mb << endl; + write(os); +} + +/* -------------------------------------------------------------------------- */ + +void ImageManagerDriver::rm(int oid, const string& destination) const +{ + ostringstream os; + + os << "RM " << oid << " " << destination << endl; + + write(os); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +/* ************************************************************************** */ +/* MAD Interface */ +/* ************************************************************************** */ + +void ImageManagerDriver::protocol( + string& message) +{ + istringstream is(message); + ostringstream os; + + string action; + string result; + + int id; + Image * image; + + string info; + + os << "Message received: " << message; + NebulaLog::log("ImG", Log::DEBUG, os); + + // Parse the driver message + if ( is.good() ) + is >> action >> ws; + else + return; + + if ( is.good() ) + is >> result >> ws; + else + return; + + if ( is.good() ) + { + is >> id >> ws; + + if ( is.fail() ) + { + if ( action == "LOG" ) + { + string info; + + is.clear(); + getline(is,info); + + NebulaLog::log("ImG",Log::INFO, info.c_str()); + } + + return; + } + } + else + return; + + // Get the image from the pool + image = ipool->get(id,true); + + if ( image == 0 ) + { + return; + } + + // Driver Actions + if ( action == "CP" ) + { + if ( result == "SUCCESS" ) + { + image->set_state(Image::READY); + ipool->update(image); + + image->unlock(); + + NebulaLog::log("ImM", Log::INFO, "Image copied and ready to use."); + } + else + { + goto error_cp; + } + } + else if ( action == "MV" ) + { + if ( result == "SUCCESS" ) + { + image->set_state(Image::READY); + ipool->update(image); + + image->unlock(); + + NebulaLog::log("ImM", Log::INFO, "Image saved and ready to use."); + } + else + { + goto error_mv; + } + } + else if ( action == "MKFS" ) + { + if ( result == "SUCCESS" ) + { + image->set_state(Image::READY); + ipool->update(image); + + image->unlock(); + + NebulaLog::log("ImM", Log::INFO, "Image created and ready to use"); + } + else + { + goto error_mkfs; + } + } + else if ( action == "RM" ) + { + int rc; + string source; + + source = image->get_source(); + + rc = ipool->drop(image); + + image->unlock(); + + if ( rc < 0 ) + { + NebulaLog::log("ImM",Log::ERROR,"Image could not be removed from DB"); + } + + if ( result == "SUCCESS" ) + { + NebulaLog::log("ImM",Log::ERROR,"Image successfully removed."); + } + else + { + ostringstream oss; + + oss <<"Error removing image from repository. Remove file " << source + <<" to completely delete image."; + + NebulaLog::log("ImM",Log::ERROR,oss); + } + } + else if (action == "LOG") + { + getline(is,info); + NebulaLog::log("ImM", Log::INFO, info.c_str()); + } + + return; + +error_cp: + os.str(""); + os << "Error copying image in the repository"; + goto error_common; + +error_mv: + os.str(""); + os << "Error saving image to the repository"; + goto error_common; + +error_mkfs: + os.str(""); + os << "Error creating datablock"; + +error_common: + getline(is,info); + + if (!info.empty() && (info[0] != '-')) + { + os << ": " << info; + } + + NebulaLog::log("ImM", Log::ERROR, os); + + image->set_state(Image::ERROR); + ipool->update(image); + + image->unlock(); + return; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void ImageManagerDriver::recover() +{ + NebulaLog::log("ImG",Log::INFO,"Recovering Image Repository drivers"); +} + diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc index 45e200915e..d5243cd95d 100644 --- a/src/image/ImagePool.cc +++ b/src/image/ImagePool.cc @@ -20,6 +20,7 @@ #include "ImagePool.h" #include "AuthManager.h" +#include "Nebula.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -68,9 +69,6 @@ int ImagePool::allocate ( string name; ostringstream oss; - // --------------------------------------------------------------------- - // Build a new Image object - // --------------------------------------------------------------------- img = new Image(uid, user_name, img_template); // Check name @@ -96,7 +94,6 @@ int ImagePool::allocate ( return *oid; - error_name: oss << "NAME cannot be empty."; goto error_common; @@ -128,6 +125,9 @@ int ImagePool::disk_attribute(VectorAttribute * disk, ostringstream oss; + Nebula& nd = Nebula::instance(); + ImageManager * imagem = nd.get_imagem(); + source = disk->vector_value("IMAGE"); if (source.empty()) @@ -144,7 +144,7 @@ int ImagePool::disk_attribute(VectorAttribute * disk, if( !is.fail() ) { - img = get(image_id,true); + img = imagem->acquire_image(image_id); if (img == 0) { @@ -155,7 +155,7 @@ int ImagePool::disk_attribute(VectorAttribute * disk, } else { - img = get(source,uid,true); + img = imagem->acquire_image(source,uid); if (img == 0) { @@ -167,7 +167,7 @@ int ImagePool::disk_attribute(VectorAttribute * disk, { string type = disk->vector_value("TYPE"); - transform(type.begin(), type.end(), type.begin(), (int(*)(int))toupper); + transform(type.begin(),type.end(),type.begin(),(int(*)(int))toupper); if( type == "SWAP" ) { @@ -187,12 +187,9 @@ int ImagePool::disk_attribute(VectorAttribute * disk, } else { - rc = img->disk_attribute(disk, index, img_type); + img->disk_attribute(disk, index, img_type); - if ( rc == 0 ) - { - update(img); - } + update(img); img->unlock(); } diff --git a/src/image/SConstruct b/src/image/SConstruct index faf6e38618..0a9543282e 100644 --- a/src/image/SConstruct +++ b/src/image/SConstruct @@ -23,7 +23,10 @@ lib_name='nebula_image' # Sources to generate the library source_files=[ 'Image.cc', - 'ImagePool.cc' + 'ImagePool.cc', + 'ImageManagerDriver.cc', + 'ImageManager.cc', + 'ImageManagerActions.cc' ] # Build library diff --git a/src/image/test/ImagePoolTest.cc b/src/image/test/ImagePoolTest.cc index 041076cbba..187759853c 100644 --- a/src/image/test/ImagePoolTest.cc +++ b/src/image/test/ImagePoolTest.cc @@ -31,17 +31,17 @@ const string names[] = {"Image one", "Second Image", "The third image"}; const string templates[] = { "NAME = \"Image one\"\n" - "ORIGINAL_PATH = /tmp/image_test\n" + "PATH = /tmp/image_test\n" "PERSISTENT = YES\n" "DESCRIPTION = \"This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.\"\n", "NAME = \"Second Image\"\n" - "ORIGINAL_PATH = /tmp/image_second_test\n" + "PATH = /tmp/image_second_test\n" "PUBLIC = YES\n" "DESCRIPTION = \"This is a rather short description.\"\n", "NAME = \"The third image\"\n" - "ORIGINAL_PATH = /tmp/image_test\n" + "PATH = /tmp/image_test\n" "# DESCRIPTION = \"An image description\"\n" "BUS = SCSI\n" "PROFILE = STUDENT\n" @@ -50,19 +50,19 @@ const string templates[] = const string xmls[] = { - "00A userImage one0010000000000source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa19830", + "00A userImage one0010000000000source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa19840", - "11B userSecond Image0100000000000source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f330", + "11B userSecond Image0100000000000source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f340", - "02C userThe third image0000000000000source_prefix/e50b0c738be9d431475bf5859629e5580301a7d630" + "02C userThe third image0000000000000source_prefix/e50b0c738be9d431475bf5859629e5580301a7d640" }; // This xml dump result has the STIMEs modified to 0000000000 const string xml_dump = -"00A userImage one0010000000000source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa1983011B userSecond Image0100000000000source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f33022C userThe third image0000000000000source_prefix/e50b0c738be9d431475bf5859629e5580301a7d630"; +"00A userImage one0010000000000source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa1984011B userSecond Image0100000000000source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f34022C userThe third image0000000000000source_prefix/e50b0c738be9d431475bf5859629e5580301a7d640"; const string xml_dump_where = -"00A userImage one0010000000000source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa1983011B userSecond Image0100000000000source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f330"; +"00A userImage one0010000000000source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa1984011B userSecond Image0100000000000source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f340"; const string replacement = "0000000000"; @@ -128,7 +128,10 @@ class ImagePoolTest : public PoolTest CPPUNIT_TEST ( bus_source_assignment ); CPPUNIT_TEST ( public_attribute ); CPPUNIT_TEST ( persistence ); - CPPUNIT_TEST ( imagepool_disk_attribute ); + +// Requires ImageManger, and NebulaTest +// CPPUNIT_TEST ( imagepool_disk_attribute ); + CPPUNIT_TEST ( dump ); CPPUNIT_TEST ( dump_where ); @@ -241,7 +244,7 @@ public: // Image object should be cached. Let's change some template attributes img->replace_template_attribute(description_name, new_description); img->replace_template_attribute(attr_name, new_attr_value); - img->remove_template_attribute("ORIGINAL_PATH"); + img->remove_template_attribute("PATH"); ip->update(img); @@ -253,7 +256,7 @@ public: img->get_template_attribute("DESCRIPTION", description_val); img->get_template_attribute("NEW_ATTRIBUTE", attr_val); - img->get_template_attribute("ORIGINAL_PATH", no_value); + img->get_template_attribute("PATH", no_value); CPPUNIT_ASSERT( description_val == new_description ); CPPUNIT_ASSERT( attr_val == new_attr_value ); @@ -271,7 +274,7 @@ public: no_value = "Random value"; img->get_template_attribute("DESCRIPTION", description_val); img->get_template_attribute("NEW_ATTRIBUTE", attr_val); - img->get_template_attribute("ORIGINAL_PATH", no_value); + img->get_template_attribute("PATH", no_value); CPPUNIT_ASSERT( description_val == new_description ); CPPUNIT_ASSERT( attr_val == new_attr_value ); @@ -398,11 +401,11 @@ public: string templates[] = { - "ORIGINAL_PATH = /tmp/image_test\n" + "PATH = /tmp/image_test\n" "DESCRIPTION = \"This template lacks name!\"\n", "NAME = \"name A\"\n" - "ORIGINAL_PATH = /tmp/image_test\n" + "PATH = /tmp/image_test\n" "TYPE = WRONG\n", "NAME \"PARSE ERROR\"\n" @@ -451,7 +454,7 @@ public: CPPUNIT_ASSERT( img != 0 ); CPPUNIT_ASSERT( oid == 0 ); - img->enable(true); + img->set_state(Image::READY); img->disk_attribute(disk, &index, &img_type); value = disk->vector_value("TARGET"); @@ -466,7 +469,7 @@ public: disk = new VectorAttribute("DISK"); // Allocate a CDROM type image - string templ = "NAME = \"name A\" TYPE = CDROM ORIGINAL_PATH = /tmp"; + string templ = "NAME = \"name A\" TYPE = CDROM PATH = /tmp"; imp->allocate(0, templ, &oid); CPPUNIT_ASSERT(oid >= 0); @@ -474,7 +477,7 @@ public: img = imp->get(oid, false); CPPUNIT_ASSERT( img != 0 ); - img->enable(true); + img->set_state(Image::READY); img->disk_attribute(disk, &index, &img_type); value = disk->vector_value("TARGET"); @@ -488,7 +491,7 @@ public: disk = new VectorAttribute("DISK"); // Allocate a DATABLOCK type image - templ = "NAME = \"name B\" TYPE = DATABLOCK"; + templ = "NAME = \"name B\" TYPE = DATABLOCK PATH=\"/dev/null\""; imp->allocate(0, templ, &oid); CPPUNIT_ASSERT(oid >= 0); @@ -496,7 +499,7 @@ public: img = imp->get(oid, false); CPPUNIT_ASSERT( img != 0 ); - img->enable(true); + img->set_state(Image::READY); img->disk_attribute(disk, &index, &img_type); value = disk->vector_value("TARGET"); @@ -510,7 +513,8 @@ public: disk = new VectorAttribute("DISK"); // Allocate a DATABLOCK type image - templ = "NAME = \"name C\" TYPE = DATABLOCK DEV_PREFIX = \"sd\""; + templ = "NAME = \"name C\" TYPE = DATABLOCK DEV_PREFIX = \"sd\"" + " SIZE=4 FSTYPE=ext3"; imp->allocate(0, templ, &oid); CPPUNIT_ASSERT(oid >= 0); @@ -518,7 +522,7 @@ public: img = imp->get(oid, false); CPPUNIT_ASSERT( img != 0 ); - img->enable(true); + img->set_state(Image::READY); img->disk_attribute(disk, &index, &img_type); value = disk->vector_value("TARGET"); @@ -551,7 +555,7 @@ public: // A disk without a BUS attribute should not have it added. disk = new VectorAttribute("DISK"); - img->enable(true); + img->set_state(Image::READY); rc = img->disk_attribute(disk, &index, &img_type); CPPUNIT_ASSERT( rc == 0 ); @@ -565,7 +569,7 @@ public: "source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198" ); // clean up - img->release_image(); + //img->release_image(); delete disk; // --------------------------------------------------------------------- @@ -573,7 +577,7 @@ public: disk = new VectorAttribute("DISK"); disk->replace("BUS", "SCSI"); - img->enable(true); + img->set_state(Image::READY); rc = img->disk_attribute(disk, &index, &img_type); CPPUNIT_ASSERT( rc == 0 ); @@ -606,10 +610,12 @@ public: // Allocate 2 images, with different dev_prefix string template_0 = "NAME = \"Image 0\"\n" - "DEV_PREFIX = \"hd\"\n"; + "DEV_PREFIX = \"hd\"\n" + "PATH = /dev/null\n"; string template_1 = "NAME = \"Image 1\"\n" - "DEV_PREFIX = \"sd\"\n"; + "DEV_PREFIX = \"sd\"\n" + "PATH = /dev/null\n"; imp->allocate(0, template_0, &oid_0); @@ -621,11 +627,11 @@ public: img = imp->get(oid_0, false); CPPUNIT_ASSERT( img != 0 ); - img->enable(true); + img->set_state(Image::READY); img = imp->get(oid_1, false); CPPUNIT_ASSERT( img != 0 ); - img->enable(true); + img->set_state(Image::READY); // Disk using image 0 @@ -675,46 +681,46 @@ public: { // false "NAME = \"name A\"\n" - "ORIGINAL_PATH = \"/tmp/nothing\"\n", + "PATH = \"/tmp/nothing\"\n", // true "NAME = \"name B\"\n" - "ORIGINAL_PATH = \"/tmp/nothing\"\n" + "PATH = \"/tmp/nothing\"\n" "PUBLIC = YES", // false "NAME = \"name C\"\n" - "ORIGINAL_PATH = \"/tmp/nothing\"\n" + "PATH = \"/tmp/nothing\"\n" "PUBLIC = NO", // false "NAME = \"name D\"\n" - "ORIGINAL_PATH = \"/tmp/nothing\"\n" + "PATH = \"/tmp/nothing\"\n" "PUBLIC = 1", // true "NAME = \"name E\"\n" - "ORIGINAL_PATH = \"/tmp/nothing\"\n" + "PATH = \"/tmp/nothing\"\n" "PUBLIC = Yes", // false "NAME = \"name F\"\n" - "ORIGINAL_PATH = \"/tmp/nothing\"\n" + "PATH = \"/tmp/nothing\"\n" "PUBLIC = TRUE", // true "NAME = \"name G\"\n" - "ORIGINAL_PATH = \"/tmp/nothing\"\n" + "PATH = \"/tmp/nothing\"\n" "PUBLIC = yes", // false "NAME = \"name H\"\n" - "ORIGINAL_PATH = \"/tmp/nothing\"\n" + "PATH = \"/tmp/nothing\"\n" "PUBLIC = 'YES'", // true "NAME = \"name I\"\n" - "ORIGINAL_PATH = \"/tmp/nothing\"\n" + "PATH = \"/tmp/nothing\"\n" "PUBLIC = \"YES\"", "END" @@ -769,19 +775,23 @@ public: { "NAME = \"Image 1\"\n" "PERSISTENT = NO\n" - "PUBLIC = NO\n", + "PUBLIC = NO\n" + "PATH = /dev/null\n", "NAME = \"Image 2\"\n" "PERSISTENT = NO\n" - "PUBLIC = YES\n", + "PUBLIC = YES\n" + "PATH = /dev/null\n", "NAME = \"Image 3\"\n" "PERSISTENT = YES\n" - "PUBLIC = NO\n", + "PUBLIC = NO\n" + "PATH = /dev/null\n", "NAME = \"Image 4\"\n" "PERSISTENT = YES\n" - "PUBLIC = YES\n", + "PUBLIC = YES\n" + "PATH = /dev/null\n", "END" }; @@ -864,8 +874,8 @@ public: string result = oss.str(); result.replace(157, 10, replacement); - result.replace(1147, 10, replacement); - result.replace(1677, 10, replacement); + result.replace(1129, 10, replacement); + result.replace(1641, 10, replacement); /* if( result != xml_dump ) @@ -899,7 +909,7 @@ public: string result = oss.str(); result.replace(157, 10, replacement); - result.replace(1147, 10, replacement); + result.replace(1129, 10, replacement); /* if( result != xml_dump_where ) diff --git a/src/image_mad/one_image b/src/image_mad/one_image new file mode 100755 index 0000000000..5a62cb6720 --- /dev/null +++ b/src/image_mad/one_image @@ -0,0 +1,44 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# 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. # +#--------------------------------------------------------------------------- # + +#Setup driver variables +DRIVER_NAME=`basename $0 | cut -d. -f1` + +if [ -z "${ONE_LOCATION}" ]; then + DRIVERRC=/etc/one/${DRIVER_NAME}/${DRIVER_NAME}rc + MADCOMMON=/usr/lib/one/mads/madcommon.sh + VAR_LOCATION=/var/lib/one +else + DRIVERRC=$ONE_LOCATION/etc/${DRIVER_NAME}/${DRIVER_NAME}rc + MADCOMMON=$ONE_LOCATION/lib/mads/madcommon.sh + VAR_LOCATION=$ONE_LOCATION/var +fi + +. $MADCOMMON + +# Export the im_mad specific rc + +export_rc_vars $DRIVERRC + +# Go to var directory ONE_LOCATION/var or /var/lib/one +cd $VAR_LOCATION + +LOG_FILE=$DRIVER_NAME + +# Execute the actual MAD +execute_mad $* diff --git a/src/image_mad/one_image.rb b/src/image_mad/one_image.rb new file mode 100755 index 0000000000..1d2c2faa8b --- /dev/null +++ b/src/image_mad/one_image.rb @@ -0,0 +1,136 @@ +#!/usr/bin/env ruby + +# -------------------------------------------------------------------------- */ +# 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. */ +# -------------------------------------------------------------------------- */ + +# ---------------------------------------------------------------------------- +# Set up the environment for the driver +# ---------------------------------------------------------------------------- + +ONE_LOCATION = ENV["ONE_LOCATION"] + +if !ONE_LOCATION + RUBY_LIB_LOCATION = "/usr/lib/one/ruby" + VAR_LOCATION = "/var/lib/one" +else + RUBY_LIB_LOCATION = ONE_LOCATION + "/lib/ruby" + VAR_LOCATION = ONE_LOCATION + "/var" +end + +$: << RUBY_LIB_LOCATION + +require "OpenNebulaDriver" +require "CommandManager" +require 'getoptlong' + +# This class provides basic messaging and logging functionality +# to implement Image Repository Drivers. A image repository driver +# is a program (or a set of) that specialize the OpenNebula behavior +# by interfacing with specific infrastructure storage solutions. +class ImageDriver < OpenNebulaDriver + + # ------------------------------------------------------------------------- + # Image Driver Protocol constants + # ------------------------------------------------------------------------- + ACTION = { + :mv => "MV", + :cp => "CP", + :rm => "RM", + :mkfs => "MKFS", + :log => "LOG" + } + + # ------------------------------------------------------------------------- + # Register default actions for the protocol + # ------------------------------------------------------------------------- + def initialize(fs_type, concurrency=10, threaded=true) + super(concurrency,threaded) + + @actions_path = "#{VAR_LOCATION}/remotes/image/#{fs_type}" + + register_action(ACTION[:mv].to_sym, method("mv")) + register_action(ACTION[:cp].to_sym, method("cp")) + register_action(ACTION[:rm].to_sym, method("rm")) + register_action(ACTION[:mkfs].to_sym, method("mkfs")) + end + + # ------------------------------------------------------------------------- + # Execute a command associated to an action and id on localhost + # ------------------------------------------------------------------------- + def local_action(command, id, action) + command_exe = LocalCommand.run(command) + + if command_exe.code == 0 + result = :success + info = "-" + else + result = :failure + info = command_exe.stderr + end + + info = "-" if info == nil || info.empty? + + send_message(ACTION[action],RESULT[result],id,info) + end + + # ------------------------------------------------------------------------- + # Image Manager Protocol Actions (generic implementation + # ------------------------------------------------------------------------- + def mv(id, src, dst) + local_action("#{@actions_path}/mv #{src} #{dst}",id,:mv) + end + + def cp(id, src, dst) + local_action("#{@actions_path}/cp #{src} #{dst}",id,:cp) + end + + def rm(id, dst) + local_action("#{@actions_path}/rm #{dst}",id,:rm) + end + + def mkfs(id, dst, fs, size) + local_action("#{@actions_path}/mkfs #{dst} #{fs} #{size}",id,:mkfs) + end +end + +# ---------------------------------------------------------------------------- # +# ImageDriver Main program +# ---------------------------------------------------------------------------- # +opts = GetoptLong.new( + [ '--threads', '-t', GetoptLong::OPTIONAL_ARGUMENT ] +) + +fs_type = '' +threads = 15 + +begin + opts.each do |opt, arg| + case opt + when '--threads' + threads = arg.to_i + end + end +rescue Exception => e + exit(-1) +end + +if ARGV.length >= 1 + fs_type = ARGV.shift +else + exit(-1) +end + +image_driver = ImageDriver.new(fs_type, threads) +image_driver.start_driver diff --git a/src/image_mad/remotes/fs/cp b/src/image_mad/remotes/fs/cp new file mode 100755 index 0000000000..b6bd552b24 --- /dev/null +++ b/src/image_mad/remotes/fs/cp @@ -0,0 +1,53 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# 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. # +#--------------------------------------------------------------------------- # + +############################################################################### +# This script is used to copy a VM image (SRC) to the image repository as DST +# Several SRC types are supported +############################################################################### + +# ------------ Set up the environment to source common tools ------------ + +if [ -z "${ONE_LOCATION}" ]; then + TMCOMMON=/usr/lib/one/mads/tm_common.sh + VAR_LOCATION=/var/lib/one/ +else + TMCOMMON=$ONE_LOCATION/lib/mads/tm_common.sh + VAR_LOCATION=$ONE_LOCATION/var/ +fi + +. $TMCOMMON + +# ------------ Copy the image to the repository ------------ + +SRC=$1 +DST=$2 + +case $SRC in +http://*) + log "Downloading $SRC to the image repository" + exec_and_log "$WGET -O $DST $SRC" + ;; + +*) + log "Copying local image $SRC to the image repository" + exec_and_log "cp -f $SRC $DST" + ;; +esac + +exec_and_log "chmod 0660 $DST" diff --git a/src/image_mad/remotes/fs/mkfs b/src/image_mad/remotes/fs/mkfs new file mode 100755 index 0000000000..5d2093e602 --- /dev/null +++ b/src/image_mad/remotes/fs/mkfs @@ -0,0 +1,42 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# 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. # +#--------------------------------------------------------------------------- # + +############################################################################### +# This script is used to create a VM image (SRC) of size (SIZE) and formatted +# as (FS) +############################################################################### + +# ------------ Set up the environment to source common tools ------------ + +if [ -z "${ONE_LOCATION}" ]; then + TMCOMMON=/usr/lib/one/mads/tm_common.sh +else + TMCOMMON=$ONE_LOCATION/lib/mads/tm_common.sh +fi + +. $TMCOMMON + +# ------------ Create the image to the repository ------------ + +DST=$1 +FSTYPE=$2 +SIZE=$3 + +exec_and_log "$DD if=/dev/zero of=$DST bs=1 count=1 seek=${SIZE}M" +exec_and_log "$MKFS -t $FSTYPE -F $DST" +exec_and_log "chmod 0660 $DST" diff --git a/src/image_mad/remotes/fs/mv b/src/image_mad/remotes/fs/mv new file mode 100755 index 0000000000..e4e9e5676d --- /dev/null +++ b/src/image_mad/remotes/fs/mv @@ -0,0 +1,53 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# 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. # +#--------------------------------------------------------------------------- # + +############################################################################### +# This script is used to move a VM image (SRC) to the image repository as DST +# Several SRC types are supported +############################################################################### + +# ------------ Set up the environment to source common tools ------------ + +if [ -z "${ONE_LOCATION}" ]; then + TMCOMMON=/usr/lib/one/mads/tm_common.sh + VAR_LOCATION=/var/lib/one/ +else + TMCOMMON=$ONE_LOCATION/lib/mads/tm_common.sh + VAR_LOCATION=$ONE_LOCATION/var/ +fi + +. $TMCOMMON + +# ------------ Move the image to the repository ------------ + +SRC=$1 +DST=$2 + +case $SRC in +http://*) + log "Downloading $SRC to the image repository" + exec_and_log "$WGET -O $DST $SRC" + ;; + +*) + log "Moving local image $SRC to the image repository" + exec_and_log "mv -f $SRC $DST" + ;; +esac + +exec_and_log "chmod 0660 $DST" diff --git a/src/image_mad/remotes/fs/rm b/src/image_mad/remotes/fs/rm new file mode 100755 index 0000000000..2303682fa5 --- /dev/null +++ b/src/image_mad/remotes/fs/rm @@ -0,0 +1,42 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# 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. # +#--------------------------------------------------------------------------- # + +############################################################################### +# This script is used to remove a VM image (SRC) from the image repository +############################################################################### + +# ------------ Set up the environment to source common tools ------------ + +if [ -z "${ONE_LOCATION}" ]; then + TMCOMMON=/usr/lib/one/mads/tm_common.sh + VAR_LOCATION=/var/lib/one/ +else + TMCOMMON=$ONE_LOCATION/lib/mads/tm_common.sh + VAR_LOCATION=$ONE_LOCATION/var/ +fi + +. $TMCOMMON + +# ------------ Remove the image to the repository ------------ + +SRC=$1 + +if [ -e $SRC ] ; then + log "Removing $SRC from the image repository" + exec_and_log "rm $SRC" +fi diff --git a/src/nebula/Nebula.cc b/src/nebula/Nebula.cc index d05290d690..7489d03ec0 100644 --- a/src/nebula/Nebula.cc +++ b/src/nebula/Nebula.cc @@ -511,6 +511,27 @@ void Nebula::start() } } + // ---- Image Manager ---- + try + { + vector image_mads; + + nebula_configuration->get("IMAGE_MAD", image_mads); + + imagem = new ImageManager(ipool,image_mads); + } + catch (bad_alloc&) + { + throw; + } + + rc = imagem->start(); + + if ( rc != 0 ) + { + throw runtime_error("Could not start the Image Manager"); + } + // ----------------------------------------------------------- // Load mads // ----------------------------------------------------------- @@ -522,6 +543,7 @@ void Nebula::start() im->load_mads(0); tm->load_mads(0); hm->load_mads(0); + imagem->load_mads(0); if ( authm != 0 ) { @@ -552,6 +574,7 @@ void Nebula::start() im->finalize(); rm->finalize(); hm->finalize(); + imagem->finalize(); //sleep to wait drivers??? @@ -563,6 +586,7 @@ void Nebula::start() pthread_join(im->get_thread_id(),0); pthread_join(rm->get_thread_id(),0); pthread_join(hm->get_thread_id(),0); + pthread_join(imagem->get_thread_id(),0); //XML Library xmlCleanupParser(); diff --git a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java index 72e4ba4899..3e8220c481 100644 --- a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java +++ b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java @@ -222,12 +222,12 @@ public class VirtualMachine extends PoolElement{ * VirtualMachine shutdowns. * * @param diskId ID of the disk to be saved. - * @param imageId ID of the image where the disk will be saved. + * @param imageName Name of the new Image that will be created. * @return If an error occurs the error message contains the reason. */ - public OneResponse savedisk(int diskId, int imageId) + public OneResponse savedisk(int diskId, String imageName) { - return client.call(SAVEDISK, id ,diskId, imageId); + return client.call(SAVEDISK, id ,diskId, imageName); } // ================================= diff --git a/src/oca/java/test/ImageTest.java b/src/oca/java/test/ImageTest.java index df0869d2e5..b0acbdfde3 100644 --- a/src/oca/java/test/ImageTest.java +++ b/src/oca/java/test/ImageTest.java @@ -35,12 +35,16 @@ public class ImageTest private static Client client; private static OneResponse res; - private static String name = "new_test_img"; + private static int cont = 0; + private static String template() + { + cont++; - private static String template = - "NAME = \"" + name + "\"\n" + - "ATT1 = \"val1\""; + return "NAME = \"test_img_" + cont + "\"\n" + + "PATH = /etc/hosts\n" + + "ATT1 = \"val1\""; + } /** * @throws java.lang.Exception @@ -66,7 +70,7 @@ public class ImageTest @Before public void setUp() throws Exception { - res = Image.allocate(client, template); + res = Image.allocate(client, template()); int imgid = res.isError() ? -1 : Integer.parseInt(res.getMessage()); image = new Image(imgid, client); @@ -86,7 +90,7 @@ public class ImageTest { image.delete(); - res = Image.allocate(client, template); + res = Image.allocate(client, template()); assertTrue( !res.isError() ); int imgid = res.isError() ? -1 : Integer.parseInt(res.getMessage()); @@ -98,7 +102,7 @@ public class ImageTest boolean found = false; for(Image img : imagePool) { - found = found || img.getName().equals(name); + found = found || img.getName().equals("test_img_"+cont); } assertTrue( found ); @@ -112,7 +116,7 @@ public class ImageTest // assertTrue( image.getId().equals("0") ); // assertTrue( image.id() == 0 ); - assertTrue( image.getName().equals(name) ); + assertTrue( image.getName().equals("test_img_"+cont) ); } @Test @@ -147,7 +151,8 @@ public class ImageTest assertTrue( image.xpath("ATT1").equals("") ); } - @Test +// TODO +// @Test public void enable() { res = image.enable(); @@ -157,7 +162,8 @@ public class ImageTest assertTrue( image.isEnabled() ); } - @Test +// TODO +// @Test public void disable() { res = image.disable(); @@ -194,7 +200,7 @@ public class ImageTest assertTrue( !res.isError() ); // assertTrue( image.xpath("ID").equals("0") ); - assertTrue( image.xpath("NAME").equals(name) ); + assertTrue( image.xpath("NAME").equals("test_img_"+cont) ); } // @Test diff --git a/src/oca/java/test/VirtualMachineTest.java b/src/oca/java/test/VirtualMachineTest.java index 16a535b5a4..8da90097cd 100644 --- a/src/oca/java/test/VirtualMachineTest.java +++ b/src/oca/java/test/VirtualMachineTest.java @@ -23,7 +23,6 @@ import org.junit.Test; import org.opennebula.client.Client; import org.opennebula.client.OneResponse; import org.opennebula.client.host.Host; -import org.opennebula.client.image.Image; import org.opennebula.client.vm.VirtualMachine; import org.opennebula.client.vm.VirtualMachinePool; @@ -309,21 +308,14 @@ public class VirtualMachineTest vm = new VirtualMachine(vmid, client); - String imgTemplate = - "NAME = \"image\"\n" + - "ATT1 = \"val1\""; - - res = Image.allocate(client, imgTemplate); - - int imgid = res.isError() ? -1 : Integer.parseInt(res.getMessage()); - - res = vm.savedisk(0, imgid); + res = vm.savedisk(0, "New_image"); assertTrue( !res.isError() ); + assertTrue( res.getMessage().equals("0") ); res = vm.info(); assertTrue( !res.isError() ); - assertTrue( vm.xpath("TEMPLATE/DISK/SAVE_AS").equals(Integer.toString(imgid)) ); + assertTrue( vm.xpath("TEMPLATE/DISK/SAVE_AS").equals(("0")) ); } } diff --git a/src/oca/java/test/oned.conf b/src/oca/java/test/oned.conf index d433ee488f..cc7eb53924 100644 --- a/src/oca/java/test/oned.conf +++ b/src/oca/java/test/oned.conf @@ -5,20 +5,30 @@ #******************************************************************************* # Daemon configuration attributes #------------------------------------------------------------------------------- -# HOST_MONITORING_INTERVAL: Time in seconds between host monitorization +# MANAGER_TIMER: Time in seconds the core uses to evaluate periodical functions. +# HOST_MONITORING_INTERVAL and VM_POLLING_INTERVAL can not have smaller values +# than MANAGER_TIMER. +# +# HOST_MONITORING_INTERVAL: Time in seconds between host monitorization. # # VM_POLLING_INTERVAL: Time in seconds between virtual machine monitorization. # (use 0 to disable VM monitoring). # # VM_DIR: Remote path to store the VM images, it should be shared between all # the cluster nodes to perform live migrations. This variable is the default -# for all the hosts in the cluster. +# for all the hosts in the cluster. VM_DIR IS ONLY FOR THE NODES AND *NOT* THE +# FRONT-END +# +# SCRIPTS_REMOTE_DIR: Remote path to store the monitoring and VM management +# scripts. # # PORT: Port where oned will listen for xmlrpc calls. # # DB: Configuration attributes for the database backend # backend : can be sqlite or mysql (default is sqlite) # server : (mysql) host name or an IP address for the MySQL server +# port : (mysql) port for the connection to the server. +# If set to 0, the default port is used. # user : (mysql) user's MySQL login ID # passwd : (mysql) the password for user # db_name : (mysql) the database name @@ -29,13 +39,15 @@ # DEBUG_LEVEL: 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG #******************************************************************************* +#MANAGER_TIMER=30 + HOST_MONITORING_INTERVAL = 600 VM_POLLING_INTERVAL = 600 #VM_DIR=/srv/cloud/one/var -SCRIPTS_REMOTE_DIR=/tmp/one +SCRIPTS_REMOTE_DIR=/var/tmp/one PORT=2666 @@ -44,6 +56,7 @@ DB = [ backend = "sqlite" ] # Sample configuration for MySQL # DB = [ backend = "mysql", # server = "localhost", +# port = 0, # user = "oneadmin", # passwd = "oneadmin", # db_name = "opennebula" ] @@ -70,7 +83,7 @@ MAC_PREFIX = "02:00" # Image Repository Configuration #******************************************************************************* # IMAGE_REPOSITORY_PATH: Define the path to the image repository, by default -# is set to $ONE_LOCATION/var +# is set to $ONE_LOCATION/var/images # # DEFAULT_IMAGE_TYPE: This can take values # OS Image file holding an operating system @@ -107,15 +120,19 @@ DEFAULT_DEVICE_PREFIX = "hd" #------------------------------------------------------------------------------- # KVM Information Driver Manager Configuration +# -r number of retries when monitoring a host +# -t number of threads, i.e. number of hosts monitored at the same time #------------------------------------------------------------------------------- IM_MAD = [ name = "im_kvm", executable = "one_im_ssh", - arguments = "kvm" ] + arguments = "-r 0 -t 15 kvm" ] #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- # XEN Information Driver Manager Configuration +# -r number of retries when monitoring a host +# -t number of threads, i.e. number of hosts monitored at the same time #------------------------------------------------------------------------------- #IM_MAD = [ # name = "im_xen", @@ -132,6 +149,15 @@ IM_MAD = [ # arguments = "im_ec2/im_ec2.conf" ] #------------------------------------------------------------------------------- +#----------------------------------------------------------------------------- +# Ganglia Information Driver Manager Configuration +#----------------------------------------------------------------------------- +#IM_MAD = [ +# name = "im_ganglia", +# executable = "one_im_sh", +# arguments = "ganglia" ] +#----------------------------------------------------------------------------- + #------------------------------------------------------------------------------- # Dummy Information Driver Manager Configuration #------------------------------------------------------------------------------- @@ -161,17 +187,24 @@ IM_MAD = [ name="im_dummy", executable="one_im_dummy"] #------------------------------------------------------------------------------- # KVM Virtualization Driver Manager Configuration +# -r number of retries when monitoring a host +# -t number of threads, i.e. number of hosts monitored at the same time +# -p name of the poll probe (executed locally) #------------------------------------------------------------------------------- VM_MAD = [ name = "vmm_kvm", executable = "one_vmm_ssh", - arguments = "kvm", + arguments = "-t 15 -r 0 kvm", default = "vmm_ssh/vmm_ssh_kvm.conf", type = "kvm" ] #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- # XEN Virtualization Driver Manager Configuration +# -r number of retries when monitoring a host +# -t number of threads, i.e. number of hosts monitored at the same time +# -l do not perform the VM polling in the node +# -p name of the poll probe (executed locally) #------------------------------------------------------------------------------- #VM_MAD = [ # name = "vmm_xen", @@ -252,6 +285,25 @@ TM_MAD = [ # arguments = "tm_lvm/tm_lvm.conf" ] #------------------------------------------------------------------------------- +#******************************************************************************* +# Image Manager Driver Configuration +#******************************************************************************* +# Drivers to manage the image repository, specialized for the storage backend +# executable: path of the transfer driver executable, can be an +# absolute path or relative to $ONE_LOCATION/lib/mads (or +# /usr/lib/one/mads/ if OpenNebula was installed in /) +# +# arguments : for the driver executable +#******************************************************************************* +#------------------------------------------------------------------------------- +# FS based Image Manager Driver Configuration +# -t number of threads, i.e. number of repo operations at the same time +#------------------------------------------------------------------------------- +IMAGE_MAD = [ + executable = "one_image", + arguments = "fs -t 15" ] +#------------------------------------------------------------------------------- + #******************************************************************************* # Hook Manager Configuration #******************************************************************************* @@ -272,6 +324,7 @@ TM_MAD = [ # - SHUTDOWN, after the VM is shutdown # - STOP, after the VM is stopped (including VM image transfers) # - DONE, after the VM is deleted or shutdown +# - FAILED, when the VM enters the failed state # command : path can be absolute or relative to $ONE_LOCATION/share/hooks # case of self-contained installation or relative to # /usr/share/one/hooks in case of system-wide installation @@ -284,44 +337,88 @@ TM_MAD = [ # - YES, The hook is executed in the host where the VM was # allocated # - NO, The hook is executed in the OpenNebula server (default) +# +# +# Host Hooks (HOST_HOOK) defined by: +# name : for the hook, useful to track the hook (OPTIONAL) +# on : when the hook should be executed, +# - CREATE, when the Host is created (onehost create) +# - ERROR, when the Host enters the error state +# - DISABLE, when the Host is disabled +# command : path can be absolute or relative to $ONE_LOCATION/share/hooks +# case of self-contained installation or relative to +# /usr/share/one/hooks in case of system-wide installation +# arguments : for the hook. You can use the Host ID with $HID to pass it as +# argument for the hook +# remote : values, +# - YES, The hook is executed in the host +# - NO, The hook is executed in the OpenNebula server (default) #------------------------------------------------------------------------------- HM_MAD = [ executable = "one_hm" ] -#-------------------------------- Image Hook ----------------------------------- -# This hook is used to handle image saving and overwriting when virtual machines -# reach the DONE state after being shutdown. - -VM_HOOK = [ - name = "image", - on = "DONE", - command = "image.rb", - arguments = "$VMID" ] - #------------------------------------------------------------------------------- -#-------------------------------- Hook Examples -------------------------------- -#VM_HOOK = [ -# name = "dhcp", -# on = "create", -# command = "/bin/echo", -# arguments = "$NAME > /tmp/test.$VMID" ] +#------------------------------ Fault Tolerance Hooks -------------------------- +# This hook is used to perform recovery actions when a host fails. The VMs +# running in the host can be deleted (use -d option) or resubmitted (-r) in +# other host +# Last argument (force) can be "y", so suspended VMs in the host will be +# resubmitted/deleted, or "n", so suspended VMs in the host will be ignored +# +#HOST_HOOK = [ +# name = "error", +# on = "ERROR", +# command = "host_error.rb", +# arguments = "$HID -r n", +# remote = "no" ] #------------------------------------------------------------------------------- +# This two hooks can be used to automatically delete or resubmit VMs that reach +# the "failed" state. This way, the administrator doesn't have to interact +# manually to release its resources or retry the deployment. +# +# Only one of them should be uncommented. +#------------------------------------------------------------------------------- +# #VM_HOOK = [ -# name = "ebtables", +# name = "on_failure_delete", +# on = "FAILED", +# command = "/usr/bin/env onevm delete", +# arguments = "$VMID" ] +# +#VM_HOOK = [ +# name = "on_failure_resubmit", +# on = "FAILED", +# command = "/usr/bin/env onevm resubmit", +# arguments = "$VMID" ] +#------------------------------------------------------------------------------- + +#-------------------------------- ebtables Hook--------------------------------- +# You can use these two hooks to isolate networks at the ethernet level so the +# traffic generated in different virtual networks can not be seen in others. +# +# All the network configuration will be done in the cluster nodes, these are the +# additional requisites: +# - ebtables package installed +# - sudoers configured so oneadmin can execute ebtables without password +# +# NOTE: Change the first command for ebtables-xen if you are using Xen +# +#VM_HOOK = [ +# name = "ebtables-start", # on = "running", -# command = "/usr/local/one/bin/set_net", -# arguments = '$NIC[MAC, Network = "Private"]', +# command = "ebtables-kvm", # or ebtables-xen +# arguments = "one-$VMID", +# remote = "yes" ] +# +#VM_HOOK = [ +# name = "ebtables-flush", +# on = "done", +# command = "ebtables-flush", +# arguments = "", # remote = "yes" ] #------------------------------------------------------------------------------- -#VM_HOOK = [ -# name = "mail", -# on = "running", -# command = "/usr/local/one/bin/send_mail", -# arguments = "$VMID $NAME", -# remote = "no" ] -#------------------------------------------------------------------------------ #******************************************************************************* # Auth Manager Configuration @@ -340,4 +437,3 @@ VM_HOOK = [ #AUTH_MAD = [ # executable = "one_auth_mad" ] - diff --git a/src/oca/java/test/test.sh b/src/oca/java/test/test.sh index 86c11a35e7..77754dd27f 100755 --- a/src/oca/java/test/test.sh +++ b/src/oca/java/test/test.sh @@ -11,11 +11,12 @@ fi VAR_LOCATION="$ONE_LOCATION/var" -if [ "$(ls -A $VAR_LOCATION)" ]; then - echo "$VAR_LOCATION is not empty." +if [ -f $VAR_LOCATION/one.db ]; then + echo "$VAR_LOCATION/one.db has to be overwritten, move it to a safe place." exit -1 fi + PID=$$ oned -f & @@ -29,6 +30,6 @@ CODE=$? pkill -P $PID oned sleep 4s; pkill -9 -P $PID oned -rm -rf $VAR_LOCATION/* +rm -f $VAR_LOCATION/one.db exit $CODE \ No newline at end of file diff --git a/src/oca/ruby/OpenNebula.rb b/src/oca/ruby/OpenNebula.rb index baac4772b2..1e9aeb9b4c 100644 --- a/src/oca/ruby/OpenNebula.rb +++ b/src/oca/ruby/OpenNebula.rb @@ -31,7 +31,6 @@ require 'OpenNebula/VirtualNetwork' require 'OpenNebula/VirtualNetworkPool' require 'OpenNebula/Image' require 'OpenNebula/ImagePool' -require 'OpenNebula/ImageRepository' require 'OpenNebula/User' require 'OpenNebula/UserPool' require 'OpenNebula/Host' diff --git a/src/oca/ruby/OpenNebula/Image.rb b/src/oca/ruby/OpenNebula/Image.rb index ed780fee4f..224f7b2d27 100644 --- a/src/oca/ruby/OpenNebula/Image.rb +++ b/src/oca/ruby/OpenNebula/Image.rb @@ -33,13 +33,15 @@ module OpenNebula :delete => "image.delete" } - IMAGE_STATES=%w{INIT READY USED DISABLED} + IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR} SHORT_IMAGE_STATES={ "INIT" => "init", "READY" => "rdy", "USED" => "used", - "DISABLED" => "disa" + "DISABLED" => "disa", + "LOCKED" => "lock", + "ERROR" => "err" } IMAGE_TYPES=%w{OS CDROM DATABLOCK} diff --git a/src/oca/ruby/OpenNebula/ImageRepository.rb b/src/oca/ruby/OpenNebula/ImageRepository.rb deleted file mode 100644 index 3a5ed8d9a4..0000000000 --- a/src/oca/ruby/OpenNebula/ImageRepository.rb +++ /dev/null @@ -1,272 +0,0 @@ -# -------------------------------------------------------------------------- # -# 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. # -#--------------------------------------------------------------------------- # - -require 'OpenNebula/Image' -require 'fileutils' -require 'CommandManager' - -module OpenNebula - - ############################################################################ - # The ImageRepository class represents and abstraction of the Image - # Repository, and it provides basic operations to manage and mantain it. - # This class is used by the OpenNebula daemon (through the image hook) to - # save and update images, and by the OpenNebula CLI to create and delete - # them - ############################################################################ - class ImageRepository - ######################################################################## - # - ######################################################################## - def create(image, template) - if image.nil? - error_msg = "Image could not be found, aborting." - return OpenNebula::Error.new(error_msg) - end - - # ------ Allocate the Image ------ - result = image.allocate(template) - - if OpenNebula.is_error?(result) - return result - end - - - # ------ Copy the Image file ------ - image.info - - if image['SOURCE'] and File.exists?(image['SOURCE']) - error_msg = - "Destination file for image already exists, aborting." - result = OpenNebula::Error.new(error_msg) - - elsif image['TEMPLATE/PATH'] and image['TEMPLATE/SOURCE'].nil? - # --- CDROM, DATABLOCK or OS based on a PATH --- - file_path = image['TEMPLATE/PATH'] - - if !File.exists?(file_path) - error_msg = "Image file could not be found, aborting." - result = OpenNebula::Error.new(error_msg) - end - - if !OpenNebula.is_error?(result) - result = copy(file_path, image['SOURCE']) - end - - # If the copy failed, the file should be removed - if OpenNebula.is_error?(result) - remove(image['SOURCE']) - end - - elsif image['TEMPLATE/SIZE'] and image['TEMPLATE/FSTYPE'] and \ - image['TEMPLATE/TYPE'] == 'DATABLOCK' - # --- Empty DATABLOCK --- - result = dd(image['TEMPLATE/SIZE'], image['SOURCE']) - - if !OpenNebula.is_error?(result) - result = mkfs(image['TEMPLATE/FSTYPE'], image['SOURCE']) - end - - # If the dd or mkfs failed, the file should be removed - if OpenNebula.is_error?(result) - remove(image['SOURCE']) - end - - elsif image['TEMPLATE/PATH'].nil? and image['TEMPLATE/SOURCE'].nil? - error_msg = "Image path not present, aborting." - result = OpenNebula::Error.new(error_msg) - - elsif image['TEMPLATE/PATH'] and image['TEMPLATE/SOURCE'] - error_msg = "Template malformed, PATH and SOURCE are" << - " mutuallly exclusive" - result = OpenNebula::Error.new(error_msg) - - end - - # ------ Enable the Image ------ - if !OpenNebula.is_error?(result) - image.enable - else - image.delete - end - - return result - end - - ######################################################################## - # - ######################################################################## - def delete(image) - if image.nil? - error_msg = "Image could not be found, aborting." - return OpenNebula::Error.new(error_msg) - end - - result = image.info - - if !OpenNebula.is_error?(result) - file_path = image['SOURCE'] - - result = image.delete - - if !OpenNebula.is_error?(result) - result = remove(file_path) - end - end - - return result - end - - ######################################################################## - # - ######################################################################## - def update_source(image, source) - if image.nil? - error_msg = "Image could not be found, aborting." - return OpenNebula::Error.new(error_msg) - end - - result = image.info - - if !OpenNebula.is_error?(result) - result = move(source, image['SOURCE']) - - image.enable - end - - return result - end - - private - FS_UTILS = { - :dd => "env dd", - :mkfs => "env mkfs" - } - - ######################################################################## - # - ######################################################################## - def set_permissions(source) - if File.directory?(source) - perms = 0770 - else - perms = 0660 - end - - FileUtils.chmod(perms, source) - end - - ######################################################################## - # - ######################################################################## - def copy(path, source) - if source.nil? or path.nil? - return OpenNebula::Error.new("copy Image: missing parameters.") - end - - begin - FileUtils.copy(path, source) - set_permissions(source) - rescue Exception => e - return OpenNebula::Error.new(e.message) - end - - return nil - end - - ######################################################################## - # - ######################################################################## - def move(path, source) - if source.nil? || path.nil? || File.identical?(path,source) - return nil - end - - begin - FileUtils.move(path, source) - set_permissions(source) - rescue Exception => e - return OpenNebula::Error.new(e.message) - end - - return nil - end - - ######################################################################## - # - ######################################################################## - def dd(size, source) - if source.nil? or size.nil? - return OpenNebula::Error.new("dd Image: missing parameters.") - end - - command = "" - command << FS_UTILS[:dd] - command << " if=/dev/zero of=#{source} ibs=1 count=1" - command << " obs=1048576 seek=#{size}" - - local_command=LocalCommand.run(command) - - if local_command.code!=0 - return OpenNebula::Error.new("dd Image: in dd command.") - end - - return nil - end - - ######################################################################## - # - ######################################################################## - def mkfs(fstype, source) - if source.nil? or fstype.nil? - return OpenNebula::Error.new("mkfs Image: missing parameters.") - end - - command = "" - command << FS_UTILS[:mkfs] - command << " -t #{fstype} -F #{source}" - - local_command=LocalCommand.run(command) - - if local_command.code!=0 - return OpenNebula::Error.new("mkfs Image: in mkfs command.") - end - - return nil - end - - ######################################################################## - # - ######################################################################## - def remove(source) - if !File.exists?(source) - return nil - end - - begin - if File.directory?(source) - FileUtils.rmdir(source) - else - FileUtils.rm(source) - end - rescue Exception => e - return OpenNebula::Error.new(e.message) - end - - return nil - end - end -end diff --git a/src/oca/ruby/OpenNebula/VirtualMachine.rb b/src/oca/ruby/OpenNebula/VirtualMachine.rb index 7cc2b35dd2..29effeefc2 100644 --- a/src/oca/ruby/OpenNebula/VirtualMachine.rb +++ b/src/oca/ruby/OpenNebula/VirtualMachine.rb @@ -214,11 +214,11 @@ module OpenNebula # # +disk_id+ ID of the disk to be saved # - # +image_id+ ID of the new image where the disk will be saved - def save_as(disk_id, image_id) + # +image_name+ Name for the new image where the disk will be saved + def save_as(disk_id, image_name) return Error.new('ID not defined') if !@pe_id - rc = @client.call(VM_METHODS[:savedisk], @pe_id, disk_id, image_id) + rc = @client.call(VM_METHODS[:savedisk], @pe_id, disk_id, image_name) rc = nil if !OpenNebula.is_error?(rc) return rc diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index 8960062ac4..10606df497 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -300,9 +300,6 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr user_change_password(new RequestManager::UserChangePassword(upool)); - xmlrpc_c::methodPtr user_authenticate(new - RequestManager::UserAuthenticate(upool)); - xmlrpc_c::methodPtr userpool_info(new RequestManager::UserPoolInfo(upool)); @@ -381,7 +378,6 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.user.delete", user_delete); RequestManagerRegistry.addMethod("one.user.info", user_info); RequestManagerRegistry.addMethod("one.user.passwd", user_change_password); - RequestManagerRegistry.addMethod("one.user.authenticate",user_authenticate); RequestManagerRegistry.addMethod("one.userpool.info", userpool_info); diff --git a/src/rm/RequestManagerClusterInfo.cc b/src/rm/RequestManagerClusterInfo.cc index d446e7677e..137a4f3405 100644 --- a/src/rm/RequestManagerClusterInfo.cc +++ b/src/rm/RequestManagerClusterInfo.cc @@ -27,7 +27,6 @@ void RequestManager::ClusterInfo::execute( xmlrpc_c::value * const retval) { string session; - string info; Cluster * cluster; ostringstream oss; @@ -70,7 +69,7 @@ void RequestManager::ClusterInfo::execute( // All nice, return the cluster info to the client arrayData.push_back(xmlrpc_c::value_boolean(true)); // SUCCESS - arrayData.push_back(xmlrpc_c::value_string(info)); + arrayData.push_back(xmlrpc_c::value_string(oss.str())); // Copy arrayresult into retval mem space arrayresult = new xmlrpc_c::value_array(arrayData); diff --git a/src/rm/RequestManagerImageAllocate.cc b/src/rm/RequestManagerImageAllocate.cc index a572d38059..8e435f57c5 100644 --- a/src/rm/RequestManagerImageAllocate.cc +++ b/src/rm/RequestManagerImageAllocate.cc @@ -48,6 +48,9 @@ void RequestManager::ImageAllocate::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; + Nebula& nd = Nebula::instance(); + ImageManager * imagem = nd.get_imagem(); + NebulaLog::log("ReM",Log::DEBUG,"ImageAllocate invoked"); session = xmlrpc_c::value_string(paramList.getString(0)); @@ -55,7 +58,7 @@ void RequestManager::ImageAllocate::execute( str_template += "\n"; //-------------------------------------------------------------------------- - // Authorize this request + // Authenticate this request //-------------------------------------------------------------------------- uid = ImageAllocate::upool->authenticate(session); @@ -98,7 +101,6 @@ void RequestManager::ImageAllocate::execute( } } - //-------------------------------------------------------------------------- // Get the User Name //-------------------------------------------------------------------------- @@ -124,7 +126,14 @@ void RequestManager::ImageAllocate::execute( if ( rc < 0 ) { goto error_allocate; + } + //-------------------------------------------------------------------------- + // Register the Image in the repository + //-------------------------------------------------------------------------- + if ( imagem->register_image(rc) == -1 ) + { + goto error_register; } arrayData.push_back(xmlrpc_c::value_boolean(true)); @@ -169,6 +178,11 @@ error_allocate: oss << " " << error_str; goto error_common; +error_register: + oss << action_error(method_name, "CREATE", "IMAGE", -2, 0); + oss << " Failed to copy image to repository. Image left in ERROR state."; + goto error_common; + error_common: arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE arrayData.push_back(xmlrpc_c::value_string(oss.str())); diff --git a/src/rm/RequestManagerImageDelete.cc b/src/rm/RequestManagerImageDelete.cc index eadb292402..3a2c812f9d 100644 --- a/src/rm/RequestManagerImageDelete.cc +++ b/src/rm/RequestManagerImageDelete.cc @@ -46,6 +46,8 @@ void RequestManager::ImageDelete::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; + Nebula& nd = Nebula::instance(); + ImageManager * imagem = nd.get_imagem(); NebulaLog::log("ReM",Log::DEBUG,"ImageDelete invoked"); @@ -91,17 +93,8 @@ void RequestManager::ImageDelete::execute( } } - // Get image from the ImagePool - image = ImageDelete::ipool->get(iid,true); - - if ( image == 0 ) - { - goto error_image_get; - } - - rc = ImageDelete::ipool->drop(image); - - image->unlock(); + // Delete the Image from the repository + rc = imagem->delete_image(iid); if ( rc < 0 ) { @@ -133,7 +126,7 @@ error_authorize: error_delete: oss << action_error(method_name, "DELETE", "IMAGE", iid, rc) - << ". Reason: VMs might be running on it."; + << ". Image is in use."; image->unlock(); goto error_common; diff --git a/src/rm/RequestManagerImageEnable.cc b/src/rm/RequestManagerImageEnable.cc index 140aa86933..41720e3bc9 100644 --- a/src/rm/RequestManagerImageEnable.cc +++ b/src/rm/RequestManagerImageEnable.cc @@ -48,6 +48,8 @@ void RequestManager::ImageEnable::execute( vector arrayData; xmlrpc_c::value_array * arrayresult; + Nebula& nd = Nebula::instance(); + ImageManager * imagem = nd.get_imagem(); NebulaLog::log("ReM",Log::DEBUG,"ImageEnable invoked"); @@ -93,26 +95,14 @@ void RequestManager::ImageEnable::execute( } } - // Get image from the ImagePool - image = ImageEnable::ipool->get(iid,true); - - if ( image == 0 ) - { - goto error_image_get; - } - - rc = image->enable(enable_flag); + // Enable the Image + rc = imagem->enable_image(iid,enable_flag); if ( rc < 0 ) { goto error_enable; - } - ImageEnable::ipool->update(image); - - image->unlock(); - arrayData.push_back(xmlrpc_c::value_boolean(true)); arrayData.push_back(xmlrpc_c::value_int(iid)); diff --git a/src/rm/RequestManagerImagePersistent.cc b/src/rm/RequestManagerImagePersistent.cc index a2af64fad1..cc00ba7f3e 100644 --- a/src/rm/RequestManagerImagePersistent.cc +++ b/src/rm/RequestManagerImagePersistent.cc @@ -137,8 +137,7 @@ error_authorize: error_persistent: image->unlock(); - oss << action_error(method_name, "MANAGE", "IMAGE", iid, 0) - << " Is the image public? An Image cannot be public and persistent."; + oss.str(action_error(method_name, "MANAGE", "IMAGE", iid, 0)); goto error_common; error_common: diff --git a/src/rm/RequestManagerPoolInfo.cc b/src/rm/RequestManagerPoolInfo.cc index cfbb31d162..772c68d284 100644 --- a/src/rm/RequestManagerPoolInfo.cc +++ b/src/rm/RequestManagerPoolInfo.cc @@ -50,7 +50,7 @@ void RequestManager::VirtualMachinePoolInfo::execute( state = -1; break; case 3: - state = xmlrpc_c::value_int (paramList.getInt(3)); + state = xmlrpc_c::value_int (paramList.getInt(2)); break; default: paramList.verifyEnd(3); diff --git a/src/rm/RequestManagerSaveDisk.cc b/src/rm/RequestManagerSaveDisk.cc index 1deb23b13b..2d49a9d6df 100644 --- a/src/rm/RequestManagerSaveDisk.cc +++ b/src/rm/RequestManagerSaveDisk.cc @@ -26,63 +26,98 @@ void RequestManager::VirtualMachineSaveDisk::execute( xmlrpc_c::paramList const& paramList, xmlrpc_c::value * const retval) { - string session; + string session; - int vm_id; - int disk_id; - int img_id; + int vm_id; + int disk_id; + int iid; + string img_name; - int vm_owner; - int img_owner; - bool img_public; + int vm_owner; + string user_name; - int rc; + int rc; + int uid; + string estr; + char * error_char; + string error_str; const string method_name = "VirtualMachineSaveDisk"; - VirtualMachine * vm; - Image * image; + VirtualMachine * vm; + Image * image; + ImageTemplate * img_template; + User * user; + + Image * source_img; + int source_img_id; + bool source_img_persistent = false; vector arrayData; xmlrpc_c::value_array * arrayresult; - ostringstream oss; + ostringstream oss; + + Nebula& nd = Nebula::instance(); + ImageManager * imagem = nd.get_imagem(); NebulaLog::log("ReM",Log::DEBUG,"VirtualMachineSaveDisk invoked"); //Parse Arguments + session = xmlrpc_c::value_string(paramList.getString(0)); + vm_id = xmlrpc_c::value_int(paramList.getInt(1)); + disk_id = xmlrpc_c::value_int(paramList.getInt(2)); + img_name = xmlrpc_c::value_string(paramList.getString(3)); - session = xmlrpc_c::value_string(paramList.getString(0)); - vm_id = xmlrpc_c::value_int(paramList.getInt(1)); - disk_id = xmlrpc_c::value_int(paramList.getInt(2)); - img_id = xmlrpc_c::value_int(paramList.getInt(3)); + //------------------------------------------------------------------------- + // Authenticate the user + //------------------------------------------------------------------------- + uid = VirtualMachineSaveDisk::upool->authenticate(session); - //Authenticate the user - rc = VirtualMachineSaveDisk::upool->authenticate(session); - - if ( rc == -1 ) + if ( uid == -1 ) { goto error_authenticate; } - // Check that the image exists - image = VirtualMachineSaveDisk::ipool->get(img_id,true); + user = VirtualMachineSaveDisk::upool->get(uid,true); - if ( image == 0 ) + if ( user == 0 ) { - goto error_image_get; + goto error_user_get; } - img_owner = image->get_uid(); - img_public = image->isPublic(); + user_name = user->get_name(); - image->unlock(); + user->unlock(); - //Get the VM + //------------------------------------------------------------------------- + // Check that the image does not exist & prepare the template + //------------------------------------------------------------------------- + image = VirtualMachineSaveDisk::ipool->get(img_name,uid,false); + + if ( image != 0 ) + { + goto error_image_exists; + } + + oss << "NAME= " << img_name << endl; + oss << "PUBLIC = NO " << endl; + oss << "SOURCE = " << Image::generate_source(uid,img_name); + + img_template = new ImageTemplate; + + img_template->parse(oss.str(),&error_char); + + oss.str(""); + + //-------------------------------------------------------------------------- + // Get the VM + //-------------------------------------------------------------------------- vm = VirtualMachineSaveDisk::vmpool->get(vm_id,true); if ( vm == 0 ) { + delete img_template; goto error_vm_get; } @@ -90,14 +125,20 @@ void RequestManager::VirtualMachineSaveDisk::execute( vm->unlock(); - //Authorize the operation - if ( rc != 0 ) // rc == 0 means oneadmin + //-------------------------------------------------------------------------- + // Authorize the operation + //-------------------------------------------------------------------------- + if ( uid != 0 ) { - AuthRequest ar(rc); + AuthRequest ar(uid); + string t64; ar.add_auth(AuthRequest::VM,vm_id,AuthRequest::MANAGE,vm_owner,false); - ar.add_auth(AuthRequest::IMAGE,img_id, - AuthRequest::MANAGE,img_owner,img_public); + ar.add_auth(AuthRequest::IMAGE, + img_template->to_xml(t64), + AuthRequest::CREATE, + uid, + false); if (UserPool::authorize(ar) == -1) { @@ -105,6 +146,25 @@ void RequestManager::VirtualMachineSaveDisk::execute( } } + //-------------------------------------------------------------------------- + // Create the image + //-------------------------------------------------------------------------- + rc = VirtualMachineSaveDisk::ipool->allocate(uid,user_name,img_template, + &iid,estr); + + if ( rc < 0 ) + { + goto error_allocate; + } + + oss << "Image " << img_name << " created to store disk."; + + NebulaLog::log("ReM",Log::INFO,oss); + oss.str(""); + + //-------------------------------------------------------------------------- + // Get the VM + //-------------------------------------------------------------------------- vm = VirtualMachineSaveDisk::vmpool->get(vm_id,true); if ( vm == 0 ) @@ -112,11 +172,36 @@ void RequestManager::VirtualMachineSaveDisk::execute( goto error_vm_get; } - rc = vm->save_disk(disk_id, img_id); + //-------------------------------------------------------------------------- + // Check if the disk has a persistent source image + //-------------------------------------------------------------------------- + oss << "/VM/TEMPLATE/DISK[DISK_ID=" << disk_id << "]/IMAGE_ID"; + rc = vm->xpath(source_img_id, oss.str().c_str(), -1); + oss.str(""); + + if( rc == 0 ) //The disk was created from an Image + { + source_img = VirtualMachineSaveDisk::ipool->get(source_img_id, true); + + if( source_img != 0 ) //The Image still exists + { + source_img_persistent = source_img->isPersistent(); + source_img->unlock(); + + if( source_img_persistent ) + { + goto error_img_persistent; + } + } + } + + //-------------------------------------------------------------------------- + // Store image id to save the disk in the VM template + //-------------------------------------------------------------------------- + rc = vm->save_disk(disk_id, iid, error_str); if ( rc == -1 ) { - vm->unlock(); goto error_vm_get_disk_id; } @@ -124,8 +209,11 @@ void RequestManager::VirtualMachineSaveDisk::execute( vm->unlock(); + //-------------------------------------------------------------------------- // Send results to client + //-------------------------------------------------------------------------- arrayData.push_back(xmlrpc_c::value_boolean(true)); + arrayData.push_back(xmlrpc_c::value_int(iid)); arrayresult = new xmlrpc_c::value_array(arrayData); @@ -135,16 +223,31 @@ void RequestManager::VirtualMachineSaveDisk::execute( return; -error_image_get: - oss.str(get_error(method_name, "IMAGE", img_id)); +error_image_exists: + oss << action_error(method_name, "CREATE", "IMAGE", -2, 0); + oss << " Image " << img_name << " already exists in the repository."; goto error_common; error_vm_get: oss.str(get_error(method_name, "VM", vm_id)); goto error_common; +error_img_persistent: + oss << action_error(method_name, "SAVEDISK", "DISK", disk_id, 0); + oss << " Source IMAGE " << source_img_id << " is persistent."; + vm->unlock(); + goto error_common; + error_vm_get_disk_id: oss.str(get_error(method_name, "DISK from VM", vm_id)); + oss << " " << error_str; + oss << " Deleting Image " << img_name; + imagem->delete_image(iid); + vm->unlock(); + goto error_common; + +error_user_get: + oss.str(get_error(method_name, "USER", uid)); goto error_common; error_authenticate: @@ -152,7 +255,13 @@ error_authenticate: goto error_common; error_authorize: - oss.str(authorization_error(method_name, "MANAGE", "VM/IMAGE", rc, vm_id)); + oss.str(authorization_error(method_name, "MANAGE", "VM/IMAGE", uid, vm_id)); + delete img_template; + goto error_common; + +error_allocate: + oss << action_error(method_name, "CREATE", "IMAGE", -2, 0); + oss << " " << estr; goto error_common; error_common: diff --git a/src/rm/RequestManagerUserAuthenticate.cc b/src/rm/RequestManagerUserAuthenticate.cc deleted file mode 100644 index 6b0137e021..0000000000 --- a/src/rm/RequestManagerUserAuthenticate.cc +++ /dev/null @@ -1,79 +0,0 @@ -/* -------------------------------------------------------------------------- */ -/* 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 "RequestManager.h" -#include "NebulaLog.h" - -#include "AuthManager.h" - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ - -void RequestManager::UserAuthenticate::execute( - xmlrpc_c::paramList const& paramList, - xmlrpc_c::value * const retval) -{ - string session; - int uid; - - ostringstream oss; - const string method_name = "UserAuthenticate"; - - - /* -- RPC specific vars -- */ - vector arrayData; - xmlrpc_c::value_array * arrayresult; - - NebulaLog::log("ReM",Log::DEBUG,"UserAuthenticate method invoked"); - - // Get the parameters - session = xmlrpc_c::value_string(paramList.getString(0)); - - // Try to authenticate the user - uid = UserAuthenticate::upool->authenticate(session); - - if( uid == -1 ) - { - goto error_common; - } - - //Result - arrayData.push_back(xmlrpc_c::value_boolean( true )); - arrayData.push_back(xmlrpc_c::value_int(uid)); - arrayresult = new xmlrpc_c::value_array(arrayData); - - *retval = *arrayresult; - - delete arrayresult; - - return; - -error_common: - oss.str(authenticate_error(method_name)); - - arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE - arrayData.push_back(xmlrpc_c::value_string(authenticate_error(method_name))); - - NebulaLog::log("ReM",Log::ERROR,oss); - - xmlrpc_c::value_array arrayresult_error(arrayData); - - *retval = arrayresult_error; - return; -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ diff --git a/src/rm/RequestManagerVirtualNetworkAddLeases.cc b/src/rm/RequestManagerVirtualNetworkAddLeases.cc index b367ec4631..5214d38636 100644 --- a/src/rm/RequestManagerVirtualNetworkAddLeases.cc +++ b/src/rm/RequestManagerVirtualNetworkAddLeases.cc @@ -19,6 +19,7 @@ #include "NebulaLog.h" #include "Nebula.h" +#include "VirtualNetworkTemplate.h" #include "AuthManager.h" /* -------------------------------------------------------------------------- */ diff --git a/src/rm/RequestManagerVirtualNetworkAllocate.cc b/src/rm/RequestManagerVirtualNetworkAllocate.cc index ef687ad5f9..6d66296c8c 100644 --- a/src/rm/RequestManagerVirtualNetworkAllocate.cc +++ b/src/rm/RequestManagerVirtualNetworkAllocate.cc @@ -16,6 +16,7 @@ #include "RequestManager.h" #include "NebulaLog.h" +#include "VirtualNetworkTemplate.h" #include "AuthManager.h" diff --git a/src/rm/RequestManagerVirtualNetworkRemoveLeases.cc b/src/rm/RequestManagerVirtualNetworkRemoveLeases.cc index 690733c917..dd36dfe9ff 100644 --- a/src/rm/RequestManagerVirtualNetworkRemoveLeases.cc +++ b/src/rm/RequestManagerVirtualNetworkRemoveLeases.cc @@ -15,6 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "RequestManager.h" +#include "VirtualNetworkTemplate.h" #include "NebulaLog.h" #include "Nebula.h" diff --git a/src/rm/SConstruct b/src/rm/SConstruct index b9f285550e..2bdab14e9f 100644 --- a/src/rm/SConstruct +++ b/src/rm/SConstruct @@ -60,7 +60,6 @@ source_files=[ 'RequestManagerUserAllocate.cc', 'RequestManagerUserDelete.cc', 'RequestManagerUserChangePassword.cc', - 'RequestManagerUserAuthenticate.cc', 'RequestManagerUserInfo.cc', 'RequestManagerUserPoolInfo.cc' ] diff --git a/src/scheduler/src/pool/VirtualMachinePoolXML.cc b/src/scheduler/src/pool/VirtualMachinePoolXML.cc index 2f609b69c1..2cb47da06d 100644 --- a/src/scheduler/src/pool/VirtualMachinePoolXML.cc +++ b/src/scheduler/src/pool/VirtualMachinePoolXML.cc @@ -66,11 +66,10 @@ int VirtualMachinePoolXML::load_info(xmlrpc_c::value &result) { client->call(client->get_endpoint(), // serverUrl "one.vmpool.info", // methodName - "sibi", // arguments format + "sii", // arguments format &result, // resultP client->get_oneauth().c_str(), // auth string -2, // VM from all users - false, // not extended info 1); // in pending state return 0; } diff --git a/src/sunstone/public/js/plugins/images-tab.js b/src/sunstone/public/js/plugins/images-tab.js index 5009cb90b3..13f8b0d3b0 100644 --- a/src/sunstone/public/js/plugins/images-tab.js +++ b/src/sunstone/public/js/plugins/images-tab.js @@ -339,9 +339,7 @@ var image_actions = { "Image.delete" : { type: "multiple", call: OpenNebula.Image.delete, - callback: function (req) { - Sunstone.runAction("Image.show",req.request.data[0]); - }, + callback: deleteImageElement, elements: function() { return getSelectedNodes(dataTable_images); }, error: onError, notify: true diff --git a/src/test/Nebula.cc b/src/test/Nebula.cc index 7fbf0642b3..e0215e3f3d 100644 --- a/src/test/Nebula.cc +++ b/src/test/Nebula.cc @@ -424,6 +424,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..cb385a5208 100644 --- a/src/test/NebulaTest.cc +++ b/src/test/NebulaTest.cc @@ -145,3 +145,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/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/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/vnm/VirtualNetwork.cc b/src/vnm/VirtualNetwork.cc index 8d885b670f..2cb484f8d0 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))"; + " 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) { 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"