diff --git a/SConstruct b/SConstruct index ac58affdd1..3bf25cec2b 100644 --- a/SConstruct +++ b/SConstruct @@ -63,6 +63,7 @@ main_env.Append(LIBPATH=[ cwd+'/src/pool', cwd+'/src/template', cwd+'/src/vm', + cwd+'/src/vm_template', cwd+'/src/vmm', cwd+'/src/lcm', cwd+'/src/tm', @@ -190,6 +191,7 @@ build_scripts=[ 'src/nebula/SConstruct', 'src/pool/SConstruct', 'src/vm/SConstruct', + 'src/vm_template/SConstruct', 'src/vmm/SConstruct', 'src/lcm/SConstruct', 'src/rm/SConstruct', @@ -240,6 +242,7 @@ if testing=='yes': 'src/vm/test/SConstruct', 'src/vnm/test/SConstruct', 'src/xml/test/SConstruct', + 'src/vm_template/test/SConstruct', ]) else: main_env.Append(testing='no') diff --git a/include/Attribute.h b/include/Attribute.h index dcaa05d765..e5213333f1 100644 --- a/include/Attribute.h +++ b/include/Attribute.h @@ -82,8 +82,12 @@ public: */ virtual AttributeType type() = 0; -private: + /** + * Clones the current attribute + */ + virtual Attribute* clone() const = 0; +protected: /** * The attribute name. */ @@ -107,6 +111,11 @@ public: SingleAttribute(const string& name, const string& value): Attribute(name),attribute_value(value){}; + SingleAttribute(const SingleAttribute& sa):Attribute(sa.attribute_name) + { + attribute_value = sa.attribute_value; + }; + ~SingleAttribute(){}; /** @@ -173,6 +182,14 @@ public: return SIMPLE; }; + /** + * Clones the current attribute + */ + Attribute* clone() const + { + return new SingleAttribute(*this); + }; + private: string attribute_value; @@ -195,6 +212,11 @@ public: VectorAttribute(const string& name,const map& value): Attribute(name),attribute_value(value){}; + VectorAttribute(const VectorAttribute& va):Attribute(va.attribute_name) + { + attribute_value = va.attribute_value; + }; + ~VectorAttribute(){}; /** @@ -256,6 +278,14 @@ public: return VECTOR; }; + /** + * Clones the current attribute + */ + Attribute* clone() const + { + return new VectorAttribute(*this); + }; + private: static const char * magic_sep; diff --git a/include/AuthManager.h b/include/AuthManager.h index 307ebc29e1..e456f02fee 100644 --- a/include/AuthManager.h +++ b/include/AuthManager.h @@ -276,11 +276,12 @@ public: */ enum Operation { - CREATE, /** Authorization to create an object (host, vm, net, image)*/ - DELETE, /** Authorization to delete an object */ - USE, /** Authorization to use an object */ - MANAGE, /** Authorization to manage an object */ - INFO /** Authorization to view an object */ + CREATE, /** Authorization to create an object */ + DELETE, /** Authorization to delete an object */ + USE, /** Authorization to use an object */ + MANAGE, /** Authorization to manage an object */ + INFO, /** Authorization to view an object */ + INSTANTIATE /** Authorization to instantiate a VM from a TEMPLATE */ }; /** @@ -293,7 +294,8 @@ public: NET, IMAGE, USER, - CLUSTER + CLUSTER, + TEMPLATE }; /** diff --git a/include/Nebula.h b/include/Nebula.h index e7be3edca4..a677815583 100644 --- a/include/Nebula.h +++ b/include/Nebula.h @@ -25,6 +25,7 @@ #include "VirtualNetworkPool.h" #include "HostPool.h" #include "UserPool.h" +#include "VMTemplatePool.h" #include "VirtualMachineManager.h" #include "LifeCycleManager.h" @@ -81,6 +82,11 @@ public: return cpool; }; + VMTemplatePool * get_tpool() + { + return tpool; + }; + // -------------------------------------------------------------- // Manager Accessors // -------------------------------------------------------------- @@ -233,9 +239,9 @@ private: //Constructors and = are private to only access the class through instance // ----------------------------------------------------------------------- - Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0),upool(0), - ipool(0),cpool(0),lcm(0),vmm(0),im(0),tm(0),dm(0),rm(0),hm(0),authm(0), - imagem(0) + Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0), + upool(0),ipool(0),cpool(0),tpool(0),lcm(0),vmm(0),im(0),tm(0),dm(0), + rm(0),hm(0),authm(0),imagem(0) { const char * nl = getenv("ONE_LOCATION"); @@ -300,6 +306,11 @@ private: delete cpool; } + if ( tpool != 0) + { + delete tpool; + } + if ( vmm != 0) { delete vmm; @@ -392,6 +403,7 @@ private: UserPool * upool; ImagePool * ipool; ClusterPool * cpool; + VMTemplatePool * tpool; // --------------------------------------------------------------- // Nebula Managers diff --git a/include/RequestManager.h b/include/RequestManager.h index 7c84223380..e604581e30 100644 --- a/include/RequestManager.h +++ b/include/RequestManager.h @@ -24,6 +24,7 @@ #include "VirtualNetworkPool.h" #include "ImagePool.h" #include "ClusterPool.h" +#include "VMTemplatePool.h" #include #include @@ -46,10 +47,11 @@ public: UserPool * _upool, ImagePool * _ipool, ClusterPool * _cpool, + VMTemplatePool * _tpool, int _port, string _xml_log_file) :vmpool(_vmpool),hpool(_hpool),vnpool(_vnpool),upool(_upool), - ipool(_ipool),cpool(_cpool),port(_port),socket_fd(-1), + ipool(_ipool),cpool(_cpool),tpool(_tpool),port(_port),socket_fd(-1), xml_log_file(_xml_log_file) { am.addListener(this); @@ -130,10 +132,15 @@ private: ImagePool * ipool; /** - * Pointer to the Image Pool, to access images + * Pointer to the Cluster Pool, to access clusters */ ClusterPool * cpool; + /** + * Pointer to the Template Pool, to access templates + */ + VMTemplatePool * tpool; + /** * Port number where the connection will be open */ @@ -314,10 +321,12 @@ private: VirtualMachinePool * _vmpool, VirtualNetworkPool * _vnpool, ImagePool * _ipool, + VMTemplatePool * _tpool, UserPool * _upool): vmpool(_vmpool), vnpool(_vnpool), ipool(_ipool), + tpool(_tpool), upool(_upool) { _signature="A:ss"; @@ -333,6 +342,7 @@ private: VirtualMachinePool * vmpool; VirtualNetworkPool * vnpool; ImagePool * ipool; + VMTemplatePool * tpool; UserPool * upool; }; @@ -502,6 +512,185 @@ private: UserPool * upool; }; + /* ---------------------------------------------------------------------- */ + /* Template Interface */ + /* ---------------------------------------------------------------------- */ + + class TemplateAllocate: public xmlrpc_c::method + { + public: + TemplateAllocate( + VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:ss"; + _help="Allocates a template in the pool"; + }; + + ~TemplateAllocate(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplateDelete: public xmlrpc_c::method + { + public: + TemplateDelete(VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:si"; + _help="Deletes a Template"; + }; + + ~TemplateDelete(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplateInfo: public xmlrpc_c::method + { + public: + TemplateInfo(VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:si"; + _help="Returns information for a Template"; + }; + + ~TemplateInfo(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplateUpdate: public xmlrpc_c::method + { + public: + TemplateUpdate(VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:siss"; + _help="Modifies Template attribute"; + }; + + ~TemplateUpdate(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplateRemoveAttribute: public xmlrpc_c::method + { + public: + TemplateRemoveAttribute(VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:sis"; + _help="Removes Template attribute"; + }; + + ~TemplateRemoveAttribute(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplatePublish: public xmlrpc_c::method + { + public: + TemplatePublish(VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:sib"; + _help="Publish/Unpublish the Template"; + }; + + ~TemplatePublish(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + + /* ---------------------------------------------------------------------- */ + + class TemplatePoolInfo: public xmlrpc_c::method + { + public: + TemplatePoolInfo( + VMTemplatePool * _tpool, + UserPool * _upool): + tpool(_tpool), + upool(_upool) + { + _signature="A:sii"; + _help="Returns the template pool"; + }; + + ~TemplatePoolInfo(){}; + + void execute( + xmlrpc_c::paramList const& paramList, + xmlrpc_c::value * const retvalP); + + private: + VMTemplatePool * tpool; + UserPool * upool; + }; + /* ---------------------------------------------------------------------- */ /* Host Interface */ /* ---------------------------------------------------------------------- */ diff --git a/include/Template.h b/include/Template.h index d81cf4b8c2..2c623ffb42 100644 --- a/include/Template.h +++ b/include/Template.h @@ -47,6 +47,20 @@ public: separator(_separator), xml_root(_xml_root){}; + Template(const Template& t) + { + multimap::const_iterator it; + + replace_mode = t.replace_mode; + separator = t.separator; + xml_root = t.xml_root; + + for (it = t.attributes.begin() ; it != t.attributes.end() ; it++) + { + attributes.insert(make_pair(it->first,(it->second)->clone())); + } + } + /** * The class destructor frees all the attributes conforming the template */ @@ -161,8 +175,10 @@ public: * @param name the attribute name. * @param value the attribute value, an int, 0 if the attribute is not * defined or not Single + * + * @returns True if the Single attribute was found */ - virtual void get( + virtual bool get( string& name, int& value) const; diff --git a/include/User.h b/include/User.h index c2437bc617..be2acaecae 100644 --- a/include/User.h +++ b/include/User.h @@ -134,15 +134,6 @@ private: */ int insert_replace(SqlDB *db, bool replace); - /** - * Callback function to unmarshall a User object (User::select) - * @param num the number of columns read from the DB - * @param names the column names - * @param vaues the column values - * @return 0 on success - */ - int select_cb(void *nil, int num, char **values, char **names); - /** * Bootstraps the database table(s) associated to the User */ diff --git a/include/VMTemplate.h b/include/VMTemplate.h new file mode 100644 index 0000000000..7a92818bda --- /dev/null +++ b/include/VMTemplate.h @@ -0,0 +1,190 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#ifndef VMTEMPLATE_H_ +#define VMTEMPLATE_H_ + +#include "PoolObjectSQL.h" +#include "VirtualMachineTemplate.h" + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +/** + * The VMTemplate class. + */ +class VMTemplate : public PoolObjectSQL +{ +public: + + /** + * Function to write a VMTemplate on an output stream + */ + friend ostream& operator<<(ostream& os, VMTemplate& u); + + /** + * Function to print the VMTemplate object into a string in XML format + * @param xml the resulting XML string + * @return a reference to the generated string + */ + string& to_xml(string& xml) const; + + /** + * Returns true if the object is public + * @return true if the Virtual Network is public + */ + bool isPublic() + { + return (public_template == 1); + }; + + /** + * Publish or unpublish an object + * @param pub true to publish the object + * @return 0 on success + */ + bool publish(bool pub) + { + if (pub == true) + { + public_template = 1; + } + else + { + public_template = 0; + } + + return true; + }; + + // ------------------------------------------------------------------------ + // Template Contents + // ------------------------------------------------------------------------ + + /** + * Returns a copy of the VirtualMachineTemplate + * @return A copy of the VirtualMachineTemplate + */ + VirtualMachineTemplate * clone_template() const + { + return new VirtualMachineTemplate( + *(static_cast(obj_template))); + + // TODO: Check if there is a more efficient way to do this copy. + /*string xml_str; + VirtualMachineTemplate * new_template = new VirtualMachineTemplate(); + + obj_template->to_xml(xml_str); + new_template->from_xml(xml_str); + + return new_template;*/ + }; + +private: + // ------------------------------------------------------------------------- + // Friends + // ------------------------------------------------------------------------- + + friend class VMTemplatePool; + + // ------------------------------------------------------------------------- + // VMTemplate Attributes + // ------------------------------------------------------------------------- + + /** + * Owner's name + */ + string user_name; + + /** + * Public scope of the VMTemplate + */ + int public_template; + + /** + * Registration time + */ + time_t regtime; + + // ************************************************************************* + // DataBase implementation (Private) + // ************************************************************************* + + /** + * Execute an INSERT or REPLACE Sql query. + * @param db The SQL DB + * @param replace Execute an INSERT or a REPLACE + * @return 0 one success + */ + int insert_replace(SqlDB *db, bool replace); + + /** + * Bootstraps the database table(s) associated to the VMTemplate + */ + static void bootstrap(SqlDB * db) + { + ostringstream oss(VMTemplate::db_bootstrap); + + db->exec(oss); + }; + + /** + * Rebuilds the object from an xml formatted string + * @param xml_str The xml-formatted string + * + * @return 0 on success, -1 otherwise + */ + int from_xml(const string &xml_str); + +protected: + + // ************************************************************************* + // Constructor + // ************************************************************************* + VMTemplate(int id, int uid, string _user_name, + VirtualMachineTemplate * _template_contents); + + ~VMTemplate(); + + // ************************************************************************* + // DataBase implementation + // ************************************************************************* + + static const char * db_names; + + static const char * db_bootstrap; + + static const char * table; + + /** + * Writes the VMTemplate in the database. + * @param db pointer to the db + * @return 0 on success + */ + int insert(SqlDB *db, string& error_str); + + /** + * Writes/updates the VMTemplate data fields in the database. + * @param db pointer to the db + * @return 0 on success + */ + int update(SqlDB *db) + { + return insert_replace(db, true); + }; +}; + +#endif /*VMTEMPLATE_H_*/ diff --git a/include/VMTemplatePool.h b/include/VMTemplatePool.h new file mode 100644 index 0000000000..92660f6226 --- /dev/null +++ b/include/VMTemplatePool.h @@ -0,0 +1,146 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#ifndef VMTEMPLATE_POOL_H_ +#define VMTEMPLATE_POOL_H_ + +#include "PoolSQL.h" +#include "VMTemplate.h" + +/** + * The VMTemplate Pool class. + */ +class VMTemplatePool : public PoolSQL +{ +public: + + VMTemplatePool(SqlDB * db) : PoolSQL(db, VMTemplate::table){}; + + ~VMTemplatePool(){}; + + /** + * Allocates a new object, writting it in the pool database. No memory is + * allocated for the object. + * @param uid user id (the owner of the Template) + * @param user_name Owner's user name + * @param template_contents a VM Template object + * @param oid the id assigned to the Template + * @param error_str Returns the error reason, if any + * + * @return the oid assigned to the object, -1 in case of failure + */ + int allocate(int uid, + string user_name, + VirtualMachineTemplate * template_contents, + int * oid, + string& error_str); + + /** + * Gets an object from the pool (if needed the object is loaded from the + * database). + * @param oid the object unique identifier + * @param lock locks the object if true + * + * @return a pointer to the object, 0 in case of failure + */ + VMTemplate * get(int oid, bool lock) + { + return static_cast(PoolSQL::get(oid,lock)); + }; + + /** + * Gets an object from the pool (if needed the object is loaded from the + * database). + * @param name of the object + * @param uid id of owner + * @param lock locks the object if true + * + * @return a pointer to the object, 0 in case of failure + */ + VMTemplate * get(const string& name, int uid, bool lock) + { + return static_cast(PoolSQL::get(name,uid,lock)); + }; + + /** + * Updates the object's data in the data base. The object mutex SHOULD be + * locked. + * @param objsql a pointer to the object + * + * @return 0 on success. + */ + int update(VMTemplate * vm_template) + { + return vm_template->update(db); + }; + + /** + * Drops the object's data in the data base. The object mutex SHOULD be + * locked. + * @param objsql a pointer to the object + * @return 0 on success. + */ + int drop(VMTemplate * vm_template) + { + return PoolSQL::drop(vm_template); + }; + + /** + * Dumps the pool in XML format. A filter can be also added to the + * query + * @param oss the output stream to dump the pool contents + * @param where filter for the objects, defaults to all + * + * @return 0 on success + */ + int dump(ostringstream& oss, const string& where) + { + return PoolSQL::dump(oss, "VMTEMPLATE_POOL",VMTemplate::table,where); + }; + + /** + * Bootstraps the database table(s) associated to the pool + */ + static void bootstrap(SqlDB *_db) + { + VMTemplate::bootstrap(_db); + }; + +private: + //-------------------------------------------------------------------------- + // Configuration Attributes for Images + // ------------------------------------------------------------------------- + + // TODO + + //-------------------------------------------------------------------------- + // Pool Attributes + // ------------------------------------------------------------------------- + + // TODO + + + /** + * Factory method to produce Image objects + * @return a pointer to the new Image + */ + PoolObjectSQL * create() + { + return new VMTemplate(-1,-1,"", 0); + }; +}; + +#endif /*VMTEMPLATE_POOL_H_*/ diff --git a/include/VirtualMachinePool.h b/include/VirtualMachinePool.h index c069357f61..cedf998473 100644 --- a/include/VirtualMachinePool.h +++ b/include/VirtualMachinePool.h @@ -41,8 +41,10 @@ public: /** * Function to allocate a new VM object * @param uid user id (the owner of the VM) + * @param user_name Owner's user name * @param vm_template a VM Template object describing the VM * @param oid the id assigned to the VM (output) + * @param error_str Returns the error reason, if any * @param on_hold flag to submit on hold * @return oid on success, -1 error inserting in DB or -2 error parsing * the template diff --git a/include/VirtualMachineTemplate.h b/include/VirtualMachineTemplate.h index a8c76404b6..c19fbdf171 100644 --- a/include/VirtualMachineTemplate.h +++ b/include/VirtualMachineTemplate.h @@ -19,6 +19,8 @@ #include "Template.h" +#include + using namespace std; /** @@ -32,6 +34,8 @@ public: ~VirtualMachineTemplate(){}; + VirtualMachineTemplate(VirtualMachineTemplate& vmt):Template(vmt){}; + private: friend class VirtualMachine; }; diff --git a/include/test/NebulaTest.h b/include/test/NebulaTest.h index a60b93141e..9078500764 100644 --- a/include/test/NebulaTest.h +++ b/include/test/NebulaTest.h @@ -26,6 +26,7 @@ #include "HostPool.h" #include "UserPool.h" #include "ClusterPool.h" +#include "VMTemplatePool.h" #include "VirtualMachineManager.h" #include "LifeCycleManager.h" @@ -43,7 +44,8 @@ protected: NebulaTest():mysql(false), need_host_pool(false), need_vm_pool(false), need_vnet_pool(false), need_image_pool(false), - need_user_pool(false), need_cluster_pool(false),need_vmm(false), + need_user_pool(false), need_cluster_pool(false), + need_template_pool(false),need_vmm(false), need_im(false), need_tm(false), need_lcm(false), need_dm(false), need_rm(false), need_hm(false), @@ -63,6 +65,7 @@ public: bool need_image_pool; bool need_user_pool; bool need_cluster_pool; + bool need_template_pool; bool need_vmm; bool need_im; @@ -100,6 +103,8 @@ public: virtual ClusterPool* create_cpool(SqlDB* db); + virtual VMTemplatePool* create_tpool(SqlDB* db); + // ------------------------------------------------------------------------ // Managers // ------------------------------------------------------------------------ @@ -129,6 +134,7 @@ public: UserPool * upool, ImagePool * ipool, ClusterPool * cpool, + VMTemplatePool * tpool, string log_file); virtual HookManager* create_hm(VirtualMachinePool * vmpool); diff --git a/install.sh b/install.sh index f9dd157f59..8c83a9f1ea 100755 --- a/install.sh +++ b/install.sh @@ -360,6 +360,7 @@ BIN_FILES="src/nebula/oned \ src/cli/oneuser \ src/cli/oneimage \ src/cli/onecluster \ + src/cli/onetemplate \ share/scripts/one \ src/authm_mad/oneauth" @@ -404,6 +405,8 @@ RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/OpenNebula/Host.rb \ src/oca/ruby/OpenNebula/ImagePool.rb \ src/oca/ruby/OpenNebula/Cluster.rb \ src/oca/ruby/OpenNebula/ClusterPool.rb \ + src/oca/ruby/OpenNebula/Template.rb \ + src/oca/ruby/OpenNebula/TemplatePool.rb \ src/oca/ruby/OpenNebula/XMLUtils.rb" #------------------------------------------------------------------------------- @@ -716,7 +719,8 @@ CLI_BIN_FILES="src/cli/onevm \ src/cli/onevnet \ src/cli/oneuser \ src/cli/oneimage \ - src/cli/onecluster" + src/cli/onecluster \ + src/cli/onetemplate" #----------------------------------------------------------------------------- # Sunstone files @@ -825,6 +829,7 @@ MAN_FILES="share/man/oneauth.8.gz \ share/man/oneuser.8.gz \ share/man/onevm.8.gz \ share/man/onevnet.8.gz \ + share/man/onetemplate.8.gz \ share/man/econe-describe-images.8.gz \ share/man/econe-describe-instances.8.gz \ share/man/econe-register.8.gz \ diff --git a/share/test/do_tests.sh b/share/test/do_tests.sh index c56fa0a3e6..1e18096337 100755 --- a/share/test/do_tests.sh +++ b/share/test/do_tests.sh @@ -17,7 +17,8 @@ TESTS="$TWD_DIR/vnm/test \ $TWD_DIR/vm/test \ $TWD_DIR/um/test \ $TWD_DIR/lcm/test \ - $TWD_DIR/pool/test" + $TWD_DIR/pool/test \ + $TWD_DIR/vm_template/test" #------------------------------------------------------------------------------- # COMMAND LINE PARSING diff --git a/src/authm/AuthManager.cc b/src/authm/AuthManager.cc index 094f05076a..cc88d57de5 100644 --- a/src/authm/AuthManager.cc +++ b/src/authm/AuthManager.cc @@ -86,9 +86,10 @@ void AuthRequest::add_auth(Object ob, case IMAGE: oss << "IMAGE:" ; break; case USER: oss << "USER:" ; break; case CLUSTER: oss << "CLUSTER:" ; break; + case TEMPLATE: oss << "TEMPLATE:" ; break; } - if (op == CREATE) //encode the ob_id, it is a template + if (op == CREATE || op == INSTANTIATE) //encode the ob_id, it is a template { string * encoded_id = base64_encode(ob_id); @@ -128,6 +129,10 @@ void AuthRequest::add_auth(Object ob, case INFO: oss << "INFO:" ; break; + + case INSTANTIATE: + oss << "INSTANTIATE:" ; + break; } oss << owner << ":" << pub; @@ -147,7 +152,14 @@ void AuthRequest::add_auth(Object ob, switch (op) { case CREATE: - if ( ob == VM || ob == NET || ob == IMAGE ) + if ( ob == VM || ob == NET || ob == IMAGE || ob == TEMPLATE ) + { + auth = true; + } + break; + + case INSTANTIATE: + if ( ob == VM ) { auth = true; } @@ -158,7 +170,7 @@ void AuthRequest::add_auth(Object ob, break; case USE: - if (ob == NET || ob == IMAGE) + if (ob == NET || ob == IMAGE || ob == TEMPLATE) { auth = (owner == uid) || pub; } diff --git a/src/authm_mad/simple_permissions.rb b/src/authm_mad/simple_permissions.rb index 51af54cbe5..e69dae12e5 100644 --- a/src/authm_mad/simple_permissions.rb +++ b/src/authm_mad/simple_permissions.rb @@ -48,7 +48,20 @@ class SimplePermissions VmUsage.new(cpu, memory) end - + + # Checks if the quota is enabled, and if it is not exceeded + def check_quota_enabled(uid, object, id, auth_result) + if @quota_enabled and object=='VM' and auth_result + STDERR.puts 'quota enabled' + @quota.update(uid.to_i) + if !@quota.check(uid.to_i, get_vm_usage(id)) + auth_result="Quota exceeded" + end + end + + return auth_result + end + # Method called by authorization driver def auth(uid, tokens) result=true @@ -71,21 +84,18 @@ class SimplePermissions case action when 'CREATE' - auth_result=true if %w{VM NET IMAGE}.include? object - - if @quota_enabled and object=='VM' and auth_result - STDERR.puts 'quota enabled' - @quota.update(uid.to_i) - if !@quota.check(uid.to_i, get_vm_usage(id)) - auth_result="Quota exceeded" - end - end - + auth_result=true if %w{VM NET IMAGE TEMPLATE}.include? object + auth_result = check_quota_enabled(uid, object, id, auth_result) + + when 'INSTANTIATE' + auth_result = true if %w{VM}.include? object + auth_result = check_quota_enabled(uid, object, id, auth_result) + when 'DELETE' auth_result = (owner == uid) when 'USE' - if %w{VM NET IMAGE}.include? object + if %w{VM NET IMAGE TEMPLATE}.include? object auth_result = ((owner == uid) | (pub=='1')) elsif object == 'HOST' auth_result=true diff --git a/src/cli/client_utilities.rb b/src/cli/client_utilities.rb index b177db2c68..90e7307bd1 100644 --- a/src/cli/client_utilities.rb +++ b/src/cli/client_utilities.rb @@ -268,15 +268,19 @@ def get_entity_id(name, pool_class) pool=pool_class.new(get_one_client) result=pool.info - # TODO: Check for errors + class_name=pool_class.name.split('::').last.gsub(/Pool$/, '') + + if( OpenNebula.is_error?(result) ) + puts "Error: #{class_name} Pool info could not be retrieved. " + + result.message + exit -1 + end objects=pool.select {|object| object.name==name } - class_name=pool_class.name.split('::').last.gsub(/Pool$/, '') - if objects.length>0 if objects.length>1 - puts "There are multiple #{class_name}'s with name #{name}." + puts "There are multiple #{class_name}s with name #{name}." exit -1 else result=objects.first.id @@ -313,6 +317,10 @@ def get_cluster_id(name) get_entity_id(name, OpenNebula::ClusterPool) end +def get_template_id(name) + get_entity_id(name, OpenNebula::TemplatePool) +end + def str_running_time(data) stime=Time.at(data["STIME"].to_i) if data["ETIME"]=="0" diff --git a/src/cli/onetemplate b/src/cli/onetemplate new file mode 100755 index 0000000000..890b5fb77a --- /dev/null +++ b/src/cli/onetemplate @@ -0,0 +1,411 @@ +#!/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. # +#--------------------------------------------------------------------------- # + +ONE_LOCATION=ENV["ONE_LOCATION"] + +if !ONE_LOCATION + RUBY_LIB_LOCATION="/usr/lib/one/ruby" +else + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" +end + +$: << RUBY_LIB_LOCATION + + +require 'OpenNebula' +require 'CommandManager' +require 'client_utilities' +require 'command_parse' + +ShowTableTemplate={ + :id => { + :name => "ID", + :desc => "ONE identifier for the Template", + :size => 4, + :proc => lambda {|d,e| d.id } + }, + :user=> { + :name => "USER", + :desc => "Name of the owner", + :size => 8, + :proc => lambda {|d,e| + d["USERNAME"] + } + }, + :name => { + :name => "NAME", + :desc => "Name of the Template", + :size => 20, + :proc => lambda {|d,e| + d.name + } + }, + :regtime => { + :name => "REGTIME", + :desc => "Registration time of the Template", + :size => 20, + :proc => lambda {|d,e| + str_register_time(d) + } + }, + :public => { + :name => "PUBLIC", + :desc => "Whether the Template is public or not", + :size => 3, + :proc => lambda {|d,e| + if d["PUBLIC"].to_i == 1 then "Yes" else "No" end} + }, + + :default => [:id, :user, :name, :regtime, :public] +} + + + +class TemplateShow + + def initialize(client, filter_flag="-2") + @templatepool=OpenNebula::TemplatePool.new(client, filter_flag.to_i) + @table=ShowTable.new(ShowTableTemplate) + end + + def header_template_small + scr_bold + scr_underline + print @table.header_str + scr_restore + puts "" + end + + def top(options=nil) + delay=1 + delay=options[:delay] if options && options[:delay] + + result=nil + + begin + while true + scr_cls + scr_move(0,0) + result=list_short(options) + sleep delay + end + rescue Exception + end + result + end + + def list_short(options=nil) + res=@templatepool.info() + + if options + @table.columns=options[:columns] if options[:columns] + end + + if OpenNebula.is_error?(res) + result=res + puts res.message + exit -1 + else + + if options[:filter_flag] + objs=@templatepool.select{|element| + element['USERNAME']==options[:filter_flag] } + else + objs=@templatepool + end + + result=[true, ""] + header_template_small + + if options + puts @table.data_str(objs, options) + else + puts @table.data_str(objs) + end + + result + end + end +end + + +########################## +## COMMAND LINE PARSING ## +########################## + +class OneTemplateParse < CommandParse + + COMMANDS_HELP=<<-EOT + +Description: + +This command enables the user to manage templates. + + +Commands: + +* create (Registers a Template from a template file) + onetemplate create + + file is a file name where the Template description is located + +* addattr (Add a new Template attribute) + onetemplate addattr + +* update (Modifies a Template attribute) + onetemplate update + +* rmattr (Deletes a Template attribute) + onetemplate rmattr + +* publish (Publish a Template) + onetemplate publish + +* unpublish (Unpublish an Template) + onetemplate unpublish + +* list (Shows Templates in the pool) + onetemplate list + + where filter_flag can be + a, all --> all the known Templates + m, mine --> the Templates belonging to the user in ONE_AUTH + and all the Public Templates + uid --> Templates of the user identified by this uid + user --> Templates of the user identified by the username + +* top (Lists Templates continuously) + onetemplate top + +* show (Gets information about an specific Template) + onetemplate show + +* delete (Deletes a Template) + onetemplate delete + +EOT + + def text_commands + COMMANDS_HELP + end + + def text_command_name + "onetemplate" + end + + def list_options + table=ShowTable.new(ShowTableTemplate) + table.print_help + end +end + + +def get_user_flags + ops=Hash.new + if ARGV[0] + case ARGV[0] + when "a", "all" + ops[:filter_user]="-2" + when "m", "mine" + ops[:filter_user]="-1" + else + if !ARGV[0].match(/^[0123456789]+$/) + ops[:filter_user]="-2" + ops[:filter_flag]=ARGV[0] + else + ops[:filter_user]=ARGV[0] + end + end + else + ops[:filter_user]="-2" + end + + ops +end + +def get_template(template_path) + begin + template = File.read(ARGV[0]) + rescue + result = OpenNebula::Error.new("Can not read template: #{ARGV[0]}") + end + + if !is_successful?(result) + puts result.message + exit -1 + end + + return template +end + +onetemplate_opts=OneTemplateParse.new +onetemplate_opts.parse(ARGV) +ops=onetemplate_opts.options + +result=[false, "Unknown error"] + +command=ARGV.shift + +case command +when "create", "register", "add" + check_parameters("create", 1) + template_contents = get_template(ARGV[0]) + + template = OpenNebula::Template.new(OpenNebula::Template.build_xml, get_one_client) + + result=template.allocate(template_contents) + if !OpenNebula.is_error?(result) + puts "ID: " + template.id.to_s if ops[:verbose] + exit 0 + end + +when "update", "addattr" + check_parameters("update", 3) + template_id = get_template_id(ARGV[0]) + + template = OpenNebula::Template.new_with_id(template_id, get_one_client) + + result = template.update(ARGV[1],ARGV[2]) + if is_successful?(result) + puts "Modified template" if ops[:verbose] + end + +when "rmattr" + check_parameters("rmattr", 2) + template_id = get_template_id(ARGV[0]) + + template = OpenNebula::Template.new_with_id(template_id, get_one_client) + + result = template.remove_attr(ARGV[1]) + if is_successful?(result) + puts "Removed template attribute" if ops[:verbose] + end + +when "publish" + check_parameters("publish", 1) + template_id = get_template_id(ARGV[0]) + + template = OpenNebula::Template.new_with_id(template_id, get_one_client) + + result = template.publish + if is_successful?(result) + puts "Template published" if ops[:verbose] + end + +when "unpublish" + check_parameters("unpublish", 1) + template_id = get_template_id(ARGV[0]) + + template = OpenNebula::Template.new_with_id(template_id, get_one_client) + + result = template.unpublish + if is_successful?(result) + puts "Template unpublished" if ops[:verbose] + end + +when "list" + ops.merge!(get_user_flags) + if !ops[:xml] + templatelist = TemplateShow.new(get_one_client, ops[:filter_user].to_i) + ops[:columns] = ops[:list] if ops[:list] + result = templatelist.list_short(ops) + else + templatepool = OpenNebula::TemplatePool.new(get_one_client, + ops[:filter_user].to_i) + templatepool.info + puts templatepool.to_xml + end + +when "top" + ops.merge!(get_user_flags) + templatelist = TemplateShow.new(get_one_client, ops[:filter_user].to_i) + ops[:columns] = ops[:list] if ops[:list] + result = templatelist.top(ops) + +when "show" + check_parameters("get_info", 1) + args = expand_args(ARGV) + + args.each do |param| + template_id = get_template_id(param) + + template = OpenNebula::Template.new_with_id(template_id, get_one_client) + result = template.info + + if is_successful?(result) + if !ops[:xml] + str="%-15s: %-20s" + str_h1="%-80s" + + print_header(str_h1, "TEMPLATE #{template[:id]} INFORMATION", true) + + puts str % ["ID", template.id.to_s] + puts str % ["NAME", template.name] + + value = template['REGTIME'].to_i + if value==0 + value='-' + else + value=Time.at(value).strftime("%m/%d %H:%M:%S") + end + puts str % ["REGISTER TIME", value] + if template['PUBLIC'].to_i == 1 + public_str = "Yes" + else + public_str = "No" + end + puts str % ["PUBLIC", public_str] + + puts + + print_header(str_h1,"TEMPLATE CONTENTS",false) + + puts template.template_str + else + puts template.to_xml + end + end + end + +when "delete" + check_parameters("delete", 1) + args = expand_args(ARGV) + + args.each do |param| + template_id = get_template_id(param) + template = OpenNebula::Template.new( + OpenNebula::Template.build_xml(template_id), + get_one_client) + + result = template.delete + if is_successful?(result) + puts "Template correctly deleted" if ops[:verbose] + end + end + +else + onetemplate_opts.print_help + exit -1 +end + +if OpenNebula.is_error?(result) + puts "Error: " + result.message + exit -1 +end + + diff --git a/src/cli/onevm b/src/cli/onevm index 0c81b07caa..1af1f1eee8 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -318,9 +318,15 @@ machine with the functionality present in onevm. Commands: * create (Submits a new virtual machine, adding it to the ONE VM pool) - onevm create