opennebula-3.4.1/0000755000175000017500000000000011750754334013554 5ustar drazzibdrazzibopennebula-3.4.1/SConstruct0000644000175000017500000001724311750754334015615 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # # a copy of the License at # # # # http://www.apache.org/licenses/LICENSE-2.0 # # # # Unless required by applicable law or agreed to in writing, software # # distributed under the License is distributed on an "AS IS" BASIS, # # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # # See the License for the specific language governing permissions and # # limitations under the License. # #--------------------------------------------------------------------------- # import os import sys import shutil sys.path.append("./share/scons") from lex_bison import * # This is the absolute path where the project is located cwd=os.getcwd() # Environment that will be applied to each scons child main_env=Environment() main_env['ENV']['PATH']=os.environ['PATH'] # snippet borrowed from http://dev.gentoo.org/~vapier/scons-blows.txt # makes scons aware of build related environment variables if os.environ.has_key('CC'): main_env['CC'] = os.environ['CC'] if os.environ.has_key('CFLAGS'): main_env['CCFLAGS'] += SCons.Util.CLVar(os.environ['CFLAGS']) if os.environ.has_key('CXX'): main_env['CXX'] = os.environ['CXX'] if os.environ.has_key('CXXFLAGS'): main_env['CXXFLAGS'] += SCons.Util.CLVar(os.environ['CXXFLAGS']) if os.environ.has_key('LDFLAGS'): main_env['LINKFLAGS'] += SCons.Util.CLVar(os.environ['LDFLAGS']) else: os.environ['LDFLAGS']="" # Add builders for flex and bison add_lex(main_env) add_bison(main_env) # Include dirs main_env.Append(CPPPATH=[ cwd+'/include', ]) # Library dirs main_env.Append(LIBPATH=[ cwd+'/src/common', cwd+'/src/log', cwd+'/src/sql', cwd+'/src/host', cwd+'/src/cluster', cwd+'/src/datastore', cwd+'/src/group', cwd+'/src/mad', cwd+'/src/nebula', cwd+'/src/pool', cwd+'/src/template', cwd+'/src/vm', cwd+'/src/vm_template', cwd+'/src/vmm', cwd+'/src/lcm', cwd+'/src/tm', cwd+'/src/dm', cwd+'/src/im', cwd+'/src/image', cwd+'/src/rm', cwd+'/src/vnm', cwd+'/src/hm', cwd+'/src/um', cwd+'/src/authm', cwd+'/src/acl', cwd+'/src/xml', ]) # Compile flags main_env.Append(CPPFLAGS=[ "-g", "-Wall" ]) # Linking flags main_env.Append(LINKFLAGS=['-g', '-pthread']) ####################### # EXTRA CONFIGURATION # ####################### # SQLITE sqlite_dir=ARGUMENTS.get('sqlite_dir', 'none') if sqlite_dir!='none': main_env.Append(LIBPATH=[sqlite_dir+"/lib"]) main_env.Append(CPPPATH=[sqlite_dir+"/include"]) sqlite=ARGUMENTS.get('sqlite', 'yes') if sqlite=='yes': main_env.Append(sqlite='yes') main_env.Append(CPPFLAGS=["-DSQLITE_DB"]) main_env.Append(LIBS=['sqlite3']) else: main_env.Append(sqlite='no') # MySQL mysql=ARGUMENTS.get('mysql', 'no') if mysql=='yes': main_env.Append(mysql='yes') main_env.Append(CPPFLAGS=["-DMYSQL_DB"]) main_env.Append(LIBS=['mysqlclient']) else: main_env.Append(mysql='no') # xmlrpc xmlrpc_dir=ARGUMENTS.get('xmlrpc', 'none') if xmlrpc_dir!='none': main_env.Append(LIBPATH=[xmlrpc_dir+"/lib"]) main_env.Append(CPPPATH=[xmlrpc_dir+"/include"]) # build lex/bison build_parsers=ARGUMENTS.get('parsers', 'no') if build_parsers=='yes': main_env.Append(parsers='yes') 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'],)) except Exception, e: print "" print "Error searching for xmlrpc-c libraries. Please check this"+\ " things:" print "" print " * You have installed development libraries for xmlrpc-c. One"+\ " way to check" print " this is calling xmlrpc-c-config that is provided with the"+\ " development" print " package." print " * Check that the version of xmlrpc-c is at least 1.06. You"+\ " can do this also" print " calling:" print " $ xmlrpc-c-config --version" print " * If all this requirements are already met please send log"+\ " files located in" print " .xmlrpc_test to the mailing list." print "" exit(-1) else: main_env.Replace(mysql='yes') shutil.rmtree('.xmlrpc_test', True) shutil.rmtree('src/nebula/.xmlrpc_test', True) shutil.rmtree('src/scheduler/.xmlrpc_test', True) # libxml2 main_env.ParseConfig('xml2-config --libs --cflags') # SCONS scripts to build build_scripts=[ 'src/sql/SConstruct', 'src/log/SConstruct', 'src/common/SConstruct', 'src/template/SConstruct', 'src/host/SConstruct', 'src/cluster/SConstruct', 'src/datastore/SConstruct', 'src/group/SConstruct', 'src/mad/SConstruct', 'src/mad/utils/SConstruct', 'src/nebula/SConstruct', 'src/pool/SConstruct', 'src/vm/SConstruct', 'src/vm_template/SConstruct', 'src/vmm/SConstruct', 'src/lcm/SConstruct', 'src/rm/SConstruct', 'src/tm/SConstruct', 'src/im/SConstruct', 'src/image/SConstruct', 'src/dm/SConstruct', 'src/scheduler/SConstruct', 'src/vnm/SConstruct', 'src/hm/SConstruct', 'src/um/SConstruct', 'src/authm/SConstruct', 'src/acl/SConstruct', 'src/xml/SConstruct', 'share/man/SConstruct' ] # Testing testing=ARGUMENTS.get('tests', 'no') if testing=='yes': main_env.Append(testing='yes') main_env.ParseConfig('cppunit-config --cflags --libs') main_env.Append(CPPPATH=[ cwd+'/include/test', '/usr/include/cppunit/' #not provided by cppunit-config command ]) main_env.Append(LIBPATH=[ cwd+'/src/test', ]) main_env.Append(LIBS=[ 'nebula_test_common', ]) build_scripts.extend([ 'src/authm/test/SConstruct', 'src/common/test/SConstruct', 'src/host/test/SConstruct', 'src/cluster/test/SConstruct', 'src/datastore/test/SConstruct', 'src/group/test/SConstruct', 'src/image/test/SConstruct', 'src/lcm/test/SConstruct', 'src/pool/test/SConstruct', 'src/template/test/SConstruct', 'src/test/SConstruct', 'src/um/test/SConstruct', 'src/vm/test/SConstruct', 'src/vnm/test/SConstruct', 'src/xml/test/SConstruct', 'src/vm_template/test/SConstruct', ]) else: main_env.Append(testing='no') for script in build_scripts: env=main_env.Clone() SConscript(script, exports='env') opennebula-3.4.1/include/0000755000175000017500000000000011750754334015177 5ustar drazzibdrazzibopennebula-3.4.1/include/ClusterPool.h0000644000175000017500000001230711750754334017626 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 CLUSTER_POOL_H_ #define CLUSTER_POOL_H_ #include "Cluster.h" #include "SqlDB.h" using namespace std; class ClusterPool : public PoolSQL { public: ClusterPool(SqlDB * db); ~ClusterPool(){}; /* ---------------------------------------------------------------------- */ /* Constants for DB management */ /* ---------------------------------------------------------------------- */ /** * Name for the "none" cluster */ static const string NONE_CLUSTER_NAME; /** * Identifier for the "none" cluster */ static const int NONE_CLUSTER_ID; /* ---------------------------------------------------------------------- */ /* Methods for DB management */ /* ---------------------------------------------------------------------- */ /** * Allocates a new cluster, writting it in the pool database. No memory is * allocated for the object. * @param name Cluster name * @param oid the id assigned to the Cluster * @param error_str Returns the error reason, if any * * @return the oid assigned to the object, -1 in case of failure */ int allocate(string name, int * oid, string& error_str); /** * Function to get a cluster from the pool, if the object is not in memory * it is loaded from the DB * @param oid cluster unique id * @param lock locks the cluster mutex * @return a pointer to the cluster, 0 if the cluster could not be loaded */ Cluster * 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 lock locks the object if true * * @return a pointer to the object, 0 in case of failure */ Cluster * get(const string& name, bool lock) { // The owner is set to -1, because it is not used in the key() method return static_cast(PoolSQL::get(name,-1,lock)); }; /** * Generate an index key for the object * @param name of the object * @param uid owner of the object, only used if needed * * @return the key, a string */ string key(const string& name, int uid) { // Name is enough key because Clusters can't repeat names. return name; }; /** Update a particular Cluster * @param user pointer to Cluster * @return 0 on success */ int update(Cluster * cluster) { return cluster->update(db); }; /** * Drops the Cluster from the data base. The object mutex SHOULD be * locked. * @param objsql a pointer to a Cluster object * @param error_msg Error reason, if any * @return 0 on success, * -1 DB error, * -2 object is a system cluster (ID < 100) * -3 Cluster's User IDs set is not empty */ int drop(PoolObjectSQL * objsql, string& error_msg); /** * Bootstraps the database table(s) associated to the Cluster pool * @return 0 on success */ static int bootstrap(SqlDB * _db) { return Cluster::bootstrap(_db); }; /** * Dumps the Cluster 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, "CLUSTER_POOL", Cluster::table, where); }; private: /** * Factory method to produce objects * @return a pointer to the new object */ PoolObjectSQL * create() { return new Cluster(-1,""); }; }; #endif /*CLUSTER_POOL_H_*/ opennebula-3.4.1/include/RequestManagerDelete.h0000644000175000017500000002107611750754334021424 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 REQUEST_MANAGER_DELETE_H_ #define REQUEST_MANAGER_DELETE_H_ #include "Request.h" #include "Nebula.h" #include "AuthManager.h" using namespace std; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class RequestManagerDelete: public Request { protected: RequestManagerDelete(const string& method_name, const string& help) :Request(method_name,"A:si",help) { auth_op = AuthRequest::MANAGE; Nebula& nd = Nebula::instance(); clpool = nd.get_clpool(); aclm = nd.get_aclm(); }; ~RequestManagerDelete(){}; /* -------------------------------------------------------------------- */ void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); bool delete_authorization(int oid, RequestAttributes& att); /* -------------------------------------------------------------------- */ virtual int drop(int oid, PoolObjectSQL * object, string& error_msg); virtual int get_cluster_id(PoolObjectSQL * object) { return ClusterPool::NONE_CLUSTER_ID; }; virtual int del_from_cluster(Cluster* cluster, int id, string& error_msg) { return -1; }; protected: ClusterPool * clpool; AclManager * aclm; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class TemplateDelete : public RequestManagerDelete { public: TemplateDelete(): RequestManagerDelete("TemplateDelete", "Deletes a virtual machine template") { Nebula& nd = Nebula::instance(); pool = nd.get_tpool(); auth_object = PoolObjectSQL::TEMPLATE; }; ~TemplateDelete(){}; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class VirtualNetworkDelete: public RequestManagerDelete { public: VirtualNetworkDelete(): RequestManagerDelete("VirtualNetworkDelete", "Deletes a virtual network") { Nebula& nd = Nebula::instance(); pool = nd.get_vnpool(); auth_object = PoolObjectSQL::NET; }; ~VirtualNetworkDelete(){}; /* -------------------------------------------------------------------- */ int get_cluster_id(PoolObjectSQL * object) { return static_cast(object)->get_cluster_id(); }; int del_from_cluster(Cluster* cluster, int id, string& error_msg) { return cluster->del_vnet(id, error_msg); }; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class ImageDelete: public RequestManagerDelete { public: ImageDelete(): RequestManagerDelete("ImageDelete", "Deletes an image") { Nebula& nd = Nebula::instance(); pool = nd.get_ipool(); auth_object = PoolObjectSQL::IMAGE; }; ~ImageDelete(){}; /* -------------------------------------------------------------------- */ int drop(int oid, PoolObjectSQL * object, string& error_msg); }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class HostDelete : public RequestManagerDelete { public: HostDelete(): RequestManagerDelete("HostDelete", "Deletes a host") { Nebula& nd = Nebula::instance(); pool = nd.get_hpool(); auth_object = PoolObjectSQL::HOST; auth_op = AuthRequest::ADMIN; }; ~HostDelete(){}; /* -------------------------------------------------------------------- */ int get_cluster_id(PoolObjectSQL * object) { return static_cast(object)->get_cluster_id(); }; int del_from_cluster(Cluster* cluster, int id, string& error_msg) { return cluster->del_host(id, error_msg); }; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class GroupDelete: public RequestManagerDelete { public: GroupDelete(): RequestManagerDelete("GroupDelete", "Deletes a group") { Nebula& nd = Nebula::instance(); pool = nd.get_gpool(); auth_object = PoolObjectSQL::GROUP; auth_op = AuthRequest::ADMIN; }; ~GroupDelete(){}; /* -------------------------------------------------------------------- */ int drop(int oid, PoolObjectSQL * object, string& error_msg); }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class UserDelete: public RequestManagerDelete { public: UserDelete(): RequestManagerDelete("UserDelete", "Deletes a user") { Nebula& nd = Nebula::instance(); pool = nd.get_upool(); gpool = nd.get_gpool(); auth_object = PoolObjectSQL::USER; auth_op = AuthRequest::ADMIN; }; ~UserDelete(){}; /* -------------------------------------------------------------------- */ GroupPool * gpool; /* -------------------------------------------------------------------- */ int drop(int oid, PoolObjectSQL * object, string& error_msg); }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class DatastoreDelete: public RequestManagerDelete { public: DatastoreDelete(): RequestManagerDelete("DatastoreDelete", "Deletes a datastore") { Nebula& nd = Nebula::instance(); pool = nd.get_dspool(); auth_object = PoolObjectSQL::DATASTORE; auth_op = AuthRequest::ADMIN; }; ~DatastoreDelete(){}; /* -------------------------------------------------------------------- */ int get_cluster_id(PoolObjectSQL * object) { return static_cast(object)->get_cluster_id(); }; int del_from_cluster(Cluster* cluster, int id, string& error_msg) { return cluster->del_datastore(id, error_msg); }; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class ClusterDelete: public RequestManagerDelete { public: ClusterDelete(): RequestManagerDelete("ClusterDelete", "Deletes a cluster") { Nebula& nd = Nebula::instance(); pool = nd.get_clpool(); auth_object = PoolObjectSQL::CLUSTER; auth_op = AuthRequest::ADMIN; }; ~ClusterDelete(){}; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif opennebula-3.4.1/include/VirtualMachineManagerDriver.h0000644000175000017500000001437111750754334022740 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 VIRTUAL_MACHINE_MANAGER_DRIVER_H_ #define VIRTUAL_MACHINE_MANAGER_DRIVER_H_ #include #include #include #include "Mad.h" #include "VirtualMachinePool.h" using namespace std; /** * VirtualMachineManagerDriver provides a base class to implement VM Manager * Drivers. This class implements the protocol and recover functions * from the Mad interface. Classes derived from the VirtualMachineManagerDriver * must implement the deployment function to generate specific VM * deployment information for the unerlying MAD. */ class VirtualMachineManagerDriver : public Mad { public: VirtualMachineManagerDriver( int userid, const map& attrs, bool sudo, VirtualMachinePool * pool); virtual ~VirtualMachineManagerDriver(){}; /** * Implements the VM Manager driver protocol. * @param message the string read from the driver */ void protocol( string& message); /** * TODO: What do we need here? just poll the active VMs to recover * connections? Or an specific recover action from the MAD? */ void recover(); /** * Generates a driver-specific deployment file: * @param vm pointer to a virtual machine * @param file_name to generate the deployment description * @return 0 on success */ virtual int deployment_description( const VirtualMachine * vm, const string& file_name) const = 0; protected: /** * Gets a configuration attr from driver configuration file (single * version) * @param name of config attribute * @param value of the attribute */ void get_default( const char * name, string& value) const { string sn = name; driver_conf.get(sn,value); } /** * Gets a configuration attr from driver configuration file (vector * version) * @param name of config vector attribute for the domain * @param vname of the attribute * @param value of the attribute */ void get_default( const char * name, const char * vname, string& value) const; private: /** * Configuration file for the driver */ Template driver_conf; /** * Pointer to the Virtual Machine Pool, to access VMs */ VirtualMachinePool * vmpool; friend class VirtualMachineManager; /** * Sends a deploy request to the MAD: "DEPLOY ID XML_DRV_MSG" * @param oid the virtual machine id. * @param drv_msg xml data for the mad operation */ void deploy ( const int oid, const string& drv_msg) const; /** * Sends a shutdown request to the MAD: "SHUTDOWN ID XML_DRV_MSG" * @param oid the virtual machine id. * @param drv_msg xml data for the mad operation */ void shutdown ( const int oid, const string& drv_msg) const; /** * Sends a reboot request to the MAD: "REBOOT ID XML_DRV_MSG" * @param oid the virtual machine id. * @param drv_msg xml data for the mad operation */ void reboot ( const int oid, const string& drv_msg) const; /** * Sends a cancel request to the MAD: "CANCEL ID XML_DRV_MSG" * @param oid the virtual machine id. * @param drv_msg xml data for the mad operation */ void cancel ( const int oid, const string& drv_msg) const; /** * Sends a checkpoint request to the MAD: "CHECKPOINT ID XML_DRV_MSG" * @param oid the virtual machine id. * @param drv_msg xml data for the mad operation */ void checkpoint ( const int oid, const string& drv_msg) const; /** * Sends a save request to the MAD: "SAVE ID XML_DRV_MSG" * @param oid the virtual machine id. * @param drv_msg xml data for the mad operation */ void save ( const int oid, const string& drv_msg) const; /** * Sends a save request to the MAD: "RESTORE ID XML_DRV_MSG" * @param oid the virtual machine id. * @param drv_msg xml data for the mad operation */ void restore ( const int oid, const string& drv_msg) const; /** * Sends a migrate request to the MAD: "MIGRATE ID XML_DRV_MSG" * @param oid the virtual machine id. * @param drv_msg xml data for the mad operation */ void migrate ( const int oid, const string& drv_msg) const; /** * Sends a poll request to the MAD: "POLL ID XML_DRV_MSG" * @param oid the virtual machine id. * @param drv_msg xml data for the mad operation */ void poll ( const int oid, const string& drv_msg) const; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif /*VIRTUAL_MACHINE_MANAGER_DRIVER_H_*/ opennebula-3.4.1/include/VirtualNetwork.h0000644000175000017500000002731011750754334020353 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 VIRTUAL_NETWORK_H_ #define VIRTUAL_NETWORK_H_ #include "PoolSQL.h" #include "Leases.h" #include "VirtualNetworkTemplate.h" #include "Clusterable.h" #include #include #include #include #include using namespace std; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** * 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, public Clusterable { public: /** * Possible types of networks */ enum NetworkType { UNINITIALIZED = -1, RANGED = 0, FIXED = 1 }; // ************************************************************************* // Virtual Network Public Methods // ************************************************************************* /** * Factory method for virtual network templates */ Template * get_new_template() const { return new VirtualNetworkTemplate; } /** * Adds Leases to the virtual network (Only implemented for FIXED networks) * @param leases template in the form LEASES = [IP=XX, MAC=XX]. * MAC is optional. The template can only contain one LEASE * definition. * @param error_msg If the action fails, this message contains the reason. * @return 0 on success */ int add_leases(VirtualNetworkTemplate * leases, string& error_msg); /** * Removes Leases from the virtual network; if they are not used.(Only * implemented for FIXED networks) * @param leases template in the form LEASES = [IP=XX]. * The template can only contain one LEASE definition. * @param error_msg If the action fails, this message contains * the reason. * @return 0 on success */ int remove_leases(VirtualNetworkTemplate* leases, string& error_msg); /** * Holds a Lease, marking it as used * @param leases template in the form LEASES = [IP=XX]. * The template can only contain one LEASE definition. * @param error_msg If the action fails, this message contains the reason. * @return 0 on success */ int hold_leases(VirtualNetworkTemplate * leases, string& error_msg); /** * Releases a Lease on hold * @param leases template in the form LEASES = [IP=XX]. * The template can only contain one LEASE definition. * @param error_msg If the action fails, this message contains * the reason. * @return 0 on success */ int free_leases(VirtualNetworkTemplate* leases, string& error_msg); /** * Gets a new lease for a specific VM * @param vid VM identifier * @param _ip pointer to string for IP to be stored into * @param _mac pointer to string for MAC to be stored into * @param _bridge name of the physical bridge this VN binds to * @return 0 if success */ int get_lease(int vid, string& _ip, string& _mac, string& _bridge) { _bridge = bridge; return leases->get(vid,_ip,_mac); }; /** * Asks for an specific lease of the given virtual network * @param vid VM identifier * @param _ip the ip of the requested lease * @param _mac pointer to string for MAC to be stored into * @param _bridge name of the physical bridge this VN binds to * @return 0 if success */ int set_lease(int vid, const string& _ip, string& _mac, string& _bridge) { _bridge = bridge; return leases->set(vid,_ip,_mac); }; /** * Release previously given lease * @param _ip IP identifying the lease * @return 0 if success */ void release_lease(const string& ip) { return leases->release(ip); }; /** * Check if a VM is the owner of the ip * @param ip of the lease to be checked * @param vid the ID of the VM * @return true if the ip was already assigned */ bool is_owner (const string& ip, int vid) { return leases->is_owner(ip, vid); }; /** * Gets size of the network (used + free) * @return number of hosts that can be fitted in this network */ unsigned int get_size() { return leases->size; }; /** * Function to print the VirtualNetwork object into a string in * XML format * @param xml the resulting XML string * @return a reference to the generated string */ string& to_xml(string& xml) const; /** * Function to print the VirtualNetwork object into a string in * XML format. The extended XML includes the LEASES * @param xml the resulting XML string * @return a reference to the generated string */ string& to_xml_extended(string& xml) const; /** * Modifies the given nic attribute adding the following attributes: * * IP: leased from network * * MAC: leased from network * * BRIDGE: for this virtual network * @param nic attribute for the VM template * @param vid of the VM getting the lease * @return 0 on success */ int nic_attribute(VectorAttribute * nic, int vid); private: // ------------------------------------------------------------------------- // Friends // ------------------------------------------------------------------------- friend class VirtualNetworkPool; // ************************************************************************* // Virtual Network Private Attributes // ************************************************************************* // ------------------------------------------------------------------------- // Binded physical attributes // ------------------------------------------------------------------------- /** * Name of the bridge this VNW binds to */ string bridge; /** * Name of the physical device the bridge should be attached to */ string phydev; /** * VLAN ID of the NIC */ string vlan_id; /** * Whether or not to isolate this network with the vnm driver */ int vlan; // ------------------------------------------------------------------------- // Virtual Network Description // ------------------------------------------------------------------------- /** * Holds the type of this network */ NetworkType type; /** * Pointer to leases class, can be fixed or ranged. * Holds information on given (and, optionally, possible) leases */ Leases * leases; unsigned int ip_start; unsigned int ip_end; // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* /** * Execute an INSERT or REPLACE Sql query. * @param db The SQL DB * @param replace Execute an INSERT or a REPLACE * @param error_str Returns the error reason, if any * @return 0 on success */ int insert_replace(SqlDB *db, bool replace, string& error_str); /** * Bootstraps the database table(s) associated to the Virtual Network * @return 0 on success */ static int bootstrap(SqlDB * db) { int rc; ostringstream oss_vnet(VirtualNetwork::db_bootstrap); ostringstream oss_lease(Leases::db_bootstrap); rc = db->exec(oss_vnet); rc += db->exec(oss_lease); return rc; }; /** * Function to print the VirtualNetwork object into a string in * XML format * @param xml the resulting XML string * @param extended If true, leases are included * @return a reference to the generated string */ string& to_xml_extended(string& xml, bool extended) const; /** * 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); //************************************************************************** // Constructor //************************************************************************** VirtualNetwork(int uid, int gid, const string& _uname, const string& _gname, int _cluster_id, const string& _cluster_name, VirtualNetworkTemplate * _vn_template = 0); ~VirtualNetwork(); // ************************************************************************* // DataBase implementation // ************************************************************************* static const char * table; static const char * db_names; static const char * db_bootstrap; /** * Reads the Virtual Network (identified with its OID) from the database. * @param db pointer to the db * @return 0 on success */ int select(SqlDB * db); /** * Reads the Virtual Network (identified with its OID) from the database. * @param db pointer to the db * @param name of the network * @param uid of the owner * * @return 0 on success */ int select(SqlDB * db, const string& name, int uid); /** * Reads the Virtual Network leases from the database. * @param db pointer to the db * @return 0 on success */ int select_leases(SqlDB * db); /** * Writes the Virtual Network and its associated template and leases in the database. * @param db pointer to the db * @return 0 on success */ int insert(SqlDB * db, string& error_str); /** * Writes/updates the Virtual Network data fields in the database. * @param db pointer to the db * @return 0 on success */ int update(SqlDB * db) { string error_str; return insert_replace(db, true, error_str); } /** * Deletes a VNW from the database and all its associated information: * - VNW template * - given leases * @param db pointer to the db * @return 0 on success */ int drop(SqlDB * db); }; #endif /*VIRTUAL_NETWORK_H_*/ opennebula-3.4.1/include/UserTemplate.h0000644000175000017500000000325611750754334017770 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 USER_TEMPLATE_H_ #define USER_TEMPLATE_H_ #include "Template.h" using namespace std; /** * User Template class, it represents the attributes of an user */ class UserTemplate : public Template { public: UserTemplate() : Template(true,'=',"TEMPLATE"){}; ~UserTemplate(){}; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif /*IMAGE_TEMPLATE_H_*/ opennebula-3.4.1/include/RequestManagerUpdateTemplate.h0000644000175000017500000001326511750754334023141 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 REQUEST_MANAGER_UPDATE_TEMPLATE_H #define REQUEST_MANAGER_UPDATE_TEMPLATE_H #include "Request.h" #include "Nebula.h" using namespace std; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class RequestManagerUpdateTemplate: public Request { protected: RequestManagerUpdateTemplate(const string& method_name, const string& help) :Request(method_name,"A:sis",help) { auth_op = AuthRequest::MANAGE; }; ~RequestManagerUpdateTemplate(){}; /* -------------------------------------------------------------------- */ void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class TemplateUpdateTemplate: public RequestManagerUpdateTemplate { public: TemplateUpdateTemplate(): RequestManagerUpdateTemplate("TemplateUpdateTemplate", "Updates a virtual machine template") { Nebula& nd = Nebula::instance(); pool = nd.get_tpool(); auth_object = PoolObjectSQL::TEMPLATE; }; ~TemplateUpdateTemplate(){}; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class ImageUpdateTemplate: public RequestManagerUpdateTemplate { public: ImageUpdateTemplate(): RequestManagerUpdateTemplate("ImageUpdateTemplate", "Updates an image template") { Nebula& nd = Nebula::instance(); pool = nd.get_ipool(); auth_object = PoolObjectSQL::IMAGE; }; ~ImageUpdateTemplate(){}; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class HostUpdateTemplate : public RequestManagerUpdateTemplate { public: HostUpdateTemplate(): RequestManagerUpdateTemplate("HostUpdateTemplate", "Updates a host template") { Nebula& nd = Nebula::instance(); pool = nd.get_hpool(); auth_object = PoolObjectSQL::HOST; }; ~HostUpdateTemplate(){}; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class VirtualNetworkUpdateTemplate : public RequestManagerUpdateTemplate { public: VirtualNetworkUpdateTemplate(): RequestManagerUpdateTemplate("VirtualNetworkUpdateTemplate", "Updates a vnet template") { Nebula& nd = Nebula::instance(); pool = nd.get_vnpool(); auth_object = PoolObjectSQL::NET; }; ~VirtualNetworkUpdateTemplate(){}; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class UserUpdateTemplate : public RequestManagerUpdateTemplate { public: UserUpdateTemplate(): RequestManagerUpdateTemplate("UserUpdateTemplate", "Updates a user template") { Nebula& nd = Nebula::instance(); pool = nd.get_upool(); auth_object = PoolObjectSQL::USER; }; ~UserUpdateTemplate(){}; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class DatastoreUpdateTemplate : public RequestManagerUpdateTemplate { public: DatastoreUpdateTemplate(): RequestManagerUpdateTemplate("DatastoreUpdateTemplate", "Updates a datastore template") { Nebula& nd = Nebula::instance(); pool = nd.get_dspool(); auth_object = PoolObjectSQL::DATASTORE; }; ~DatastoreUpdateTemplate(){}; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif opennebula-3.4.1/include/User.h0000644000175000017500000002237511750754334016277 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 USER_H_ #define USER_H_ #include "PoolSQL.h" #include "UserTemplate.h" using namespace std; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** * The User class. */ class User : public PoolObjectSQL { public: /** * Characters that can not be in a name */ static const string INVALID_NAME_CHARS; /** * Characters that can not be in a password */ static const string INVALID_PASS_CHARS; /** * Function to print the User object into a string in XML format * @param xml the resulting XML string * @return a reference to the generated string */ string& to_xml(string& xml) const; /** * Check if the user is enabled * @return true if the user is enabled */ bool isEnabled() const { return enabled; } /** * Returns user password * @return the User's password */ const string& get_password() const { return password; }; /** * Enables the current user */ void enable() { enabled = true; }; /** * Disables the current user */ void disable() { enabled = false; invalidate_session(); }; /** * Checks if a name is valid, i.e. it is not empty and does not * contain invalid characters. * @param uname Name to be checked * @param error_str Returns the error reason, if any * @return true if the string is valid */ static bool name_is_valid(const string& uname, string& error_str); /** * Checks if a password is valid, i.e. it is not empty and does not * contain invalid characters. * @param pass Password to be checked * @param error_str Returns the error reason, if any * @return true if the string is valid */ static bool pass_is_valid(const string& pass, string& error_str); /** * Sets user password. It checks that the new password does not contain * forbidden chars. * @param _password the new pass * @param error_str Returns the error reason, if any * @returns -1 if the password is not valid */ int set_password(const string& passwd, string& error_str) { int rc = 0; if (pass_is_valid(passwd, error_str)) { password = passwd; invalidate_session(); } else { rc = -1; } return rc; }; /** * Returns user password * @return the user's auth driver */ const string& get_auth_driver() const { return auth_driver; }; /** * Sets the user auth driver. * * @param _auth_driver the new auth. driver * @param error_str Returns the error reason, if any * @return 0 on success, -1 otherwise */ int set_auth_driver(const string& _auth_driver, string& error_str) { auth_driver = _auth_driver; invalidate_session(); return 0; }; /** * Splits an authentication token (:) * @param secret, the authentication token * @param username * @param password * @return 0 on success **/ static int split_secret(const string secret, string& user, string& pass); /** * Factory method for image templates */ Template * get_new_template() const { return new UserTemplate; } private: // ------------------------------------------------------------------------- // Friends // ------------------------------------------------------------------------- friend class UserPool; // ------------------------------------------------------------------------- // User Attributes // ------------------------------------------------------------------------- /** * User's password */ string password; /** * Authentication driver for this user */ string auth_driver; /** * Flag marking user enabled/disabled */ bool enabled; // ************************************************************************* // Authentication session (Private) // ************************************************************************* /** * Until when the session_token is valid */ time_t session_expiration_time; /** * Last authentication token validated by the driver, can * be trusted until the session_expiration_time */ string session_token; /** * Checks if a session token is authorized and still valid * * @param token The authentication token * @return true if the token is still valid */ bool valid_session(const string& token) { return (( session_token == token ) && ( time(0) < session_expiration_time ) ); }; /** * Resets the authentication session */ void invalidate_session() { session_token.clear(); session_expiration_time = 0; }; /** * Stores the given session token for a limited time. This eliminates the * need to call the external authentication driver until the time expires. * * @param token The authenticated token * @param validity_time */ void set_session(const string& token, time_t validity_time) { session_token = token; session_expiration_time = time(0) + validity_time; }; // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* /** * Execute an INSERT or REPLACE Sql query. * @param db The SQL DB * @param replace Execute an INSERT or a REPLACE * @param error_str Returns the error reason, if any * @return 0 one success */ int insert_replace(SqlDB *db, bool replace, string& error_str); /** * Bootstraps the database table(s) associated to the User * @return 0 on success */ static int bootstrap(SqlDB * db) { ostringstream oss_user(User::db_bootstrap); return db->exec(oss_user); }; /** * 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 // ************************************************************************* User(int id, int _gid, const string& _uname, const string& _gname, const string& _password, const string& _auth_driver, bool _enabled): PoolObjectSQL(id,USER,_uname,-1,_gid,"",_gname,table), password(_password), auth_driver(_auth_driver), enabled(_enabled), session_expiration_time(0), session_token("") { obj_template = new UserTemplate; }; virtual ~User() { if (obj_template != 0) { delete obj_template; } }; // ************************************************************************* // DataBase implementation // ************************************************************************* static const char * db_names; static const char * db_bootstrap; static const char * table; /** * Writes the User in the database. * @param db pointer to the db * @return 0 on success */ int insert(SqlDB *db, string& error_str) { return insert_replace(db, false, error_str); }; /** * Writes/updates the User data fields in the database. * @param db pointer to the db * @return 0 on success */ int update(SqlDB *db) { string error_str; return insert_replace(db, true, error_str); } }; #endif /*USER_H_*/ opennebula-3.4.1/include/TransferManagerDriver.h0000644000175000017500000000537611750754334021616 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 TRANSFER_MANAGER_DRIVER_H_ #define TRANSFER_MANAGER_DRIVER_H_ #include #include #include #include "Mad.h" #include "VirtualMachinePool.h" using namespace std; /** * TransferManagerDriver provides a base class to implement TM * Drivers. This class implements the protocol and recover functions * from the Mad interface. */ class TransferManagerDriver : public Mad { public: TransferManagerDriver( int userid, const map& attrs, bool sudo, VirtualMachinePool * pool): Mad(userid,attrs,sudo), vmpool(pool){}; virtual ~TransferManagerDriver(){}; /** * Implements the VM 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 TransferManager; /** * Pointer to the Virtual Machine Pool, to access VMs */ VirtualMachinePool * vmpool; /** * Sends a transfer request to the MAD: "TRANSFER ID XFR_FILE" * @param oid the virtual machine id. * @param xfr_file is the path to the transfer script */ void transfer (const int oid, const string& xfr_file) const; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif /*TRANSFER_MANAGER_DRIVER_H_*/ opennebula-3.4.1/include/DatastorePool.h0000644000175000017500000001402611750754334020133 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 DATASTORE_POOL_H_ #define DATASTORE_POOL_H_ #include "Datastore.h" #include "SqlDB.h" using namespace std; class DatastorePool : public PoolSQL { public: DatastorePool(SqlDB * db); ~DatastorePool(){}; /* ---------------------------------------------------------------------- */ /* Constants for DB management */ /* ---------------------------------------------------------------------- */ /** * Name for the system datastore */ static const string SYSTEM_DS_NAME; /** * Identifier for the system datastore */ static const int SYSTEM_DS_ID; /** * Name for the default datastore */ static const string DEFAULT_DS_NAME; /** * Identifier for the default datastore */ static const int DEFAULT_DS_ID; /* ---------------------------------------------------------------------- */ /* Methods for DB management */ /* ---------------------------------------------------------------------- */ /** * Allocates a new Datastore, writing it in the pool database. No memory is * allocated for the object. * @param uid the user id of the Datastore owner * @param gid the id of the group this object is assigned to * @param uname name of the user * @param gname name of the group * @param ds_template Datastore definition template * @param oid the id assigned to the Datastore * @param cluster_id the id of the cluster this Datastore will belong to * @param cluster_name the name of the cluster this Datastore will belong to * @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, int gid, const string& uname, const string& gname, DatastoreTemplate * ds_template, int * oid, int cluster_id, const string& cluster_name, string& error_str); /** * Function to get a Datastore from the pool, if the object is not in memory * it is loaded from the DB * @param oid Datastore unique id * @param lock locks the Datastore mutex * @return a pointer to the Datastore, 0 if the Datastore could not be loaded */ Datastore * 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 lock locks the object if true * * @return a pointer to the object, 0 in case of failure */ Datastore * get(const string& name, bool lock) { // The owner is set to -1, because it is not used in the key() method return static_cast(PoolSQL::get(name,-1,lock)); }; /** * Generate an index key for the object * @param name of the object * @param uid owner of the object, only used if needed * * @return the key, a string */ string key(const string& name, int uid) { // Name is enough key because Datastores can't repeat names. return name; }; /** Update a particular Datastore * @param user pointer to Datastore * @return 0 on success */ int update(Datastore * datastore) { return datastore->update(db); }; /** * Drops the Datastore data in the data base. The object mutex SHOULD be * locked. * @param objsql a pointer to the Datastore object * @param error_msg Error reason, if any * @return 0 on success, -1 DB error * -3 Datastore's Image IDs set is not empty */ int drop(PoolObjectSQL * objsql, string& error_msg); /** * Bootstraps the database table(s) associated to the Datastore pool * @return 0 on success */ static int bootstrap(SqlDB * _db) { return Datastore::bootstrap(_db); }; /** * Dumps the Datastore 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, "DATASTORE_POOL", Datastore::table, where); }; private: /** * Factory method to produce objects * @return a pointer to the new object */ PoolObjectSQL * create() { return new Datastore(-1,-1,"","", 0, -1, ""); }; }; #endif /*DATASTORE_POOL_H_*/ opennebula-3.4.1/include/Nebula.h0000644000175000017500000003166211750754334016566 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ #ifndef NEBULA_H_ #define NEBULA_H_ #include "SqlDB.h" #include "NebulaTemplate.h" #include "VirtualMachinePool.h" #include "VirtualNetworkPool.h" #include "HostPool.h" #include "UserPool.h" #include "VMTemplatePool.h" #include "GroupPool.h" #include "DatastorePool.h" #include "ClusterPool.h" #include "VirtualMachineManager.h" #include "LifeCycleManager.h" #include "InformationManager.h" #include "TransferManager.h" #include "DispatchManager.h" #include "RequestManager.h" #include "HookManager.h" #include "AuthManager.h" #include "AclManager.h" #include "ImageManager.h" #include "Callbackable.h" class Nebula : public Callbackable { public: static Nebula& instance() { static Nebula nebulad; return nebulad; }; // -------------------------------------------------------------- // Pool Accessors // -------------------------------------------------------------- VirtualMachinePool * get_vmpool() { return vmpool; }; HostPool * get_hpool() { return hpool; }; VirtualNetworkPool * get_vnpool() { return vnpool; }; UserPool * get_upool() { return upool; }; ImagePool * get_ipool() { return ipool; }; GroupPool * get_gpool() { return gpool; }; VMTemplatePool * get_tpool() { return tpool; }; DatastorePool * get_dspool() { return dspool; }; ClusterPool * get_clpool() { return clpool; }; // -------------------------------------------------------------- // Manager Accessors // -------------------------------------------------------------- VirtualMachineManager * get_vmm() { return vmm; }; LifeCycleManager * get_lcm() { return lcm; }; InformationManager * get_im() { return im; }; TransferManager * get_tm() { return tm; }; DispatchManager * get_dm() { return dm; }; HookManager * get_hm() { return hm; }; AuthManager * get_authm() { return authm; }; ImageManager * get_imagem() { return imagem; }; AclManager * get_aclm() { return aclm; }; // -------------------------------------------------------------- // Environment & Configuration // -------------------------------------------------------------- /** * Returns the value of DEBUG_LEVEL in oned.conf file * @return the debug level, to instantiate Log'ers */ Log::MessageType get_debug_level() const { Log::MessageType clevel = Log::ERROR; int log_level_int; nebula_configuration->get("DEBUG_LEVEL", log_level_int); if (0 <= log_level_int && log_level_int <= 3 ) { clevel = static_cast(log_level_int); } return clevel; } /** * Returns the value of ONE_LOCATION env variable. When this variable is * not defined the nebula location is "/". * @return the nebula location. */ const string& get_nebula_location() { return nebula_location; }; /** * Returns the path where mad executables are stored, if ONE_LOCATION is * defined this path points to $ONE_LOCATION/bin, otherwise it is * /usr/lib/one/mads. * @return the mad execs location. */ const string& get_mad_location() { return mad_location; }; /** * Returns the path where defaults for mads are stored, if ONE_LOCATION is * defined this path points to $ONE_LOCATION/etc, otherwise it is /etc/one * @return the mad defaults location. */ const string& get_defaults_location() { return etc_location; }; /** * Returns the path where logs (oned.log, schedd.log,...) are generated * if ONE_LOCATION is defined this path points to $ONE_LOCATION/var, * otherwise it is /var/log/one. * @return the log location. */ const string& get_log_location() { return log_location; }; /** * Returns the default var location. When ONE_LOCATION is defined this path * points to $ONE_LOCATION/var, otherwise it is /var/lib/one. * @return the log location. */ const string& get_var_location() { return var_location; }; /** * Returns the default var location. When ONE_LOCATION is defined this path * points to $ONE_LOCATION/var, otherwise it is /var/lib/one. * @return the log location. */ const string& get_ds_location() { return ds_location; }; /** * Returns the Transfer Manager for the system datastore * @return the tm name. */ string get_system_ds_tm_mad() { Datastore * ds; string tm_mad = ""; ds = dspool->get(DatastorePool::SYSTEM_DS_ID, true); if ( ds == 0 ) { NebulaLog::log("DaS", Log::ERROR, "Can not get system datastore"); return tm_mad; } tm_mad = ds->get_tm_mad(); ds->unlock(); return tm_mad; }; /** * Returns the path of the log file for a VM, depending where OpenNebula is * installed, * $ONE_LOCATION/var/$VM_ID/vm.log * or * /var/log/one/$VM_ID.log * @return the log location for the VM. */ string get_vm_log_filename(int oid) { ostringstream oss; if (nebula_location == "/") { oss << log_location << oid << ".log"; } else { oss << nebula_location << "var/" << oid << "/vm.log"; } return oss.str(); }; const string& get_nebula_hostname() { return hostname; }; static string version() { return "OpenNebula 3.4.1"; }; static string db_version() { return "3.4.1"; } void start(); void get_configuration_attribute( const char * name, string& value) const { string _name(name); nebula_configuration->Template::get(_name,value); }; private: // ----------------------------------------------------------------------- //Constructors and = are private to only access the class through instance // ----------------------------------------------------------------------- Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0), upool(0),ipool(0),gpool(0),tpool(0),dspool(0),clpool(0), lcm(0),vmm(0),im(0),tm(0),dm(0),rm(0),hm(0),authm(0),aclm(0),imagem(0) { const char * nl = getenv("ONE_LOCATION"); if (nl == 0) //OpenNebula installed under root directory { nebula_location = "/"; mad_location = "/usr/lib/one/mads/"; etc_location = "/etc/one/"; log_location = "/var/log/one/"; var_location = "/var/lib/one/"; remotes_location = "/var/lib/one/remotes/"; ds_location = "/var/lib/one/datastores/"; } else { nebula_location = nl; if ( nebula_location.at(nebula_location.size()-1) != '/' ) { nebula_location += "/"; } mad_location = nebula_location + "lib/mads/"; etc_location = nebula_location + "etc/"; log_location = nebula_location + "var/"; var_location = nebula_location + "var/"; remotes_location = nebula_location + "var/remotes/"; ds_location = nebula_location + "var/datastores/"; } }; ~Nebula() { if ( vmpool != 0) { delete vmpool; } if ( vnpool != 0) { delete vnpool; } if ( hpool != 0) { delete hpool; } if ( upool != 0) { delete upool; } if ( ipool != 0) { delete ipool; } if ( gpool != 0) { delete gpool; } if ( tpool != 0) { delete tpool; } if ( dspool != 0) { delete dspool; } if ( clpool != 0) { delete clpool; } if ( vmm != 0) { delete vmm; } if ( lcm != 0) { delete lcm; } if ( im != 0) { delete im; } if ( tm != 0) { delete tm; } if ( dm != 0) { delete dm; } if ( rm != 0) { delete rm; } if ( hm != 0) { delete hm; } if ( authm != 0) { delete authm; } if ( aclm != 0) { delete aclm; } if ( imagem != 0) { delete imagem; } if ( nebula_configuration != 0) { delete nebula_configuration; } if ( db != 0 ) { delete db; } }; Nebula(Nebula const&){}; Nebula& operator=(Nebula const&){return *this;}; // --------------------------------------------------------------- // Environment variables // --------------------------------------------------------------- string nebula_location; string mad_location; string etc_location; string log_location; string var_location; string hook_location; string remotes_location; string ds_location; string hostname; // --------------------------------------------------------------- // Configuration // --------------------------------------------------------------- OpenNebulaTemplate * nebula_configuration; // --------------------------------------------------------------- // Nebula Pools // --------------------------------------------------------------- SqlDB * db; VirtualMachinePool * vmpool; HostPool * hpool; VirtualNetworkPool * vnpool; UserPool * upool; ImagePool * ipool; GroupPool * gpool; VMTemplatePool * tpool; DatastorePool * dspool; ClusterPool * clpool; // --------------------------------------------------------------- // Nebula Managers // --------------------------------------------------------------- LifeCycleManager * lcm; VirtualMachineManager * vmm; InformationManager * im; TransferManager * tm; DispatchManager * dm; RequestManager * rm; HookManager * hm; AuthManager * authm; AclManager * aclm; ImageManager * imagem; // --------------------------------------------------------------- // Implementation functions // --------------------------------------------------------------- friend void nebula_signal_handler (int sig); /** * Bootstraps the database control tables * * @return 0 on success */ int bootstrap(); /** * Callback function for the check_db_version method. Stores the read * version in loaded_db_version * @param _loaded_db_version returned columns * @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 *_loaded_db_version, int num, char **values, char **names); /** * Reads the current DB version. * * @return 0 on success, * -1 if there is a version mismatch, * -2 if the DB needs a bootstrap */ int check_db_version(); }; #endif /*NEBULA_H_*/ opennebula-3.4.1/include/MySqlDB.h0000644000175000017500000000721211750754334016625 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ #ifndef MYSQL_DB_H_ #define MYSQL_DB_H_ #include #include #include #include #include #include #include "NebulaLog.h" #include "SqlDB.h" #include "ObjectSQL.h" using namespace std; #ifdef MYSQL_DB #include /** * SqliteDB class. Provides a wrapper to the mysql database interface. */ class MySqlDB : public SqlDB { public: MySqlDB(const string& _server, int _port, const string& _user, const string& _password, const string& _database); ~MySqlDB(); /** * Wraps the mysql_query function call * @param cmd the SQL command * @param obj Callbackable obj to call if the query succeeds * @return 0 on success */ int exec(ostringstream& cmd, Callbackable* obj=0); /** * This function returns a legal SQL string that can be used in an SQL * statement. The string is encoded to an escaped SQL string, taking into * account the current character set of the connection. * @param str the string to be escaped * @return a valid SQL string or NULL in case of failure */ char * escape_str(const string& str); /** * Frees a previously scaped string * @param str pointer to the str */ void free_str(char * str); private: /** * The MySql connection handler */ MYSQL * db; /** * MySQL Connection parameters */ string server; int port; string user; string password; string database; /** * Fine-grain mutex for DB access */ pthread_mutex_t mutex; /** * Function to lock the DB */ void lock() { pthread_mutex_lock(&mutex); }; /** * Function to unlock the DB */ void unlock() { pthread_mutex_unlock(&mutex); }; }; #else //CLass stub class MySqlDB : public SqlDB { public: MySqlDB( string server, int port, string user, string password, string database) { throw runtime_error("Aborting oned, MySQL support not compiled!"); }; ~MySqlDB(){}; int exec(ostringstream& cmd, Callbackable* obj=0){return -1;}; char * escape_str(const string& str){return 0;}; void free_str(char * str){}; }; #endif #endif /*MYSQL_DB_H_*/ opennebula-3.4.1/include/RequestManagerImage.h0000644000175000017500000000776011750754334021250 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 REQUEST_MANAGER_IMAGE_H #define REQUEST_MANAGER_IMAGE_H #include "Request.h" #include "Nebula.h" using namespace std; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class RequestManagerImage: public Request { protected: RequestManagerImage(const string& method_name, const string& help, const string& params) :Request(method_name,params,help) { Nebula& nd = Nebula::instance(); pool = nd.get_ipool(); auth_object = PoolObjectSQL::IMAGE; auth_op = AuthRequest::MANAGE; }; ~RequestManagerImage(){}; /* --------------------------------------------------------------------- */ virtual void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att) = 0; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class ImageEnable : public RequestManagerImage { public: ImageEnable(): RequestManagerImage("ImageEnable", "Enables or disables an image", "A:sib"){}; ~ImageEnable(){}; void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class ImagePersistent : public RequestManagerImage { public: ImagePersistent(): RequestManagerImage("ImagePersistent", "Makes an image persistent or non-persistent", "A:sib"){}; ~ImagePersistent(){}; void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class ImageChangeType : public RequestManagerImage { public: ImageChangeType(): RequestManagerImage("ImageChangeType", "Changes the type of an image", "A:sis"){}; ~ImageChangeType(){}; void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif opennebula-3.4.1/include/ImagePool.h0000644000175000017500000001514511750754334017232 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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_POOL_H_ #define IMAGE_POOL_H_ #include "PoolSQL.h" #include "Image.h" #include "NebulaLog.h" #include #include #include #include class AuthRequest; using namespace std; /** * The Image Pool class. */ class ImagePool : public PoolSQL { public: ImagePool(SqlDB * db, const string& _default_type, const string& _default_dev_prefix, vector& restricted_attrs); ~ImagePool(){}; /** * Function to allocate a new Image object * @param uid the user id of the image's owner * @param gid the id of the group this object is assigned to * @param uname name of the user * @param gname name of the group * @param img_template template associated with the image * @param ds_id the id of the datastore * @param ds_name the name of the datastore * @param ds_data the datastore data * @param oid the id assigned to the Image * @param error_str Returns the error reason, if any * @return the oid assigned to the object, * -1 in case of failure * -2 in case of template parse failure */ int allocate ( int uid, int gid, const string& uname, const string& gname, ImageTemplate * img_template, int ds_id, const string& ds_name, const string& ds_data, int * oid, string& error_str); /** ** Function to get a Image from the pool, if the object is not in memory * it is loaded from the DB * @param oid Image unique id * @param lock locks the Image mutex * @return a pointer to the Image, 0 if the Image could not be loaded */ Image * 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 */ Image * get(const string& name, int uid, bool lock) { return static_cast(PoolSQL::get(name,uid,lock)); }; /** * Update a particular Image * @param image pointer to Image * @return 0 on success */ int update(Image * image) { return image->update(db); }; /** * Bootstraps the database table(s) associated to the Image pool * @return 0 on success */ static int bootstrap(SqlDB *_db) { return Image::bootstrap(_db); }; /** * Dumps the Image 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, "IMAGE_POOL", Image::table, where); } /** * Generates a DISK attribute for VM templates using the Image metadata * @param disk the disk to be generated * @param disk_id the id for this disk * @param index number of datablock images used by the same VM. Will be * automatically increased. * @param img_type will be set to the used image's type * @param uid of VM owner (to look for the image id within its images) * @param image_id on success returns the acquired image id * @param error_str string describing the error * @return 0 on success, * -1 error, * -2 not using the pool, */ int disk_attribute(VectorAttribute * disk, int disk_id, int * index, Image::ImageType * img_type, int uid, int& image_id, string& error_str); /** * Generates an Authorization token for the DISK attribute * @param disk the disk to be authorized * @param uid of owner (to look for the image id within her images) * @param ar the AuthRequest */ void authorize_disk(VectorAttribute * disk, int uid, AuthRequest * ar); static const string& default_type() { return _default_type; }; static const string& default_dev_prefix() { return _default_dev_prefix; }; private: //-------------------------------------------------------------------------- // Configuration Attributes for Images // ------------------------------------------------------------------------- /** * Default image type **/ static string _default_type; /** * Default device prefix **/ static string _default_dev_prefix; //-------------------------------------------------------------------------- // Pool Attributes // ------------------------------------------------------------------------- /** * Factory method to produce Image objects * @return a pointer to the new Image */ PoolObjectSQL * create() { return new Image(-1,-1,"","",0); }; }; #endif /*IMAGE_POOL_H_*/ opennebula-3.4.1/include/Clusterable.h0000644000175000017500000000436411750754334017624 0ustar drazzibdrazzib/* ------------------------------------------------------------------------ */ /* Copyright 2002-2012, 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 CLUSTERABLE_H_ #define CLUSTERABLE_H_ using namespace std; class Clusterable { public: /** * Changes the cluster this object belongs to * * @param _cluster_id Id of the new cluster * @param _cluster Name of the new cluster */ void set_cluster(int _cluster_id, const string& _cluster) { cluster_id = _cluster_id; cluster = _cluster; }; /** * Returns the cluster ID * * @return The cluster ID */ int get_cluster_id() const { return cluster_id; }; /** * Returns the cluster name * * @return The cluster name */ const string& get_cluster_name() const { return cluster; }; protected: Clusterable(int _cluster_id, const string& _cluster): cluster_id(_cluster_id), cluster(_cluster){}; ~Clusterable(){}; /** * ID of the cluster this object belongs to. */ int cluster_id; /** * Name of the cluster this object belongs to. */ string cluster; }; #endif /*CLUSTERABLE_H_*/ opennebula-3.4.1/include/RequestManagerChmod.h0000644000175000017500000001165611750754334021257 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 REQUEST_MANAGER_CHMOD_H_ #define REQUEST_MANAGER_CHMOD_H_ #include "Request.h" #include "Nebula.h" using namespace std; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class RequestManagerChmod : public Request { protected: RequestManagerChmod(const string& method_name, const string& help, const string& params = "A:siiiiiiiiii") :Request(method_name,params,help){}; ~RequestManagerChmod(){}; /* -------------------------------------------------------------------- */ virtual void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class VirtualMachineChmod : public RequestManagerChmod { public: VirtualMachineChmod(): RequestManagerChmod("VirtualMachineChmod", "Changes permission bits of a virtual machine") { Nebula& nd = Nebula::instance(); pool = nd.get_vmpool(); auth_object = PoolObjectSQL::VM; }; ~VirtualMachineChmod(){}; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class TemplateChmod : public RequestManagerChmod { public: TemplateChmod(): RequestManagerChmod("TemplateChmod", "Changes permission bits of a virtual machine template") { Nebula& nd = Nebula::instance(); pool = nd.get_tpool(); auth_object = PoolObjectSQL::TEMPLATE; }; ~TemplateChmod(){}; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class VirtualNetworkChmod: public RequestManagerChmod { public: VirtualNetworkChmod(): RequestManagerChmod("VirtualNetworkChmod", "Changes permission bits of a virtual network") { Nebula& nd = Nebula::instance(); pool = nd.get_vnpool(); auth_object = PoolObjectSQL::NET; }; ~VirtualNetworkChmod(){}; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class ImageChmod: public RequestManagerChmod { public: ImageChmod(): RequestManagerChmod("ImageChmod", "Changes permission bits of an image") { Nebula& nd = Nebula::instance(); pool = nd.get_ipool(); auth_object = PoolObjectSQL::IMAGE; }; ~ImageChmod(){}; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class DatastoreChmod: public RequestManagerChmod { public: DatastoreChmod(): RequestManagerChmod("DatastoreChmod", "Changes permission bits of a datastore") { Nebula& nd = Nebula::instance(); pool = nd.get_dspool(); auth_object = PoolObjectSQL::DATASTORE; }; ~DatastoreChmod(){}; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif opennebula-3.4.1/include/DispatchManager.h0000644000175000017500000002056611750754334020413 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 DISPATCH_MANAGER_H_ #define DISPATCH_MANAGER_H_ #include "ActionManager.h" #include "HostPool.h" #include "VirtualMachinePool.h" using namespace std; extern "C" void * dm_action_loop(void *arg); class DispatchManager : public ActionListener { public: DispatchManager( VirtualMachinePool * _vmpool, HostPool * _hpool): hpool(_hpool), vmpool(_vmpool) { am.addListener(this); }; ~DispatchManager() {} ; enum Actions { SUSPEND_SUCCESS,/**< Send by LCM when a VM is suspended*/ STOP_SUCCESS, /**< Send by LCM when a VM is stopped*/ DONE, /**< Send by LCM when a VM is shut down*/ FAILED, /**< Send by LCM when one of the execution steps fails*/ RESUBMIT, /**< Send by LCM when a VM is ready for resubmission*/ FINALIZE }; /** * Triggers specific actions to the Dispatch Manager. This function * wraps the ActionManager trigger function. * @param action the DM action * @param vid VM unique id. This is the argument of the passed to the * invoked action. */ void trigger( Actions action, int _vid); /** * This functions creates a new thread for the Dispatch Manager. This * thread will wait in an action loop till it receives ACTION_FINALIZE. * @return 0 on success. */ int start(); /** * Gets the thread identification. * @return pthread_t for the manager thread (that in the action loop). */ pthread_t get_thread_id() const { return dm_thread; }; //-------------------------------------------------------------------------- // DM Actions, the RM and the Scheduler will invoke this methods //-------------------------------------------------------------------------- /** * Deploys a VM. A new history record MUST be added before calling this * function. Also the VM MUST have its mutex locked. If the function fails * the calling funtion is responsible for recovering from the error. * @param vm pointer to a VirtualMachine with its mutex locked. * @return 0 on success */ int deploy ( VirtualMachine * vm); /** * Migrates a VM. The following actions must be performed before calling * this function: * - Lock the VM mutex. * - Update the History statistics of the current host. * - Add a new History record with the new host. * If the function fails the calling funtion is responsible for recovering * from the error. * @param vm pointer to a VirtualMachine with its mutex locked. * @return 0 on success */ int migrate( VirtualMachine * vm); /** * Migrates a VM. The following actions must be performed before calling * this function: * - Lock the VM mutex. * - Update the History statistics of the current host. * - Add a new History record with the new host. * If the function fails the calling funtion is responsible for recovering * from the error. * @param vm pointer to a VirtualMachine with its mutex locked. * @return 0 on success */ int live_migrate( VirtualMachine * vm); /** * Shuts down a VM. * @param vid VirtualMachine identification * @return 0 on success, -1 if the VM does not exits or -2 if the VM is * in a wrong a state */ int shutdown ( int vid); /** * Holds a VM. * @param vid VirtualMachine identification * @return 0 on success, -1 if the VM does not exits or -2 if the VM is * in a wrong a state */ int hold( int vid); /** * Releases a VM. * @param vid VirtualMachine identification * @return 0 on success, -1 if the VM does not exits or -2 if the VM is * in a wrong a state */ int release( int vid); /** * Stops a VM. * @param vid VirtualMachine identification * @return 0 on success, -1 if the VM does not exits or -2 if the VM is * in a wrong a state */ int stop( int vid); /** * Cancels a VM. * @param vid VirtualMachine identification * @return 0 on success, -1 if the VM does not exits or -2 if the VM is * in a wrong a state */ int cancel( int vid); /** * Suspends a VM. * @param vid VirtualMachine identification * @return 0 on success, -1 if the VM does not exits or -2 if the VM is * in a wrong a state */ int suspend( int vid); /** * Resumes a VM. * @param vid VirtualMachine identification * @return 0 on success, -1 if the VM does not exits or -2 if the VM is * in a wrong a state */ int resume( int vid); /** * Restart a previusly deployed VM. * @param vid VirtualMachine identification * @return 0 on success, -1 if the VM does not exits or -2 if the VM is * in a wrong a state */ int restart( int vid); /** * Ends a VM life cycle inside ONE. * @param vid VirtualMachine identification * @return 0 on success, -1 if the VM does not exits or -2 if the VM is * in a wrong a state */ int finalize( int vid); /** * Moves a VM to PENDING state preserving any resource (i.e. leases) and id * @param vid VirtualMachine identification * @return 0 on success, -1 if the VM does not exits or -2 if the VM is * in a wrong a state */ int resubmit( int vid); /** * Reboots a VM preserving any resource and RUNNING state * @param vid VirtualMachine identification * @return 0 on success, -1 if the VM does not exits or -2 if the VM is * in a wrong a state */ int reboot( int vid); private: /** * Thread id for the Dispatch Manager */ pthread_t dm_thread; /** * Pointer to the Host Pool, to access hosts */ HostPool * hpool; /** * Pointer to the Virtual Machine Pool, to access hosts */ VirtualMachinePool * vmpool; /** * Action engine for the Manager */ ActionManager am; /** * Function to execute the Manager action loop method within a new pthread * (requires C linkage) */ friend void * dm_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); //-------------------------------------------------------------------------- // DM Actions associated with a VM state transition //-------------------------------------------------------------------------- void suspend_success_action(int vid); void stop_success_action(int vid); void done_action(int vid); void failed_action(int vid); void resubmit_action(int vid); }; #endif /*DISPATCH_MANAGER_H*/ opennebula-3.4.1/include/VirtualNetworkTemplate.h0000644000175000017500000000337211750754334022051 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 VIRTUAL_NETWORK_TEMPLATE_H_ #define VIRTUAL_NETWORK_TEMPLATE_H_ #include "Template.h" using namespace std; /** * Virtual Network Template class, it represents a VN configuration file. */ class VirtualNetworkTemplate : public Template { public: VirtualNetworkTemplate(): Template(false,'=',"TEMPLATE"){}; ~VirtualNetworkTemplate(){}; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif /*VIRTUAL_NETWORK_TEMPLATE_H_*/ opennebula-3.4.1/include/HostShare.h0000644000175000017500000001065211750754334017254 0ustar drazzibdrazzib/* ------------------------------------------------------------------------ */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* ------------------------------------------------------------------------ */ #ifndef HOST_SHARE_H_ #define HOST_SHARE_H_ #include "ObjectXML.h" #include using namespace std; /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ /** * The HostShare class. It represents a logical partition of a host... */ class HostShare : public ObjectXML { public: HostShare( int _max_disk=0, int _max_mem=0, int _max_cpu=0); ~HostShare(){}; /** * Add a new VM to this share * @param cpu requested by the VM * @param mem requested by the VM * @param disk requested by the VM */ void add(int cpu, int mem, int disk) { cpu_usage += cpu; mem_usage += mem; disk_usage += disk; running_vms++; } /** * Delete a VM from this share * @param cpu requested by the VM * @param mem requested by the VM * @param disk requested by the VM */ void del(int cpu, int mem, int disk) { cpu_usage -= cpu; mem_usage -= mem; disk_usage -= disk; running_vms--; } /** * Check if this share can host a VM. * @param cpu requested by the VM * @param mem requested by the VM * @param disk requested by the VM * * @return true if the share can host the VM or it is the only one * configured */ bool test(int cpu, int mem, int disk) const { return (((max_cpu - cpu_usage ) >= cpu) && ((max_mem - mem_usage ) >= mem) && ((max_disk - disk_usage) >= disk)); } /** * Function to write a HostShare to an output stream */ friend ostream& operator<<(ostream& os, HostShare& hs); /** * Function to print the HostShare 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; private: int disk_usage; /**< Disk allocated to VMs (in Mb). */ int mem_usage; /**< Memory allocated to VMs (in Mb) */ int cpu_usage; /**< CPU allocated to VMs (in percentage) */ int max_disk; /**< Total disk capacity (in Mb) */ int max_mem; /**< Total memory capacity (in Mb) */ int max_cpu; /**< Total cpu capacity (in percentage) */ int free_disk; /**< Free disk from the IM monitor */ int free_mem; /**< Free memory from the IM monitor */ int free_cpu; /**< Free cpu from the IM monitor */ int used_disk; /**< Used disk from the IM monitor */ int used_mem; /**< Used memory from the IM monitor */ int used_cpu; /**< Used cpu from the IM monitor */ int running_vms;/**< Number of running VMs in this Host */ // ---------------------------------------- // Friends // ---------------------------------------- friend class Host; friend class HostPool; /** * Rebuilds the object from an xml node * @param node The xml node pointer * * @return 0 on success, -1 otherwise */ int from_xml_node(const xmlNodePtr node); }; #endif /*HOST_SHARE_H_*/ opennebula-3.4.1/include/RequestManagerAcl.h0000644000175000017500000001002111750754334020705 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 REQUEST_MANAGER_ACL_H #define REQUEST_MANAGER_ACL_H #include "Request.h" #include "Nebula.h" using namespace std; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class RequestManagerAcl: public Request { protected: RequestManagerAcl( const string& method_name, const string& help, const string& params) :Request(method_name,params,help) { auth_object = PoolObjectSQL::ACL; auth_op = AuthRequest::MANAGE; Nebula& nd = Nebula::instance(); aclm = nd.get_aclm(); }; ~RequestManagerAcl(){}; /* -------------------------------------------------------------------- */ virtual void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att) = 0; /* -------------------------------------------------------------------- */ AclManager * aclm; }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class AclAddRule : public RequestManagerAcl { public: AclAddRule(): RequestManagerAcl("AclAddRule", "Adds a new ACL rule", "A:ssss") {}; ~AclAddRule(){}; void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class AclDelRule : public RequestManagerAcl { public: AclDelRule(): RequestManagerAcl("AclDelRule", "Deletes an existing ACL rule", "A:si") {}; ~AclDelRule(){}; void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ class AclInfo: public RequestManagerAcl { public: AclInfo(): RequestManagerAcl("AclInfo", "Returns the ACL rule set", "A:s") {}; ~AclInfo(){}; void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif opennebula-3.4.1/include/SSLTools.h0000644000175000017500000000350611750754334017036 0ustar drazzibdrazzib/* ------------------------------------------------------------------------ */ /* Copyright 2002-2012, 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 SSL_TOOLS_H_ #define SSL_TOOLS_H_ #include using namespace std; /** * The SSLTools class provides a simple interface to common SSL utils used * in OpenNebula */ class SSLTools { public: /** * sha1 digest * @param in the string to be hashed * @return sha1 hash of str */ static string sha1_digest(const string& in); /** * Base 64 encoding * @param in the string to encoded * @return a pointer to the encoded string (must be freed) or 0 in case of * error */ static string * base64_encode(const string& in); private: SSLTools(){}; ~SSLTools(){}; }; #endif /*SSL_TOOLS_H_*/ opennebula-3.4.1/include/VMTemplate.h0000644000175000017500000001206011750754334017365 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 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; // ------------------------------------------------------------------------ // Template Contents // ------------------------------------------------------------------------ /** * Factory method for virtual machine templates */ Template * get_new_template() const { return new VirtualMachineTemplate; } /** * Returns a copy of the VirtualMachineTemplate * @return A copy of the VirtualMachineTemplate */ VirtualMachineTemplate * clone_template() const { return new VirtualMachineTemplate( *(static_cast(obj_template))); }; private: // ------------------------------------------------------------------------- // Friends // ------------------------------------------------------------------------- friend class VMTemplatePool; // ------------------------------------------------------------------------- // VMTemplate Attributes // ------------------------------------------------------------------------- /** * 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 * @param error_str Returns the error reason, if any * @return 0 one success */ int insert_replace(SqlDB *db, bool replace, string& error_str); /** * Bootstraps the database table(s) associated to the VMTemplate * @return 0 on success */ static int bootstrap(SqlDB * db) { ostringstream oss(VMTemplate::db_bootstrap); return 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, int gid, const string& uname, const string& gname, 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 * @param error_str Returns the error reason, if any * @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) { string err; return insert_replace(db, true, err); }; }; #endif /*VMTEMPLATE_H_*/ opennebula-3.4.1/include/LibVirtDriver.h0000644000175000017500000000471011750754334020101 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 LIBVIRT_DRIVER_H_ #define LIBVIRT_DRIVER_H_ #include #include #include #include "VirtualMachineManagerDriver.h" class LibVirtDriver : public VirtualMachineManagerDriver { public: LibVirtDriver( int userid, const map &attrs, bool sudo, VirtualMachinePool * pool, const string _emulator): VirtualMachineManagerDriver(userid, attrs,sudo,pool), emulator(_emulator) {}; ~LibVirtDriver(){}; private: static const char * vmware_vnm_name; int deployment_description( const VirtualMachine * vm, const string& file_name) const { int rc = -1; if (emulator == "kvm") { rc = deployment_description_kvm(vm,file_name); } else if (emulator == "vmware") { rc = deployment_description_vmware(vm,file_name); } return rc; } int deployment_description_kvm( const VirtualMachine * vm, const string& file_name) const; int deployment_description_vmware( const VirtualMachine * vm, const string& file_name) const; const string emulator; }; #endif /*LIBVIRT_DRIVER_H_*/ opennebula-3.4.1/include/Template.h0000644000175000017500000002255511750754334017134 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ #ifndef TEMPLATE_H_ #define TEMPLATE_H_ #include #include #include #include #include #include "Attribute.h" using namespace std; /** * Base class for file templates. A template is a file (or a string for the * matter of fact) containing a set of attribute definitions of the form: * NAME = VALUE * where NAME is a string representing the name of the attribute, and VALUE can * be a single string or a vector value (array of string pairs). The file can * contain several attributes with the same name. */ class Template { public: Template(bool _replace_mode = false, const char _separator = '=', const char * _xml_root = "TEMPLATE"): replace_mode(_replace_mode), 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 */ virtual ~Template(); /** * Parse a string representing the template, each attribute is inserted * in the template class. * @param parse_str string with template attributes * @param error_msg error string, must be freed by the calling function. * This string is null if no error occurred. * @return 0 on success. */ int parse(const string &parse_str, char **error_msg); /** * Parse a template file. * @param filename of the template file * @param error_msg error string, must be freed by the calling function. * This string is null if no error occurred. * @return 0 on success. */ int parse(const char * filename, char **error_msg); /** * Parse a string representing the template, automatically detecting if * it is the default syntax, or an XML template. Each attribute is inserted * in the template class. * @param parse_str string with template attributes, or XML template * @param error_msg error string, must be freed by the calling function. * This string is null if no error occurred. * @return 0 on success. */ int parse_str_or_xml(const string &parse_str, string& error_msg); /** * Marshall a template. This function generates a single string with the * template attributes ("VAR=VAL..."). * @param str_tempalte string that hold the template * @param delim to separate attributes */ void marshall(string &str, const char delim='\n'); /** * Writes the template in a simple xml string: * * The name of the root element is set when the Template object is created * @param xml string that hold the xml template representation * @return a reference to the generated string */ string& to_xml(string& xml) const; /** * Writes the template in a plain text string * @param str string that hold the template representation * @return a reference to the generated string */ string& to_str(string& str) const; /** * Sets a new attribute, the attribute MUST BE ALLOCATED IN THE HEAP, and * will be freed when the template destructor is called. * @param attr pointer to the attribute */ virtual void set(Attribute * attr); /** * Removes an attribute from the template. The attributes are returned. The * attributes MUST be freed by the calling funtion * @param name of the attribute * @param values a vector containing a pointer to the attributes * @return the number of attributes removed */ virtual int remove( const string& name, vector& values); /** * Removes an attribute from the template, and frees the attributes. * @param name of the attribute * @return the number of attributes removed */ virtual int erase(const string& name); /** * Gets all the attributes with the given name. * @param name the attribute name. * @return the number of elements in the vector */ virtual int get( const string& name, vector& values) const; /** * Gets all the attributes with the given name, non-const version * @param name the attribute name. * @return the number of elements in the vector */ virtual int get( const string& name, vector& values); /** * Gets the value of a Single attributes (string) with the given name. * @param name the attribute name. * @param value the attribute value, a string, "" if the attribute is not * defined or not Single */ virtual void get( const string& name, string& value) const; /** * Gets the value of a Single attributes (int) with the given name. * @param name the attribute name. * @param value the attribute value, an int, 0 if the attribute is not * defined or not Single * * @return True if the Single attribute was found */ virtual bool get( const string& name, int& value) const; friend ostream& operator<<(ostream& os, const Template& t); /** * Rebuilds the template from a xml formatted string * @param xml_str The xml-formatted string * * @return 0 on success, -1 otherwise */ int from_xml(const string &xml_str); /** * Rebuilds the object from an xml node * @param node The xml node pointer * * @return 0 on success, -1 otherwise */ int from_xml_node(const xmlNodePtr node); protected: /** * The template attributes */ multimap attributes; /** * Builds a SingleAttribute from the given node * @param node The xml element to build the attribute from. * * @return the attribute, or 0 if the node doesn't contain a single att. */ Attribute* single_xml_att(const xmlNode * node); /** * Builds a VectorAttribute from the given node * @param node The xml element to build the attribute from. * * @return the attribute, or 0 if the node doesn't contain a vector att. */ Attribute* vector_xml_att(const xmlNode * node); /** * Stores the attributes as restricted, these attributes will be used in * Template::check * @param rattrs Attributes to restrict * @param restricted_attributes The attributes will be stored here */ static void set_restricted_attributes( vector& rattrs, vector& restricted_attributes); /** * Checks the template for RESTRICTED ATTRIBUTES * @param rs_attr the first restricted attribute found if any * @return true if a restricted attribute is found in the template */ bool check(string& rs_attr, const vector &restricted_attributes); private: bool replace_mode; /** * Mutex to perform just one flex-bison parsing at a time */ static pthread_mutex_t mutex; /** * Character to separate key from value when dump onto a string **/ char separator; /** * Name of the Root element for the XML document */ string xml_root; /** * Builds the template attribute from the node * @param root_element The xml element to build the template from. */ void rebuild_attributes(const xmlNode * root_element); }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif /*TEMPLATE_H_*/ opennebula-3.4.1/include/VirtualMachineTemplate.h0000644000175000017500000000512711750754334021764 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 VIRTUAL_MACHINE_TEMPLATE_H_ #define VIRTUAL_MACHINE_TEMPLATE_H_ #include "Template.h" #include using namespace std; /** * Virtual Machine Template class, it represents a VM configuration file. */ class VirtualMachineTemplate : public Template { public: VirtualMachineTemplate(): Template(false,'=',"TEMPLATE"){}; ~VirtualMachineTemplate(){}; VirtualMachineTemplate(VirtualMachineTemplate& vmt):Template(vmt){}; /** * Checks the template for RESTRICTED ATTRIBUTES * @param rs_attr the first restricted attribute found if any * @return true if a restricted attribute is found in the template */ bool check(string& rs_attr) { return Template::check(rs_attr, restricted_attributes); }; private: friend class VirtualMachinePool; static vector restricted_attributes; /** * Stores the attributes as restricted, these attributes will be used in * VirtualMachineTemplate::check * @param rattrs Attributes to restrict */ static void set_restricted_attributes(vector& rattrs) { Template::set_restricted_attributes(rattrs, restricted_attributes); }; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif /*VIRTUAL_MACHINE_TEMPLATE_H_*/ opennebula-3.4.1/include/HostPool.h0000644000175000017500000001473511750754334017131 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ #ifndef HOST_POOL_H_ #define HOST_POOL_H_ #include "PoolSQL.h" #include "Host.h" #include #include #include #include using namespace std; /** * The Host Pool class. */ class HostPool : public PoolSQL { public: HostPool(SqlDB * db, vector hook_mads, const string& hook_location, const string& remotes_location); ~HostPool(){}; /** * Function to allocate a new Host object * @param oid the id assigned to the Host * @return the oid assigned to the object or -1 in case of failure */ int allocate ( int * oid, const string& hostname, const string& im_mad_name, const string& vmm_mad_name, const string& vnm_mad_name, int cluster_id, const string& cluster_name, string& error_str); /** * Function to get a Host from the pool, if the object is not in memory * it is loaded from the DB * @param oid Host unique id * @param lock locks the Host mutex * @return a pointer to the Host, 0 if the Host could not be loaded */ Host * get( int oid, bool lock) { return static_cast(PoolSQL::get(oid,lock)); }; /** * Function to get a Host from the pool, if the object is not in memory * it is loaded from the DB * @param hostname * @param lock locks the Host mutex * @return a pointer to the Host, 0 if the Host could not be loaded */ Host * get(string name, bool lock) { // The owner is set to -1, because it is not used in the key() method return static_cast(PoolSQL::get(name,-1,lock)); }; /** * Generate an index key for the object * @param name of the object * @param uid owner of the object, only used if needed * * @return the key, a string */ string key(const string& name, int uid) { // Name is enough key because Hosts can't repeat names. return name; }; /** * Bootstraps the database table(s) associated to the Host pool * @return 0 on success */ static int bootstrap(SqlDB *_db) { return Host::bootstrap(_db); }; /** * Get the least monitored hosts * @param discovered hosts, map to store the retrieved hosts hids and * hostnames * @param host_limit max. number of hosts to monitor at a time * @return int 0 if success */ int discover(map * discovered_hosts, int host_limit); /** * Allocates a given capacity to the host * @param oid the id of the host to allocate the capacity * @param cpu amount of CPU * @param mem amount of main memory * @param disk amount of disk */ void add_capacity(int oid,int cpu, int mem, int disk) { Host * host = get(oid, true); if ( host != 0 ) { host->add_capacity(cpu, mem, disk); update(host); host->unlock(); } }; /** * De-Allocates a given capacity to the host * @param oid the id of the host to allocate the capacity * @param cpu amount of CPU * @param mem amount of main memory * @param disk amount of disk */ void del_capacity(int oid,int cpu, int mem, int disk) { Host * host = get(oid, true); if ( host != 0 ) { host->del_capacity(cpu, mem, disk); update(host); host->unlock(); } }; int drop(PoolObjectSQL * objsql, string& error_msg) { Host * host = static_cast(objsql); if ( host->get_share_running_vms() > 0 ) { error_msg = "Can not remove a host with running VMs"; return -1; } return PoolSQL::drop(objsql, error_msg); }; /** * Dumps the HOST 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, "HOST_POOL", Host::table, where); }; /** * Finds a set objects that satisfies a given condition * @param oids a vector with the oids of the objects. * @param the name of the DB table. * @param where condition in SQL format. * * @return 0 on success */ int search(vector& oids, const string& where) { return PoolSQL::search(oids, Host::table, where); }; private: /** * Factory method to produce Host objects * @return a pointer to the new Host */ PoolObjectSQL * create() { return new Host(-1,"","","","",-1,""); }; /** * Callback function to get the IDs of the hosts to be monitored * (Host::discover) * @param num the number of columns read from the DB * @param names the column names * @param vaues the column values * @return 0 on success */ int discover_cb(void * _map, int num, char **values, char **names); }; #endif /*HOST_POOL_H_*/ opennebula-3.4.1/include/GroupPool.h0000644000175000017500000001246511750754334017306 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 GROUP_POOL_H_ #define GROUP_POOL_H_ #include "Group.h" #include "SqlDB.h" using namespace std; class GroupPool : public PoolSQL { public: GroupPool(SqlDB * db); ~GroupPool(){}; /* ---------------------------------------------------------------------- */ /* Constants for DB management */ /* ---------------------------------------------------------------------- */ /** * Default name for the oneadmin group */ static const string ONEADMIN_NAME; /** * Identifier for the oneadmin group */ static const int ONEADMIN_ID; /** * Default name for the users group */ static const string USERS_NAME; /** * Identifier for the user group */ static const int USERS_ID; /* ---------------------------------------------------------------------- */ /* Methods for DB management */ /* ---------------------------------------------------------------------- */ /** * Allocates a new group, writting it in the pool database. No memory is * allocated for the object. * @param name Group name * @param oid the id assigned to the Group * @param error_str Returns the error reason, if any * * @return the oid assigned to the object, -1 in case of failure */ int allocate(string name, int * oid, string& error_str); /** * Function to get a group from the pool, if the object is not in memory * it is loaded from the DB * @param oid group unique id * @param lock locks the group mutex * @return a pointer to the group, 0 if the group could not be loaded */ Group * 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 lock locks the object if true * * @return a pointer to the object, 0 in case of failure */ Group * get(const string& name, bool lock) { // The owner is set to -1, because it is not used in the key() method return static_cast(PoolSQL::get(name,-1,lock)); }; /** * Generate an index key for the object * @param name of the object * @param uid owner of the object, only used if needed * * @return the key, a string */ string key(const string& name, int uid) { // Name is enough key because Groups can't repeat names. return name; }; /** Update a particular Group * @param user pointer to Group * @return 0 on success */ int update(Group * group) { return group->update(db); }; /** * Drops the Group from the data base. The object mutex SHOULD be * locked. * @param objsql a pointer to a Group object * @param error_msg Error reason, if any * @return 0 on success, * -1 DB error, * -2 object is a system group (ID < 100) * -3 Group's User IDs set is not empty */ int drop(PoolObjectSQL * objsql, string& error_msg); /** * Bootstraps the database table(s) associated to the Group pool * @return 0 on success */ static int bootstrap(SqlDB * _db) { return Group::bootstrap(_db); }; /** * Dumps the Group 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, "GROUP_POOL", Group::table, where); }; private: /** * Factory method to produce objects * @return a pointer to the new object */ PoolObjectSQL * create() { return new Group(-1,""); }; }; #endif /*GROUP_POOL_H_*/ opennebula-3.4.1/include/HookManagerDriver.h0000644000175000017500000000675111750754334020730 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 HOOK_MANAGER_DRIVER_H_ #define HOOK_MANAGER_DRIVER_H_ #include #include #include #include "Mad.h" #include "VirtualMachinePool.h" using namespace std; /** * HookManagerDriver provides a base class to implement Hook (Execution) * Drivers. This class implements the protocol and recover functions * from the Mad interface. This class may be used to further specialize * the Execution driver. */ class HookManagerDriver : public Mad { public: HookManagerDriver( int userid, const map& attrs, bool sudo, VirtualMachinePool * _vmpool) : Mad(userid,attrs,sudo), vmpool(_vmpool){}; virtual ~HookManagerDriver(){}; /** * Implements the Hook driver protocol. * @param message the string read from the driver */ void protocol( string& message); /** * TODO: What do we need here? just poll the Hosts to recover.. */ void recover(); /**
Username Password
retrieving
opennebula-3.4.1/src/cloud/occi/lib/ui/views/0000755000175000017500000000000011750754334020706 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/views/index.erb0000644000175000017500000000671611750754334022521 0ustar drazzibdrazzib OpenNebula Self-Service <%if session[:lang]%> <%end%>
opennebula-3.4.1/src/cloud/occi/lib/ui/public/0000755000175000017500000000000011750754334021027 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/public/css/0000755000175000017500000000000011750754334021617 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/public/css/layout.css0000644000175000017500000001205111750754334023645 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ body { background: #f5f5f5; } .outer-center, .inner-center { padding: 0; } .outer-center { border: 0; } .inner-south { padding: 0; } #dialog div { border: 0; } .tab { padding: 5px 10px 0 10px; } body { font-family: Arial, Verdana, Geneva, Helvetica, sans-serif; font-size: 13px; } #header { padding: 0 10px 0 10px; background-color: #353735; border:0; } #footer { padding-top: 9px; font-size: 0.8em; color: white; text-align: center; background-color: #353735; border:0; } #footer a { color: white; text-decoration: underline; } #logo { padding-top: 6px; font-weight: bold; color: white; float:left; } #login-info { padding-top: 4px; float: right; padding-right: 5px; } #links { padding-top: 4px; margin-right: 40px; float: right; } #login-info, #login-info a, #links, #links a { color: white; } #login-info, #login-info a { font-weight: bold; } .sunstone-color { color: #0098C3; } #logo-wrapper { float: right; margin-top: 0px; margin-right: 20px; } #menu { padding-right: 0; padding-left: 0; border:0; border-right: 1px solid #353735; background-image: -webkit-gradient( linear, left top, right top, color-stop(0.95, rgb(99,102,99)), color-stop(1, rgb(53,55,53)) ); background-image: -moz-linear-gradient( left center, rgb(99,102,99) 95%, rgb(53,55,53) 100% ); } #navigation { list-style: none; padding: 0; } .navigation li.topTab { line-height: 2em; text-align: left; padding-left: 15px; } .navigation li.subTab { line-height: 1.8em; font-size: 12px; text-align: left; padding-left: 30px; } .navigation li.subsubTab { line-height: 1.7em; font-size: 11px; text-align: left; padding-left: 40px; } .navigation li.topTab span.plusIcon, .navigation li.subTab span.plusIcon { display : none; float: right; margin-right: 1em; } .navigation li.topTab span.plusIcon { margin-top: 5px; } .navigation li.subTab span.plusIcon { margin-top: 3px; } #navigation li { color: #ffffff; cursor: pointer; } #navigation li:hover, .navigation-active-li { background-image: -webkit-gradient( linear, left top, right top, color-stop(0.95, #0098C3), color-stop(1, rgb(53,55,53)) ); background-image: -moz-linear-gradient( left center, #0098C3 95%, rgb(53,55,53) 100% ); /* background-image: -webkit-gradient( linear, right top, left top, color-stop(0, rgb(0,152,192)), color-stop(1, rgb(255,255,255)) ); background-image: -moz-linear-gradient( right center, rgb(0,152,192) 0%, rgb(255,255,255) 100% ); */ } .navigation-active-li { font-weight: bold; } #navigation li:hover { color: #ffffff !important; } #language { float:right; margin-top:2px; margin-right:25px; width: 100px; } #language select { width: 100px; height: 22px; } /* top menu css */ #menutop_container{ margin:0px 171px; color:#FFFFFF; font-size:13px; font-weight:bold; } #menutop_navbar{ float:left; height:25px; font-size:13px; } #menutop_navbar ul{ float:left; height:25px; color:#000000; margin: 0 0; padding-left: 1px; } #menutop_navbar ul{ background-color: #353735; } #menutop_navbar ul li{ float:left; min-width:72px; margin:0px 0 0 0; height:22px; display: inline; text-align:center; padding-left:5px; padding-right: 5px; padding-top: 4px; padding-bottom: 4px; border-left:1px solid white; cursor:pointer; color: white; } #menutop_navbar ul li:hover { background-color: #E69138; } /* end top menu css */opennebula-3.4.1/src/cloud/occi/lib/ui/public/css/application.css0000644000175000017500000002476211750754334024647 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ body { font: 9pt Arial, Verdana, Geneva, Helvetica, sans-serif; } p { margin:0 10px 10px; } a { color: #000C96; text-decoration: none; } a:hover { color: #127FE4; text-decoration: none; } select, button { padding: 2px; } h2 { float:left; font-size:20px; margin-bottom: 5px; padding-bottom: 0} h3 { border-bottom: 1px solid #CCCCCC; color: #353735; font-size: 14px; font-weight: normal; padding: 5px 8px; margin: 0 0; } table#dashboard_table{ width:100%; margin: 0; } table#dashboard_table tr { vertical-align: top; } table#dashboard_table > tbody > tr > td{ width:50%; } div.panel { background-color: #ffffff; padding:0; margin: 10px; border: 1px #ddd solid; min-height: 50px; -webkit-border-radius: 3px; -moz-border-radius: 3px; -moz-box-shadow: 5px 5px 5px #888; -webkit-box-shadow: 5px 5px 5px #888; box-shadow: 5px 5px 5px #888; } div.panel h3 { border: 0; padding:5px 10px 5px 10px; margin: 0; color: white; font-weight: bold; background-color: #353735; -webkit-border-radius: 3px 3px 0 0; -moz-border-radius: 3px 3px 0 0; } div.panel .new-resource { float: right; } div.panel h3 a { color: white; font-weight: bold; } div.panel_info { padding: 5px; } div.panel_info table.info_table { background: none; width: 100%; margin:0; } div.panel_info table.info_table tr { border: 0; border-bottom: 1px dotted #ccc; } div.panel_info table.info_table > tbody > tr > td { border: 0; width: 100%!important; } div.panel_info table.info_table td.value_td { text-align: right; } .green { color: green!important; } .red { color: #B81515!important; } ul.multi_action_menu { list-style: none; position: absolute; text-align: left; padding:0; border: 1px solid #D3D3D3; background-color: #F0EDED;} ul.multi_action_menu li { cursor: pointer; padding: 2px 5px;} ul.multi_action_menu li:hover { background-color: #D3D3D3;} div.action_block { display:inline; margin-right: 5px; border-right: 1px solid #D3D3D3; } div.action_blocks { margin-bottom: 0.5em; text-align: right; margin-top: 0.5em; } input, textarea, select { border: 0; border: 1px #bbbbbb solid; } input, textarea { -webkit-border-radius: 3px; -moz-border-radius: 3px; } form.create_form{ margin:0; padding:0;} fieldset{ margin:0 0; border:none; border-top:1px solid #ccc; padding: 10px 5px;} fieldset div{ margin-bottom:.5em; padding:0; display:block; } fieldset input, fieldset textarea{ width:140px; /*border-top:1px solid #555; border-left:1px solid #555; border-bottom:1px solid #ccc; border-right:1px solid #ccc;*/ padding:1px;color:#333; vertical-align: top; margin: 0 2px; margin-bottom: 4px; } fieldset select{ width:144px; /*border-top:1px solid #555; border-left:1px solid #555; border-bottom:1px solid #ccc; border-right:1px solid #ccc;*/ padding:1px; color:#333; vertical-align: top; margin: 0 2px; margin-bottom: 4px; } /*Chrome hack*/ input[type="radio"],input[type="checkbox"] { width:20px; } legend{ margin-top:0; margin-bottom: 5px; padding:0 .5em; color:#036; background:transparent; font-size:1.0em; font-weight:bold; } label{ float: left; width:100px; padding:0 1em; text-align:left; } .dataTables_wrapper label { float: none; width: auto; padding: 0 0; text-align:right; } div.tip { display: inline-block; padding-left: 5px; vertical-align: middle; float:none; } div.tip span.ui-icon{ display:inline-block; } div.tip span.man_icon { display:none; } .img_man .man_icon { display:inline-block!important; } span.tipspan,div.full_info { position: fixed; display:block; padding:4px; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; border: 1px solid #353735; margin-left:2px; margin-right:5px; background-color: white; color: #353735; font-size:10px; } .vm_section input { float:none; } .vm_section legend{ display:none!important; } .vm_section fieldset { border:none!important; } div.show_hide { float:none; clear:both; } .vm_param label{ float:left; } fieldset div.vm_section { margin-top:-8px; margin-bottom:0px; } input:focus, textarea:focus{ background:#efefef; color:#000; } .form_buttons { margin-top:6px; text-align:left; margin-bottom:20px; } .add_remove_button { font-size:0.8em !important; height:25px !important; margin-bottom:4px; } .add_button { margin-left:148px; width:58px !important; } .remove_button { } tr.odd, tr.even { background-color: #ffffff; border: 1px #e9e9e9 solid; height:30px!important; } tr.odd td, tr.even td{ border-left: 1px #e9e9e9 solid; } tr.odd:hover{ background-color: #0098C3 !important; color: white; } tr.even:hover{ color: white; background-color: #0098C3 !important; } .show_hide label{ width: 100%; } .clear { clear: both; } /* Create dialogs */ /* host: */ #create_host_form fieldset label { width: 200px; } .action_block_info{ width: 235px; margin: auto; } .icon_right { display: inline-block; margin-left: 20px; position: relative; top: 2px; } .icon_left { float: left; margin-right: 20px; position: relative; top: 0px; /*border:1px solid;*/ } .info_table{ background: none repeat scroll 0 0 #FFFFFF; border-collapse: collapse; margin: 20px; text-align: left; display: inline-block; width:85%; vertical-align:top; overflow:auto; } .info_table > thead th,h3 { border-bottom: 2px solid #353735; color: #353735; font-size: 14px; font-weight: normal; padding: 10px 8px; } .info_table > tbody > tr > td{ border-bottom: 1px solid #CCCCCC; color: #353735; padding-top: 6px; padding-bottom: 6px; padding-left: 8px; padding-right: 8px; } /*.info_table > tbody, .info_table > thead, info_table > tbody > tr { width: 100%; }*/ .info_table td.key_td{ min-width: 150px; text-align:left; font-weight:bold; } .info_table td.graph_td{ padding-top:0px!important; padding-bottom:0px!important; vertical-align:middle!important; } .info_table td.value_td{ text-align:left; width:100%; } #dialog > div > div { margin: 0; padding: 0; } .loading_img { vertical-align:middle; display:inline; overflow:hide; } .top_button { font-size: 0.8em!important; height: 25px; margin: 3px 2px; vertical-align: middle; /*width: 89px;*/ } .top_button button { font-size: 0.9em; height: 25px; vertical-align: middle; } .image_button { font-size: 0.8em; margin: 3px 2px; vertical-align: middle; border:0; } /* .multi_action_slct{ font-size: 0.7em; vertical-align:middle; margin:3px 0; height: 25px; }*/ .ui-icon-refresh{ position:relative!important; top:14px!important; } #vm_log { padding: 0 20px 0 20px !important; } #vm_log h3 { border-bottom: 2px solid #353735; } #vm_log pre { font-size: 0.9em; } #vm_log .vm_log_error { color: red; font-weight: bold; } /* Growl */ .jGrowl-notification h1 { font-size: 1.2em; } .jGrowl-notification, .jGrowl-notify-submit { border: 2px #444444 solid; background-color: #F3F3F3!important; color: #666666; } .jGrowl-notify-error { border: 2px #660000 solid; background-color: #F39999!important; color: #660000; } .jGrowl-notify-error table td.key_error { text-transform: capitalize; width: 100%; font-weight: bold; } .jGrowl-notify-error table td.key_error:after { content:":"; } .refresh_image { position: relative; top: 8px; cursor: pointer; } .ui-widget-overlay { background: #353735; opacity: .60; filter:Alpha(Opacity=60); } .ui-tabs .ui-tabs-nav li a { /*padding: .5em 1em;*/ padding: .3em 1em; } ul.action_list{ /*background: #EDEDED;*/ border: 1px solid #525252; background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0.25, #E9E9E9), color-stop(0.63, #F5F5F5) ); background-image: -moz-linear-gradient( center bottom, #E9E9E9 25%, #F5F5F5 63% ); position:absolute; z-index:1; list-style-type:none; text-align:left; padding:5px 5px; -webkit-border-radius:4px; -webkit-border-bottom-right-radius:5px; -webkit-border-bottom-left-radius:5px; -moz-border-radius:4px; -moz-border-radius-bottomright:5px; -moz-border-radius-bottomleft:5px; border-radius:4px; border-bottom-right-radius:5px; border-bottom-left-radius:5px; } ul.action_list li a{ font-size: 0.8em; color:#575C5B; } ul.action_list li a:hover{ color:#0098C3; } .progress_bar{ height:10px; background: #8F9392; } .ui-widget{ font: 10pt Arial, Verdana, Geneva, Helvetica, sans-serif; } .ui-layout-resizer-open-hover, /* hover-color to 'resize' */ .ui-layout-resizer-dragging { background: #EEE; } .dashboard_p { color: #353735; text-align:justify; } .dashboard_p p{ padding-top:5px; } .dashboard_p img { padding-left:10px; padding-right: 10px; border:0; } opennebula-3.4.1/src/cloud/occi/lib/ui/public/css/login.css0000644000175000017500000001005711750754334023444 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ body { background: #FAFAFA; margin: 0px; } #header { height: 30px; background-color: #353735; padding: 0 10px 0 10px; } #logo { padding-top: 6px; font-size: 1.1em; font-weight: bold; color: white; font-family: Arial, Verdana, Geneva, Helvetica, sans-serif; font-size: 13px; } #wrapper{ margin-left: auto; margin-right: auto; width: 900px; text-align: center; } div#logo_selfservice { position: relative; height: 100px; width: 600px; top: 80px; margin-left: auto; margin-right: auto; background: url(../images/opennebula-selfservice-big.png) no-repeat center; vertical-align: center; } div#login { width: 400px; height: 300px; position: relative; margin-left: auto; margin-right: auto; top: 90px; padding-left: 80px; padding-right: 80px; background: url(../images/panel.png) no-repeat center ; vertical-align: center; } .box { font-size:0.8em; width: 300px; height: 25px; background: #FFFFFF; margin-left: auto; margin-right: auto; margin-bottom: 10px; border-bottom-color: gray; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; border-bottom-style: solid; border-bottom-width: 1px; border-left-color: gray; border-left-style: solid; border-left-width: 1px; border-right-color: gray; border-right-style: solid; border-right-width: 1px; border-top-color: gray; border-top-left-radius: 5px; border-top-right-radius: 5px; border-top-style: solid; border-top-width: 1px; -moz-border-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; -moz-border-radius-bottomright: 5px; -moz-border-radius-bottomleft: 5px; } div#login input#login_btn { width: 130px; height: 45px; cursor: pointer; margin-left: auto; margin-right: 43px; margin-top: 20px; background-color: transparent; border:0; float: right; background: url(../images/login.png) no-repeat center ; } div#login input#login_btn:hover { width: 130px; height: 45px; cursor: pointer; margin-left: auto; margin-right: 43px; margin-top: 20px; background-color: transparent; border:0; float: right; background: url(../images/login_over.png) no-repeat center ; } .error_message { width: 400px; margin-left: auto; margin-right: auto; display: none; position: relative; top: 80px; font-size:1.0em; } #login_spinner { left: 44px; position: relative; top: 2px; } #label_remember { color:#353735; font-size:0.4em; font-family: Arial, Helvetica, sans-serif; } .content { padding-top:40px; font-size:1.8em; margin-bottom:0px; margin-left:50px; text-align:left; font-family: Arial, Helvetica, sans-serif; } #check_remember { margin-top: 35px; margin-left:0px; }opennebula-3.4.1/src/cloud/occi/lib/ui/public/js/0000755000175000017500000000000011750754334021443 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/public/js/occi.js0000644000175000017500000004707311750754334022731 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ //Convert json into the XML that OCCI server can understand function json2xml(element,root_key) { var xml = ""; if (!root_key) root_key="ROOT"; if (typeof element == "object") { //Its an object $.each(element, function(key,value){ if (value.constructor == Array){ for (var i = 0; i < value.length; i++){ xml += json2xml(value[i],key); }; //do not wrap arrays in root_key return xml; } else xml += json2xml(value,key); }); } else { //its a simple value. Base condition xml += element.toString(); }; return "<" + root_key.toUpperCase() + ">" + xml + ""; }; $.ajaxSetup({ converters: { "xml ONEjson": function(xml){ return $.xml2json(xml); }, } }); var OCCI = { "Error": function(resp) { var error = { error : { message: resp.responseText, http_status : resp.status} }; return error; }, "is_error": function(obj) { return obj.error ? true : false; }, "Helper": { "action": function(action, params) { obj = { "action": { "perform": action } } if (params) { obj.action.params = params; } return obj; }, "request": function(resource, method, data) { var r = { "request": { "resource" : resource, "method" : method } } if (data) { if (typeof(data) != "array") { data = [data]; } r.request.data = data; } return r; }, "pool": function(resource, response) { var pool_name = resource + "_COLLECTION"; var type = resource; var pool; if (typeof(pool_name) == "undefined") { return Error('Incorrect Pool'); } var p_pool = []; if (response[pool_name]) { pool = response[pool_name][type]; } else { pull = null }; if (pool == null) { return p_pool; } else if (pool.length) { for (i=0;i'; OCCI.Action.update(params,OCCI.VM.resource,"saveas"); }, "vnc" : function(params,startstop){ var callback = params.success; var callback_error = params.error; var id = params.data.id; var resource = OCCI.VM.resource; var method = startstop; var action = OCCI.Helper.action(method); var request = OCCI.Helper.request(resource,method, id); $.ajax({ url: "ui/" + method + "/" + id, type: "POST", dataType: "json", success: function(response){ return callback ? callback(request, response) : null; }, error: function(response){ return callback_error ? callback_error(request, OCCI.Error(response)) : null; } }); }, "startvnc" : function(params){ OCCI.VM.vnc(params,"startvnc"); }, "stopvnc" : function(params){ OCCI.VM.vnc(params,"stopvnc"); }, /* "monitor" : function(params){ OCCI.Action.monitor(params,OCCI.VM.resource,false); }, "monitor_all" : function(params){ OCCI.Action.monitor(params,OCCI.VM.resource,true); } */ }, "Image": { "resource": "STORAGE", "create": function(params){ var callback = params.success; var callback_error = params.error; var data = {occixml : json2xml(params.data,OCCI.Image.resource)}; var request = OCCI.Helper.request(OCCI.Image.resource,"create", data); $.ajax({ type: 'POST', url: "storage", data: data, dataType: "xml ONEjson", success: function(response){ var res = {}; res["STORAGE"] = response; return callback ? callback(request, res) : null; }, error: function(response){ return callback_error ? callback_error(request, OCCI.Error(response)) : null; } }); }, "del": function(params){ OCCI.Action.del(params,OCCI.Image.resource); }, "list": function(params){ OCCI.Action.list(params,OCCI.Image.resource); }, "show": function(params){ OCCI.Action.show(params,OCCI.Image.resource); }, "publish": function(params){ params.data.body = { "PUBLIC":"YES" }; OCCI.Action.update(params,OCCI.Image.resource,"publish"); }, "unpublish": function(params){ params.data.body = { "PUBLIC":"NO" }; OCCI.Action.update(params,OCCI.Image.resource,"unpublish"); }, "persistent": function(params){ params.data.body = { "PERSISTENT":"YES" }; OCCI.Action.update(params,OCCI.Image.resource,"persistent"); }, "nonpersistent": function(params){ params.data.body = { "PERSISTENT":"NO" }; OCCI.Action.update(params,OCCI.Image.resource,"nonpersistent"); }, }, "Template" : { "resource" : "VMTEMPLATE", "create" : function(params){ OCCI.Action.create(params,OCCI.Template.resource); }, "del" : function(params){ OCCI.Action.del(params,OCCI.Template.resource); }, "list" : function(params){ OCCI.Action.list(params,OCCI.Template.resource); }, "show" : function(params){ OCCI.Action.show(params,OCCI.Template.resource); }, "chown" : function(params){ OCCI.Action.chown(params,OCCI.Template.resource); }, "chgrp" : function(params){ OCCI.Action.chgrp(params,OCCI.Template.resource); }, "update" : function(params){ var action_obj = {"template_raw" : params.data.extra_param }; OCCI.Action.simple_action(params, OCCI.Template.resource, "update", action_obj); }, "fetch_template" : function(params){ OCCI.Action.show(params,OCCI.Template.resource,"template"); }, "publish" : function(params){ OCCI.Action.simple_action(params,OCCI.Template.resource,"publish"); }, "unpublish" : function(params){ OCCI.Action.simple_action(params,OCCI.Template.resource,"unpublish"); }, "instantiate" : function(params) { var vm_name = params.data.extra_param ? params.data.extra_param : ""; var action_obj = { "vm_name" : vm_name }; OCCI.Action.simple_action(params,OCCI.Template.resource, "instantiate",action_obj); } }, "Instance_type" : { "resource" : "INSTANCE_TYPE", "list" : function(params){ OCCI.Action.list(params,OCCI.Instance_type.resource); }, }, } opennebula-3.4.1/src/cloud/occi/lib/ui/public/js/plugins/0000755000175000017500000000000011750754334023124 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/public/js/plugins/dashboard.js0000644000175000017500000001536311750754334025421 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ var dashboard_tab_content = '\ \ \ \
\ \ \ \ \ \ \ \ \ \ \
\
\

' + dashboard_welcome_title + '

\
\ '+ dashboard_welcome_html+'\
\
\
\
\

' + tr("Current resources") + '

\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \
'+tr("Compute")+''+$vm_count+'
' + tr("Storage") + ''+$storage_count+'
' + tr("Network") + ''+$network_count+'
\ \
\
\
\
\

' + tr("Useful links") + '

\
'+ generateDashboardLinks() +'\
\
\
\
\ \ \ \ \ \ \ \ \ \ \
\
\

' + compute_box_title + '

\ \
\
\
\

' + storage_box_title + '

\ \
\
\
\

' + network_box_title + '

\ \
\
\
'; var dashboard_tab = { title: tr("Dashboard"), content: dashboard_tab_content } Sunstone.addMainTab('dashboard_tab',dashboard_tab); function quickstart_setup(){ $('#dashboard_table #quickstart_form input',main_tabs_context).click(function(){ Sunstone.runAction($(this).val()); }); }; function generateDashboardLinks(){ var links="
    "; for (var i=0; i'+dashboard_links[i].text+''; }; links+="
"; return links; }; $(document).ready(function(){ //Dashboard link listener $("#dashboard_table h3 a",main_tabs_context).live("click", function (){ var tab = $(this).attr('href'); showTab(tab); return false; }); $('.tab_link').click(function(){ var to= $(this).attr('href').slice(1); $('.outer-west ul li#li_'+to).trigger("click"); return false; }); $('.action_link').click(function(){ var to= $(this).attr('href').slice(1); $('.outer-west ul li#li_'+to).trigger("click"); var action = $(this).attr('action'); Sunstone.runAction(action); //var to= $(this).attr('href'); //$('.outer-west ul li.topTab a[href="'+to+'"]').trigger("click"); return false; }); emptyDashboard(); quickstart_setup(); $('#li_dashboard_tab').click(function(){ hideDialog(); }); }); //puts the dashboard values into "retrieving" function emptyDashboard(){ $("#dashboard_tab .value_td span",main_tabs_context).html(spinner); } function updateDashboard(what,json_info){ var db = $('#dashboard_tab',main_tabs_context); switch (what){ case "vms": var total_vms=json_info.length; $('.vm_count',db).html(total_vms); break; case "vnets": var total_vnets=json_info.length; $('.network_count',db).html(total_vnets); break; case "images": var total_images=json_info.length; $('.storage_count',db).html(total_images); break; } } opennebula-3.4.1/src/cloud/occi/lib/ui/public/js/plugins/storage.js0000644000175000017500000005037611750754334025141 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ /*Images tab plugin*/ var images_tab_content = '
\
\
\ \ \ \ \ \ \ \ \ \ \
'+tr("All")+''+tr("ID")+''+tr("Name")+'
\
'; var create_image_tmpl = '
\
\
\

'+ tr("Fields marked with")+' '+ tr("are mandatory")+'
\

\
\ \ \
'+tr("Name that the Image will get.")+'
\
\
\ \ \
'+tr("Human readable description of the image.")+'
\
\
\
\
\ \ \
'+tr("Type of the image")+'
\
\
\ \ \
'+tr("Size of the datablock in MB.")+'
\
\
\ \ \
'+tr("Type of file system to be built. This can be any value understood by mkfs unix command.")+'
\
\
\
\
\
\
\
\ \
\ \ \ \
\ \
\
'; var image_dashboard = '
\ one-storage'+ storage_dashboard_html + '
'; var dataTable_images; var $create_image_dialog; var image_actions = { "Image.create" : { type: "create", call: OCCI.Image.create, callback: addImageElement, error: onError, notify:true }, "Image.create_dialog" : { type: "custom", call: popUpCreateImageDialog }, "Image.list" : { type: "list", call: OCCI.Image.list, callback: updateImagesView, error: onError }, "Image.show" : { type : "single", call: OCCI.Image.show, callback: updateImageElement, error: onError }, "Image.showinfo" : { type: "single", call: OCCI.Image.show, callback: updateImageInfo, error: onError }, "Image.refresh" : { type: "custom", call: function () { waitingNodes(dataTable_images); Sunstone.runAction("Image.list"); }, }, "Image.autorefresh" : { type: "custom", call: function() { OCCI.Image.list({timeout: true, success: updateImagesView, error: onError}); } }, "Image.persistent" : { type: "multiple", call: OCCI.Image.persistent, elements: imageElements, error: onError, notify: true }, "Image.nonpersistent" : { type: "multiple", call: OCCI.Image.nonpersistent, elements: imageElements, error: onError, notify: true }, // "Image.publish" : { // type: "multiple", // call: OCCI.Image.publish, // callback: function (req) { // //Sunstone.runAction("Image.show",req.request.data[0]); // }, // elements: imageElements, // error: onError, // notify: true // }, // "Image.unpublish" : { // type: "multiple", // call: OCCI.Image.unpublish, // callback: function (req) { // //Sunstone.runAction("Image.show",req.request.data[0]); // }, // elements: imageElements, // error: onError, // notify: true // }, "Image.delete" : { type: "multiple", call: OCCI.Image.del, callback: deleteImageElement, elements: imageElements, error: onError, notify: true }, } var image_buttons = { "Image.refresh" : { type: "image", text: tr("Refresh list"), img: "images/Refresh-icon.png" }, "Image.create_dialog" : { type: "create_dialog", text: tr('+ New') }, "Image.persistent" : { type: "action", text: tr("Make persistent") }, "Image.nonpersistent" : { type: "action", text: tr("Make non persistent") }, // "action_list" : { // type: "select", // actions: { // "Image.publish" : { // type: "action", // text: tr("Publish") // }, // "Image.unpublish" : { // type: "action", // text: tr("Unpublish") // }, // } // }, "Image.delete" : { type: "action", text: tr("Delete") } } var image_info_panel = { "image_info_tab" : { title: tr("Image information"), content: "" }, }; var image_create_panel = { "image_create_panel" : { title: tr("Add storage"), content: create_image_tmpl }, }; var images_tab = { title: tr("Storage"), content: images_tab_content, buttons: image_buttons } Sunstone.addActions(image_actions); Sunstone.addMainTab('images_tab',images_tab); Sunstone.addInfoPanel('image_info_panel',image_info_panel); Sunstone.addInfoPanel('image_create_panel',image_create_panel); function imageElements() { return getSelectedNodes(dataTable_images); } // Returns an array containing the values of the image_json and ready // to be inserted in the dataTable function imageElementArray(image_json){ //Changing this? It may affect to the is_public() and is_persistent() functions. var image = image_json.STORAGE; var id,name; if (image.name){ id = image.href.split("/"); id = id[id.length-1]; name = image.name; } else { id = image.ID; name = image.NAME; }; return [ '', id, name ]; } // Set up the listener on the table TDs to show the info panel function imageInfoListener(){ $('#tbodyimages tr',dataTable_images).live("click",function(e){ var target = $(e.target); if (target.is('input') || target.is('select') || target.is('option')) return true; var aData = dataTable_images.fnGetData(this); var id = $(aData[0]).val(); if (!id) return true; popDialogLoading(); Sunstone.runAction("Image.showinfo",id); return false; }); } // Callback to update an element in the dataTable function updateImageElement(request, image_json){ var id = image_json.STORAGE.ID; var element = imageElementArray(image_json); updateSingleElement(element,dataTable_images,'#image_'+id); } // Callback to remove an element from the dataTable function deleteImageElement(req){ deleteElement(dataTable_images,'#image_'+req.request.data); } // Callback to add an image element function addImageElement(request, image_json){ var element = imageElementArray(image_json); addElement(element,dataTable_images); } // Callback to refresh the list of images function updateImagesView(request, images_list){ var image_list_array = []; $.each(images_list,function(){ image_list_array.push(imageElementArray(this)); }); updateView(image_list_array,dataTable_images); updateDashboard("images",images_list); } // Callback to update the information panel tabs and pop it up function updateImageInfo(request,img){ var img_info = img.STORAGE; var info_tab = { title: tr("Image information"), content: '
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
'+tr("Image")+' "'+img_info.NAME+'" '+ tr("information")+'
'+tr("ID")+''+img_info.ID+'
'+tr("Name")+''+img_info.NAME+'
'+tr("Description")+''+(img_info.DESCRIPTION ? img_info.DESCRIPTION : "--")+'
'+tr("Type")+''+img_info.TYPE+'
'+tr("Persistent")+'
'+tr("Filesystem type")+''+(typeof img_info.FSTYPE === "string" ? img_info.FSTYPE : "--")+'
'+tr("Size (Mb)")+''+img_info.SIZE+'
\
\
' }; Sunstone.updateInfoPanelTab("image_info_panel","image_info_tab",info_tab); Sunstone.popUpInfoPanel("image_info_panel"); $('#dialog .image_close_dialog_link').button({ text:false, icons: { primary: "ui-icon-closethick" } }); $('#dialog input').click(function(){ if ($(this).is(':checked')) Sunstone.runAction("Image.persistent",[img_info.ID]) else Sunstone.runAction("Image.nonpersistent",[img_info.ID]) }); } function popUpCreateImageDialog(){ Sunstone.popUpInfoPanel("image_create_panel"); var dialog = $('#dialog'); $create_image_dialog = dialog; $('#create_image',dialog).button({ icons: { primary: "ui-icon-check" }, text: true }); /* $('#reset_image',dialog).button({ icons: { primary: "ui-icon-scissors" }, text: false }); */ $('.image_close_dialog_link',dialog).button({ icons: { primary: "ui-icon-closethick" }, text: true }); setupTips(dialog); $('#img_fstype',dialog).parents('div.img_param').hide(); $('#img_size',dialog).parents('div.img_param').hide(); /* $('#img_public',dialog).click(function(){ $('#img_persistent',$create_image_dialog).removeAttr('checked'); }); $('#img_persistent',dialog).click(function(){ $('#img_public',$create_image_dialog).removeAttr('checked'); }); */ $('#img_type',dialog).change(function(){ if ($(this).val() == "DATABLOCK"){ $('#img_fstype',$create_image_dialog).parents('div.img_param').show(); $('#img_size',$create_image_dialog).parents('div.img_param').show(); $('#upload_div',$create_image_dialog).hide(); } else { $('#img_fstype',$create_image_dialog).parents('div.img_param').hide(); $('#img_size',$create_image_dialog).parents('div.img_param').hide(); $('#upload_div',$create_image_dialog).show(); }; }); $('#upload-progress',dialog).progressbar({value:0}); $('#upload-progress',dialog).css({ border: "1px solid #AAAAAA", position: "relative", // bottom: "29px", width: "258px", // left: "133px", height: "15px", display: "inline-block", }); $('#upload-progress div',dialog).css("border","1px solid #AAAAAA"); var img_obj; var uploader = new qq.FileUploaderBasic({ button: $('#file-uploader',$create_image_dialog)[0], action: 'ui/upload', multiple: false, params: {}, showMessage: function(message){ //notifyMessage(message); }, onSubmit: function(id, fileName){ var xml = json2xml(img_obj,"STORAGE"); uploader.setParams({ occixml : xml, file: fileName }); $('#upload-progress',dialog).show(); }, onProgress: function(id, fileName, loaded, total){ $('#upload-progress',dialog).progressbar("option","value",Math.floor(loaded*100/total)); }, onComplete: function(id, fileName, responseJSON){ popUpImageDashboard(); notifyMessage("Image uploaded correctly"); Sunstone.runAction("Image.list"); return false; }, onCancel: function(id, fileName){ }, }); var file_input = false; uploader._button._options.onChange = function(input) { file_input = input; return false; }; $('#file-uploader input').removeAttr("style"); $('#file-uploader input').attr('style','margin:0;width:256px!important'); var processCreateImageForm = function(){ var dialog = $create_image_dialog; var img_json = {}; var name = $('#img_name',dialog).val(); if (!name){ notifyError(tr("You must specify a name")); return false; }; img_json["NAME"] = name; var desc = $('#img_desc',dialog).val(); if (desc){ img_json["DESCRIPTION"] = desc; } var type = $('#img_type',dialog).val(); img_json["TYPE"]= type; if (type == "DATABLOCK"){ var fstype = $('#img_fstype',dialog).val(); var im_size = $('#img_size',dialog).val(); if (!fstype || !im_size){ notifyError(tr("You must specify size and FS type")); return false; }; img_json["FSTYPE"] = fstype; img_json["SIZE"] = im_size; } else { if (!$('#file-uploader input').val()){ notifyError(tr("You must select a file to upload")); return false; }; } //img_json["PUBLIC"] = $('#img_public:checked',this).length ? "YES" : "NO"; //img_json["PERSISTENT"] = $('#img_persistent:checked',this).length ? "YES" : "NO"; return img_json; }; $('#create_image_form_easy',dialog).submit(function(){ var type = $('#img_type',dialog).val(); img_obj = processCreateImageForm(); if (!img_obj) return false; if (type == "DATABLOCK"){ Sunstone.runAction("Image.create",img_obj); popUpImageDashboard(); } else { uploader._onInputChange(file_input); }; return false; }); } function popUpImageDashboard(){ var count = dataTable_images.fnGetNodes().length; popDialog(image_dashboard); $('#dialog .storage_count').text(count); }; // Set the autorefresh interval for the datatable function setImageAutorefresh() { setInterval(function(){ var checked = $('input.check_item:checked',dataTable_images); var filter = $("#datatable_images_filter input", dataTable_images.parents("#datatable_images_wrapper")).attr('value'); if (!checked.length && !filter.length){ Sunstone.runAction("Image.autorefresh"); } },INTERVAL+someTime()); }; /* function is_public_image(id){ var data = getElementData(id,"#image",dataTable_images)[7]; return $(data).attr('checked'); }; function is_persistent_image(id){ var data = getElementData(id,"#image",dataTable_images)[8]; return $(data).attr('checked'); }; */ //The DOM is ready at this point $(document).ready(function(){ dataTable_images = $("#datatable_images",main_tabs_context).dataTable({ "bJQueryUI": true, "bSortClasses": false, "bAutoWidth":false, "sPaginationType": "full_numbers", "aoColumnDefs": [ { "bSortable": false, "aTargets": ["check"] }, { "sWidth": "60px", "aTargets": [0] }, { "sWidth": "35px", "aTargets": [1] }, ], "oLanguage": (datatable_lang != "") ? { sUrl: "locale/"+lang+"/"+datatable_lang } : "" }); dataTable_images.fnClearTable(); addElement([ spinner, '',''],dataTable_images); Sunstone.runAction("Image.list"); setImageAutorefresh(); initCheckAllBoxes(dataTable_images); tableCheckboxesListener(dataTable_images); imageInfoListener(); $('#li_images_tab').click(function(){ popUpImageDashboard(); //return false; }); $('.image_close_dialog_link').live("click",function(){ popUpImageDashboard(); return false; }); }) opennebula-3.4.1/src/cloud/occi/lib/ui/public/js/plugins/configuration.js0000644000175000017500000000626111750754334026336 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ var config_tab_content = '
\ \ \ \ \
\
\

' + tr("Self-Service UI Configuration") + '

\
\ \ \ \ \ \ \
' + tr("Language") + '\ \
\ \
\
\
'; var config_actions = { "Config.list" : { type : 'list', call : OCCI.Config.list, callback : updateConfig, error : onError }, }; var config_tab = { title: tr("Configuration"), content: config_tab_content } Sunstone.addActions(config_actions); Sunstone.addMainTab('config_tab',config_tab); function updateConfig(request, response){ var config = response; //These two variables defined in compute.js vnc_enable = config['VNC'] == 'true' || config['VNC'] == 'yes' ? true : false; use_wss = config['WSS'] == 'true' || config['WSS'] == 'yes'? true : false; }; $(document).ready(function(){ Sunstone.runAction('Config.list'); $('#li_config_tab').click(function(){ hideDialog(); }); //Set lang to the right value if (lang) $('table#config_table #lang_sel option[value="'+lang+'"]').attr('selected','selected'); //Listen to changes in language $('table#config_table #lang_sel').change(function(){ setLang($(this).val()); }); //Vendor customization, change small logo $('div#logo img').attr('src',logo_small); });opennebula-3.4.1/src/cloud/occi/lib/ui/public/js/plugins/compute.js0000644000175000017500000010054111750754334025137 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ /*Virtual Machines tab plugin*/ var INCLUDE_URI = "vendor/noVNC/include/"; //var VM_HISTORY_LENGTH = 40; function loadVNC(){ var script = ''; document.write(script); } loadVNC(); var vnc_enable=false; var use_wss=false; /* var vm_graphs = [ { title : tr("CPU"), monitor_resources : "cpu_usage", humanize_figures : false, history_length : VM_HISTORY_LENGTH }, { title : tr("Memory"), monitor_resources : "mem_usage", humanize_figures : true, history_length : VM_HISTORY_LENGTH }, { title : tr("Network transmission"), monitor_resources : "net_tx", humanize_figures : true, history_length : VM_HISTORY_LENGTH }, { title : tr("Network reception"), monitor_resources : "net_rx", humanize_figures : true, history_length : VM_HISTORY_LENGTH } ]; */ var vms_tab_content = '
\
\
\ \ \ \ \ \ \ \ \ \ \
'+tr("All")+''+tr("ID")+''+tr("Name")+' / '+tr("State")+'
\
'; var create_vm_tmpl ='
\
\ \
\
\
\ \
\
\
\ \ \
\
\ \ \
\
\
\ \ \
'+tr("You can use the wildcard %i. When creating several VMs, %i will be replaced with a different number starting from 0 in each of them")+'.
\
\
\
\ \ \ \
\
\ '; var vm_dashboard = '
\ one-compute' + compute_dashboard_html + '
'; var dataTable_vMachines; var $create_vm_dialog; var $saveas_vm_dialog; var $vnc_dialog; var rfb; var vm_actions = { "VM.create" : { type: "create", call: OCCI.VM.create, callback: addVMachineElement, error: onError, notify: true }, "VM.create_dialog" : { type: "custom", call: popUpCreateVMDialog, }, "VM.list" : { type: "list", call: OCCI.VM.list, callback: updateVMachinesView, error: onError }, "VM.show" : { type: "single", call: OCCI.VM.show, callback: updateVMachineElement, error: onError }, "VM.showinfo" : { type: "single", call: OCCI.VM.show, callback: updateVMInfo, error: onError }, "VM.refresh" : { type: "custom", call : function (){ waitingNodes(dataTable_vMachines); Sunstone.runAction("VM.list"); }, }, "VM.autorefresh" : { type: "custom", call : function() { OCCI.VM.list({timeout: true, success: updateVMachinesView,error: onError}); }, }, "VM.suspend" : { type: "multiple", call: OCCI.VM.suspend, callback: updateVMachineElement, elements: vmElements, error: onError, notify: true }, "VM.resume" : { type: "multiple", call: OCCI.VM.resume, callback: updateVMachineElement, elements: vmElements, error: onError, notify: true }, "VM.stop" : { type: "multiple", call: OCCI.VM.stop, callback: updateVMachineElement, elements: vmElements, error: onError, notify: true }, "VM.done" : { type: "multiple", call: OCCI.VM.done, callback: deleteVMachineElement, elements: vmElements, error: onError, notify: true }, "VM.shutdown" : { type: "multiple", call: OCCI.VM.shutdown, callback: updateVMachineElement, elements: vmElements, error: onError, notify: true }, "VM.cancel" : { type: "multiple", call: OCCI.VM.cancel, callback: updateVMachineElement, elements: vmElements, error: onError, notify: true }, "VM.saveasmultiple" : { type: "custom", call: function(){ var elems = vmElements(); popUpSaveasDialog(elems); } }, "VM.saveas" : { type: "single", call: OCCI.VM.saveas, callback: updateVMachineElement, error:onError }, "VM.saveas_disks" : { type: "single", call: OCCI.VM.show, callback: saveasDisksCallback, error: onError }, "VM.getInstanceTypes" : { type: "list", call: OCCI.Instance_type.list, callback: function(request,response){ if (response.constructor != Array){ response = [response]; }; var options = ""; for (var i = 0; i'+type+''; }; $('#dialog select#instance_type').html(options); }, error: onError }, "VM.startvnc" : { type: "single", call: OCCI.VM.startvnc, callback: vncCallback, error: onError, notify: true }, "VM.stopvnc" : { type: "single", call: OCCI.VM.stopvnc, error: onError, notify: true }, /* "VM.monitor" : { type: "monitor", call : OCCI.VM.monitor, callback: function(req,response) { var info = req.request.data[0].monitor; plot_graph(response,'#vm_monitoring_tab', 'vm_monitor_',info); }, error: vmMonitorError }, "VM.monitor_all" : { type: "monitor_global", call: OCCI.VM.monitor_all, callback: function(req,response) { var info = req.request.data[0].monitor; plot_global_graph(response,info); }, error: onError }, */ } var vm_buttons = { "VM.refresh" : { type: "image", text: tr("Refresh list"), img: "images/Refresh-icon.png" }, "VM.create_dialog" : { type: "action", text: tr("+ New"), alwaysActive: true }, "VM.shutdown" : { type: "confirm", text: tr("Shutdown"), tip: tr("This will shutdown the selected VMs") }, "action_list" : { type: "select", actions: { "VM.suspend" : { type: "confirm", text: tr("Suspend"), tip: tr("This will suspend the selected VMs") }, "VM.resume" : { type: "confirm", text: tr("Resume"), tip: tr("This will resume the selected VMs in stopped or suspended states") }, "VM.stop" : { type: "confirm", text: tr("Stop"), tip: "This will stop selected VMs" }, "VM.cancel" : { type: "confirm", text: tr("Cancel"), tip: tr("This will cancel selected VMs") }, "VM.saveasmultiple" : { type: "action", text: tr("Take snapshot") } } }, "VM.done" : { type: "confirm", text: tr("Delete"), tip: tr("This will delete the selected VMs from the database") } } var vm_info_panel = { "vm_info_tab" : { title: tr("Compute resource"), content: "" }, "vm_disks_tab" : { title: tr("Disks"), content: "" }, "vm_networks_tab" : { title: tr("Networks"), content: "" }, } var vm_create_panel = { "vm_create_panel" : { title: tr("Create Virtual Machine"), content: create_vm_tmpl }, }; var vms_tab = { title: tr("Compute"), content: vms_tab_content, buttons: vm_buttons } Sunstone.addActions(vm_actions); Sunstone.addMainTab('vms_tab',vms_tab); Sunstone.addInfoPanel('vm_info_panel',vm_info_panel); Sunstone.addInfoPanel('vm_create_panel',vm_create_panel); function vmElements() { return getSelectedNodes(dataTable_vMachines); } // Returns a human readable running time for a VM function str_start_time(vm){ return pretty_time(vm.STIME); } // Returns an array formed by the information contained in the vm_json // and ready to be introduced in a dataTable function vMachineElementArray(vm_json){ var vm = vm_json.COMPUTE; var id,name; if (vm.name){ id = vm.href.split("/"); id = id[id.length-1]; name = vm.name; } else { id = vm.ID; name = vm.NAME; }; return [ '', id, VMStateBulletStr(vm_json) + name ]; } //Creates a listener for the TDs of the VM table function vMachineInfoListener(){ $('#tbodyvmachines tr',dataTable_vMachines).live("click", function(e){ if ($(e.target).is('input') || $(e.target).is('a img')) {return true;} var aData = dataTable_vMachines.fnGetData(this); var id = $(aData[0]).val(); if (!id) return true; popDialogLoading(); Sunstone.runAction("VM.showinfo",id); return false; }); } // Callback to refresh a single element from the list function updateVMachineElement(request, vm_json){ var id = vm_json.COMPUTE.ID; var element = vMachineElementArray(vm_json); updateSingleElement(element,dataTable_vMachines,'#vm_'+id) } // Callback to delete a single element from the list function deleteVMachineElement(request){ deleteElement(dataTable_vMachines,'#vm_'+request.request.data); } // Callback to add an element to the list function addVMachineElement(request,vm_json){ var id = vm_json.COMPUTE.ID; var element = vMachineElementArray(vm_json); addElement(element,dataTable_vMachines); Sunstone.runAction("VM.showstate",id); } // Callback to refresh the list of Virtual Machines function updateVMachinesView(request, vmachine_list){ var vmachine_list_array = []; var el_array; $.each(vmachine_list,function(){ el_array = vMachineElementArray(this); vmachine_list_array.push(el_array); }); updateView(vmachine_list_array,dataTable_vMachines); updateDashboard("vms",vmachine_list); }; function VMStateBulletStr(vm){ var vm_state = vm.COMPUTE.STATE; var state_html = ""; switch (vm_state) { case "INIT": case "PENDING": case "HOLD": case "STOPPED": case "SUSPENDED": state_html = ''+vm_state+''; break; case "ACTIVE": case "DONE": state_html = ''+vm_state+''; break; case "FAILED": state_html = ''+vm_state+''; break; }; return state_html; } // Refreshes the information panel for a VM function updateVMInfo(request,vm){ var vm_info = vm.COMPUTE; var info_tab = { title : tr("VM information"), content: '\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \
'+tr("Virtual Machine information")+' - '+vm_info.NAME+'
'+tr("ID")+''+vm_info.ID+'
'+tr("Name")+''+vm_info.NAME+'
'+tr("Instance type")+''+(vm_info.INSTANCE_TYPE ? vm_info.INSTANCE_TYPE : "--")+'
'+tr("State")+''+tr(vm_info.STATE)+'
'+tr("CPU")+''+vm_info.CPU+'
'+tr("Memory")+''+vm_info.MEMORY+'
'+tr("Launch VNC session")+''+vncIcon(vm_info)+'
\
\
' }; var disks_str = '\ \ \ '; var disks = vm_info.DISK; if (disks){ if (disks.constructor != Array) // 1lease disks = [disks]; for (var i=0;i\ \ \ \ \ \ \ \ \ \ \ \ \ \ '; }; } else { disks_str += ''; }; disks_str += '
'+tr("Disks information")+'
'+disks[i].id+'
'+tr("Name")+''+disks[i].STORAGE.name+'
'+tr("Target")+''+disks[i].TARGET+'
'+tr("Type")+''+disks[i].TYPE+'
'+ tr("No disks defined")+'
\
\
'; var disks_tab = { title : tr("Disks"), content : disks_str }; var networks_str = '\ \ \ '; var networks = vm_info.NIC; if (networks){ if (networks.constructor != Array) // 1lease networks = [networks]; for (var i=0;i\ \ \ \ \ \ \ \ \ \ \ \ \ \ '; }; } else { networks_str += ''; }; networks_str += '
'+tr("Networks information")+'
'+net_id+'
'+tr("Name")+''+networks[i].NETWORK.name+'
'+tr("IP")+''+networks[i].IP+'
'+tr("MAC")+''+networks[i].MAC+'
'+ tr("No networks defined")+'
\
\
'; var networks_tab = { title : tr("Networks"), content : networks_str }; /* var monitoring_tab = { title: tr("Monitoring information"), content: generateMonitoringDivs(vm_graphs,"vm_monitor_") } */ Sunstone.updateInfoPanelTab("vm_info_panel","vm_info_tab",info_tab); Sunstone.updateInfoPanelTab("vm_info_panel","vm_disks_tab",disks_tab); Sunstone.updateInfoPanelTab("vm_info_panel","vm_networks_tab",networks_tab); //Sunstone.updateInfoPanelTab("vm_info_panel","vm_monitoring_tab",monitoring_tab); //Pop up the info panel and asynchronously get vm_log and stats Sunstone.popUpInfoPanel("vm_info_panel"); $('#dialog .vm_close_dialog_link').button({ text:false, icons: { primary: "ui-icon-closethick" } }); // Sunstone.runAction("VM.log",vm_info.ID); // for (var i=0; i'); }); }; var nets = $('#network_box option[clicked="clicked"]'); if (nets.length){ vm["NIC"] = []; nets.each(function(){ var value = $(this).val(); vm["NIC"].push(''); }); }; if (n_times.length){ n_times_int=parseInt(n_times,10); }; if (vm_name.indexOf("%i") == -1){ //no wildcard for (var i=0; i< n_times_int; i++){ Sunstone.runAction("VM.create",vm); }; } else { //wildcard present: replace wildcard var name = ""; for (var i=0; i< n_times_int; i++){ name = vm_name.replace(/%i/gi,i); vm["NAME"] = name; Sunstone.runAction("VM.create",vm); }; }; popUpVMDashboard(); return false; }); } //Prepares a dialog to saveas a VM function setupSaveasDialog(){ //Append to DOM dialogs_context.append('
'); $saveas_vm_dialog = $('#saveas_vm_dialog',dialogs_context); var dialog = $saveas_vm_dialog; //Put HTML in place dialog.html('\
\
\
\
\ \ \
\ \
'); dialog.dialog({ autoOpen:false, width:600, modal:true, height:350, resizable:true, }); $('#saveas_vm_form',dialog).submit(function(){ var elems = $('#saveas_tabs div.saveas_tab',this); var args = []; $.each(elems,function(){ var id = $('#vm_id',this).text(); var disk_id = $('#vm_disk_id',this).val(); var image_name = $('#image_name',this).val(); if (!id.length || !disk_id.length || !image_name.length) { notifyError(tr("Skipping VM ")+id+". "+ tr("No disk id or image name specified")); } else { var obj = { disk_id : disk_id, image_name : image_name, }; args.push(id); Sunstone.runAction("VM.saveas",id,obj); } }); if (args.length > 0){ notifySubmit("VM.saveas",args); } $saveas_vm_dialog.dialog('close'); return false; }); $('#vm_saveas_cancel',dialog).click(function(){ $saveas_vm_dialog.dialog('close'); return false; }); } function popUpSaveasDialog(elems){ var dialog = $saveas_vm_dialog; $('#saveas_tabs',dialog).tabs('destroy'); $('#saveas_tabs',dialog).empty(); $('#saveas_tabs',dialog).html('
    '); $.each(elems,function(){ var li = '
  • VM '+this+'
  • ' $('#saveas_tabs ul',dialog).append(li); var tab = '
    \
    '+tr("Saveas for VM with ID")+' '+this+'
    \
    \
    \ \ \
    \
    \ \ \
    \
    \
    '; $('#saveas_tabs',dialog).append(tab); Sunstone.runAction("VM.saveas_disks",this); }); $('#saveas_tabs',dialog).tabs(); $('button',dialog).button(); dialog.dialog('open'); } function saveasDisksCallback(req,response){ var vm_info = response.COMPUTE; var id=vm_info.ID; var select=""; var gen_option = function(id, name, source){ if (name){ return ''; } else { return ''; } } var disks = vm_info.DISK; if (!disks) { select = '';} else if (disks.constructor == Array) //several disks { for (var i=0;i
    '); $vnc_dialog = $('#vnc_dialog',dialogs_context); var dialog = $vnc_dialog; dialog.html('\
    \ \ \ \
    '+tr("Loading")+'
    \ \
    \
    \ \ '+tr("Canvas not supported.")+'\ \ '); dialog.dialog({ autoOpen:false, width:750, modal:true, height:500, resizable:true, closeOnEscape: false }); $('#sendCtrlAltDelButton',dialog).click(function(){ rfb.sendCtrlAltDel(); return false; }); dialog.bind( "dialogclose", function(event, ui) { var id = $vnc_dialog.attr('vm_id'); rfb.disconnect(); Sunstone.runAction("VM.stopvnc",id); }); $('.vnc').live("click",function(){ //Which VM is it? var id = $(this).attr('vm_id'); //Set attribute to dialog $vnc_dialog.attr('vm_id',id); //Request proxy server start Sunstone.runAction("VM.startvnc",id); return false; }); } function vncCallback(request,response){ rfb = new RFB({'target': $D('VNC_canvas'), 'encrypt': use_wss, 'true_color': true, 'local_cursor': true, 'shared': true, 'updateState': updateVNCState}); //fetch things from clicked element host - port - password vnc_port = response["port"]; //Hopefully this is returning sunstone server address, where //the proxy is running vnc_host = window.location.hostname; vnc_pw = response["password"]; setTimeout(function(){ rfb.connect(vnc_host, vnc_port, vnc_pw); $vnc_dialog.dialog('open'); },4000); } function vncIcon(vm){ var gr_icon; if (vnc_enable){ gr_icon = ''; gr_icon += '\"'+tr("Open'; } else { gr_icon = '\"'+tr("VNC'; } return gr_icon; } /* function vncIcon(vm){ var graphics = vm.TEMPLATE.GRAPHICS; var state = vm.STATE; var gr_icon; if (graphics && graphics.TYPE == "vnc" && state == "RUNNING"){ gr_icon = ''; gr_icon += '\"'+tr("Open'; } else { gr_icon = '\"'+tr("VNC'; } return gr_icon; } */ /* function vmMonitorError(req,error_json){ var message = error_json.error.message; var info = req.request.data[0].monitor; var labels = info.monitor_resources; var id_suffix = labels.replace(/,/g,'_'); var id = '#vm_monitor_'+id_suffix; $('#vm_monitoring_tab '+id).html('
    '+message+'
    '); }*/ // At this point the DOM is ready and the sunstone.js ready() has been run. $(document).ready(function(){ dataTable_vMachines = $("#datatable_vmachines",main_tabs_context).dataTable({ "bJQueryUI": true, "bSortClasses": false, "sPaginationType": "full_numbers", "bAutoWidth":false, "aoColumnDefs": [ { "bSortable": false, "aTargets": ["check"] }, { "sWidth": "60px", "aTargets": [0] }, { "sWidth": "35px", "aTargets": [1] }, ], "oLanguage": (datatable_lang != "") ? { sUrl: "locale/"+lang+"/"+datatable_lang } : "" }); dataTable_vMachines.fnClearTable(); addElement([ spinner, '',''],dataTable_vMachines); Sunstone.runAction("VM.list"); //setupCreateVMDialog(); setupSaveasDialog(); setVMAutorefresh(); setupVNC(); initCheckAllBoxes(dataTable_vMachines); tableCheckboxesListener(dataTable_vMachines); vMachineInfoListener(); $('#li_vms_tab').click(function(){ popUpVMDashboard(); }); $('.vm_close_dialog_link').live("click",function(){ popUpVMDashboard(); return false; }); })opennebula-3.4.1/src/cloud/occi/lib/ui/public/js/plugins/network.js0000644000175000017500000003154511750754334025163 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ /*Virtual networks tab plugin*/ var vnets_tab_content = '
    \
    \
    \ \ \ \ \ \ \ \ \ \ \
    '+tr("All")+''+tr("ID")+''+tr("Name")+'
    \
    '; var create_vn_tmpl = '
    \
    \
    \
    \ \
    \
    \
    \
    \
    \ \
    \ \
    \
    \
    \
    \ \
    \ \ \ \
    \
    \
    \
    '; var vnet_dashboard = '
    \ one-network' + network_dashboard_html + '
    '; var dataTable_vNetworks; var $create_vn_dialog; //Setup actions var vnet_actions = { "Network.create" : { type: "create", call: OCCI.Network.create, callback: addVNetworkElement, error: onError, notify: true }, "Network.create_dialog" : { type: "custom", call: popUpCreateVnetDialog }, "Network.list" : { type: "list", call: OCCI.Network.list, callback: updateVNetworksView, error: onError }, "Network.show" : { type: "single", call: OCCI.Network.show, callback: updateVNetworkElement, error: onError }, "Network.showinfo" : { type: "single", call: OCCI.Network.show, callback: updateVNetworkInfo, error: onError }, "Network.refresh" : { type: "custom", call: function(){ waitingNodes(dataTable_vNetworks); Sunstone.runAction("Network.list"); } }, "Network.autorefresh" : { type: "custom", call: function() { OCCI.Network.list({timeout: true, success: updateVNetworksView, error: onError}); } }, // "Network.publish" : { // type: "multiple", // call: OCCI.Network.publish, // //callback: vnShow, // elements: vnElements, // error: onError, // notify: true // }, // "Network.unpublish" : { // type: "multiple", // call: OCCI.Network.unpublish, // //callback: vnShow, // elements: vnElements, // error: onError, // notify: true // }, "Network.delete" : { type: "multiple", call: OCCI.Network.del, callback: deleteVNetworkElement, elements: vnElements, error: onError, notify: true }, }; var vnet_buttons = { "Network.refresh" : { type: "image", text: tr("Refresh list"), img: "images/Refresh-icon.png" }, "Network.create_dialog" : { type: "create_dialog", text: tr("+ New") }, // "Network.publish" : { // type: "action", // text: tr("Publish") // }, // "Network.unpublish" : { // type: "action", // text: tr("Unpublish") // }, "Network.delete" : { type: "action", text: tr("Delete") } } var vnet_info_panel = { "vnet_info_tab" : { title: tr("Network information"), content: "" }, } var vnet_create_panel = { "vnet_create_panel" : { title: tr("Create network"), content: create_vn_tmpl }, } var vnets_tab = { title: tr("Networks"), content: vnets_tab_content, buttons: vnet_buttons } Sunstone.addActions(vnet_actions); Sunstone.addMainTab('vnets_tab',vnets_tab); Sunstone.addInfoPanel('vnet_info_panel',vnet_info_panel); Sunstone.addInfoPanel('vnet_create_panel',vnet_create_panel); function vnElements(){ return getSelectedNodes(dataTable_vNetworks); } //returns an array with the VNET information fetched from the JSON object function vNetworkElementArray(vn_json){ var network = vn_json.NETWORK; if (network.name){ id = network.href.split("/"); id = id[id.length-1]; name = network.name; } else { id = network.ID; name = network.NAME; }; return [ '', id, name ]; }; //Adds a listener to show the extended info when clicking on a row function vNetworkInfoListener(){ $('#tbodyvnetworks tr',dataTable_vNetworks).live("click", function(e){ if ($(e.target).is('input')) {return true;}; var aData = dataTable_vNetworks.fnGetData(this); var id = $(aData[0]).val(); if (!id) return true; popDialogLoading(); Sunstone.runAction("Network.showinfo",id); return false; }); } //Callback to update a vnet element after an action on it function updateVNetworkElement(request, vn_json){ id = vn_json.NETWORK.ID; element = vNetworkElementArray(vn_json); updateSingleElement(element,dataTable_vNetworks,'#vnetwork_'+id); } //Callback to delete a vnet element from the table function deleteVNetworkElement(req){ deleteElement(dataTable_vNetworks,'#vnetwork_'+req.request.data); } //Callback to add a new element function addVNetworkElement(request,vn_json){ var element = vNetworkElementArray(vn_json); addElement(element,dataTable_vNetworks); } //updates the list of virtual networks function updateVNetworksView(request, network_list){ var network_list_array = []; $.each(network_list,function(){ network_list_array.push(vNetworkElementArray(this)); }); updateView(network_list_array,dataTable_vNetworks); //dependency with dashboard updateDashboard("vnets",network_list); } //updates the information panel tabs and pops the panel up function updateVNetworkInfo(request,vn){ var vn_info = vn.NETWORK; var info_tab_content = '\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '; if (vn_info.ADDRESS){ info_tab_content += '\ \ \ \ \ \ \ \ '; }; info_tab_content += '\
    '+tr("Virtual Network")+' '+vn_info.ID+' '+ tr("information")+'
    '+tr("ID")+''+vn_info.ID+'
    '+tr("Name")+''+vn_info.NAME+'
    '+tr("Used leases")+''+vn_info.USED_LEASES+'
    '+tr("Address")+''+vn_info.ADDRESS+'
    '+tr("Size")+''+vn_info.SIZE+'
    \
    \
    '; var info_tab = { title: tr("Virtual Network information"), content: info_tab_content }; Sunstone.updateInfoPanelTab("vnet_info_panel","vnet_info_tab",info_tab); Sunstone.popUpInfoPanel("vnet_info_panel"); $('#dialog .vnet_close_dialog_link').button({ text:false, icons: { primary: "ui-icon-closethick" } }); } function popUpCreateVnetDialog() { //$create_vn_dialog.dialog('open'); //Handle submission of the easy mode Sunstone.popUpInfoPanel("vnet_create_panel"); var dialog=$('#dialog'); $create_vn_dialog = dialog; $('#create_vn',dialog).button({ icons: { primary: "ui-icon-check" }, text: true }); /* $('#reset_vn',dialog).button({ icons: { primary: "ui-icon-scissors" }, text: false }); */ $('.vnet_close_dialog_link',dialog).button({ icons: { primary: "ui-icon-closethick" }, text: true }); $('#create_vn_form_easy',dialog).submit(function(){ //Fetch values var name = $('#name',this).val(); if (!name.length){ notifyError(tr("Virtual Network name missing!")); return false; } var bridge = $('#bridge',this).val(); //TODO: Name and bridge provided?! var network_json = null; var network_addr = $('#net_address',this).val(); var network_size = $('#net_size',this).val(); if (!network_addr.length){ notifyError(tr("Please provide a network address")); return false; }; //we form the object for the request network_json = { "SIZE" : network_size, "ADDRESS" : network_addr, "NAME" : name }; Sunstone.runAction("Network.create",network_json); popUpVNetDashboard(); return false; }); } function popUpVNetDashboard(){ var count = dataTable_vNetworks.fnGetNodes().length; popDialog(vnet_dashboard); $('#dialog .network_count').text(count); } function setVNetAutorefresh() { setInterval(function(){ var checked = $('input.check_item:checked',dataTable_vNetworks); var filter = $("#datatable_vnetworks_filter input", dataTable_vNetworks.parents("#datatable_vnetworks_wrapper")).attr('value'); if (!checked.length && !filter.length){ Sunstone.runAction("Network.autorefresh"); } },INTERVAL+someTime()); }; //The DOM is ready and the ready() from sunstone.js //has been executed at this point. $(document).ready(function(){ dataTable_vNetworks = $("#datatable_vnetworks",main_tabs_context).dataTable({ "bJQueryUI": true, "bSortClasses": false, "bAutoWidth":false, "sPaginationType": "full_numbers", "aoColumnDefs": [ { "bSortable": false, "aTargets": ["check"] }, { "sWidth": "60px", "aTargets": [0] }, { "sWidth": "35px", "aTargets": [1] }, ], "oLanguage": (datatable_lang != "") ? { sUrl: "locale/"+lang+"/"+datatable_lang } : "" }); dataTable_vNetworks.fnClearTable(); addElement([ spinner, '',''],dataTable_vNetworks); Sunstone.runAction("Network.list"); setVNetAutorefresh(); initCheckAllBoxes(dataTable_vNetworks); tableCheckboxesListener(dataTable_vNetworks); vNetworkInfoListener(); $('#li_vnets_tab').click(function(){ popUpVNetDashboard(); //return false; }); $('.vnet_close_dialog_link').live("click",function(){ popUpVNetDashboard(); return false; }); }); opennebula-3.4.1/src/cloud/occi/lib/ui/public/js/login.js0000644000175000017500000000604111750754334023112 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ function auth_success(req, response){ window.location.href = "./ui"; } function auth_error(req, error){ var status = error.error.http_status; switch (status){ case 401: $("#error_box").text("Invalid username or password"); break; case 500: $("#error_box").text("OpenNebula is not running or there was a server exception. Please check the server logs."); break; case 0: $("#error_box").text("No answer from server. Is it running?"); break; default: $("#error_box").text("Unexpected error. Status "+status+". Check the server logs."); }; $("#error_box").fadeIn("slow"); $("#login_spinner").hide(); } function authenticate(){ var username = $("#username").val(); var password = $("#password").val(); password = Crypto.SHA1(password); var remember = $("#check_remember").is(":checked"); $("#error_box").fadeOut("slow"); $("#login_spinner").show(); var obj = { data: {username: username, password: password}, remember: remember, success: auth_success, error: auth_error }; if (('localStorage' in window) && (window['localStorage'] !== null) && (localStorage['lang'])){ obj['lang'] = localStorage['lang']; }; OCCI.Auth.login(obj); } $(document).ready(function(){ $('div#logo_selfservice').css("background","url("+logo_big+") no-repeat center"); $("#login_form").submit(function (){ authenticate(); return false; }); //compact login elements according to screen height if (screen.height <= 600){ $('div#logo_selfservice').css("top","15px"); $('div#login').css("top","10px"); $('.error_message').css("top","10px"); }; $("input#username.box").focus(); $("#login_spinner").hide(); }); opennebula-3.4.1/src/cloud/occi/lib/ui/public/js/locale.js0000644000175000017500000000503611750754334023244 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ var lang="" var locale = {}; var datatable_lang = ""; function tr(str){ var tmp = locale[str]; if ( tmp == null || tmp == "" ) { //console.debug("Missing translation: "+str); tmp = str; } return tmp; }; //Pops up loading new language dialog. Retrieves the user template, updates the LANG variable. //Updates template and session configuration and reloads the view. function setLang(lang_str){ var dialog = $('
    '+ tr("Loading new language... please wait")+ ' '+spinner+'
    ').dialog({ draggable:false, modal:true, resizable:false, buttons:{}, width: 460, minHeight: 50 }); if (('localStorage' in window) && (window['localStorage'] !== null)){ localStorage['lang']=lang_str; }; $.post('ui/config',JSON.stringify({lang:lang_str}),function(){window.location.href = "./ui"}); }; $(document).ready(function(){ //Update static translations $('#doc_link').text(tr("Documentation")); $('#support_link').text(tr("Support")); $('#community_link').text(tr("Community")); $('#welcome').text(tr("Welcome")); $('#logout').text(tr("Sign out")); });opennebula-3.4.1/src/cloud/occi/lib/ui/public/js/layout.js0000644000175000017500000001370511750754334023324 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 file is mostly a copy of layout.js from Sunstone. //Instead of opening a south panel, it opens an east panel. //Apart from document.ready() modifications, the rest of different lines are //makerd with MODIFIED var activeTab; var outerLayout, innerLayout; function hideDialog(){ innerLayout.close("east");//MODIFIED } function popDialog(content){ $("#dialog").html(content); innerLayout.open("east");//MODIFIED } function popDialogLoading(){ var loading = '
    loading...
    '; popDialog(loading); } function showTab(tabname,highlight_tab){ //Since menu items no longer have an element //we no longer expect #tab_id here, but simply tab_id //So safety check - remove # from #tab_id if present to ensure compatibility if (tabname.indexOf('#') == 0) tabname = tabname.substring(1); if (highlight_tab && highlight_tab.indexOf('#') == 0) highlight_tab == highlight.substring(1); var activeTab = tabname; if (!highlight_tab) highlight_tab = activeTab; //clean selected menu $("#navigation li").removeClass("navigation-active-li"); $("div#header ul#menutop_ul li").removeClass("navigation-active-li"); //select tab in left menu var li = $("#navigation li#li_"+highlight_tab) li.addClass("navigation-active-li"); //select tab in top menu var top_li = $("div#header ul#menutop_ul li#top_"+highlight_tab); top_li.addClass("navigation-active-li"); //show tab $(".tab").hide(); $('#'+activeTab).show(); // innerLayout.close("south");//MODIFIED commented }; function setupTabs(){ var topTabs = $(".outer-west ul li.topTab"); var subTabs = $(".outer-west ul li.subTab"); subTabs.live("click",function(){ //leave floor to topTab listener in case of tabs with both classes if ($(this).hasClass('topTab')) return false; var tab = $(this).attr('id').substring(3); showTab(tab); return false; }); topTabs.live("click",function(e){ var tab = $(this).attr('id').substring(3); //Subtabs have a class with the name of this tab var subtabs = $('div#menu li.'+tab); //toggle subtabs only when clicking on the icon or when clicking on an //already selected menu if ($(e.target).is('span') || $(this).hasClass("navigation-active-li")){ //for each subtab, we hide the subsubtabs subtabs.each(function(){ //for each subtab, hide its subtabs var subsubtabs = $(this).attr('id').substr(3); //subsubtabs class subsubtabs = $('div#menu li.'+subsubtabs); subsubtabs.hide(); }); //hide subtabs and reset icon to + position, since all subsubtabs //are hidden subtabs.fadeToggle('fast'); $('span',subtabs).removeClass('ui-icon-circle-minus'); $('span',subtabs).addClass('ui-icon-circle-plus'); //toggle icon on this tab $('span',this).toggleClass('ui-icon-circle-plus ui-icon-circle-minus'); }; //if we are clicking on the icon only, do not show the tab if ($(e.target).is('span')) return false; showTab(tab); return false; }); }; function setupTopMenu(){ $('div#header ul#menutop_ul li').live('click',function(){ var tab = "#" + $(this).attr('id').substring(4); showTab(tab); }); }; $(document).ready(function () { $(".tab").hide(); setupTabs(); //setupTopMenu(); outerLayout = $('body').layout({ applyDefaultStyles: false , center__paneSelector: ".outer-center" , west__paneSelector: ".outer-west" , west__size: 160 , north__size: 26 , south__size: 26 , spacing_open: 0 // ALL panes , spacing_closed: 0 // ALL panes //, north__spacing_open: 0 //, south__spacing_open: 0 , north__maxSize: 200 , south__maxSize: 200 , south__closable: false , north__closable: false , west__closable: false , south__resizable: false , north__resizable: false , west__resizable: false }); var factor = 0.45; var dialog_height = Math.floor($(".outer-center").width()*factor); innerLayout = $('div.outer-center').layout({ fxName: "slide" , initClosed: true , center__paneSelector: ".inner-center" , east__paneSelector: ".inner-east" , east__size: dialog_height , east__minSize: 400 , spacing_open: 5 // ALL panes , spacing_closed: 5 // ALL panes }); }); opennebula-3.4.1/src/cloud/occi/lib/ui/public/customize/0000755000175000017500000000000011750754334023051 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/public/customize/custom.js0000644000175000017500000001464511750754334024733 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ //OpenNebula Self-Service customization file. //Use tr("String") to enable text translation. //You can use HTML and the following variables. var $vm_count = ''; var $storage_count = ''; var $network_count = ''; //Login logo 591x43px var logo_big = "images/opennebula-selfservice-big.png"; //Top left logo 179x14px var logo_small = "images/opennebula-selfservice-small.png"; //////////////////////////////////////////////////////////////// // Dashboard tab customization //////////////////////////////////////////////////////////////// //// //Dashboard Welcome box //// var dashboard_welcome_title = tr("Welcome to OpenNebula Self-Service"); var dashboard_welcome_image = "images/opennebula-selfservice-icon.png" var dashboard_welcome_html = '

    '+tr("OpenNebula Self-Service is a simplified user interface to manage OpenNebula compute, storage and network resources. It is focused on easiness and usability and features a limited set of operations directed towards end-users.")+'

    \

    '+tr("Additionally, OpenNebula Self-Service allows easy customization of the interface (e.g. this text) and brings multi-language support.")+'

    \

    '+tr("Have a cloudy experience!")+'

    '; //// //Dashboard useful links box //Array of { href: "address", text: "text" },... //// var dashboard_links = [ { href: "http://opennebula.org/documentation:documentation", text: tr("Documentation") }, { href: "http://opennebula.org/support:support", text: tr("Support") }, { href: "http://opennebula.org/community:community", text: tr("Community") } ]; //// //Dashboard right-side boxes //// var compute_box_title = tr("Compute"); var compute_box_image = "images/server_icon.png"; //scaled to 100px width var compute_box_html = '

    '+tr("Compute resources are Virtual Machines attached to storage and network resources. OpenNebula Self-Service allows you to easily create, remove and manage them, including the possibility of pausing a Virtual Machine or taking a snapshot of one of their disks.")+'

    '; var storage_box_title = tr("Storage"); var storage_box_image = "images/storage_icon.png"; //scaled to 100px width var storage_box_html = '

    '+tr("Storage pool is formed by several images. These images can contain from full operating systems to be used as base for compute resources, to simple data. OpenNebula Self-Service offers you the possibility to create or upload your own images.")+'

    '; var network_box_title = tr("Network"); var network_box_image = "images/network_icon.png"; var network_box_html = '

    '+tr("Your compute resources connectivity is performed using pre-defined virtual networks. You can create and manage these networks using OpenNebula Self-Service.")+'

    '; /////////////////////////////////////////////////////////// //Compute tab /////////////////////////////////////////////////////////// var compute_dashboard_image = "images/one-compute.png"; var compute_dashboard_html = '

    ' + tr("This is a list of your current compute resources. Virtual Machines use previously defined images and networks. You can easily create a new compute element by cliking \'new\' and filling-in an easy wizard.")+'

    \

    '+tr("You can also manage compute resources and perform actions such as stop, resume, shutdown or cancel.")+'

    \

    '+tr("Additionally, you can take a \'snapshot\' of the storage attached to these resources. They will be saved as new resources, visible from the Storage view and re-usable.")+'

    \

    '+tr("There are currently")+' '+$vm_count+' '+ tr("virtual machines")+'.

    '; /////////////////////////////////////////////////////////// //Storage tab /////////////////////////////////////////////////////////// var storage_dashboard_image = "images/one-storage.png"; var storage_dashboard_html = '

    '+tr("The Storage view offers you an overview of your current images. Storage elements are attached to compute resources at creation time. They can also be extracted from running virtual machines by taking an snapshot.")+'

    \

    '+tr("You can add new storages by clicking \'new\'. Image files will be uploaded to OpenNebula and set ready to be used.")+'

    \

    '+tr("Additionally, you can run several operations on defined storages, such as defining their persistance. Persistent images can only be used by 1 virtual machine, and the changes made by it have effect on the base image. Non-persistent images are cloned before being used in a Virtual Machine, therefore changes are lost unless a snapshot is taken prior to Virtual Machine shutdown.")+'

    \

    '+tr("There are currently")+' '+$storage_count+' '+ tr("images")+'.

    '; /////////////////////////////////////////////////////////// //Network tab /////////////////////////////////////////////////////////// var network_dashboard_image = "image/one-network.png"; var network_dashboard_html = '

    '+tr("In this view you can easily manage OpenNebula Network resources. You can add or remove virtual networks.")+'

    \

    '+tr("Compute resources can be attached to these networks at creation time. Virtual machines will be provided with an IP and the correct parameters to ensure connectivity.")+'

    \

    '+ tr("There are currently")+' '+$network_count+' '+ tr("networks")+'.

    ';opennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/0000755000175000017500000000000011750754334022266 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/es_ES/0000755000175000017500000000000011750754334023264 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/es_ES/es_ES.js0000644000175000017500000003004711750754334024624 0ustar drazzibdrazzib//Translated by Hector Sanjuan lang="es_ES" datatable_lang="es_datatable.txt" locale={ "Additionally, OpenNebula Self-Service allows easy customization of the interface (e.g. this text) and brings multi-language support.":"Además, OpenNebula Self-Service permite una fácil personalización de la interfaz (por ejemplo, de este mismo texto) y viene con soporte para múltiples lenguajes.", "Additionally, you can run several operations on defined storages, such as defining their persistance. Persistent images can only be used by 1 virtual machine, and the changes made by it have effect on the base image. Non-persistent images are cloned before being used in a Virtual Machine, therefore changes are lost unless a snapshot is taken prior to Virtual Machine shutdown.":"Además, puede ejecutar varias operaciones en los almacenamientos presentes, como definir su persistencia. Las imágenes persistentes sólo pueden ser usadas por 1 máquina virtual, y los cambios realizados por ella tiene efecto en la imágen base. Las imágenes no persistentes son clonadas antes de ser utilizadas en una máquina virtual, por tanto los cambios se pierden a menos que se tome una instantánea antes de apagar la máquina virtual.", "Additionally, you can take a 'snapshot' of the storage attached to these resources. They will be saved as new resources, visible from the Storage view and re-usable.":"Además, puede tomar una 'instantánea' de los almacenamientos asociado a estos recursos. Ésta será salvaguardada como un nuevo recurso, visible y reutilizable desde la vista de almacenamientos.", "Address":"Dirección", "Add storage":"Añadir almacenamiento", "All":"Todos", "are mandatory":"son obligatorios", "Cancel":"Cancelar", "Cannot contact server: is it running and reachable?":"No se puede contactar con el servidor: ¿está funcionando y es alcanzable?", "Canvas not supported.":"Canvas no soportado", "CD-ROM":"CD-ROM", "Changing language":"Cambiando el lenguaje", "Close":"Cerrar", "Community":"Comunidad", "Compute":"Máquinas Virtuales", "Compute resource":"máquina virtual", "Compute resources are Virtual Machines attached to storage and network resources. OpenNebula Self-Service allows you to easily create, remove and manage them, including the possibility of pausing a Virtual Machine or taking a snapshot of one of their disks.":"Las máquinas virtuales están asociadas a recursos de almacenamiento y de red. OpenNebula Self-Service le permite crearlos, borrarlos y administrarlos fácilmente, incluyendo la posibilidad de pausar una máquina virtual o de tomar una instantánea de alguno de sus discos.", "Compute resources can be attached to these networks at creation time. Virtual machines will be provided with an IP and the correct parameters to ensure connectivity.":"Las máquinas virtuales pueden asociarse a estas redes en el momento de su creación. Las máquinas virtuales serán provistas de una IP y de los parámetros correctos para asegurar conectividad.", "Configuration":"Configuración", "Confirmation of action":"Confirmar operación", "CPU":"CPU", "Create":"Crear", "Create network":"Crear red", "Create new compute resource":"Crear nueva máquina virtual", "Create new network resource":"Crear nueva red", "Create new storage resource":"Crear nuevo almacenamiento", "Create Virtual Machine":"Crear máquina virtual", "Create # VMs":"Crear # MVs", "Current resources":"Recursos actuales", "Dashboard":"Portada", "Datablock":"Datablock", "Delete":"Borrar", "Description":"Descripción", "disk id":"id del disco", "Disks":"Discos", "Disks information":"Información de discos", "Documentation":"Documentación", "Do you want to proceed?":"¿Desea continuar?", "English":"Inglés", "Error":"Error", "Fields marked with":"Campos marcados con", "Filesystem type":"Sistema de ficheros", "FS type":"tipo de FS", "Have a cloudy experience!":"¡Nos vemos en las nubes!", "Human readable description of the image.":"Descripción de la imagen.", "ID":"ID", "Image":"Imagen", "Image information":"Información de la imagen", "Image name":"Nombre de la imagen", "images":"imágenes", "Images":"Imágenes", "Info":"Información", "information":"Información", "Instance type":"Tipo de instancia", "In this view you can easily manage OpenNebula Network resources. You can add or remove virtual networks.":"En esta vista puede gestionar fácilmente los recursos de red de OpenNebula. Puede añadir o borrar redes virtuales.", "IP":"IP", "Language":"Lenguaje", "Launch VNC session":"Lanzar sesión VNC", "Loading":"Cargando", "Loading new language... please wait":"Cargando nuevo lenguaje... espere, por favor", "MAC":"MAC", "Make non persistent":"Hacer no persistente", "Make persistent":"Hacer persistente", "Memory":"Memoria", "Monitoring information":"Información de monitorización", "Name":"Nombre", "Name that the Image will get.":"Nombre para la imagen.", "Network":"Red", "Network Address":"Dirección de red", "Network information":"Información de red", "Network is unreachable: is OpenNebula running?":"No se puede alcanzar la red: ¿está OpenNebula funcionando?", "Network reception":"Recepción de red", "networks":"redes", "Networks":"Redes", "Networks information":"Información de redes", "Network Size":"Tamaño de red", "Network transmission":"Transmisión de red", "+ New":"+ Nuevo", "No disk id or image name specified":"No se ha especificado ID de disco o nombre de la imagen", "No disks defined":"No hay discos definidos", "No networks defined":"No hay redes definidas", "OK":"OK", "OpenNebula Self-Service is a simplified user interface to manage OpenNebula compute, storage and network resources. It is focused on easiness and usability and features a limited set of operations directed towards end-users.":"OpenNebula Self-Service es una interfaz de usuario simplificada para administrar máquinas virtuales, almacenamiento y red de OpenNebula. Está basada en la facilidad de uso y cuenta con un número limitado de operaciones dirigidas a los usuarios finales.", "Open VNC Session":"Abrir sesión VNC", "OS":"OS", "Persistence of the image":"Persistencia de la imagen", "Persistent":"Persistente", "Please, choose and modify the template you want to update":"Por favor, escoja y modifique la plantilla que desea actualizar", "Please provide a network address":"Por favor, proporcione una dirección de red", "Please select":"Por favor escoja", "Previous action":"Acción anterior", "Public":"Público", "Public scope of the image":"Imagen pública", "Publish":"Publicar", "Refresh list":"Refrescar lista", "Resume":"Reanudar", "Retrieving":"Cargando", "Saveas for VM with ID":"Instantánea a MV con ID", "See more":"Ver más", "Select a template":"Seleccione una plantilla", "Select disk":"Seleccione un disco", "Select image to upload":"Seleccione una imagen para subir", "Self-Service UI Configuration":"Configuración de la interfaz Self-Service", "Shutdown":"Apagar", "Sign out":"Desconectar", "Size":"Tamaño", "Size (Mb)":"Tamaño (Mb)", "Size of the datablock in MB.":"Tamaño del datablcok en MB", "Skipping VM ":"Saltando MV", "Spanish":"Español", "State":"Estado", "Stop":"Detener", "Storage":"Almacenamiento", "Storage pool is formed by several images. These images can contain from full operating systems to be used as base for compute resources, to simple data. OpenNebula Self-Service offers you the possibility to create or upload your own images.":"La lista de almacenamiento está formada por varias imágenes. Estas imágenes pueden contener desde sistemas operativos completos para ser usados como base en máquinas virtuales, hasta simples datos. OpenNebula Self-Service ofrece la posibilidad de crear o subir sus propias imágenes.", "String":"String", "style":"estilo", "Submitted":"Hecho", "Support":"Soporte", "Suspend":"Suspender", "Take snapshot":"Tomar instantánea", "Target":"Target", "There are currently":"Actualmente hay", "The Storage view offers you an overview of your current images. Storage elements are attached to compute resources at creation time. They can also be extracted from running virtual machines by taking an snapshot.":"La vista de almacenamiento le ofrece la visión general de sus imágenes. Los elementos de almacenamiento se asocian a máquinas virtuales en el momento de la creación. También pueden ser extraídos de una máquina virtual en ejecución tomando una instantánea", "This is a list of your current compute resources. Virtual Machines use previously defined images and networks. You can easily create a new compute element by cliking 'new' and filling-in an easy wizard.":"Esta es una lista de sus máquinas virtuales actuales. Las máquinas virtuales utilizan imagenes y redes definidas previamente. Puede crear fácilmente una nueva máquina virtual haciendo click en 'New' y rellenado un sencillo formulario.", "This will cancel selected VMs":"Esto cancelará las MVs seleccionadas", "This will delete the selected VMs from the database":"Esto borrará las MVs seleccionadas de la base de datos", "This will resume the selected VMs in stopped or suspended states":"Esto reanudará las MVs seleccionadas paradas o suspendidas", "This will shutdown the selected VMs":"Esto apagará las MVs seleccionadas", "This will suspend the selected VMs":"Esto suspenderá las MVs seleccionadas", "Type":"Tipo", "Type of file system to be built. This can be any value understood by mkfs unix command.":"Tipo de sistema de archivos a generar. Es válido cualquier valor entendido por el comando mkfs", "Type of the image":"Tipo de la imagen", "Unauthorized":"No autorizado", "Unpublish":"Despublicar", "Update":"Actualizar", "Update template":"Actualizar plantilla", "Used leases":"Leases usados", "Useful links":"Enlances útiles", "Virtual Machine information":"Información de máquina virtual", "virtual machines":"máquinas virtuales", "Virtual Network":"Red virtual", "Virtual Network information":"Información de red virtual", "Virtual Network name missing!":"¡Falta el nombre de la red!", "VM information":"Información de MV", "VM Name":"Nombre", "VNC connection":"Conexión VNC", "VNC Disabled":"VNC Desabilitado", "Welcome":"Bienvenid@", "Welcome to OpenNebula Self-Service":"Bienvenid@ a OpenNebula Self-Service", "You can add new storages by clicking 'new'. Image files will be uploaded to OpenNebula and set ready to be used.":"Puede añadir nuevos almacenamientos haciendo click en 'new'. Los ficheros de imagen pueden ser subidos a OpenNebula y preparados para ser usado.", "You can also manage compute resources and perform actions such as stop, resume, shutdown or cancel.":"También puede administrar las máquinas virtuales y realizar acciones como detener, reanudar, apagar o cancelar.", "You can use the wildcard %i. When creating several VMs, %i will be replaced with a different number starting from 0 in each of them":"Puede utilizar el comodín %i. Durante la creación de varias máquinas virtuales, %i será reemplazado por un número distinto en cada una de ellas, empezando por 0", "You have to confirm this action.":"Necesita confirmar esta acción", "You must select a file to upload":"Debe seleccionar un fichero para subir", "You must specify a name":"Debe especificar un nombre", "You must specify size and FS type":"Debe especificar un tamaño y un tipo de FS", "You need to select something.":"Debe seleccionar algo", "Your compute resources connectivity is performed using pre-defined virtual networks. You can create and manage these networks using OpenNebula Self-Service.":"La conectividad de sus máquinas virtuales se realiza usando redes virtuales pre-definidas. Puede crear y administrar estas redes usando OpenNebula Self-Service.", }; opennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/es_ES/es_datatable.txt0000644000175000017500000000100411750754334026430 0ustar drazzibdrazzib{ "sProcessing": "Procesando...", "sLengthMenu": "Número de elementos", "sZeroRecords": "No hay elementos", "sInfo": "Mostrando del _START_ al _END_ de _TOTAL_", "sInfoEmpty": "No hay elementos", "sInfoFiltered": "(filtado de un total de _MAX_)", "sInfoPostFix": "", "sSearch": "Buscar:", "sUrl": "", "oPaginate": { "sFirst": "Primero", "sPrevious": "Anterior", "sNext": "Siguiente", "sLast": "Último" } } opennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/fr_FR/0000755000175000017500000000000011750754334023264 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/fr_FR/fr_datatable.txt0000644000175000017500000000102311750754334026431 0ustar drazzibdrazzib{ "sProcessing": "En cours...", "sLengthMenu": "Affiche _MENU_ éléments", "sZeroRecords": "Pas d'enregistrement", "sInfo": "Affiche de _START_ à _END_ sur _TOTAL_", "sInfoEmpty": "Pas d'enregistrement", "sInfoFiltered": "(filtré sur un total de _MAX_)", "sInfoPostFix": "", "sSearch": "Rechercher:", "sUrl": "", "oPaginate": { "sFirst": "Premier", "sPrevious": "Précédent", "sNext": "Suivant", "sLast": "Dernier" } } opennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/fr_FR/fr_FR.js0000644000175000017500000003102211750754334024616 0ustar drazzibdrazzib//Translated by Romain Dartigues lang="fr_FR" datatable_lang="fr_datatable.txt" locale={ "Additionally, OpenNebula Self-Service allows easy customization of the interface (e.g. this text) and brings multi-language support.":"Aditionnellement, OpenNebula Self-Service permet une personalisation aisée de l'interface (ex.: ce texte) et apporte un support multi-lingue.", "Additionally, you can run several operations on defined storages, such as defining their persistance. Persistent images can only be used by 1 virtual machine, and the changes made by it have effect on the base image. Non-persistent images are cloned before being used in a Virtual Machine, therefore changes are lost unless a snapshot is taken prior to Virtual Machine shutdown.":"En outre, vous pouvez exécuter plusieurs opérations sur une image donnée, tel que définir sa persistance. Les images persistantes peuvent seulement être utilisées par une machine virtuelle et les changements effectués auront un effet sur l'image de base. Les images non-persistantes sont clonées avant d'être utilisées dans une machine virtuelle, mais les changements sont perdus à moins qu'un snapshot soit pris avant l'extinction de la machine virtuelle.", "Additionally, you can take a \'snapshot\' of the storage attached to these resources. They will be saved as new resources, visible from the Storage view and re-usable.":"De plus, vous pouvez prendre un « snapshot » des images attachées à ces ressources. Elles seront sauvegardées en tant que nouvelles images, visibles depuis l\'onglet « Disques » et réutilisables.", "Address":"Adresse IP", "Add storage":"Ajouter du stockage ", "All":"Tout ", "are mandatory":"sont obligatoire", "Cancel":"Annuler", "Cannot contact server: is it running and reachable?":"Impossible de contacter le serveur : est-il en cours d'exécution et accessible ?", "Canvas not supported.":"Canvas non supporté", "CD-ROM":"CD-ROM", "Changing language":"Modification de la langue", "Close":"Fermer", "Community":"Communauté", "Compute":"Machines virtuelles", "Compute resource":"Ressource de calcul", "Compute resources are Virtual Machines attached to storage and network resources. OpenNebula Self-Service allows you to easily create, remove and manage them, including the possibility of pausing a Virtual Machine or taking a snapshot of one of their disks.":"Les ressources de calculs sont des machines virtuelles attachées aux ressources de stockage et de réseau. OpenNebula Self-Service vous permet d'aiséement les créer, supprimer et gérer, incluant la possibilité de mettre en pause une machine virtuelle ou de prendre un snapshot d'un de leur disques.", "Compute resources can be attached to these networks at creation time. Virtual machines will be provided with an IP and the correct parameters to ensure connectivity.":"Les machines virtuelles peuvent être rattachées à ces réseaux lors de la création. Une adresse IP ainsi que les paramètres corrects afin d'assurer une connectivité seront fournis aux machines virtuelles.", "Configuration":"Configuration", "Confirmation of action":"Confirmation de l\'action", "CPU":"CPU", "Create":"Créer", "Create network":"Créer le réseau", "Create new compute resource":"Créer une nouvelle machine virtuelle", "Create new network resource":"Créer un nouveau réseau", "Create new storage resource":"Créer une nouvelle image", "Create Virtual Machine":"Créer une machine virtuelle", "Create # VMs":"Créer # VMs", "Current resources":"Ressources actuelles", "Dashboard":"Tableau de bord", "Datablock":"Block de données", "Delete":"Supprimer", "Description":"Description", "disk id":"identifiant disque", "Disks":"Disques", "Disks information":"Informations des disques", "Documentation":"Documentation", "Do you want to proceed?":"Souhaitez-vous continuer ?", "English":"Anglais", "Error":"Erreur", "Fields marked with":"Champs marqués par", "Filesystem type":"Type de système de fichiers", "French":"Français", "French Canadian":"Québécois", "FS type":"Type de FS", "Have a cloudy experience!":"Ayez une expérience dans le Cloud !", "Human readable description of the image.":"Description humainement lisible de l'image.", "ID":"ID", "Image":"Image", "Image information":"Information de l'image", "Image name":"Nom de l'image", "images":"images", "Images":"Images", "Info":"Info.", "information":"information", "Instance type":"Type d\'instance", "In this view you can easily manage OpenNebula Network resources. You can add or remove virtual networks.":"Dans cette vue vous pouvez aisément gérer les réseaux d\'OpenNebula. Vous pouvez ajouter ou supprimer des réseaux virtuels.", "IP":"IP", "Language":"Langue", "Launch VNC session":"Exécuter une session VNC", "Loading":"Chargement", "Loading new language... please wait":"Chargement d\'une nouvelle langue... veuillez patienter", "MAC":"MAC", "Make non persistent":"Rendre non-persistant", "Make persistent":"Rendre persistant", "Memory":"Mémoire", "Monitoring information":"Information de surveillance", "Name":"Nom", "Name that the Image will get.":"Nom que l\'Image va avoir.", "Network":"Réseau", "Network Address":"Adresse réseau", "Network information":"Information réseau", "Network is unreachable: is OpenNebula running?":"Le réseau est injoignable : est-ce qu\'OpenNebula tourne ?", "Network reception":"Réception réseau", "networks":"réseaux", "Networks":"Réseaux", "Networks information":"Informations réseaux", "Network Size":"Taille du réseau", "Network transmission":"Transmission réseau", "+ New":"+ Nouveau", "No disk id or image name specified":"Aucun identifiant de disque ou nom d\'image", "No disks defined":"Aucun disque défini", "No networks defined":"Aucun réseau défini", "OK":"OK", "OpenNebula Self-Service is a simplified user interface to manage OpenNebula compute, storage and network resources. It is focused on easiness and usability and features a limited set of operations directed towards end-users.":"OpenNebula Self-Service est une interface utilisateur simplifiée pour gérer les machines virtuelles, les images disques et les réseaux d'OpenNebula. Il est axé sur la facilité et la convivialité d\'un nombre limité d\'opérations destinées aux utilisateurs finaux.", "Open VNC Session":"Ouvrir une session VNC", "OS":"OS", "Persistence of the image":"Persistance de l\'image", "Persistent":"Persistant", "Please, choose and modify the template you want to update":"Veuillez choisir et modifier le modèle que vous souhaitez mettre à jour", "Please provide a network address":"Veuillez renseigner une adresse réseau", "Please select":"Veuillez sélectionner", "Previous action":"Action précédente", "Public":"Publique", "Public scope of the image":"Visibilité publique de l\'image", "Publish":"Publier", "Refresh list":"Rafraîchir la liste", "Resume":"Reprendre", "Retrieving":"Récupération", "Saveas for VM with ID":"Sauvegarder sous pour une VM avec ID", "See more":"Voir plus", "Select a template":"Sélectionner un modèle", "Select disk":"Sélectionner un disque", "Select image to upload":"Sélectionner une image à envoyer", "Self-Service UI Configuration":"Configuration de l\'interface de Self-Service", "Shutdown":"Éteindre", "Sign out":"Déconnecter", "Size":"Taille", "Size (Mb)":"Taille (Mb)", "Size of the datablock in MB.":"Taille du bloc de données en Mo.", "Skipping VM ":"Passer la VM", "Spanish":"Espagnol", "State":"État", "Stop":"Stop", "Storage":"Disques", "Storage pool is formed by several images. These images can contain from full operating systems to be used as base for compute resources, to simple data. OpenNebula Self-Service offers you the possibility to create or upload your own images.":"Le dépot de stockage est formé par plusieurs images disques. Ces images peuvent contenir un système d\'exploitation complet pour être utilisé comme base pour les machines virtuelles, ou de simples données. Open-Nebula Self-Service vous offre la possibilité de créer ou d\'envoyer vos propres images.", "String":"Chaîne", "style":"style", "Submitted":"Soumis", "Support":"Support", "Suspend":"Suspendre", "Take snapshot":"Prendre un snapshot", "Target":"Cible", "There are currently":"Il y a actuellement", "The Storage view offers you an overview of your current images. Storage elements are attached to compute resources at creation time. They can also be extracted from running virtual machines by taking an snapshot.":"L\'onglet Disques vous offre un aperçu de vos images disques actuelles. Les images sont attachées aux machines virtuelles lors de la création. Elles peuvent également être sauvegardées en prenant un snapshot.", "This is a list of your current compute resources. Virtual Machines use previously defined images and networks. You can easily create a new compute element by cliking \'new\' and filling-in an easy wizard.":"Ceci est la liste de vos machines virtuelles actuelles. Ces machines virtuelles utilisent des images et réseaux prédéfinis. Vous pouvez facilement créer une nouvelle machine virtuelle en cliquant sur « nouveau » et en remplissant le formulaire.", "This will cancel selected VMs":"Ceci va annuler les VMs sélectionnées", "This will delete the selected VMs from the database":"Ceci va supprimer les VMs sélectionnées de la base de données", "This will resume the selected VMs in stopped or suspended states":"Ceci va reprendre les VMs sélectionnées qui sont stoppées ou en pause", "This will shutdown the selected VMs":"Ceci va éteindre les VMs sélectionnées", "This will suspend the selected VMs":"Ceci va mettre en pause les VMs sélectionnées", "Type":"Type", "Type of file system to be built. This can be any value understood by mkfs unix command.":"Type de système de fichier à créer. Ce peut être n\'importe quelle valeur comprise par la commande unix mkfs.", "Type of the image":"Type de l\'image", "Unauthorized":"Non autorisé", "Unpublish":"Retirer", "Update":"Mettre à jour", "Update template":"Mettre à jour le modèle", "Used leases":"IP utilisées", "Useful links":"Liens utiles", "Virtual Machine information":"Informations sur la machine virtuelle", "virtual machines":"machines virtuelles", "Virtual Network":"Réseau Virtuel", "Virtual Network information":"Informations sur le Réseau Virtuel", "Virtual Network name missing!":"Le nom du Réseau Virtuel est manquant !", "VM information":"Information VM", "VM Name":"Nom VM", "VNC connection":"Connexion VNC", "VNC Disabled":"VNC désactivé", "Welcome":"Bienvenue", "Welcome to OpenNebula Self-Service":"Bienvenue dans OpenNebula Self-Service", "You can add new storages by clicking \'new\'. Image files will be uploaded to OpenNebula and set ready to be used.":"Vous pouvez ajouter de nouvelles images en cliquant sur « nouveau ». Les fichiers image seront envoyés à OpenNebula et prêts à être utilisés.", "You can also manage compute resources and perform actions such as stop, resume, shutdown or cancel.":"Vous pouvez aussi gérer les machines virtuelles et exécuter des actions telles que arrêter, reprendre, éteindre ou annuler.", "You can use the wildcard %i. When creating several VMs, %i will be replaced with a different number starting from 0 in each of them":"Vous pouvez utiliser le joker %i. Lors de la création de plusieurs VMs, %i sera remplacé par un nombre commençant à 0 dans chaqu\'une d\'entre elles.", "You have to confirm this action.":"Vous devez confirmer cette action.", "You must select a file to upload":"Vous devez sélectionner un fichier à envoyer", "You must specify a name":"Vous devez spécifier un nom", "You must specify size and FS type":"Vous devez spécifier une taille et un type de FS", "You need to select something.":"Vous devez sélectionner quelque chose.", "Your compute resources connectivity is performed using pre-defined virtual networks. You can create and manage these networks using OpenNebula Self-Service.":"La connectivité des machines virtuelles est effectuée par des réseaux virtuels pré-définis. Vous pouvez créer et gérer ces réseaux en utilisant OpenNebula Self-Service", }; opennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/fr_CA/0000755000175000017500000000000011750754334023240 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/fr_CA/fr_datatable.txt0000644000175000017500000000102311750754334026405 0ustar drazzibdrazzib{ "sProcessing": "En cours...", "sLengthMenu": "Affiche _MENU_ éléments", "sZeroRecords": "Pas d'enregistrement", "sInfo": "Affiche de _START_ à _END_ sur _TOTAL_", "sInfoEmpty": "Pas d'enregistrement", "sInfoFiltered": "(filtré sur un total de _MAX_)", "sInfoPostFix": "", "sSearch": "Rechercher:", "sUrl": "", "oPaginate": { "sFirst": "Premier", "sPrevious": "Précédent", "sNext": "Suivant", "sLast": "Dernier" } } opennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/fr_CA/fr_CA.js0000644000175000017500000003123411750754334024553 0ustar drazzibdrazzib//Translated by Romain Dartigues lang="fr_CA" datatable_lang="fr_datatable.txt" locale={ "Additionally, OpenNebula Self-Service allows easy customization of the interface (e.g. this text) and brings multi-language support.":"Aditionnellement, OpenNebula Libre-Service permet une personalisation aisée de l'interface (ex.: ce texte) et apporte un support multilingue.", "Additionally, you can run several operations on defined storages, such as defining their persistance. Persistent images can only be used by 1 virtual machine, and the changes made by it have effect on the base image. Non-persistent images are cloned before being used in a Virtual Machine, therefore changes are lost unless a snapshot is taken prior to Virtual Machine shutdown.":"En outre, vous pouvez exécuter plusieurs opérations sur une image définie, tel que définir leur persistance. Les images persistantes peuvent seulement être utilisées par une machine virtuelle et les changements effectués auront un effet sur l'image de base. Les images non-persistantes sont clonées avant d'être utilisées dans une machine virtuelle, mais les changements sont perdus en moins qu'un instantané soit pris avant l'extinction de la machine virtuelle.", "Additionally, you can take a \'snapshot\' of the storage attached to these resources. They will be saved as new resources, visible from the Storage view and re-usable.":"De plus, vous pouvez prendre un \"instantané\" d\'une image raccordée à ces ressources. Elles seront sauvegardées en tant que nouvelles ressources, visibles depuis la vue \"Images\" et réutilisables.", "Address":"Adresse ", "Add storage":"Ajouter des images", "All":"Tout ", "are mandatory":"sont obligatoire", "Cancel":"Annuler", "Cannot contact server: is it running and reachable?":"Impossible de contacter le serveur: est-il en cours d'exécution et accessible ?", "Canvas not supported.":"Modèle non supporté.", "CD-ROM":"CD-ROM", "Changing language":"Modification de la langue", "Close":"Fermer", "Community":"Communauté", "Compute":"Machines virtuelles", "Compute resource":"Ressource de calcul", "Compute resources are Virtual Machines attached to storage and network resources. OpenNebula Self-Service allows you to easily create, remove and manage them, including the possibility of pausing a Virtual Machine or taking a snapshot of one of their disks.":"Les ressources de calculs sont des machines virtuelles attachées aux ressources de stockage et de réseau. OpenNebula Libre-Service vous permet d'aiséement les créer, supprimer et gérer, incluant la possibilité de mettre en pause une machine virtuelle ou de prendre un instantané d'un de leur disques.", "Compute resources can be attached to these networks at creation time. Virtual machines will be provided with an IP and the correct parameters to ensure connectivity.":"Les ressources de calculs peuvent être rattachées à ces réseaux lors de la création. Une adresse IP ainsi que les paramètres corrects afin d'assurer une connectivité seront fournis aux machines virtuelles.", "Configuration":"Configuration", "Confirmation of action":"Confirmation de l\'action", "CPU":"CPU", "Create":"Créer", "Create network":"Créer le réseau", "Create new compute resource":"Créer une nouvelle ressource de calcul", "Create new network resource":"Créer une nouvelle ressource réseau", "Create new storage resource":"Créer une nouvelle ressource de stockage", "Create Virtual Machine":"Créer une machine virtuelle", "Create # VMs":"Créer # MVs", "Current resources":"Ressources actuelles", "Dashboard":"Tableau de bord", "Datablock":"Block de données", "Delete":"Supprimer", "Description":"Description", "disk id":"identifiant disque", "Disks":"Disques", "Disks information":"Informations des disques", "Documentation":"Documentation", "Do you want to proceed?":"Souhaitez-vous continuer ?", "English":"Anglais", "Error":"Erreur", "Fields marked with":"Champs marqués par", "Filesystem type":"Type de système de fichiers", "FS type":"Type de FS", "French":"Français", "French Canadian":"Québécois", "Have a cloudy experience!":"Ayez une expérience dans le Nuage!", "Human readable description of the image.":"Description humainement lisible de l'image.", "ID":"ID", "Image":"Image", "Image information":"Information de l'image", "Image name":"Nom de l'image", "images":"images", "Images":"Images", "Info":"Info.", "information":"information", "Instance type":"Type d\'instance", "In this view you can easily manage OpenNebula Network resources. You can add or remove virtual networks.":"Dans cette vue vous pouvez aisément gérer les ressources Réseau d\'OpenNebula. Vous pouvez ajouter ou supprimer des réseaux virtuels.", "IP":"IP", "Language":"Langue", "Launch VNC session":"Exécuter une session VNC", "Loading":"Chargement", "Loading new language... please wait":"Chargement d\'une nouvelle langue... veuillez patienter", "MAC":"MAC", "Make non persistent":"Rendre non-persistant", "Make persistent":"Rendre persistant", "Memory":"Mémoire", "Monitoring information":"Information de surveillance", "Name":"Nom", "Name that the Image will get.":"Nom que l\'Image va avoir.", "Network":"Réseau", "Network Address":"Adresse réseau", "Network information":"Information réseau", "Network is unreachable: is OpenNebula running?":"Le réseau est injoignable: est-ce qu\'OpenNebula tourne ?", "Network reception":"Réception réseau", "networks":"réseaux", "Networks":"Réseaux", "Networks information":"Informations réseaux", "Network Size":"Taille du réseau", "Network transmission":"Transmission réseau", "+ New":"+ Nouveau", "No disk id or image name specified":"Aucun identifiant de disque ou nom d\'image", "No disks defined":"Aucun disque défini", "No networks defined":"Aucun réseau défini", "OK":"OK", "OpenNebula Self-Service is a simplified user interface to manage OpenNebula compute, storage and network resources. It is focused on easiness and usability and features a limited set of operations directed towards end-users.":"OpenNebula Libre-Service est une interface utilisateur simplifiée pour gérer les ressources de calcul, stockage et réseau OpenNebula. Il est axé sur la facilité et la convivialité d\'un nombre limité d\'opérations destinées aux utilisateurs finaux.", "Open VNC Session":"Ouvrir une session VNC", "OS":"OS", "Persistence of the image":"Persistance de l\'image", "Persistent":"Persistant", "Please, choose and modify the template you want to update":"Veuillez choisir et modifier le modèle que vous souhaitez mettre à jour", "Please provide a network address":"Veuillez renseigner une adresse réseau", "Please select":"Veuillez sélectionner", "Previous action":"Action précédente", "Public":"Publique", "Public scope of the image":"Visibilité publique de l\'image", "Publish":"Publier", "Refresh list":"Rafraîchir la liste", "Resume":"Reprendre", "Retrieving":"Récupération", "Saveas for VM with ID":"Sauvegarder sous pour une MV avec ID", "See more":"Voir plus", "Select a template":"Sélectionner un modèle", "Select disk":"Sélectionner un disque", "Select image to upload":"Sélectionner une image à téléverser", "Self-Service UI Configuration":"Configuration de l\'interface utilisateur du Libre-Service", "Shutdown":"Éteindre", "Sign out":"Déconnecter", "Size":"Taille", "Size (Mb)":"Taille (Mb)", "Size of the datablock in MB.":"Taille du bloc de données en MB.", "Skipping VM ":"Passer la MV", "Spanish":"Espagnol", "State":"État", "Stop":"Arrêter", "Storage":"Stockage", "Storage pool is formed by several images. These images can contain from full operating systems to be used as base for compute resources, to simple data. OpenNebula Self-Service offers you the possibility to create or upload your own images.":"Le dépot de stockage est formé par plusieurs images. Ces images peuvent contenir du système d\'exploitation complet pour être utilisé comme base pour les ressources de calculs, à de simple données. Open-Nebula Libre-Service vous offre la possibilité de créer ou de téléverser vos propres images.", "String":"Chaîne", "style":"style", "Submitted":"Soumis", "Support":"Support", "Suspend":"Suspendre", "Take snapshot":"Prendre un instantané", "Target":"Cible", "There are currently":"Il y a présentement", "The Storage view offers you an overview of your current images. Storage elements are attached to compute resources at creation time. They can also be extracted from running virtual machines by taking an snapshot.":"La vue de stockage vous offre un aperçu de vos images actuelles. Les éléments de stockage sont attachés aux ressources de calculs lors de la création. Ils peuvent également être extrait d\'une machine virtuelle en cours d\'exécution en prenant un instantané.", "This is a list of your current compute resources. Virtual Machines use previously defined images and networks. You can easily create a new compute element by cliking \'new\' and filling-in an easy wizard.":"Ceci est une liste de vos ressources de calculs actuelles. Les machines virtuelles utilisent des images et réseaux prédéfinis. Vous pouvez facilement créer un nouvel élément de calcul en cliquant sur \"Nouveau\" et en remplissant un assistant.", "This will cancel selected VMs":"Ceci va annuler les MVs sélectionnées", "This will delete the selected VMs from the database":"Ceci va supprimer les MVs sélectionnées de la base de données", "This will resume the selected VMs in stopped or suspended states":"Ceci va reprendre les MVs sélectionnées qui sont stoppées ou en pause", "This will shutdown the selected VMs":"Ceci va éteindre les MVs sélectionnées", "This will suspend the selected VMs":"Ceci va mettre en pause les MVs sélectionnées", "Type":"Type", "Type of file system to be built. This can be any value understood by mkfs unix command.":"Type de système de fichier à créer. Ce peut être n\'importe quelle valeur comprise par la commande unix mkfs.", "Type of the image":"Type de l\'image", "Unauthorized":"Non autorisé", "Unpublish":"Retirer", "Update":"Mettre à jour", "Update template":"Mettre à jour le modèle", "Used leases":"Baux utilisés", "Useful links":"Liens utiles", "Virtual Machine information":"Informations sur la machine virtuelle", "virtual machines":"machines virtuelles", "Virtual Network":"Réseau Virtuel", "Virtual Network information":"Informations sur le Réseau Virtuel", "Virtual Network name missing!":"Le nom du Réseau Virtuel est manquant!", "VM information":"Information MV", "VM Name":"Nom MV", "VNC connection":"Connexion VNC", "VNC Disabled":"VNC désactivé", "Welcome":"Bienvenue", "Welcome to OpenNebula Self-Service":"Bienvenue au Libre-Service OpenNebula", "You can add new storages by clicking \'new\'. Image files will be uploaded to OpenNebula and set ready to be used.":"Vous pouvez ajouter de nouveaux stockages en cliquant sur \"Nouveau\". Les fichiers image seront téléversés à OpenNebula et prêts à être utilisés.", "You can also manage compute resources and perform actions such as stop, resume, shutdown or cancel.":"Vous pouvez aussi gérer les ressources de calculs et exécuter des actions telles qu'arrêter, reprendre, éteindre ou annuler.", "You can use the wildcard %i. When creating several VMs, %i will be replaced with a different number starting from 0 in each of them":"Vous pouvez utiliser le joker %i. Lors de la création de plusieurs MVs, %i sera remplacé par un nombre commençant à 0 dans chaqu\'une d\'entre elles.", "You have to confirm this action.":"Vous devez confirmer cette action.", "You must select a file to upload":"Vous devez sélectionner un fichier à téléverser", "You must specify a name":"Vous devez spécifier un nom", "You must specify size and FS type":"Vous devez spécifier une taille et un type de Système de Fichiers", "You need to select something.":"Vous devez sélectionner quelque chose.", "Your compute resources connectivity is performed using pre-defined virtual networks. You can create and manage these networks using OpenNebula Self-Service.":"Votre connectivité de ressources de calculs est effectuée des réseaux virtuels pré-définis. Vous pouvez créer et gérer ces réseaux en utilisant OpenNebula Libre-Service", }; opennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/en_US/0000755000175000017500000000000011750754334023277 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/en_US/en_US.js0000644000175000017500000001504511750754334024653 0ustar drazzibdrazzib//Translated by lang="en_US" datatable_lang="" locale={ "Additionally, OpenNebula Self-Service allows easy customization of the interface (e.g. this text) and brings multi-language support.":"", "Additionally, you can run several operations on defined storages, such as defining their persistance. Persistent images can only be used by 1 virtual machine, and the changes made by it have effect on the base image. Non-persistent images are cloned before being used in a Virtual Machine, therefore changes are lost unless a snapshot is taken prior to Virtual Machine shutdown.":"", "Additionally, you can take a \'snapshot\' of the storage attached to these resources. They will be saved as new resources, visible from the Storage view and re-usable.":"", "Address":"", "Add storage":"", "All":"", "are mandatory":"", "Cancel":"", "Cannot contact server: is it running and reachable?":"", "Canvas not supported.":"", "CD-ROM":"", "Changing language":"", "Close":"", "Community":"", "Compute":"", "Compute resource":"", "Compute resources are Virtual Machines attached to storage and network resources. OpenNebula Self-Service allows you to easily create, remove and manage them, including the possibility of pausing a Virtual Machine or taking a snapshot of one of their disks.":"", "Compute resources can be attached to these networks at creation time. Virtual machines will be provided with an IP and the correct parameters to ensure connectivity.":"", "Configuration":"", "Confirmation of action":"", "CPU":"", "Create":"", "Create network":"", "Create new compute resource":"", "Create new network resource":"", "Create new storage resource":"", "Create Virtual Machine":"", "Create # VMs":"", "Current resources":"", "Dashboard":"", "Datablock":"", "Delete":"", "Description":"", "disk id":"", "Disks":"", "Disks information":"", "Documentation":"", "Do you want to proceed?":"", "English":"", "Error":"", "Fields marked with":"", "Filesystem type":"", "FS type":"", "Have a cloudy experience!":"", "Human readable description of the image.":"", "ID":"", "Image":"", "Image information":"", "Image name":"", "images":"", "Images":"", "Info":"", "information":"", "Instance type":"", "In this view you can easily manage OpenNebula Network resources. You can add or remove virtual networks.":"", "IP":"", "Language":"", "Launch VNC session":"", "Loading":"", "Loading new language... please wait":"", "MAC":"", "Make non persistent":"", "Make persistent":"", "Memory":"", "Monitoring information":"", "Name":"", "Name that the Image will get.":"", "Network":"", "Network Address":"", "Network information":"", "Network is unreachable: is OpenNebula running?":"", "Network reception":"", "networks":"", "Networks":"", "Networks information":"", "Network Size":"", "Network transmission":"", "+ New":"", "No disk id or image name specified":"", "No disks defined":"", "No networks defined":"", "OK":"", "OpenNebula Self-Service is a simplified user interface to manage OpenNebula compute, storage and network resources. It is focused on easiness and usability and features a limited set of operations directed towards end-users.":"", "Open VNC Session":"", "OS":"", "Persistence of the image":"", "Persistent":"", "Please, choose and modify the template you want to update":"", "Please provide a network address":"", "Please select":"", "Previous action":"", "Public":"", "Public scope of the image":"", "Publish":"", "Refresh list":"", "Resume":"", "Retrieving":"", "Saveas for VM with ID":"", "See more":"", "Select a template":"", "Select disk":"", "Select image to upload":"", "Self-Service UI Configuration":"", "Shutdown":"", "Sign out":"", "Size":"", "Size (Mb)":"", "Size of the datablock in MB.":"", "Skipping VM ":"", "Spanish":"", "State":"", "Stop":"", "Storage":"", "Storage pool is formed by several images. These images can contain from full operating systems to be used as base for compute resources, to simple data. OpenNebula Self-Service offers you the possibility to create or upload your own images.":"", "String":"", "style":"", "Submitted":"", "Support":"", "Suspend":"", "Take snapshot":"", "Target":"", "There are currently":"", "The Storage view offers you an overview of your current images. Storage elements are attached to compute resources at creation time. They can also be extracted from running virtual machines by taking an snapshot.":"", "This is a list of your current compute resources. Virtual Machines use previously defined images and networks. You can easily create a new compute element by cliking \'new\' and filling-in an easy wizard.":"", "This will cancel selected VMs":"", "This will delete the selected VMs from the database":"", "This will resume the selected VMs in stopped or suspended states":"", "This will shutdown the selected VMs":"", "This will suspend the selected VMs":"", "Type":"", "Type of file system to be built. This can be any value understood by mkfs unix command.":"", "Type of the image":"", "Unauthorized":"", "Unpublish":"", "Update":"", "Update template":"", "Used leases":"", "Useful links":"", "Virtual Machine information":"", "virtual machines":"", "Virtual Network":"", "Virtual Network information":"", "Virtual Network name missing!":"", "VM information":"", "VM Name":"", "VNC connection":"", "VNC Disabled":"", "Welcome":"", "Welcome to OpenNebula Self-Service":"", "You can add new storages by clicking \'new\'. Image files will be uploaded to OpenNebula and set ready to be used.":"", "You can also manage compute resources and perform actions such as stop, resume, shutdown or cancel.":"", "You can use the wildcard %i. When creating several VMs, %i will be replaced with a different number starting from 0 in each of them":"", "You have to confirm this action.":"", "You must select a file to upload":"", "You must specify a name":"", "You must specify size and FS type":"", "You need to select something.":"", "Your compute resources connectivity is performed using pre-defined virtual networks. You can create and manage these networks using OpenNebula Self-Service.":"", }; opennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/generate_translation_template.rb0000755000175000017500000000311211750754334030716 0ustar drazzibdrazzib#!/usr/bin/env ruby # -*- coding: utf-8 -*- # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # tr_strings = `grep -h -o -R -e 'tr("[[:print:]]*")' ../js/* ../customize/* ../../../../../../sunstone/public/js/sunstone.js ../../../../../../sunstone/public/js/sunstone-util.js | cut -d'"' -f 2 | sort -u` puts "//Translated by" puts 'lang="en_US"' puts 'datatable_lang=""' puts "locale={" tr_strings.each_line do | line | puts " \"#{line.chomp}\":\"\"," end puts "};" opennebula-3.4.1/src/cloud/occi/lib/ui/public/locale/upgrade_translation.js0000755000175000017500000000354011750754334026676 0ustar drazzibdrazzib#!/usr/bin/js /* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ if (!arguments[0] || !arguments[1]){ print("Usage: upgrade_translation.js > "); quit(); }; var from = arguments[0]; var to = arguments[1]; load(from); var tr=""; var locale_old= {}; for (tr in locale){ locale_old[tr] = locale[tr]; }; var lang_old = lang; var dt_lang_old = datatable_lang load(to); for (tr in locale){ if (locale_old[tr]){ locale[tr] = locale_old[tr] }; }; print("//Translated by"); print('lang="'+lang_old+'"'); print('datatable_lang="'+dt_lang_old+'"'); print("locale={"); for (tr in locale){ print(' "'+tr+'":"'+locale[tr]+'",'); }; print("};");opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/0000755000175000017500000000000011750754334022274 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/lib/ui/public/images/opennebula-selfservice-big.png0000644000175000017500000002257611750754334030215 0ustar drazzibdrazzib‰PNG  IHDRO+a=l sBIT|dˆ pHYs œ œ“–štEXtSoftwarewww.inkscape.org›î< IDATxœí{üeSÝÇßk.H’븄§Ûƒ)ã²lÙ!)†Ixx*]Evjž4*—dŒf™‘Y’ÑM#׌$!´i[dƵ¨&Ô¸6‰ra?|×oœ9¿µöÙûÜ~óc¿_¯ó2ÎÞg¯õ;{Ÿ½¿ë{ù|UžçTEGúíÀNÀzÀ:î5xxøpÍì_*¼¦¯èH¿xs`sÜo3[ù"Ñ‘ÞXɳé6³ÿ¨z¼^¡#ý_ÀhϦ‡lfŸí÷|z…Žô›€5=›ž¶™}¸ßóé5ʤ#·ã-·÷·6OâC8½–(“*dÎ>þœ'ñ’ŠÇ[¹G?Zõ³ L:9ã-€§qç¸3OâÅýšË«eÒ·£<›Ì“ø¹~Ï終ï ÷¢#=8Øø¯’Ÿ¹ø9`lfÿÖÖ kzÍxংíŸ~ÔÆq/ÆyÞ?8ºãõŠßxÞÿðë>Ï¥—L¦zÞ¿øH§Ò[”Ißœ lR°Ï"`6ð<‰ÿݯ¹UàõÀÛÖ}X™tuà‹À6ÀVÀÚnÓ®ÀÕ]šcÑøëg=›pÿ}A™ôZàËyÿ±×sz“òÊùmd'à†þNåµÃˆV;èH¿UGú|àäÇXÊprlŽ<(ÿ¤#=í~k†'êH¿~¨'QSÓ eÒ7*“~¸†ÃÉñ&à+À}ʤÛö|r}D™t;`p,°;þk¯ÆVʤŸîÅo85²"2¿;•IëùäjjºHÐxÒ‘V:ÒS‘ÁGÕÁ8+‡ t¤÷íà85ýg,pÔPO¢¦¦eÒÑÀuÀg*~t]àjgp {”I'7Ѧgo¨ð™ÑÀ eÒåÉ#]SSˆ×xÒ‘^ ˜‹¬\J‡öJ° ð3é)]ùÑlé^›ã¯`jäÓ:Ò¶™=¾ê¤k†„ýt¤w°™½q¨'RSÓÄÑ„Sþ œ ,@ ÞØ÷HeÒ3ò$~²ûSì-.A{÷‚]îG’Ì{Uéú1Âù°Ïß~Œ&^œoìü¬Û|s6â=mæïýžÈk‰f÷î9À»[|æ&àP`¾ÍìK¾œö^à»ÀÆÇš¦#}¯Íì¥%ç[3´œ¦#½µÍìËC=‘šš¶ ¼o÷æI¼TrB™t&Rayö_©>½®ë3ì=ãï¿ì’'qÚãñCçà9`Û<‰ïjxïLeÒcñWÄÔÆSiò$®Ó`†€¥Æ“Žô‡€ìû ð5àŒVO›Ù€«t¤ß‰¸’“À® 8GGú:›Ù§*Í<€ŽôÄs¶ððˆÍìÓÝ8v`¼«õïÛÃÀÃ6³Ï÷j̆±RU´>ò·>ÜË¿¹A|¿‡c¢#½2’Ä>y0<Œœãžk×èHoˆÈ/lŽT0=Ьæ³×¢¦™Ë\ù­ý Ñy{¼ŸÆµ2éÆÀÍ_i4œò$~^™ôK@øÌ8Ú4ž”IWA®Ëu=£‡Çó$îÇ÷ñ®Àû?íƒáaãé¬&Ãi€éˆp}Ï6ŸÄI)”IWDŠÆ"Ï—‡‡ó$~¡Ýc–w `Ó<‰_žyeÒU‘ïp-D/ê>Œ9Ñ¢ ¬ <,Ì“¸+¶A· #=8±`¿;€}lf+ ËÙÌþøœŽô¥À…ø+0VGò¾æ;†ŽôHµ^#·ØÌ~Óm 심$·Bn"cšŽq¢7õc›Ùûªü 9­ü/ð!d•ÔçÏu¤o®.°™ éµøŽ}8~ï߇mf_p¬£í€wÒôêHÏ.fÙÌ>^vÜ ¯#}a´eБÞù¾÷ÄÿX¬#}#ò}ϱ™}´‹c¿ùm|¿k|`¿{Ÿ§ÚÌ>Sâ¸[¾ã£6³Ÿ+9·CÝžf~n3ÛõœBg¬9»!†S3ëH_̶™ÍÜçF{ö½Þfö´§µuàýcôqp~×uª ®Lÿƒ|/¾°Õ3ʤ×àîÝÖ”R&ݹïØåeÒ/Û’<‰oëæøn¯6 l¶¾7ó$~I™ôrüá»àï,0þF¼rØŽÁ!Ü—•I-ð `NžÄ®pìã|Ïy:OâO*“® œè)m üG™t+àäÀá®Ï“¸ôõ®Lz°‘gS|f ¼¬L:x£g¿£ó$¾§äX §î‰„7hÚþ4p'b ÌÎ»vöá•{Ê s¯Lúrî.Ë“¸çeeð<¼#°ÏóÀGªNØÌþJGú$ŒçãPéïØÌ>âÙ¶'þ›:Ò€S +ñ0νŽÒ‘>860V!:Òk FÞçlÐ5¢Cn+àéÇ” Ý1Êš©#ý>DØÏ'ê8Àîõ%é¯ØÌž[bÌ¿ÞÓôÞÚÀ×Ã;8n)œ’ý4Ä8.J" ¼Ï½Ž×‘þ6p²ÍlG*ém€þm4²©›ëçu¤°™m%,º6þóü× SÜ"pŒ®«gëHïŒ lÙb×µ€ƒÏêHŸ|ñZûæÙ C"¤P= Ð}Gó†<‰_¢Ü9 ¢LúnDðuÇ»¾ùÛ?œ L: ˜ÕEeík)66^ñü?‰,V»M‘×7ø=çIüà íêTÓA±F[NŒ> Ü¡#·Ú¹i¼ÅßÉNÍŒ@þ¶»u¤‹:[q*¢x]d85òFàû:Ò“;óÀ×¢äP×Ö¤gèHŒ$ìG5±•ãn¾Žôw0…C›©þ]ø¡ŽôÎã2¬Ñ‘¡#}òne85¢ßÚ5Tô$T¤èÞtH·S&¡Lz"’ûÙÊpjfMàtàeÒµº=·¡Â‚¡°õþ.ÔU”IwGîLJк8©‘QÈóîeÒªço€Ñˆ”O³áDžÄ9’Àíc àý%Çø0áûÞ¬’Ç(D™t´2éYÀUN>6~¡Lz‘2©Ï]4îXD}­ §f"àFeÒéC]•9BGzÂ7ÅÑ é×í $ÐÇ^·32¯v¿¼5ku¤÷.³³ŽôAˆáÊ­(Ã*Àå:ÒE†jÓÞß;CGz—6Çü;²"if`F›Çl‰Žô€¡ÚM±™M€ßéH‡Â­ØƒÎôr¾ÌéàóCŽŽô(¤ú¶/ãÖî½â/„½O‰2é ' Ù1ʤ+!Þ†Ne¶¬ëIöj!”šð6àeÒJáÐ"”I'#ÆK'FÙêÀ¯•I?ÖÆgWe°7ª‘ÙÀ‹meÇûhàý'€KJ#ˆËÏ»(•"PÀÿpÞ«2ãn„Í;Uõ?¸Àõ°F a±Gv3ùÓföO„­r­#½nÉCUQ¯ ±â!(ôN¸Ð ¡;Âs#3]ø­_(:»ÙŸ<àyÿC½ø;t¤¿N®ü&V.v‰ÞCÁ¾.‡m¸r ’ËÓ)߮͡á¼?(Øå0àïʤ'*“¶jÙÒŠï#!’nðfà2§ôjàœ‚m[*“ÎQ&ä­©‚2é‡oS¢µX Fçv»=OžÄ6p>är¥‚(“¾°'èÜ<‰C†Y)œÁñ3º÷»|p¡2i¨ha`Üu‘ÅGÙç|+öCBçC®痀Û{0æ-÷’x×. Íh¿xiNGrvŠ’ÚÆ†Â+.45‡âêuˆæÿÏÚ7±¸PBõH`ŽŽt'+±EÈßz$^šT~…ØEGzÓvrUƒ!ñÀÓºšÒ‘ÞùþB,FnJ' ®÷CdîËç]¬PÌó%äÁùi$ŸaÄ{ðy¤¡ˆ\Âû°BGz/äÚ*bp’w’ßA~s¾Po/™Jñï|-dñgeÒ«•I÷ªºbU&ý2°Á.ÿ~Œ(ˆä«Ì@V÷!6Cfðð ’›êãŸnûƒnßž'ñ/sb$u2é}ʤ“•IW«2†2é8ä^œð+$7o6žœäÝ…æu‘2©/áº,/#¹N—7¼ ­¡Øaa¯SQH° ßÂ_h2À3HCá™Èïú[HujQžÞ0ž7í~o—â/2à>$/úä^{ò=%ø®LÚ^eFá/¸Ïf¶ãlzó ¶•Íçid1p²@l§·Þ\à<‰6¾™'ñ ʤ|‘ý)é$ðþÕywT ¢Lú6ä¹âj¤’oaó—$ rî|¡ðõïØ× õ¡º€/#Õtƒ"]ÎðÚYŒøŒ¯ʤWºB¾1‚pÂV‘‘Ó ÷^TJÄŸC«þ*ɾ>EÍ|ÃÉ'tÊ!„г™ý\Èp°™}Ðfö@Äó1ÅhU¸ ØÂc85}RÎüÏÀ.{ 3ïÓG'ÊÿØ2d8¸ó´+ç•&OâÈ5êû­ùØñ`Þë’‹˜ŠTÍ5ó2ð‰<‰¿2œÜÜîDŸ¡Ê¤"oë°!OâyÈ뉒YñÖÏS&æ*°¼(“îF8Ïè'ÀÞ!ÃÉÍmQžÄE Ö/*“®YrÞÌΓxOŸ¡áywS&õV=*“Ž'\ÕDñé„SP¾ìú{ò$~.Oâ3çLˆ¤9픡ÅǃÀNy_ÒCË“ø¥<‰/@οïÚz+ðÉ‚9õ„"ãiP‰o7p9T>Ñ4 æâP›Ù–FžSB?iàccǘì»ø_›ÙR¥Æ®dýLϦ(%õ1Õf6ïvFÕ…Í$»c3{þ›Áˆw­SBß÷¥6³S+g2~ÄM¨~8Øf¶TÊfv!R–ïCQ­ b¨) O%e´Òlfs›Ù“‘•l_p–!âzeY 7xuæÜjûÏ~3O⟖œÛbdõü˜g󮮽ʰ'OâÛ‘\šÆ–ȃû:'ré#t¸øTY!Ò<‰¿‹D"šƒhE•åZ{ª~€?œ<É×ñ Ù-D¼\mãB“¡"©\µ`!yÏEÒ%îð¼b°Çy"þg{ì™'ñƒeæŸ'ñ}„«ò,sŒn2 9¹¾y/ô@%I¶làJ›ÙR7.Ê•¿[üÍ+?€3®\~ÌÄÀ¡N)2`œŽ$A7»‹w§|ÂÛ}6³eî.ÇùBJU™‚ü¸›ó¾ #mÚ•´Ð‘~ a‘½J 6³¹ŽôéøÛoL@ª&ËpN+“‡Ùˆ§Ñ×~7dÕ·\ãDAwl>ßf¶ì÷7À!ÀÝ„Ã-]%OâŸ:ñÅÿCŒÙ²÷±iʤYžÄÍêâ» ’fž¥b%ržÄÏ)“~1šÙâ¤ë®ãJ½ “|=<›'ñýE;¸‡œV&ÝÑ>{gÉc¿8 øRӮϓ¸P+0Oâ)“^€äï4³?M‹Qw>B!»sº–šˆßë´ø\Ãi€<‰ÂžóáÓx¸¢d¸¶‘«èUsÿÝH™ôýìK9 ±h}1êroGèH¯„? "¥_–ʉ–6³·ëH[$ÙwÐÔþ=ž°§f'évª3þÍàï9Ò‘ã”Ø[Qö" ­ºWÕ‘ÕI›ÙE:ÒSÄàFF#aÑvu¬B¹1Ï“t¤›ƒ„ÂsUrp~YuPg¸]ŽßxÚªêñ†ˆm:Íç½%6³ t¤E=oy?œ¨Lz&ú"~¥æFF?R&}WžÄÍsCí§(S¹óI(4ô~úlc¦Ó™ãÇ\C±cíVÎÃo<5V¿½¹àóU\»­‰¸3 Wr޲ý}B]Ó² ï´eËYˆ6H³§h‚Žô›ÙÊFáﻲxj ªä˜U] ʃ[IGz•~¶µi“PqŽxÚá.† léZ¡œªLzº2~Ãv€±ˆW¢Q‹'tmŽeè®ÍaƒófÌæ:ŸÉˆwe…‚§Lº±3‚¡ø~ÜŽNSˆ•‘E³/´ÚÌe˜'ñ-ʤólp*ċߨÊ%²›[WU…PAVORt`i¾Sȱ=ſǪ]']gRMäcuW©ÖmŠŒ²Ð\šy¼(y¸¡•V£¼}ÕÜ«NðÉêû(ûÐ-ªS°­.,TÂþm'¬X•~}ß«8Ïg+ž¡Z›”F‚EH~M+ª¡öB .t=>PÒCê#”ãØ\ÂéÅyLj‡ùò‚Ýwkúÿ~]›eïÖ<‰ççIü)ä!7péûš,ë©]ïÇU ‡½—溊²PTWÅ dµ»P,C?Ï]_UûG ¢U!z±Z ¹ðž!ܾ¥›„€‹VEݦl늲ÆS°ê§[ØÌ^‹ß=úÚ¸¬Òî¦Sʬ®Hû×@ÑߪÆk¤J+“^´= …<ËVPù(ów÷…<‰oE’fØeueÒþ¿_×f7„‡y?š'ñ1ˆ*D£ñ´<Þ«p>þ>ŽïR&Ðß{þîºWt1íL†û¹ 2q ­(§¹dÞ®àÔºCåÿ¿v‚ŒeXKGº]‹v‹Àû®Ú*¹WR¦9% ” _Á¿ú:VGºjrz¿¾ï%{æE8/¯ãï?n3ÛhD„~s«5ËfÐõža„C›êH·{ó  ®2«¨MR・_×f™PÑ«Š<‰Ï$쩊såïǥɓø?ˆ€ªïS(dwv•Dî„BeúÛ¡Ÿç®¯¿¡Q6³/èH_?Ëe`¶Žô޶iÑ‘C±û±jÿ«ñ´wbBÆSã¦(¾<ŸòùGeè™êo/q‰À3ѹFÞHuÝš¢ìoYÖ+Ø ‹*\Çã(Á}ÎGsBfÈ“3ÉM å®5Ò‹•Vè4Ñá*Rû ÑË›s[äIü 2éøWûomøwèÚ|¿$F»„dTzÉ‹”KânÄçAé„[ñß“ÏAÑýø÷„"íÐÜ"³ð7ªÞ_™t:~ ±Ùnñ·ÀûU+.Kã*ŸÅ_±ú7Ê'Þ—¡Q‚ ä§LGâ­¾Šq¯vÚöDÂI‘¥eŸAD#KãÚ­ÄÍ75üû6$¼ç;á¿´™õj¼9©$iö&”3‚´ñm›Ù^6– q Žô]CëR8‰‹P©q³ñT”¸¿&-Œ'7VHT´nGŒUŸ÷k"Ëóu¤ß@wúã B™ô$ü¤ؤDÙòSø§F«ð«Ö¯€”w·%ϱ<àå…yŸÔbŒ!'Oâ;•IÇàb¥‘Ŧϋ|IžÄ„Ë›¹¿˜äÖʤ›‰ŒvÈ ø{B.Ê“x§ÙsFØÌÞƒôî q²ŽôÉ%“m—AGzŒŽôw)n 2¥ í¤}\[Œ*œM¸ {i•˜F Uì¼h¯ylfŸÁ¯"=’ÁZPEǹ QšõqXSë;"eîUø"aÏfsÒô“„ûñíQb¬—½·Íì"‡Ó\œ*Nï9ïC:ͯÕhQÅ£LúD8ÕG£h.þ¹¢8gçµÂ=øÏÁª”¥ ý^–žƒ<‰ÿIØÈ›¤LÚϼšNE^¾\qÿv ]Ë£s”IK7[V&=H™tVàµCÓî³…2iHSn¹§Ñ’Ÿ‚xŸ|½ˆàÜu¤(+¨#½ ¢]RtÃÈë·Ã:Ò÷Ú̶´˜u¤ ,þw·Íl³gà<ü2ôo.Õ‘žh3Û²âBGza%ñSmf/huŒåœŸ †±Oþ¡ ?@®ÁfÞ£#=Ãf6tƒYŠŽô Hé¯O D1¼JeÉÉ:Ò·µái{<ápå"šrœ&Ôø¥v³×ëåÚÌ´ü>:àü}¨Æçºk¿eßKéwÓ[ã·H£èkʤ¿,Ðìù~ïÚ¢FÅã<‰ŸT&ý9¢ÞÌg•IoÍ“¸¥>“k‚û]üÛ‹À^ÎHVäI¼H™ô!üQ…(“ž˜'±7ÔëÚâ„´‡šC0çáïÛ¹>p2é~y·Ô°S&=‚°Êö4×à¸Wü éÏ×,Üê»ÿ'q‘G¾2.„v Ò ¹™í€©Ê¤Ç¶Ê±R&=3õ±ˆÁ êK@_šÁO”IwÈ“¸e¥½2évn\Ÿ±œåIü%Ïû=céI³™} ¹A]€ïnÒ‘ž­#} Žôx÷ÀDSGzéƒu¤ç jÎE†Ó?};ȧZ¸]Gú«¡$[é5pá‰Ç¤ül3{áê¿]€+u¤ƒ¹î»8ÜÖóK‡rûËî_¥§XˆS‡²Ó‘þžŽt°÷¡ŽôºÀoÜ\|ß÷“ '†Õ‘>&$Á #=RGúhàÂRß è;ÝØÿ­À ߘ. v%~7x·8‹pØpgàn·0ò⾓©ÈïÇúî÷.ؘ£LºÌC]™t-eÒs 'Œû¼nGö>eÒc•IƒÉûʤ›#©ÅmÞ: §Bù×#úNË,Z•IG*“~iŽë+BXÌà|ß6–÷.S& õcD™tŒ2éEÈsÀwV£Ç­„ò$~žòÍÉ+‹@—äkˆ±îãàšæßL#Îø, “Ÿ'ñ2¡X>5_¸V™t/§°÷`ÄûøŸ;Mõ´ŸŽYææl3{Žôç‘ðVˆHžË§Ýÿ/Ö‘¾Ç½¿ió1 X‚ôˆûK• {Xñ6¬#}3²bY€Tøh$üRÔ¢a>á~p‡!8Ÿ¥»3p‡Žô/ß¹1ŸB¾ƒqHØ`cÏç8¢lß´å›Ù[¡x@Çø·ŽôQ„ÃÇŸÔ‘¾Ñ%¸nƹׄŨ–оd4âQ: áúºñ lœçæVüpˇïn²9ˆu¤ç"ïúÀ»‘PHOµSܹ8p3íM€_ëH߈ü~îB .6E’O·¥7ùXË'ñ‹Ê¤ÇgvÙØ[™ôAä<ŒE”ÆC÷¨%xú•åI|¿ÚôyûF ƒ'+“ÎþˆÜ Æðʵù^ÂFä ÿÆÀSñ`Ÿ¬Ã;‡ã£ˆvÚëÅAH1`º8]JžÄ/+“NFªÃ}¹¹{”I¯@Zp-@äo6CÎALX$à0×°×Ì¢u¸÷9ÊY•È“x2é·÷åÛ¸G™ôFÄàŸèCíˆÜc‹Bð!ÞU§!ýç|Õû Ò7÷8Eú¿ ‰û!çnKüžð~’'ñ-Û{ ›ˆÍì÷t¤WA¬Ë2"|£ Ç­C<èô‚ºÅ[Ü«Jwå§Îëù²™ý½ŽôøI0ê^€«ôå&…<¬ÚÖ«±™=WGú]HîE᪪§{²UÙØ½ªŽ}\H‚Ãföé; W£mã^CÁL¤eHѵ½ƒ{ %Ñ IKŒDŒ½2‚¿'ºÆ¶>ŽDÄÍ"š¬J±üAˆ£šWêà ÷@>pclÃ:Û˜G ŸežÄ7(“JØXìé^U¸¢©LÏp†øu„SHæäIÜK½¾)Àæ„{ÎAZmUi·õ,Ҡٛʒ'ñóʤ{ Έ”ÍfT—5y ùmöo¨ËfvòÅõ•¼ØÁföü» /ûÛÌÆZmfŒhu«\þfÂí°Å…}§uáP“i?ÎǹHÒr£;åÏgÚ̶ʇ) 'nAñ1 8=ë›åò\>EµêNwQpýºqö*7³+àÈ<‰‹ u†ÓO',>]”»ä´¡ºé©»†p…l¯h•ÞíDñepU–û#iÝà?À„<‰¯o1îýˆaÛ-»âÀûºÔº¦2Áìz›Ù«‘æÀ?ïÒX9’0·µÍl¨š§¼çA1ïIDAT sñ7,ÃÀÎ6³¥’1¹å‹¸ ø€ÍlÏUÀ‡ˆ™”o±ãÅföe›Ù#Õ;u£Ïr-eªð$ÔÒI™ðwlf'µÚÉy §¶qüœp¸¹+ØÌ>‰äu’D;âUvÇ8Õð]i߀ʀ}ò$.¬øub‡;SQ®ÁÃbàáPb_fûíPOΓ¸e^bžÄÇ"áîN 拉 =ôúÅe„õÔæåIܩڒ<‰ŸEÎ×Ìõ4°kžÄ¥ºƒäI|3"€z[‡ã>ì˜'ñPè£Æ€Íì_mf÷BB¡ve¸ØÆföÃ6³ÝRp‚ÄA«œ„ø!0Þf6”¬ëÅfö*$þz&á„»#9b»»òþW%Nn¢+ÕU6³3‘Y;O÷;ÙÌ~¥ŠNSÓø·!U{WUüèB`o›ÙPèÑ7ÖqHÅbYo×BÄXðÉDt—è¾'2¿G*|4G¼~樂àgGäIœ!¿Ï‹*|ì9$iûPE˜gœÅyOFŒ¨›Zíïáz`‹<‰{ê] \øqG$ñ¸J>ç`Ó<‰}-ŸBc]‚œïïS\ääc!b¨í 3õ—[ò8öíºÈ“x‰«P{?Õ™g‘EĦΠª2îHÚ—¨®è¾).Ú¬‡ºT¥(•Üí$»éHoÄ+1å÷ÁZ‚(CÏ®hk—“´-¢Üº/õ5v\àær^™²ó‚ñ&éHŸ| Ü¿ú"â½ ˜SÁÛt7þ˜pY%ò— W¿ørož*Ø¿òÅfö éY„sPJ7ܵ™½ Ø[Gz ÄÍ<±à¸O#Uh—ÛÌ–½¡$û7r·0Áµ:¹ÉøÊm— •e?TÖb3{–Žô•H¾×~ Nn} Q÷¾)6xÒUúÎÏx °oË á¥#ý$§pOÄxð%?…xª¾k3{,ôôÝÕp^žÄû¹’æ#Þ‰æûÁ³Hùß3ËMž±~ÄʤïEÎ×D É!B’çI\vúÕ~—wâ?í6Po WQ6]™t6²`ÜÁ Ö/#‰õ·?Ë“¸­ªcw¾R&=9ß‘h‰¯jëy$Dwpó"–áüÏÉNCEg3X‹l Ò¯*7ã/Š*õÌÉ“ø¤ÊnwDÆawüE)Ï!^ù¹À©x:£u¦2éÙȽýƒH{¨`>rîÎ/#kÐTž·WaîÊ¨×æ•D@…¬L«ððj5Îs€Oœs¼ÏÒ‘^1¢VqsyÄf¶g7éÕJ¨µÝ˜ÿpã.|µTÓ-OèH¯ü°×FñÊ÷ÝÓj§¯ôDœòMˆ¡ðð7›Ù®µˆp=ä6B®«Õãî¾6„d{†Žôʈ É:ˆ6Ü?ëŸz}ÊâDÿ6@ª…ÖDBÊt9½oäûX ¹>ê^÷jÌá€2éšÈy‹¤>ÜáÂF½kuäw³R¼òrþî »š(“®‡œ¯u‘…韅]ì³çsEäž²6R9ýo^ùý,wRmOý¢ªñTSSSSSSSÓKJ˱×ÔÔÔÔÔÔÔÔÔÆSMMMMMMMM%j㩦¦¦¦¦¦¦¦µñTSSSSSSSSÚxª©©©©©©©©@m<ÕÔÔÔÔÔÔÔTàÿ¯%ѤV]ÈÒIEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/opennebula-selfservice-icon.png0000644000175000017500000001703711750754334030400 0ustar drazzibdrazzib‰PNG  IHDR€FœbsRGB®ÎébKGDÿÿÿ ½§“ pHYs œ œ“–štIMEÛ  ­¬TxŸIDATxÚíœy|UÕÙï¿ÏZûœ““@ˆ""!99€u@&ç¹*8´Z}o[ê\µ½ÚÞû¾Ho{;Z_phmk[[‹¶ÚÖª•IP+!@ "F0€"’“œ³÷zîç3ZïýØûžßçÃð9{ﵟµÖ³~ϰֳ!‹,²È"‹,²È"‹,²È"‹,²È"‹,²È"‹,²È"‹ÿo!](---ŠäEbVm™¢ÃD$Pts AÕ®v­Û¶m[â_¡cãÆ+儦1VÑ}îüðÅúúúÖŽ÷Œ3¦nAî qâ%IÖÔTÕÔ|’wÅãñ1@ ð‰ÄKµµµ»?åîØòxùdÏxCn·q楪ªªÔ§Ñ°×áÿ¦"^q¦5ö*™!F QLZK$°Ø÷‹‡ÿ¹_q¿G>é@ý¿D(ŠY±÷¢²wÀ€·Ö××ÿ®ã=Ñ‚èqs–‚°†¿ÔÁÇŸÎBùž »Ãáð,`ŧٗ’’’¼ ]œoÕ®ð¿ hø4Ú6íÿÆ&Ä®¶ÖÞ-"³€þª*À>Um<."7„møG±Xì„Ϻ¨ª „E$‚0Ã¥ãÆ+îÃ@XDì'~—S+"a„°Z•ÿ;"”éKøÓlÖ¨˜Pq†1æv#f”ª¦ÔéK/:u°¨TˆÈy"2^3ŒgšËÊʾ^SS³­ƒ"  €L<·‰D"R[[Û ø‡2E¥¥¥¡ "ùùù­UUU~¦­îk-x<îÎ;DD€i¡œÐ9À/>î">|x8//Ï;̾˜ñãÇG“¡d“0mµµµ=0‹tX€çZ¯<4dȈèdÇÚ­ž³楻”––Yc¯äXUMªêüÖDë}ëׯ§Ã}OÅb±…&d¾-Èé"rn8'ü*pw<·ÀåŽqꪂd°É {SÆGó¢ý+'TÖ;uKw°cáöªí-](++Š„ÎDˆ‹H?UÝ›ûGbâ¹ 6lo¿¯¢¢¢Ô†ìE€ŸÒÔ3; áøÜ¼Ü¢øÄøæ@ƒV¯\½¨§˰X¾1æŠòòò—׬YóîáLbEEE™ñÌi"RäÆ'Æ·j +‚ xaÍš5{{|HLÿXÁåñò)žñ¦9çšqü¶ººúýö6Êãå'Z±§ŠJ«ïûhnnÞ}ÿ#œ¬¢ÓÅÈ(@†MV¤‚¿á²bÏpÎ5øIÿ±ššš=Ý Æ™–¡²—ý”?oýúõ]ÈUWW/­¬¬ìƒå89BsKKKÛ±cGãà!ƒ/E8ÕbW›°i#“€ˆˆˆª:£æ‹Cuè/ ÇþdÆ ¶7ZYYy®±æ&„ÉîGá‹yùy‹Åb?®®®^ žŒ‘Û/$¡³Pb"’/"‚xxçÅ&Äî¬^Yý‡.“ïPÞJEä$²óza˜«)>1þE„„Úû"V®#?þÇk×®ÝÜ…¦ó1wdžÉ#’‘áôH(rjlbìûÕoT?Ïx'‰ÈíÖØ]о´+€xÆ;¸]ŒìµÖ® ™`ذaQ‡»Ñó5#æHñÒb¨oCö  ADÎ0Ƽ)Qù°§»ÂŠLúm*ú§ƒ­ß÷!,ͼdl(:&CX!TŠ‘ÉŠ6¨êr§î  IŒ #7åæçÎn§ñX,v‚±æ"œ 8U]íœ{QÑ5ªjÄÈLñäöòòò#:*¬ˆä r2ШªËUµ&#Ãhƒ¹züøñƒºú²¢Oglý¥ãâãFléÇ&Ä.‘$4«ê?œº—TuB>ÂW¼°wKiii~'Þ6äxEw«ê3.p œºÕ€1bN1˜o–M(ÝÁlz]ñv¥5™Éô2¾X–mÐàAWZk¿iŒ´9uÕNÝU}WD&‰ÈŒŒoâõJsŠŽÊ³Ï©[°Y»vm J- "’gÄ ëºr}A}ýJ[¢í’D¸DUïpê¶ŠH®seEEŸaÆEg¾€013‘ÿ«ÕµÎlnj¾Ì¥ÜLàûªº_s¼°w~×pUU78u7§ÚRk W«ê ™ ˆ‡B¡Q=ˆÞì;ÿqU­‘xˆÐÅü‰N5@D®F[œºÛ“­ÉKšµùRç»ËîAQcÌe999S{˜¼uι¯ïJîºjÇ;®’ÁÕ(©ª‘É!Bçu°ïŸñxüHùbÆaopÎÝÙ´Î ’ÁL绫P~ Dí Q@Pš=¼}‡v®u¯ˆ¤kÄät¹¾=‚{V¯Zý÷¿ý<>!>TÞ0†í„þCúûÀ逨ê«ÎwÏzÎ ¼ˆWàœó5¥Ï[Ïž*F&;ug”””<Ö‰ÒáÙê•ÕOg›†øÄø‹À ω+êIð½»ö¾:`à€?!ÜbŒ™U/{®§û (¨‘ÉVzÉ¥ÜbcŒIF nŸ8yÎs0 ôx<þwÍXUmu¸G«WV?Õnb¶mÛ¶¦bBÅ}Þ$12FD¦™8æ—ÿ¬8qå[¨sîñíïmŸ¿}û«¡¢¢¢Å†íx”òCEŠP¤N‡ëñ ŒÐDÀÞ®+sû–w³ê¿"ô5 e¤¨¼/Ff<ô¸õì¯m×) Ï8U##}#…®$M¼Zuêê­XxFM~O‚×××·=nÅž."Ç…Mø²@ƒº¤ÂÃH 0‚ÌðB^¼[P¥¨1c’ÉdØ `Ø=ø,íê_$[’oÚ|û¦ cŽŠ¦¢ù½“rÏ ºNñMÄEFˆ‘UmUtI‡ÉO ²gÏ[X9¸˜Ì„û"’«¢'ôF™ÌY_1’nб'Irkg©%ì Úºk™·OÑÖLÇÂÆ™Àf³þ¥Ýþ¤'ÁGñÂA¸#•9„æ.ÃÕ ¨ ¢Fý `uuõj§îIÀ òyƒ™ÔÃm¹ßHŽèA¶±Š†_E#---ö#P}ç\·Li2™L‰·¢´ûO>¾×yRL(=4½¬~çˆfüƒ6Ewõ ð>Bã!œ]¼”¦^ Ú#"³*++—­Zµêåž”%7?÷b”SPte˜ð;@ôˆ>}ú ͬЎRˆàTu‡ª~´ªj¾ª¾‰ò”¢~/1|CcccCaQaG¦éêg/ã§ÚRGÃgŠÈ$Q™ÙÕN*ºC_U­ª¾ªª/õ6ˆŠn*,,L´›AúxžW tò¥ ú‹ÊQµÜ‘H$öçæç6›´+¤#ÉŠökÏÂö¸jF]ŽkȰ^ÔŠ=:3ÏèÑ££À‘‡bÓ²·¥ÖážœˆŒ5Öü{<¿°¤¤¤O†!ìøñãÅⱯˆ‘[E¤ØëÔ=]UUÕØ…Æx9Þ¼c‰Åb%bä¢ÌsM·¨SôÍ ¸W­\õ½U+W}wÕÊUßÃñ‚ˆì#»}ç¯Ý´iÓþO+óUSSó¶:]¤ÄÈx ÚqN‚õ(糧C³º ƒlßWÑåÀ.àÀ`u&iÕŽ>.­¨¨8¶}àKJJ"Æ3#”gBÒUƘ&§nO&gµÖÆÚÃòòò£-?˜£èyžS_7däˆ \‹ÅÆt˜l›[{6‰r0*¼ººº¶²²²GLŽ-"ç!LÁrLa¿Âªø„ø;™x Â$髪IçÜ/ƒdðT«5Ǫ½%š^¯x͈É#ggf–ÌóA[ðZMMMc|büI &"eֳߋÅc5˜mŽB¸X2àC#æ¦O”Ÿ?ˆÿ¤>¥¢çdÂ$Qýh§šSµ^®÷¤ˆÜ*ÈiÆ3?ŽÅcÏ‹‘=(cEd¦ˆ W´Î8SÝ•¹À„L4?ìÃd&ŸÙTû[mmm²²²r£¢;Œ˜#Q®©œP©"²GÑéFÌ”®ruÅþýû×ö-\(F®äL2¡Ê •Ï)º[Ñ"r‘ Ň• ®©©y«bBÅw­Ø6AÎ3bŽD82Cµ¦]‹Tuo Á¯\ÊýtíÚµÍ=„)„ù7ïrU5‚äd&ÿ<ÒžJ¶&Î %È×ÄÈÉVì éÜ<Тªµ4µ¼ði§Õ«««ëãñøoÕè$éÓñZmmm2ÿ\U‘KEälkìt?Ó·ªîDùÅê•«ÿÑ¥é„ æ,,Ó3iãñœsûTõÑý{÷¿ÐÚÚº.7/÷YE¿""cŒ1ßA¢™=˜ÐÁúPWW·¯bBÅÞzærº™’ÃUõÝŒ2â°vW¯\ýFYYÙ­áœðkªzBiFuêšTu•ªþ¥É4=Y·¦n_/1âZ‡{ƈ9[@XÑ]êt‘óÝ/V¯^½´ï)//ÿž Ùmbä"Aƪja?°I.hÙßòË·Þz«)coªú ⤓ò$=õêõÚ¯©j«}È \ÐØUÖ ž5ÆLwΈ eÛªªªÞ9î¸ãþG$©3b.ŽFðPö:çj€ßïØ¾ã±ö}Ù«hŽ·nÁœ+F&«j^f27¿RÁ#uuumEÛ_6¡ìîîl”ÂŒ£¸eÂÙ@‹q¦ÍZ«Š¾£Îá¶Xk53g+*++¿%V®N‘¢Ìb{GUW§ cÌ—w­oÝá†fܸqMÄmígœqI’»‚Dðnmmíž®”7lذèࡃŸNWtYSÐtqN*§ÀZ{¤ˆDUõÃFÓøö¦ªM½ù!åååC¬µ# úÍšÒúµk×néHýãÇÏ …BGfèï½vÅh·³………#:^>|x΀ŽÎxá;zʃÇb±¡Æ˜>M4íÚXµ±«7í•••eÂf¸ Q‡ÛgÝT]]½½ã8”••õ ‡ÃÅÎ9¿ººú1cÆE£ÑQj´Ÿ¢ ËúªõïödÊF]“Ÿ3Öªí§ªû‚ x§±±q߀ŽNJR{ïÖÕÕµ•ÆKŠÍMJ2Y³²fS—3ù¡P¨Ä3XDÔ7þ{~‹¿1 åzž78#צž6„þé­Ë® L$/ìi°³ølÂd‡à¿6¼OéðÅë"¢Àêæp³Ëë¿>•Ó+%%%‘T*%™ TkvX³È"‹,²È"‹,²Èâ_# PaÞ²±xzèÑˆÝ Ô’jZÉÍgÿsE3X¦Ÿ ¦?B‚û<·øÑ¾ù¼EÃ{%¨‹-ítí`xhe×#`VŠQùÕuhPÅ ÓöfFyÞÒx:1 Þæú)+Aô³“˜£†â¥W"r=bÆ£ê:fByÏpÏK?á¦k>ñ[N>*I}a2ª›‰´Õu Âü%ç!ækÀ$mØäLàíC¶ùã¿çáZ®GåËXŽ1ÂÔ{Œûý˜¦}ð™PËxŒÜ“‡™÷ÜZn¦í³ Z:XüÊtàÛˆLDñHN"r96tóžíóϽJÃ@‘*[î_2ÌÀ™ EЧ‡·2òr.nC(Éü²A)FôZŒù syŸ ž5H ÚŠHò³d¼ô ¹³)AñQ÷”?¢2 Ë­ÀXÎÂ+xx¥Gzÿa"-¡mÌþªXô6gŽAä$ŒTŠºgQý=pèU;Y?D/¢$@ïðåDàë@>"Rì=F÷ÓI°`¥¾0½M½?ÜÆÜi=WûÌQCíBézeî\e΂ tÔ6¤ûW:S™+®×瞘к ÑüëQßCu7ŸÕ] T…;Ÿ1p`˜ÐÆ6Þ?`îÜCgUç¨áèÅav6†è;¬•Ùqÿ㘜æ¤p4‚A݇(sý”¸kÁËDGÏ¡$p®ó¾Á/åÐ:q§ :•Aévî_¶ÑBnž¶­wJaÈ´ãqrZšq4c+¢;Ôphûï’}°¡cp›ñå®;e#?]²†ò)v“jËéâ3âš§²‹Éc$"BžÖ3ñk„Â/ñ•ww²Û¡¥_`ðà"‚â*æÏˆ"z T3µxH.,ÛÉüe¿åºÉ{:¼#—`é 4ÁgÚò?’jM@0LC’OÔ0«}gP…{æ¥34¸¡ˆ`lƒÇ¾ÅƒS—QÔPͬYÝÄÌYfàIØeShµ¥ôË%hÙÁü%«ð—,ä¦)›OZóR@ ª ’h%?Xø:·ÖÈœE?ehSzâ´~d³î}a(­æzŒ»d"^º2P¡…y™ùËîáºÉ/öžù Cf|ùË Ãç"zƒê ×’h¾?ym©™¨ûß û€±¡/¼³½KÑÆC8}ÐL'¾ƒzßæ–i{©7ŸÝ†˜GÁ=dü«XùÖþŠùK®â®Ñö^í‚JÚ¿áj´uÍÁ¥øzÊà >ÂyØÐEÌ™Óu›<…ꃨÿágþlKG2…þæHúN탑É@(sÂè™^CÚ»Gø*è`?p.yÍî‚àó¨| ØBºxçrR-é’|?1c®Aˆ¢TáÜøæbš½Ë‚™¸à;(  1<¹òPÎ{Zso²{_™ƒ 6"òyœÆò0œ„R þ0æ½v'ÉÆÌ E EX‹—›ƒ’ƒ% Á³¤k÷NF¢i$ÝÒíÍÑèv‚–¦v@e7œTÀ]+Šˆ´Æðº8ñmlçæSj¸vòî{錷‘sc~Àé•Dƒ<´ò¶4&OÎA£ºÜŸ Ø9y„e*FÜdDÊpî†NýM—"ðMˆüœk§§ÍÃ] jȲôËÆÒ‰Àf¶<θ7ÀûG£¾;* 4'NHߪÏbƒ»¸öÔöI»˜÷ìVB›p®£ŠÊVîZEü³ŠQZPžÇ÷W"Dœ }à çÓ±ùcÓ q0¸ñä÷™¹à§LøÆ;ô,T§!’ |‰pò 4w9èØ´"ôjD¯ ÓñÅ C3„1˜ŽÏ–›DR“±ÞCÐ!dTUÂò+æ,ºý€×~ÃŒõÌYð ò{ÒçÏ>‡˜¨^‹kyñANç¼dp!íì]«‘?èÚйÎ@w ö@©:·ÍJpÿâ¿cd&H_0§ñÃWž7€ÐŠ“¿rÝI;{ìßÐ&CÐo,m]Êìi»º±t._»wa$RŠ"@Â¥¤k';%@§ï‘"ŒŽ8<hYž Õw¸ûù?‘½ì×Ó+KOÀÕ`3çèÕ"ÓýHÁœO8Iÿ­j;4«ˆv?Á4wVXÃÌë8eð“Xý.p F†á‚8FÖ¥µR£»É,äö,!/‚ ’’¤IZ’]”FW öuDÏ9ž|ÆLEÄKg#Ýâ^û·/"ägj2ÁGLÓáå¼hbUƒ0¢{È×iü¸\Pé-4ô¸wé(¬œŒ¨EØÄö—!â€í<°øàˈôÅQDH”†Ìøµ¢ú4ν‰1½8n®À~üï ío}•¼è5hÇ¢†Än©Ž–L)GU Üjnœ¶2£¼¹é2„s€0˜~¸`7Öî‚|îwiÙkÂjVßÃ¥k{EÃâ š¶c§¡Z‚1×ãQ P}ï­ºÞ=¯‡[ @¢ c™¹ÀòD—pï¾Eù¤2‹Ô$ì÷ælÏD IÏ ººw…‘$ê4íìaúC å5ÏØŽÞù&÷<&0ã°šâ¶Ò@= »_A99½ªÌ.p?cÑŽJ×+L5 ‰X­ÀX”lc×Þm úx¹ož±x¦×ë.=•ïaD³€yKoã¦É»øá‹}0R’¶÷ø [1^=ªU #QrAß§iï|Z.H-/z.„—71ÇbÔè:ª66R>úà 0w®cþé/ ÁÕÀ8à á}Ô-döìÞ¿âåíuЧ t'èÀyL-~<ŸVî]Ú/cõ(”6LÞDÍ7xxvŠûZŽTãÛ„ò#2‘|TÇröùoòÙÄû+‰ÿcnŽCôGLt2S—nD– Bä¬ôÞ ‚ð<¾WÏÜ“|XúÒ¥õS/÷czñËP¼‡]2ÜùˆT øÿÉî蟮׼™û_ù¢Ã2%Ùg"æ´t«‚Òò(6?Ô¹~êJæ/ùj¾Ä@.Eä|D˜0éÊÙ$ªOâüÇxxvŠy¯E?UرóuŠ‹ýïi'L.A$@Ô¢ ÈvÔ=HÃâô7y>ØñC† C¹tF¾Œò…Œcµ¨6¢Ï€ÿæÎh=(;ýŽb/º+@&"šŸÎ±³ d~ëo¹qrË/ãº)äÁÅï£ö2ÔŠ0ĨnFôiû(7NI÷&ÏWRZãmDëq&S-€{dø œ;+É}‹îÃØF`&Âq T÷#¦õÇÎwŸ8KŸ;+ÉC+&ÕRe&pBQºW›P]ò$MÉßsÇ)û2ÕÍ( º•ÂHÏyykW¢î9”“]˜îÕÄ!iÃiNóÁíd÷þôõ[¦½Ë¾øDÂ@/3Õh:¢ 8ý;*sÃ)ÃÉë§<ËCK¶È刜ŽpéR²&”zà/øúknšqÈt°t 3Lh$ÆöÅö¤Þcùž÷º9'÷n8j‡"6G$·Ò`Þë¶ÁrÏ’x6ŒøŽ½ÃÜ¹ŽŸ.BŽíƒç”¦¶rÛ¬÷Ò9s C§Ó&#— ºa7LÛAouñ?|¥€\ÿh¬-Æ©‡ öâx—†Å;;m¾Ì\`™2p&dqm­Ü0cK¯m¶÷CRm\;­»Í³.LñŽ—jì¶M=G ÆFWÚB`vàö×gÂÁ^Î<ÁFDì¨ËÙc+‘¼mÌž"‹,²È"‹,²È"‹,²È"‹,²È"‹,²È"‹,²È"‹,²ø/ŒÿLØ9N@Ê6¹IEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/ajax-loader.gif0000644000175000017500000000124111750754334025150 0ustar drazzibdrazzibGIF89aòÿÿÿ˜ÃÂåðB²Ò˜Ãb¿Ù‚Ìá’Òä!ÿ NETSCAPE2.0!þCreated with ajaxload.info!ù ,3ºÜþ0ÊIkc:œN˜f E±1º™Á¶.`ÄÂqÐ-[9ݦ9 JkçH!ù ,4ºÜþNŒ! „ »°æŠDqBQT`1 `LE[¨|µußía€ ×â†C²%$*!ù ,6º2#+ÊAÈÌ”V/…côNñIBa˜«pð ̳½ƨ+YíüƒÃ2©dŸ¿!ù ,3ºb%+Ê2†‘ìœV_…‹¦ …! 1D‡aªF‚°ÑbR]ó=08,Ȥr9L!ù ,2ºr'+JçdðóL &vÃ`\bT”…„¹hYB)ÏÊ@é<Ã&,ȤR’!ù ,3º Â9ãtç¼Úž0Çà!.B¶ÊW¬¢1  sa»°5÷•0° ‰»Ÿm)J!ù ,2ºÜþð ÙœU]šîÚqp•`ˆÝaœÝ4–…AFÅ0`›¶ Â@›1€ÂÖΑ!ù ,2ºÜþ0ÊI«eBÔœ)×à ŽÇq10©Ê°®PÂaVÚ¥ ub‚ž[;opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/green_bullet.png0000644000175000017500000000112711750754334025452 0ustar drazzibdrazzib‰PNG  IHDR Vu\çsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜ ;ä%ŠˆiTXtCommentCreated with GIMPd.e®IDAT(ÏmÎ;oÓPàs_ŽsãÆ¦I¡4¢‘*© DH¨R7ÄÊί`ëÄA ŒŒ,ìÝ@, ¡¶¨ TšÇvCìÚ÷ÅPrÆs¾ámNŠ7µ ùA¦Fw*¨cJ€d! tÖö6¿À‘';õïØ£ý^Xbñl¢¿nÅåàÆ°0¼n8PÕAà@y°·ªî$‡EäÀ-ªz0Q+5z½ùðºá¥ªzàµ$‚ª>Y+ÝÛã5vŒªâ®õpi¬ô»øç2#™@DŽPÕÖœHD€_G‹Ûtä Au"»/öö–¡ú8"·w¡º…\ºÖ_®;¹äË»ÏFÄ  "ª÷KoÝÙºrÁ{ÿe ‘ç-Z~¬ïùã‰Dâ¾eËÿ„òøÐÊ•O'‚d–iµÂjxÊ)¯3;DÃë†RÕS€vŤw'OßVÕ«Jc¥[zéLf$“~>ÍŸ6‰È ‹£ÅßôpDä;ˆ¾$"gG‹ûÜžÀCóBk‘£Š£ÅÛpAî¼ ‘D5ƒHQ QT=¨ÀSÀ÷¹Õ‘KoéïèPìÁs6"—ê€HP=Š\úö¥gdß²bín{/|òeËNZ¾&‚ À÷Õ 6Aò‘ ™|ÈOx üàaEݺeË?þ7Ït]†Í½ø„ª#"«£MÎÔw@Õªz†ˆ¼:3’¹]D²ÅÑâÃ]úŠHÝm¸¶¨ê®À›‡× ¿»8Z »€D+j[ «qrbbííYT•¹²¨. ôψ¼ Õƒ€‘š?!j_ô®ZuƒüÀDFÉ—/ —þygï”Òp¯ª›ß刴v††?÷¹Ï^ùÊ Ç/[¾ôMÉÓÉ5Éd€=ûÏóðÁ`$÷J&ƒ½‚ 9¼d IÂO˜z½ÞBd“cü½Qf$s€ˆ\¯ªÏvWÝæžm‹ªª‚•"rpgf$óÊÒX©2Ç¯Ž©§ªÿ<øWDÍ?œê¨Ñ ™˜i4æªMT/@ä •sɦ¾Øß×}Yl9üðÃGqÄqK—.ûçÁcüÀO0Œ1¨Ú—1½”‰êU¯Ùl&ÕèÊÙîãO¡ƒ»„ˆ¨˜h¢}QUÕ QU] ,l)10R‡~7 ¯~yq´ø‹9ÚdÜ¥äR`Ãb °ë—vcJbÕ¦ ¾¼‘ª Bªž;·MTSÕ’Àà!¶ÁÊ6üß)TªdSW÷·J_CÎ9çœ5ÉdòÈ¥gú|àˆ FÕ¨Ï 1Ɔ!j£UÅC½VcË–§i4šF•ž€È1¡›D„‰ˆQÕo¿~#"÷ªj("ÏNŽQô¾«ª^™ÉS+mœ‹YÆÑñ™‘Ì«Jc¥o-ô@;ðùðUG—gOUÜòù ª/™B€‘·%T7#Rs”}7`ðRT@dèçà“äËKÿ¸¿mú²Pò†×Ÿ¾ÛªÕ«ŽHžÉa?H¬Œ¥9vëx‚ #öcMˆo|jµ[·n¥Õl""$|?‘Î×g¢ÌHfPDþCU÷‘6¸M³QU³"rCq´Xòý Àðºá¤ª~ø°7 ³‘¯ëç ŸÌŒdn*•Æýøhi¬Ô\Ĺ=Õ·à¦!ØŠêˆÜA65“Gî& •<"¯>‚j¤ÎêJà" •‘M錦»¸ïn"—žXõs-"O“Mméá³°"†lê‘oK¡²ØØH6þYwx6¥äËõØâÆ1âê<û¶ÕUˆl"›Z½ñ¶sÏÝ'$/Ox‰ÃEd”°â%,/W&‚`$$ -+j6šŒÓl4Hø> /ïûk_µ*=‘ˆ¯ªG»ß!ù©ª¾¬4VšuÁG‹ àFç»xQl³™ÉœR+]Ý+HDö)`oyðE`DžSˆ Õ÷ `½bŠHÂî^H6õ§ðfàÓäË!òywi‡§_š¥ ¼È¡ú’¶Š'ùrø."—‘M»ô%‰êˆ4Û÷Wý¹ôíäËo^ƒeÈ>ª/oAäk¨þ+¹tuʵބj‘}ÛíÉ—À/Ï#r5ÙTu†vìœênî7KùÙÔÏ(T’ÀTŽÖÖU^¨üɵÿR²©­³ªÑ"—í,ò+à“3¶)_^ü;°<öÛ\ú4 •àÃÀ®À³P­#‚Ã*ðo*OUT?M.}÷,m{"g/sŒ:ú}¸‘Ï“MÝ1ßåºbùÐrï€jµ6è%?á㉇çÚkT­AS=B„V«E³Ù¤Ùl¢ªøA€o ¾ï;Û‘1ŠŸðèvRú™‘ÌRUÍÆt1U}è Bq)•6gF2g©êÏ€UцwÚÚ;3#™o–ÆJõ. d€ë N½K¯ÏŒd®,•îßɘîà(TŸj»õ Îè „&Ë¢ú"û¸ŠÐ´9 xì |8Õq ;Õmâ×o¤P¹ÕK—g<´DNŒàuàä˧#òON½5N}Õ]P=‘“È—O$—.“/ä6ùáˆlsö°èd0À¡¨^†ê9äËçKO·©–£úrDöuc°Õ¯‘/¯CõÓˆü­k[Ó¸ö¬Eä"TÏ'_~?ðÅ¡ ú÷ˆ ÆTáÛù4‘·kú}°º=¾vŸæþv,ªÏrãÓ"òZ'Äz*[±šÃÝÓÌãzà"Tt@Öj3l»g—!rª§‘/_ÈdS¿˜ëb Q5¡6š ´i§XDHx¾ïãû>ø ßbàÄø8Æ(žg­ -š`, ²v#%a Æ$â¤dÆ|pLĆbŒáôâhqÎÔ½4Vú¯ÌHæ=@>îæWÕ}œÍã¶nã!"¨ê1ÀNû§ïÛ©`Hõ|`[Ìû%ˆ|óµrinêQ= y3ð`l,Ò¤x‹Øfh8ÞK9‚BåBT äÒÓ©2M é¾§ˆüTW¡Z£si‰Ý¸c_¥P¹xðlàiâá ï`Ü1«oP¨¼–lê‡ÓÐåV»0ü=ðrD†PÝBg-ÇC"Ô±ÈÇõ*çMmšB•Õ„ßÞìÝ\ì¨X–Šói‡±6wþ÷v¦° œ“ç1È»Q}'""ãSÆ+>§MD¨¾Õo‘/¿—\úÊ9Qh@ Õ‰ &&ª,\‚ç%ÚÖ€¨«žç±j—UAÒÑ|Lhhš¦UÅ|ƒQßÚ’|É̆X9ÞÍ¯ÆæúZU½i¾û¯4V*`£‚ãÀ¶ZDÒ½|¿8Z¼KD®‹šãÈÄ{3#™½*¶›ü…SËvGäÐI ÒzÆ.#›Zì(éw9&´ÕZl"UtÕd›-Ø“µ¨þ›ýn’V:&jƒ¨¸ûD'v<øªk±žÁh#À `ÛÒa ÷ûÏ:Õr6°o òJD–  >66Íö<:Áf ÔQÝàÔ©ÅA-1ÓUUq‹>ÿÞEÀ;Ü5Ú §ê£ºÕ¥¨.i«Ã¦ºÚ©óÇÍ¥™&4ø~’Õ«W±ë®k\2€ „­õZZ­Ju¢Æ¶mãTkUÛµ³Èu¯ª´ÂF“f£I£Ù Ù°ê[7Ftü4lèîi ÓsµÁü@U×wìÞÊŒdº©gN>."Ç+éÄÛ\áì %+çeF2ÕYúQë%Â{Z#u‡D~¶¨‹¾Pù;T/DukLŒNí_·ÿ¤y±s.@'¤àRòå¹ô]³‚xgãÔ€[Ükà8àyDÛ„dÛ6b7Ô#ήq'ª‡¯AuWD¢SÞ º x-Ö³9«±/Ö‡6Zÿà~׎£€ç´ïm¿ÒN&_þ1¹ôg‘à÷HV:†¨±‡œ§tØcC€³ÚÝ™Ÿ–·;€‡QÝÈ r46K Ý!óeòåç“K÷äÃJ@`Éà2{;UÂ0¤ÑlҨרÕë4 K_é4Íóœzâáz!ÚT¼ÐÃ$LwÕÌ©Lñù¬¿[¯ÔÏ:K¥}ígºS°Þm]G‹ÅáuÃW«êY1ÃõÑÃë†_S-^»íSy‘ªÞ9[‘ª>ê6×\o°v; ‚ÇȦÏC—//Eµ€È¸;9#{Íy/¹ôwbŸþ²®³P=‘5n«c_Ò³ª#@õàh²©'b½˜BåBàâqXQ{,[þ§IFã|ùˆ|ÛRèBUþÕ˜­ z/p>¹ôO¦›3€÷8 ˆÚ¸ó<~eÑXª5ÔÿëS±žåª‡åˆœB6uÏvó(r>0àœ‚ˆÜ‚êyäÒ¿›æÚÓ1¼ãcÞÕ$"ïr=-Ù–a"¬±1xŠýžB††ð |? 90€ µ§UjµZgøÕ8š`0ˆJ'¶H»‘'"ûÄ7¢ªnî[¯Ôý@8¥ÏTÕ`—y;6|@b×¹Ð%ºîhûdûuZïÝÖyÞàY“”kÕļlCs»çùÀ3G6 qD^K6õ¼r—!ò¿ Õ±‰¨@¡òºYG`M.ýÄ4¿‘{·³ Xuä-Ûy®réÇ"“X<ƒ|yù¬“dYÃ㈼fZ²×ÿ""g;ö5Ê8ã÷›]=³¹fƒ±ôȸ2]ß^‚ê cõðTϘ„ì<>ìœ7:‹âz •zibË„HCYÒ`¢J«Òj¶ÚÞ±V«…1niy^;ŠZ42R»Hk52Æ`ÂÙ- Qre|ƒªvƒ¯UNiL9™K¾Wq´XΘBdîцñç–pŠZ†cƒ‹µÐ}T_Šˆi=ª.AäýdS³W2Ȧ~\EçˆÀèäY‘È&Tžaã?êƒSa€È­äÒÎÐŽ»Q}Ä%ýF²a>[;–guEʦn@õÚKDšˆ¼ú/lí¼Ñå F² ø ¹ôS]ú×ÞÛV›-Øí…ê!=Q«‰çy¬i QßeZ­&­ÐP³5ùÕj¹ ÆÐ¥xh ˜" Û´^T³?ŠÈA±ß­pž=½Ÿ NI–Ý4Ò׋È+"0SÕÜðºákzHªíªžEÆð™€Ú…ÌçâÓ êÄeÖ¿`ïÁmµ#¢zªu²©/ôøý ’EµÕv¥PÙu;ÏR´‰m$xuØ<¥DƒêÏ»°ºG5mÖ ² ÕÀ#³ÍK6ÕSÅD>œéìZ‘ñx7òå•äÒOï]Hf{¬c›q'é*'ogÐÞ^€'r€4€ÈóÉ—¯›ÁÚA»ñ­²öY{£ C+†ØòÔÓ„¡Á|Æ·Yó•QCØlYF¤Nø¦J{Ú<Ï-|cP›2;‰Èœ@û-ÀpŽÄô÷ˆ =ƃKc¥Zf$óIà(Uu4PÕ3‹v„‘ß©ê÷ÔRàéÔ7OU7Îs1ýžxN™}_C¾<´(õgT×8ÏQœ}üh¶ŒÍ*Ykó€3ošæ~h¬û|¦6=‹(ôàÍ]Z²Ùm¼Ð]ÃG$ÙÅáÒ» ›ºÏrJÌ0 ºV0]?aa´„^˜ínÎ&Ô7X‚ê ôP?ÌÍ]sʺۭ]jfíè‘GMî¿ÿs„ÀH&“ °jÕj6ª’L&Y¹r%›ñ<ªãˆ'ˆ±>O ÂÈF°¸yìCK™œÄì˜c›ïCd¸Ýf«ª-›éŽhfcDa{#Gv%‘'»´!Œ©\‘-e¶o$æÜO‘GQ݃Nè†7ħnì³%?[Ö! ´nž1„¢6ÏÕÉ¿¢º‹§Ù>ë×ëu¿Þh µZ•zÝnÿZ­FØj&<‰^"A„&$A¢¬Jˆç¼g+Ц.@ä_ŸÔp '©êÈ|Ç23’‘ã›^D¶0}´^å.÷îWªê¶ùï]I`ãU^réM¨ŽN‘å@–Beù"Üq+“™]6Ç™÷ÔDd[ Ñ9ª,á«8!pÈ7û^ÄãÇT[X'MĀ꓀ÀºÅ—ÌÒæåSm­;p lšAý’XÁ¼Þ_ª go2]ÀÜ [-iÔëÒh6¨Uk4œ«¾îÞõF êõz;áÕ„&ªÛec‰ŒvJƒÓ¶!u³m‘1<ñ«3#™}çRú`xÝp›o6Õó ˆTæ;?¥±Ò™‘ÌG€ÿ+5²NDÞ ‚,¤ž¾0‹*\êD,­bª¯æõê¢lWºI,&'tFÌDZ)+éÄÓ¤çpý}Üw·µm'vo^PàXx §dæ ú¤b¶¡xTòæXÃŒ±ÍY®ºbÁ€(›ÚD¡ÒšÂ$›ˆükÚ˜ë"÷Q½e–èð6h…aèÕë6`½V«Qk4ð€ZµJ£Ñpì¨J£Þ°)ÆXw½gÀ8Ò/ ‘Æ+ bS@º«Kc¥m™‘ÌgDäoU5‹Ùùùrf$ó¶ÒXé±Ah p‰«iÏÀ¹¢8ZÜ´cûZ.N¢¢m àt™ŽÊþeÈ5À9Àó‰"Š­—æb •MdS7ô¸ysS&%;Zµ©|„lê^ •¨îKÁ0*“M]ÐÃ]>Ø6àvòýSâƒþ%DuO •³È¦.ëáóç9à‰÷ó7í8";vaKÛD²Õ¡YÀõu±cÍU~à¬z¬ôè÷É¥/[à±Bâ€Hš {ËZ­F£nÕƒZ­ØZ«Öi6(ÎE/‚iN;Ž(öÏ„¦ëîŒPüë@9¦‹ÛܧˆÈ™‘L×PñÌHæPgû8Ó}?^JäÅÑâÇvtÔ\ù׳j/$çI›ÏQ«m{ÈbH6e€»Ó¨“ôjó³¾@¡r ùò². ´ªßDõÝÀ>ˆì ìê¾À„ËÈ6Ä·‰4v»x›¨žA¡ò’.lèTDŽ#òhÚ±\‚êåì "REõ}äË™.cyðò¶šbû™$0i—Ñæv¦=°y’Ó]SÙÐ…1Í•5~Œ8ð6òåý»®•Bå£*“/G¯÷9¶;E£^+ µz]êõ:µzFݪgQ4u£Ñ Z«ÑtjZh a¤Š¯S©iF ¦eº«)•&2#™×‹È/™뢪‡‰ÈõÃ놿¢ª×·G )3’Y&"ë°Ñ›ÂäT¨²ãÑ ¸ìn‘ëTõ•qÔ<Ñjà…Ã놫]N»æýÕï_Aä íŒy[qqª§GP¨\ Ü:)c:_Þ¼ÝE=wâé;© ïweB"»Ô§(TÎÁº¿Õ=—¢zùòùäÒWL³xßœï ²J”•_!—¾ag€¡v` È7)TÞ9måÊ|ù­¨þK¬Ÿ ’@õ~rékcc¨äËelÅ‚ès-TßC¾|¹ôo§ÌïÅØ!,äv'¶ÅQm»ŸÈ^¨~—BåÓ–úÈ—_‚MZ‹`Õ;€‹{aDÆXFäy jUË‚D¯V£Ñ°6¡Z­F½ÑÀ75!êy“QûO<ð¬»_<骑û1Ìo2#™ àÃè§ŠÈ©€ž‘†ªî>…]´£•c EäÄâhñw 5CÅÑâ¶áu׊ȋUu¹Ìß0¤À ›g#S®/ëŸÌÓh­äËoGõ9Ø9fRD@õÀO¡RÅFµ¯Ä–Ú5N]šj_QàJrSåtຘ XAþròå·b]Ý÷#r$p ªÛœw—åý+TÏbg‘NÕÊ!T¿L¡r0ŠêoYêA®ôHü gOsÅë9×ÍCäÉ{"òå+€_#²?pð\TÇceYÂÑQ£Pù(ª©v9‡¶p+ùòÀmˆüÕ}]é“LlME ¶MD>ì˜ù¬ $ÂVè5MûcƒA'ˆ×¿‰ŠªÙï~8{ÚgeS·¡úNlÒ¨GT›Û&Üäʃ| ‘S]œm±  úseGþò¥“â‘pý¬bãâÞ| 8Õ}œ÷/>±ð!ré[§¹êØäàxÖ~TKètwÝ7¡úl—¬ê9vµpc–MÝ \èæÐk;;ìýRÀy¨^¼ ÕÄÆ×î[ÌíŽ.jYÜX-icStpti¬ôåE\Y1òç*›Œ¶9CiÎ-¦d{ÖâƒjÁÈÄÆ;û¥Î&ôré:p›‰!|È: ÚyGV%¬»ú×u÷3±âZ?wöޱˆ yˆ<‚}®Þ ëK«ÝO‘zìáh ò1W—hº¹j!âOò°ÙëÙñƒ–‹›t9a Ù·Ï';Õp m³²…Ñj®µ)jaÌúVD>Ü„"·îû°•±{Þ“h¸¬÷΄!Úò°­V‹fh¦]@ßUp´v!ãÊÄ:÷¾såÏ ˆÝW-ž)"¿¦SÌ>¼=«ì¸YUOSÕTq´Xé>ÎíSL’^æ¨4VÚ œ=#’)êä4‡çÜ$^IcN¹¦³Óì‡êgŲ̂3ñ>õ£îNÇýɦ¾ÕÃ}”\úÿ!r6ÓÝŸté×ÁdS/"›ºgÆØÛC§m³MW'±S‰*7vKþS/gºGx‘ýœÑÙ‹•™ÜvË\6¯"›ú×Y+!dS z$p¶Ê€nw=kÈ~ЩøÅ6ØM×ÇÉsª3~nûy¼'õ]¢rÃñuÒékÔ¸±Õ.ïRËÜ›¢šyaŠõ|Aàmòè'\÷±EÑÔ˜v%Æ8 Ò„Üû¤Ÿ{}ŠÇ ›ý§Às‡× œèŒÎƒb£P=µeC.>è›ÅÑâsÜš©¥—~ œzVƒŠ£ÅK\±´€N*‰üxÐWÕ˘-%azI¨êŸô¤³%JßN¾üàUØ2Ït'u€jÝUüöQÞŸë–'4ÃBþð òåÿ<ßÙ—Ë4ü‘¯’MÝß…‚6KÚ¹hïÞé¼IÑŽK¢Ú­¶Óu¨þ:ÆÖžžã3s_CàLòåÿŽCõ@DVº€¾:ðªßÖ`?óžØä ?ÀÕ«öýÀ¹Õmí!_íÖµYùn£ê⇠î‡ùœúáuþºqyjGÒ@ú²çc966èéE{Ö}¾<„È ªÛå)‹?Fû!r-°[ñ>P"—>zà ¬{~‹ËLßÑ{ºr´O9õíÏ'…Ê2gœ¯¹§¦ôjŸŠÔ1ßà£äÚ=÷\(\ºv^ŒhÒÂFñöeqìHÛù[aü¯_zy¤ÑÜÆ®ÊÌôÿ»û6Ž-ì6/ëÛ§ƒH+4žx®^oŸàaT |ßj’AàG†â¶Q;A­.ßL@ CžT¸AÔæ­šõ¥/}ù«“ȘÕ/ŒÕ cœHìÓY­ëûô-~à·í»j&§cTDĦÕï‡j.­ÕZ?¾úê+Æû@Ô—¾ôe*Õ±ÞÙè!‰04žç¢u|ß·™ôÆØ§u¸0©èÉžˆªŽ9°ÄJˆpè'’ÉäÕ—öòž=û@Ô—¾üÏ•&öQS®Æµ†a½Ñ Þ¨ë/Hø>8õ+’mFdŒQcB±ª™×RÕß‹èçB5_¹êÊ«KCú@Ô—¾ôÙÑ8PKÉ»zè¡5›ÍCjµê^¨îÈž&4«ÆÇ·%°Eubq>.ûjTÃ+Ä×®ºòŠ_ϧÒŸ‡¾ô¥/‘xÈÁÞò é·Â–¿bå.ƒâyk|õÿ¦%­çšƒ–¯:¸6QÛ7¹$¹û@r 68¸ôªDø\£ÚøÍ5߸ÆôG°/}éK_úÒ—¾ô¥/}éK_vZùÿ÷ð¡uÃÛIEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/login.png0000644000175000017500000001000111750754334024102 0ustar drazzibdrazzib‰PNG  IHDR‚2ɈîiCCPICC Profilex…TÏkAþ6n©Ð"Zk²x"IY«hEÔ6ýbk Û¶Ed3IÖn6ëî&µ¥ˆäâÑ*ÞEí¡ÿ€zðd/J…ZE(Þ«(b¡-ñÍnL¶¥êÀÎ~óÞ7ï}ovß rÒ4õ€ä ÇR¢il|BjüˆŽ¢ A4%UÛìN$Aƒsù{çØz[VÃ{ûw²w­šÒ¶š„ý@àGšÙ*°ïq Yˆ<ß¡)ÇtßãØòì9NyxÁµ+=ÄY"|@5-ÎM¸SÍ%Ó@ƒH8”õqR>œ×‹”×infÆÈ½O¦»Ìî«b¡œNö½ô~N³Þ>Â! ­?F¸žõŒÕ?âaá¤æÄ†=5ôø`·©ø5Â_M'¢TqÙ. ñ˜®ýVòJ‚p8Êda€sZHO×Lnøº‡}&ׯâwVQáygÞÔÝïEÚ¯0  š HPEa˜°P@†<14²r?#«“{2u$j»tbD±A{6Ü=·Q¤Ý<þ("q”Cµ’üAþ*¯ÉOåyùË\°ØV÷”­›šºòà;Å噹×ÓÈãsM^|•Ôv“WG–¬yz¼šì?ìW—1æ‚5Äs°ûñ-_•Ì—)ŒÅãUóêK„uZ17ߟl;=â.Ï.µÖs­‰‹7V›—gýjHû“æUùO^õñügÍÄcâ)1&vŠç!‰—Å.ñ’ØK« â`mÇ•†)Òm‘ú$Õ``š¼õ/]?[x½F õQ”ÌÒT‰÷Â*d4¹oúÛÇüä÷ŠçŸ(/làÈ™ºmSqï¡e¥ns®¿Ñ}ð¶nk£~8üX<«­R5Ÿ ¼v‡zè)˜Ó––Í9R‡,Ÿ“ºéÊbRÌPÛCRR×%×eK³™UbévØ™Ón¡9B÷ħJe“ú¯ñ°ý°Rùù¬RÙ~NÖ—úoÀ¼ýEÀx‹‰ pHYs  šœ ¹IDATxí\}pUÕ_HBIÀ`m±¶P°Œ¶€LUP±áS˜ŒPÆA¬mAmb¡VÔ¡Z[e”Zù°jGЩüaPTZi°2 S ƒZ¥à V¥MHIº¿óîïÞ}'÷=x™¹;sîîÙsöìî=÷ã}´kjj’’´OBDÈoIÚ)´D/ÑÉÝèΟuëo—I$?O—†bÆî‘„¡ Â1õ…pTÛ1Íy£¿†ØBÐ"@â µ•h+ÕÖQ …ƒ¡ ’Ž"8¢­.h‡µÐ¡Y!EÐI5Î?~ü¸Aƒ*--í®ü‚Ð* °›(ßõ,M=òˆÉ'¶|Kûò8t,ßÒ‰}*ŒIccãç‡ú`Ë–-]³fM•J?ÔvPåa1ÄÝ#tP¥³gÍšµ`¤Â!C:+¤FÖ#Ï È´}ÒÄVtbúã‡\u/pÜ NeütläyŸýBýæö2²qNÛŠÍbêD‰}ó¢9 ñ ‹Ið B÷Hé;â'Ëö©ky.ÃæàËl?±O]&lLLèéËlÿxãG}8,ÿf1œß(§ÝB2î ©dzúÔKìÏlüÂ$ÂßB‘M0ªàó˜xÈISÏâÄ>÷â‡üXȸ#@‰g0’ÌD“g‹ÂÒг:'±Ï½ø!/2OŒäÆÑ6É”cÒĉ}îÄÏéØKÏpÿ̆e ¹å[¾Ï£ ØG÷T~¬ŸÇ˜¹àµRüxrrLàØB€€E@'‰ÉcßbÒÎ08GܶìkåµçŸ‘—ßï,ߟ>I.(K}þ†µp=“ÎÕõ[¿H·¸˜8‹9îóɣޕû2ö‰­nhß°]¦u»\žWÆU _•7|+ÑŽ8Ö^™”sö‰}û}/ÿZÆLû½Sh{|¸b¢û\¾¥öÙôì\™æom{Žgql!`ë°NYƒ3Fņù›ŽDÛëéðç?ïٽ_êÕ¼Ÿm«—ÛØBÀã”ÁÇ5,“ r@6l²”u{lÃTm ƒlâlsd“e²ï[9SnÚxH6þ[dÒ¼‘ÒÅúB#ƒ³Í‘MÆ!²éd“µÔžza!`bO ^&§|Ö´ÇXêó'nþÚ÷_—§žxZVþ}¥¼õ–Èб?«&L”Iã¿+géjÓ|;øŽ¬Xú¸,þóV7jYaò£™•"[ªdó‡ÿéq•Ü}c…ÞHH—îçËàsФkQ¡4Ý'ÏÎ_$5 í¤ãW¾-—õ®•gRjª1áD™1kŽ\{YO7f®ÅÏ®ß92ä0ò í c2,¶ä·š}¸`ôÈ7Î\óâ}2솅)…àX½öiA»cú Ù¸û>éWš*ìú÷ªdäES¤ÆjkåT¯]q†^ ·O»Rò?Ø*óÿÑñÿÕg’\Û_díÂÅ‚¯úÒf¬^)·j{ïùírç•çåNüR®º¼dŠ}` €´Å|ü÷À–ÀÚ‘¶zÇe¸ÞÔMûûV¤Á˜rÿ=3¤o`#²X.›²D>v>$Ë®·EÐW¦Þ6Gn»fh¨" %Oõ›ò𥭔êÔí›Ü‡ùä‰Îrã=÷ÈÔh2YøèËR« \³Å'¼~øâüoþ}ŒiÇ…ÀÎki'4‡Œ;åÐäs nu¬´!ï¤ìƒ…¥ævªÔüGdÍÃ?¡K2U“ðÛÉ\Ú”‰2·÷÷d zÕwÊßv]'cå%™nSeÝ·dàÙÜ,¹öš‡dÈäÎV‚/ûêl©>ŽÊƒ+†#¾ºF&—‹\?L÷ª?z.Væžê¤Ö¯cž {¸ ˆÝ @€±4K³ìØ1A£ùÔ%&ß×;{øÀØéöŸÉ!œ~€¾wËìIý#Ÿ;÷—Ÿ½xwJ¦ÇOêêU}÷º'n–ïtÖÙcøtyðRªsÇcs§âÂ¥÷ɨ>Rq*î)ÃFGº\³ã‘î4?u‰©Ï±Ø?ûÈÈÊZPãÄ á< äÓyÈÈkU{Nøu›$ܼËJÜ3¾?¯#¾•ÁÑÏþvÎ=«$ô5å˜b§Óœ¡Á¥ÉñJ;¸ËhØGÖQ¬è ñ‹_7úáü±…à„Eeh\4“LÌ l?nŒ³7næ;ß8óÅ›fËs[?6¾"Ï=<›RéŸ'yEQa&W|]¤jéLYþ=›&C¿ÙI:ä]! t Ÿ³ügdTùV™rk…}ú†,‹”±pghׂJHÛÒtÌŽȉø©?Ì™[”whQ!ÐÆÄÒ”¶6–þ";Ê£“ñ5yá…ˆ«?Û‘®—Χn]-7,ÚéËîš)˨âp¹,Ýô 鑇QºÈäWɆu•ò'Û)Ë»4MzÊÏhf××ñ–…¡?6Š&Ñ—žg »Šíš-mT²’ÖÆÒYŒ0›M쥶0Ê©„Ú¬+ ‹%ßùZ(#æTIÕ’Û¥ÜS*¯¼]Vm^-c{èË `]y]‡Èv¿!KæÝ"—å—L‘yó­ý—ä¼¼èRR\¢—¥¼Žrçè–ºGà¸ôáÁÞ;—k˜®[»#Ðq(‚ŽÛR,ßÒvðVµïÐ_Ù»W &°s¦îäqÙÊ“þc*ëßÿ±ìß@>Ï—BýaÇ—JðÓÍèŒ<òîZ¹ù—/Hɹ%RôÕ‹dî“;¤¼›&ûXl[ù€¤ö‘ò½¤H/Iç—½{Ç»1Ü8z¸Ïy€—JÜP:º“L|d¯¶@Ucט+ñ ½â`XñC#ȸ³ÀÀ,| iê[]ò-6­bß¾HÊôu0cÛ¹ Îû†ÿc½¬r «dÅïî j¾îêA©JʵöT²<ЀVñßÄ8n®8ÞñÌO]Ž»# ðœJ ! L€Ìò­®Õmõ¬ÌòO‹}~oùÕKKe߈éò:ñðMUÉäÞ]¬O\/ÕÙ·2?FäQïLÚsn‹c  |4‹[c}bÈ@£åª}QÏ+eù[›åŸÕ›dËÎw䣃 R_/Ò­÷…2bÌ(¹àË…®rÕÿ“‰¿¿Ûc¬¬…&Ó&ü–BN۔ɀáã´5_ ƒ•Óþ7w»§¥þÇŒÙ82Î ;(ûû4m O Ž!'4mûS?Ƙ8¶ Ä=Dà—4È|>‹&±OE —âÇœX[H"”mRAâhòla$öѽãøú±¤üTÆspn`¿e÷ÜÈ ¦rœ1eqØ×÷ûq6–çëû}«Gûú~?ÎÆò|}¿ouãh_ßïÇÙXž¯ï÷­níëûýÀ&|Gàú¤és^leZ±O ž†¬ÌÒ‰ý™‰NpäWã½ÐŽ_Øjkk÷h»°¨¨(¼O@E1‘Àò|Ú 3È3ÙX~bŸŠ€ ibhd¢³Å¯®®N8°OuðmÆUÒPSSóRŸ>}† 0 3&#&?íÛXÝL6–ŸØ§"`cBšØÆÔ§3ÅoÇŽ‡µmT9>7 ?½÷wTHÝêÕ«×vïÞýòúúú‘ýúõ+ÆÎо}û´¤swà„Àq<Ê}™ßOìO]üP8 òöÛo×nÛ¶­zÆ «5Þ‡´…—‡¸ÿYDqàã¶n£G¾º¼¼¼Bÿwçkš8¿hT%¶-üÏâ¾7ß|s£þÅÞõ—†ýÊ?Bÿ›št|©ŸÚà_WÑðM°è‹~ÚI ME;=.úÝíî² …Þ#Ä–¨Å€ï* ùøÓ%þñRô†I™ ´™ðµžÜƒAtó§ÌŒ…Ðf–˜8Ú*Èø ¥V=¤ÍDàÿüNá(hW×IEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/panel_short.png0000644000175000017500000000344111750754334025322 0ustar drazzibdrazzib‰PNG  IHDRn‘ãR÷sRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ  5gS¦æ¡IDATxÚíÝ?l“éÀñßk¿‰Ag5R‘»å$ÊP ÐuéÒi·˜JÅv]3D •JöLf@‘Ú¥ Ízš­¢,LEH HGAM"Ô¡êJ0IœÄ~;ä}á%µIø—£ŸôÈqb{x"}õè÷ÚI|7%ïøÜJé5’w|=€ÿYiEDtJ_¿÷p±®DDµË}öíN•íñý†»8Mä‘NK«ZŠwâä Ð3ØQŠv;¿ÝοÞ*}¯¸í*Ýg´«ùcò5˜¯â~5¿ áè©S ÷viµJ·›yC·{¾÷ wù”]‹ˆ¡bÕëõ‘F£qn||ü³‘‘‘zD dY–dY&ÚÝ‚š$Y»Ýn7›Í•¥¥¥åééé;«««k±ž¯bzÑÊŸ²Ý-ÜÉ>OÚÃy°MNN~vvö«‰‰‰/Ó4=âWðv¶¶¶š??ÿÇZ­ö=[ p0Ö×ןLNNþêöíÛËñ8"žEÄZì\°Ü*â]éñüâ}ÙµˆžýJ´Öððð'Fã1‡ó§±ëÝzÝÂ]\”ˆˆÁz½~xbbâK[ pðNŸ>ýÓ¡¡¡#±3ñ(FÖÕ½Â])Å;m4ç¼{ ?ÏÌÌü0v®/Öâå‡+¯ wñýjDÔŽ?þ©­èŸS§NMäÑ.®7–Õ=G%E¸+‡2Û裣G~/?^L@âu'î¤ï$IRÛÐ?I’TóX—ÿTìuâ~±|„ ïvÿÖ=ßUòÊ©[¸ú+ïnÏ¿¸Z±Eß½ã8Q¸I> {θEà¤tmÑŒàc Ü €p Ü €p Ü €p Ü €p Ü €p Ü €p Ü €p Ü €p Ü €p Ü €p Ü7€p Ü7€p Ü7€p Ü7€p Ü7€p Ü7€p Ü7€p Ü7€p Ü7€p Ü7 Ü7 Ü7 Ü7 Ü7 Ü7 Ü7 Ü7 Ü7 Ü7 €p7 €p7 €p7 €p7 À{wf{ú/I’¬Ôálw÷:q‹7À‡!Ûo¸øÀ7ÀGîb¦Ò)ÍZ胼»xƒwù™pô]'"ÚÅzw¼_îND´³,Û¶‡ý“eY;w;oq§Ôçžá.jßY[[ûÖ6ôÏÓ§OŸDÄfDlåMn—^Ùã˜ÞzôèÑßm#@ÿ,...GD+ïðf©ËYDDÒå9IDÔ"b8"ŽÔëõ±ÅÅÅ¿¤izÄv¬ÍÍÍçÇŽû寯Æ?"âqD<‹ˆf)ä=G%íüˆ¾¹²²ò|yyùkÛ pðîÝ»÷çg±‘Ÿ¶7ãå…ÊèîâHÞÎ ¿~ùòåß¶Z-³n€´¾¾þdjjê±ÏóoÇ®w•T_ó•Ø›$>ÜóIDATÓcøÇoA H‚9 Ñ·OË ‹¬Ù‹,¸:?**.+#(bBprdDXRJJ|DÖ¸àܘØòάàÄù3¦DgLþÿ¿­úÜÿÿ; ç@'&ש›@|>,("˜›t戂èèS`ÁŒè¸Ëº¢#w€o¥FæÂ'†Ç®«¬‹NÞ Ì>œææ3HÝâI±‹öôFñ™ÿ»"ãCæ#ü¾¹Ê?²¿1>9¢îÍ«eqÑ9ÉñQ‘‘…Wá‚»cÂâSS¢£&#‡Ò­þøàÄÖM×ÑÂó\mð,!¿ÆTm=Îß°)%tEXtdate:create2011-02-11T16:12:30+01:00þ‰6ü%tEXtdate:modify2010-09-16T09:13:19+02:00_G;äIEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/opennebula-selfservice-small.png0000644000175000017500000000532411750754334030554 0ustar drazzibdrazzib‰PNG  IHDR³d@-XsBIT|dˆ pHYs#šktEXtSoftwarewww.inkscape.org›î< QIDAThí™k”VUÇ{fŒ›x¿:\H°ð‚H IËÒ‚(TVbº5ÖšËS—™KLM[¥R©ŒieÊB3’#^F4ETDDÀ‘¹Í°ûðï™3çFdUø¯õ®÷œ}y.{?·½ !`è \ õÀ3ÀàeþwØ xÈž§32}C›€'‘ìíÅSÀfà˜O(ÛXàBà7@¼½D\œtÆßº® >jjç|‡tZ|4ÜÚª+ ÁGç·1·08ØLn > åæ|R¸89¸x3øh쎢[eÿ‡÷½2}]þÀ··î(¦Ÿ޲ç›a¯·÷®Ö·êcÒlܲíoüû„tîFfÞ/v&¶s¾39>Ê´=ôž.;)Nª€GÃ3Í7MÀÏÛÉ{{Ðɻێ$Zì ÔÕÈ»/^@{ p3ð0¨@Öd¿=Qô|yvvzؘ͙v‡k6ZÕÀ&àí2tº›<×¶C·È9—P2þ"ô^ÞÊ´§z6çdî`rohƒ¦3Þk•È87‘[#'½!7ƒ~ÀÀé.N. >Ú’»U§à£²:¹89ò³À™mÈy2ä·a&Ç(K´0f'ƒ7‚6åú:¢uªöÞ>Ú“îu–¡@Ð*ó¸8Im¥Ÿ­>Àªà£­¬oµ)> ø'°Xˆ"òD´9wØœ“‘qü ÷Jû!J¹.÷˜i}¯  » •4˜@ëxX ,þ… ,‹FdlýŠ”4ìL³ñ)ÏZ´ÈYTظ×PtZÌB‹ 0Âd›‘›×@ÛÎq°9n= ×ÙœÓ Æ§Ù± m΃Ƞ¿h2ââdO'Ó3:­qq2ÃÅÉ^yb.NöFkʬ¶!kÊ{ °•ýoeèuwqòd¯.N¦º8ÙÍú0Ýž3¯AαÞÅI6âŸgãf¢½­G¶–òéåâäQJ¶²ÖÅÉ.NºfÆTº8™„ö`°ÒÅÉó.NÃ+­¯@Þ•ÇÍÀ@_J òÞcQ]ý о·X7´‘#‘¡ÔšÓs<£:}Ú°Ï“sc6“ŒÏ5r‚6ç1VÏ·€oX{Ufì.6îàn”¢GbF´܉ʟEÀTÒ\ZnBðÑ"àU´^s]œ|X|´0ø¨ÉJ¿#GXe:½ Œf¹8©Ì‘Ü‚ `ZórH÷@åÈ8àu“)’O§ïï•ÀÙ¨4ÊâP”Í—  0&ÓŸ>ß™ÂðiäÀ F{%àßg†N~Šöñ! ø<0ÇÅIu… ІEhB%™±)N@›5^@%@%ªûöE†Û ÌN¾£•¦¹aö~d,÷ ç ,è? 9ÅÓÆk´ñ¾×d—9:/Œ³ñ+cV@{[¨~fÏP„;Æèmë0õ5¤WoàÀB'#¬ï»È¹ç>ªF†58#KÈÒî özOðÑ•å˜5'¢`4ø50ßÅIzFù!2ôƒ >J½'€.NFæHž|ôJûM'΢÷0äŒ*e2*Uïº2Ýf]\œ tqRƒÖõC oðÑ)ÁGƒQÄï \S…6pw`{.Bš¢ß3e@Q÷ñ̘©ÀÕ&TJÿTޤØÝþ‡µçµ(€nN>>K©I€‹ÐÆNAY#‹”g7ÍR¤©jÚ0P¤ÏF‰dô€#r2·=‘îwQ2à:”N‡—›|ô†‹“æ%(8Üçâ¤wF§=€Ç]œ¤Óºetº»-Áì¶ä\óžÁGÍÁG/Z}6ZÛþ@mŽwO'³3s÷ÉðžoÏ«LO‚º8yÂæA]L >Ú˜Ñ!EÀnMÏÁGï'et8Ëhl¦gh8´ÖCªP¤ìn-./X‹¨†Ûˆ<85æÕ¹q›ÑFît>míƒ hBË’eY湕ý24²x ÝTïf‘Žïk¿¶xn¦õÆ:ûï@éf [ŸwEº!=™¯( »¼Ìœ­°k¸ßZm¼EÄ¡”têg¿<ö/hkEDóm)ï Àí.N~‡J˜î(“¥¼ó¹ˆ÷‡¹ë¼;‘1AÆ rò"t±ÿ¶J¢T–}í×J–*ÝF¡ÃÞ|”ÊS|y}p;-Oõ#Qô®½ƒ"ò&`ŠH5Àõ虢?2–¥”<<_«o+-OD©ÙçÚëP}÷ðõL{5ZŒúL[g´ÐSí½94À‹¨–nFYiχ´!Ó«¨$닌p®µw2™ áâäb´ö3‚&X\Œy£ét2Pki>×e¹w ȶ@ðÑG8‚‹“ëï¿ >º9ój´V)ïÀۂ&dæÕ õ{‹òÎ]‹ÎPg¢,’-(3¶ÝÒœ üÀxT¡óU't¯³±ËÁGklÜÞ¨Dl¬Bõåõ(*ÿ¥šyÈëŽG ¶³¨B8ÍJ¯€n±…¸ԥȘæ¢MƒŠûš2еËNʵߎj¨Ó€Gв2úfT{¾—_žGõv™îEéìe›óˆ)ûñé|+p1:lÎ@Î3žRIP„™¨dò.NöCåÄQhžE{áQ.Nþf´k€s‘ó ´±ÛƒY(0LrqÒíS5:Ä-@v1¸ÀÅÉþè@{8Úë5´±‡VNLCöå£2¨<=¸ÐÅÉ àϨÄ8•.7-vqò0rì9.Nf œ€ÖìÜôÔþct³¥„óøîè n0-/äA©°Éˆƒ z:p•õ/Dѳð-ö¿Ý‚|ІríÁu´®ñW›²ó/¡,ç›^#Ñ¥xxEÍÉÈ—_¦t‡|-2ÒhÓ xfqÊdСr"Ê2ù“ÿV½jã*Q†<Þøœ|Ô`º“P‰w²étºË=1ø(_j}ÌF‡ÅN(+ AåÈØà£ÍÁGKÑz,E7B7#C^gum[HÏ$ ´¾âÜ ‹Ø§¢º~p#2äçÑ:¤wíg¢µ<ÝhMF6zQðÑ].ó9ô‘`ŠFõ(*¼Ÿãýtp«E‹:¥œyhÁóè‚"M52¦y”jÊNÖ·ÝS¦8Òæ¥©z(*qž¤%ÒëÂU”" k·ôÄ”¢3ýÇ¢”:8•>KÑÂÚh×£¨ØÕdzQmÙ9Á’ÌœCPznD×_mÜZf†­pqr°É²x"øhE®ÿSh]ú!G¬ >Z›é?h>šc·5Àòà£ÅEür´kÐ>4³ƒrýé>õBÁh^zP3¹†¢OéÏÐ>X|ôR¦­#rœuÁGu™öÎhßzÿ>*é K:ˆÉ‡P è@óÒÚúE²}Ž˜ç±ûdƒ¿÷À올P'?ÉûwP’­·–ôÃ=¦ƒ@'T—GWLs%¬Žˆ|iÄuoa‚Ä¢cG>„Ùñ?æ¿” °³ïØìÂõÐPL¡_Õ¸‰÷µ.g Å9d_±üïÁk}Áõå ®A‡¤ÙÀû…Åò:&Ä@’Ò|®‡ ¯k,–µB u!XÏ,ñÎ)º¼+«ýµh™‹÷¤Em6\­Ø í‘¬õOEUÑŸ¯÷ÈÛÌN6ɇBy¯&HÃ!î¾W×ÉêÓO¨¾ªŸöó]â'o°Mòx…r„)†`b°q*gghõB6_žý˜b²¸ÈàIEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/storage_icon.png0000644000175000017500000003056411750754334025466 0ustar drazzibdrazzib‰PNG  IHDR€€Ã>aË IDATxœí}[ŒdÇyÞWuêœÓ—¹ÏìÌ^x‘EYŠº‰›@œÈ¯±ÇN¶ÉCòè!Ä ìÀ/¹8R8ŠM–)ÙA;¢¸ïä’Ü%¹$÷:3Ý=ÝçZy¨ú«þª>½;;=is {vºÏ¥NUý÷ÿ¯ÿo¡µÆýöÁmò½ÀýöÞ¶ûðo÷àÞî#À¼ÝG€x»ðv>àM½øâKKw’$Bh hÝ¢m[h­Ñ4 Ú¶uG]ר›MÓ˜Ïö{]U¨ê McÊÝß6 ªº¦¾¤Öz¥ÕzK± `Gg¤”;2Iv)7“$YO’d=MÓÕD©¾J’žR*WI’)¥T’$©R*I”’*ID’$PJi)e›$I#¥¬)k!e)…(„3!ÄÀÀÖúÀm7š¦¹Ñ¶íu7ꦹ©µ¾Õ4͸mÛ¶ÕÚ¬A]›¹4 Ú¦Ac?ÓÚ4ì3´† „€L¨$A–¦H³ yš¢ßï#ϲ¥a§–îᔚ¶ ¦µ††>àA!Ä÷I•<’Jùa¥õÃZësÐzWë„0‹$ &R"I(üUJ!Q Ê~¦#xÆö!¥tý !`^gþ¶m‹Vkè¶EcwT×õAÓ4×êº~«®ëËuÓ¼ÒJy Z¿ àu­õu¼Ïoï hx€C뇄OUúI¥ðÉ,Ë>®µ~Hk½­µ6TBÔa)ˆ(F[jÑMü2!<% ¶m!Û:IæÆ%è°€ž» £E!Ä I’✔ò“‰RP!·»YUÕ•ª®Ÿk«êbÛ¶<àÊò+zòö=Cpè'Rþù$Ï?×Ëó? !> `…€Ml±n4Ldð£–mÛ iÚƒ¼   ±\BZñ¤í_›}çó Êo£1²òÏ-!«ÖÛBÊm¥Ô§¥?‘$ ê¦×Uõ"€?ÖZÀ7µÖ¯,B¾w£½«àŽÏ¤©úBžç9I’O )t½mIW0¶Eú\×5š¦F]7rÞ’½–# i UK递p„±H „€Òö;ì}Ôo'ÐíØ¸LoÇ"îEÏ:$ÒzE&Ég2!>£”úÙ¦iŽêºþv]×7MóU­õ“ï&|€w  ô¥Ô)¥~WìÚhÞðÄmǘ$É I’ÏfYöÙ¶mÿiS×T7Íðe­õ›ï¬Þ øˆRꤩúJ©mITÄØ­Ö‰L AŠŸ±b„ðì”d©A†ªiPתÊX d9TU5‡Ä D]Cº®‘$Ip8„c÷Bªo[´@HÙŒ9Ä«ëyÖo‘Œ­'‰›Ó;ØßT)<ÿAhýƒMÓü“¦iþ“~Z¿|šÀ:MÈ¥ÿ8I²”$É ¬)Øvˆ4aÿ {Mƒ\Þ°&%Gˆ¦AÓ6h,û¯ê µE‚²ªP–¥C„ª® fô´Ö,•RÎq pYq)2GkŽVuÚ"],‚8WƒŽ”E3k÷.úÎß#;¶üöiþ¦Öúßhà_(Nh§… !CJù9hšvº øwÿnÖ³_i×Ñ›ˆ1B5à‹²DÉâ ¤ôlœlnÛè:,× EY3NcË,  p+¹8ÀƒÏ1Ð)àÏoøgmÛ>à§p Äi ÀžÖøíV·ê¦€£r÷U!à^„0&“óätj2U…²(Pв@U–Mýt!kšÆsËMÈ‘Ã9‡¶:„óÀаñFÜånÀwŸýbœÁ^ÿœÖú·5ðCxgà)R”–h_j[ý( =ƲÆËN¸3fbº¢ûšÿ+ ”„R Y–¡m5†mƒº©QUuÀêºö€³~Òr ¢ü†(±vÀ(‰J©»šŒt.`ë,ÞͰãóÂïþÜ£ÐúK~殺CSu]/óüPký34ÄÎ&º®ÆÜ¢ãZÇsއáÂûH’yÞCªRäyϱ„¶,çžTR"M’² °Ù5:þ³ë 6™x%ŽÝ„_B LNð8@ݺ½Ògè^¿×ïË$ C‡ßÕõMw\×]wòûI“æ÷…®Àz€€„DÖLm[Tu…ª4²½Õ-¤0“eÒ4…²®a™$Ž¡ï»f¾ !P7M<™ôÄ2ðÚå×N<ˆ¶mõ…óôúÚšUü"`sÓýÇÎa¥ÁÍ%úN@?{åLLºG±RJ(e‚(J¥HÓI"¡[¢˜¡¬JMpxxˆétŠª®!…@–eèõzè÷ûèõzÈóÜôa‘‚bÎ_±wàÝGŽ$IpýæMýÂË—t’œ<¨«ª%D€n[ܸyƒ~ŸÉJ3uÚîD\P= mOÆeÇΙïŒÇ:eŒ>Y–Z@æèå9²<‡R €FU–˜I”Ui)©Æd2Áx2AiÅR ½ )‚Hæ2MuÛÏÇo,äk(\9;™L0Í  R…í-ÆM<+ Ìf3”e…V·° @»y”zbÊwî¨Tž>Ó.Ÿ$L¤SÆhl­fq„ÆÄævñ¤Êp‘&Ë,ÐÁ"oa‹ºn]\A)UÁXXNÀÍJ¥ Ë{= ‡C ‡C di àèè·÷÷ÑÔuàAt«Ýr/‹KëÎÄvÀºÕ¨ê £ÑUUÈó+Ã!v¶· ”‚Lè—¨Îö•$I¢ü2 OHqãx"ƒ0®¿’›¸FÝp~K#‡‰L,wIü§¸oÆÜµnd!¬k§›8dV~üYž£ßïceeÃÁ«««‡È² ¥¼yó¦õTJ%Ž{о0ñ®þÉÛÒŒÚx0Äù­¬¡QÌJŒÇܺu ©JÑë÷1°2¢ßï!Ï{Ž… aŸ…€žC*O$Ò±z) ðfAhÇOC1ݾ‚ÆéºÕä'‚°:F"-rà˜ÿŸø@’«³F,'Êóƒ™×ÊÊ †Ã!úý>Ò4uÀ>::Âþþ¾Óœµ‘eÈ{=$,Œ˜¤$»U^®J40 6,`G7i¯0 a(t6›¡ªJŒGc£½[*ô{èõûèå9ÒÌÈûØ´2ˆ%XHÙ¾FcNv;wɧ`DxfifÃz‰#´LÔQL€bYž;KB& Lª,KE‰·ß~EQ ¬Œ‚™Ø¾Äú½žW¥™ÎܽìÞ/<èOA€:•^¨9]À|Öó1 #À¶<[ª0™ª,1… UY!ˬ¶MÞ8¥ T)¤s9z`€ë?MS£ìYm¿ßﻨaM{ ¢FœµÇÛÔÜþ«ËL&cÌf…QÔf3EáÂÇ‚!ùRÊ€µ™ù8Ÿ^šk³¦îjšÝ¥yÖ+æe”Y§x¹[h°Û³Ü~<í£ÿ=E›÷ a€S{°Wo'cGUרJ“@ûèï¬(PÙèaQ(ŠfE¢( àg3”6—¡®j·ß€öpŽHzŠRÊ™{öb`òÁš«X|ÍèGðÓP—ìA RDôœïŸ¹u“ÐÐZTê€L×ßXX¼Šm^ã# àÓ³~ÓK² Íum€fCÂeYÎm {/ßiT×5tÓ8à%21BT´MŒÁÏ'¢XŽý´VŒHŒyê.ø=|­ÜÿK*Ër€ÎÆÇ$„ÓìÍW¦¼Y“)XpH“;™!XâzÏš„ÎÕ\ç?œ2Ì1Ã7‰ŠàÑLî4®ÀTޝ³Í%~ϛÛîÌܻ+¹NÆC8åð,Ü7’Ýä(ôßC.¨;Ø íY!®WFy>ZÈ_ë6Ø©;7²—Ùyf~ bWvÜ/›@G@ˆÈG¡çNQm[*´°Yþxùm0ÈëFlNà>“åàÇØéàTÏ5\÷ÑõàF°„÷\ÒsM8vj,Zûùq'×/Ÿ{š¸Ì<¾²g­³ÍŒ}yo j—ì@ N¦…òËÅúg²i«ôÌ?££%6!àÜb¥g=¥øÅ‹!b'N”°g‚÷G,™MÁ#á2ÎpBŽÕÝbà7b0žCréXËZKûHƒÀ(Åñt^~r9Þ5Aó,©ÜÀ‹Ù¤¶„¤;ûàcsÚvhG±~BÀÍ0NéÇ<ÖOÂ6äpú×Úê(‚áœ9çûu‰¥`Ùì×þ»pÀç dH óÍÝö6Ò-t¨PÏ‹€N †v(Êöy9b³¦¹±¹i-lâ ãœƒÅ÷Ѽ¼(€#.­— /õ´c§ )€"L, uïE…™Œd#S±õšw\¤Â “z©Q XÌ®ùbÎYÌcW‚¹ Íqë 좧`¾ŽìYÒ æ9 ‰,3¶¥u€e;ˆ>®iíA±/îÓæýxõ ›mz咧1ˆPª¼Ý€Á”P7&S|Ì\é^ Ùs„$+g‘(t¬®j݆óµ÷{. „6ÉÉÛÒVWÞ¸8Ј'ëÙ0ãaÞ*u²2bÝæQ‰˜ýcŠ•R)€ÆÖ/v:Ö<úÇÙm8a?Y0‘X Ç*™q ô@9e i4;¸»¢y·¶ìŽ ¡£%r^›*õ¨ýz 3ĉw !Â蘹Íè¬r4y@…Ê×è‹Í5’«N–sFŠ!›kø×Ý×µ,ó¢bα}‰è¾þN¡´kÖ4 Š¢xVùÅeu€¥cBÊw¥;Øßâððоé+ŽÕ:ÎAÜŒxˆ±Ó¼ÞC7‘1Ï’çL;÷Å+¦d™ÄDìœUàï )—ŽØ‡ÑõÎNÎÂ(Ùë"“ùsT¸yãÆI’<&¹Tf0¨Až/Û „î¥ “É—°··‡½Ý]¤i†¶iË€7Oµóò^X¤ÑhP'ý]lju"ˆ=DœëÃý%¯Übê?Ž%=çžæ¢’]×v»:+KSÔMƒk׮᭷ÞB1+ ¥@ h¥ÒnösM-›Y¢µÞ“Rü^’$&‰Âþþ>ž}æ¼øÂ ¸páööÎ"Ë2¨T¹$L§ÂŠTGÝþ¯™fÔå?ÎË¿Ø ®?nµÅz Ø5nîÍY‚Áûí\é¬ßöÑø£þdb7§*…étŠW_yo^½Š²(°¾¶†•ÕU(¥>ß6Íïú‡„ËÕXæaB|Ik/º“ÆB ‰Ý =}Ýj[»¶$‹™¼DQ˜¼ý®^}O?ý] ú}lllbwo{{g±»»‹3;;ØØØ€ZYq;tyª·bo_dò=t9fˆPXdvÚ/ð&.³Ý;ÄõA"‰”¶Ä™Ð€Ûwxûöm”EétŠétŠÙtŠª2Iµ<0áÕL#óÔªè×mÛÃ2P-Ç´´nXùV˜É«Ôl™¦ÂÏfÐÒí¬G888Àå˯!Iôz=¬®­bss »»g°»kÉloo[n±)%², Ç6^ë€S$›¶hÃ-^ˆ´mN¡¼P¤¿&M¡ˆ¶5I™Z#Ih­‘híò<˜Ã¦ŠYéJÏðJ¦Äþ¥”Aþ m7ï÷ûf{|¯‡Ü¦–I6¶¢ªõx:Õ˘‚ËG…€L$ªÊäüI)¦ú½ÚÆTë4¹})ª²4UÁk*óê«uM&ŒÆ#¼ù†©‡H•:ƒVWW°¾¾ÍÍMlmmbkk ëkëX[_sIƒA߈ÚrmӸ¾~Ÿvä_b® dM•ÇŠ³éÔ¦³•˜Yê-¨Õlæ¶ŠSup­µÏù³Õ¾U’@¦©;OÇëP~An T  WVÐ gY€2;š†«÷»g?Ãh Èû}ŒÆhlÜeÚ© €ÖƒA«k«˜ØÔ¯Ñh KÉy†²¬PU¥Û‹o’1*[ôÑ'_´ •Vmí~Ó'“‹þ6uƒY3ÃlV`4[ʲ욥Œ9¯/Èj åàX^ W­ÒåÆòùù„…à©àAÉzVªž¤˜³ƒRÆVVV°±±4Ëpp8rúÕ²mùý0TÕ´-r¥pþü9œ?û¸vý:nݺét•¤hlº3•|u\€§mó\<Íìyç&†ó¢ÅÚ>¸sã²ØEœÝã¨Þ!¦­ÊkÂ+¤Ì[ÈÖ(œ~“€¸AW¦0¯Ù´rWKÀÞ× °¹±­­- ‡CÔ6U¼±9w³@îÞNE 6¤ÛUUc8àÄ<ˆñxŒ7nàÆ888Äl6s!¢p­[4†Ö>qÓœœ×¾Îþ'ltŽ#‚õÃß©]5O—$jØ=gýŽ D5‡ÛÖ€š¸—ïô# vLáAÍ€ …OïX__ÇöÖ677Ñï÷ÑPž¡-]cLd}|7äÚ锊åZ¨€ñÌfH¤Ñî|ðAœ¿p³é £ñ‡8Le.f%„À¥î,`…wy`wN\h²|“fÄ‘ñ…MNî—®ue9›¦FÓXQÔ¶Þ«Hòœ±xÌø×H||ÄV)µsNÓkkkØÜ0JîÚÚò^ÏØþMƒñdx;ÉAr÷xåñÚéì £BË…®Ð2)U€À`0Àææ¤LÐÔ5fÅ Ó#ceá-êÓdyΩØ;H¯#–Ocˆ)¿;5ŒÂè)”Ôfõ…‰ Ç¥^4¼IJŠB¬¬®b}m X__Çp8DžçfçoÛb:›áh:õˆdõzŸ›ªYü¥Á·|bcC†-ÙóÖÕÊýóeYb2ÛÂL Y–£ßϱ¾¾,Ui¸bÆå±¥wU À±jA)§ð‘} €zQp ÎæõÿƒFÊÀ~Ø"«««X[[Ã`8D¿×sU½Z­Q–%¦Ó) ”­+ÙT4O·¾Ì£é‹¨ž´ pCˆÆâãôhÆCF”^U%ŽŽfÈs[œ±×Ãêê²ÌTÛ’RBh 쯉µ\FÏÔ?_)Uרl)Iz’ IÂz?Y‰(ª_äRÖ-À©zùôaÝ·„h£ÑUM¾ó|Ïš{y¯EeiE˜>o2XS·Ô§ Ný# U€ˆ˜†™ÆíbsCÓ46 d,€LkK¦Ö•ˆ!$¢BNñ:¹ýÖ‡nʼWæ§f¸R[«¤©™Ó¨™ûM ÷ú½ªJ^˜&ã nÌnõH$‰)lEö}fY~\ðÂ/´`kf/Á3ÚűŠã¶å³ƒ™ÿÝ|e›@I{w“ÁÄ(¨Ã7‡ØX¸JdnIp2à›{о6@íL@{” †°î[Sj¾´õJ”NL”ˆ Ÿˆ‰c‚¼ Ê×0ëG½Éc ¸AôyÙv*E¢ø„()T3¥Ð›t|{¹cé9ؾ„­\¶„,^Ó'Ý#@ÛšT•¥~núÅòŸÿà÷R¢jMQ9«ý !ÐZ­=ŽJRëÚsÀCÏ!ò̧Œñ~ZÅ|Ïuî q1wBóD{þ)8ct~G=]1w¾/Ð_zw{è< ݳ±c) ù>B®Rc8¾yà8ÅŽ?)IJ5AžÅ–!íRrJðíÔêøÅãïÛY ·}LŸX˜=NŠ(ÞÃß¹ˆü&ÔÃàéz–‹¢Xëîœ÷úbû:ÃͶÎâ);8è<2'œåEšû¡Å{m"–pò¶J‡ÖðyèZ,Æî™gÑ|5‹²;?ùpáæ„(YÛ *œåÒXæY0×IÜ–Žê÷: ßqØr Ò6@pû×a.c°8°, ‰1[Ç,]³;ÁB‘1}Átäúp2Ú±ãx¿£p!_µ Ý˾˜³õŽ ÍŸ¢¾,ÍÝÁø9Nå‘Î×Ú AŠ3„£fzÓ¼‚èÇ–¼9I;+ øjÙ;MŠ4y{±³ÅDî]Æ2…:ˆ‘ΡÙñÅ[¾Œ®B>þÓbó ÆŠPŒL戨Õ‚üØ“”ANš’»]ÏÑ©p€»É¸ã4>½€Õ´L½BèD 4tðÙµ@_ÐÎÀ¹¥„»øuÌHŒ G=A12GCÅÒ:Ü4ªï°Œ!G ïa€\×pTδ!Ë boh`>Ÿ°^z8ûz°¼ùÓCz6sG,„ ̰{=—HÀçN€¡–M/‰ev ŠXþÁ9¥pnÏaÇzÞi‰]€(¸yq!Jë²0NÒ–·ºl]ÃÓ@-O Î8óý7 ØuaÙ!—ÃBRzÛß #¢L‹T¡n¶X„Ê!¸È`\!ÒÚ2ò@t,QøòÀJâç¢Ò5牖pɦĒJ@l5 ÕÒ®.¢!à~ÕËà-ò -B9réHôâ,ô€ã"–ìöYê3’Ï]z@0öc{«*à˜|\±XXÐ|o¾Ôý2mYà†MT¢©wâ¥mø›B`zY-ž÷„ÃÎko 8oà äîs Ozìï"bëR9'êvEƒ¦ñDÏÇ÷Š˜K¯x­©›{â¶l8x) 6Ý’SNceÚ㜅KÄ„ Œ2Ïj8£Kf×4XµPÛïÜ{½`Xçûu÷†šoé]µCŸX0vßOˆÎÜd\LB.¶´Æ´mšÙ2–ܲu'ºn¿ªTûÓs“u”Ëj´‡pD(¬¦÷2%ÉyÃqSÚ4WB[šµâ…é ¹¶"î° ó`^' ¾ƒ¿ìy÷W›|a7„˜’R¢n”eñU¥Ò'…Ë:‚„Úö‹û·oV ñèÊph©ÍRU/!n0Oh‘ðçÌ¡¼'ÿ½½_,n{/ ’8ö賈Õƒ ¸Ì÷ΙH ½k'ÂÛÿ:t.mr_ /IDATËÅÞC?m3NqëægûƒáÂ÷Þä\ä^J©wz½þc/¿üò¯¾ú*44”ÝÝã'ª;8@¸Q$Zö¿g‰œjã â‹€ÏÇÁÇÍ–ž;Ï?~Ž¿k÷DÇ\çΤç‹VØu´Æ¥K—ðÌ3Ï<1\Yy,˲w–öœF}€~žéá#ÆåËWðõ¯>ú(>ôð‡f)tÁʰO­Ü©cÝcå.£*€³\w¦{0¤ØE\ÆKlRG´ro®‚?hû\ *_ᾈ¸Í_ +À!”‰adY†¦®qùòe<ýÌ3¨Ê{»»€m‹TÞîÖN­>@žç~ìcÃÕ·®âÉo} Ï?÷>ò‘àüù HÓ 2-š&LFõ­ÖŠ\žnë³¹1pàDc`_ìí”¶?¾TºËø¾EÀ¢7 ³ax±èéÐæAÚŒg÷B˜íæ”30NñÊ¥K¸ôÊ+˜ŒF8³»‹‡|I’|¾©ë÷Y}€™ÙTÑË{8wî,®^} O<ñûÈóÎ;½³g±¶¶Ž^ÞC¢$ÍØöÁ:ÔxŽ^™²Ôåd¡ïq„ÏGl‰s."ŽÔ!ŽÁb ™éS!§›Gb“C…˜N§xç·qõÍ«¸úÖ[˜M§ØX_ÇÞÞÖVV ÛR)¤½Þû³>Àd2ÁxL{Ù%®_¿ŽË—/C& ÖV×pæÌì=‹3gÎ`cc++C»×/u¿ýçöd¬wšo±þ¸™9Ee€‘ó( ^z·ŽÙ†žsïe·,4V—Bf^”%Æã1&ã1nÙú£ÃC4¬>€J—¬ÒBêT¬>€”eYàm[@>­0ô±¹±‰3gv±wv»»{ØÙÞÆææ&ÒûsïôKœ,uš[^qï^pÿ76"Ã纉õö¹€ Ó´ ÞK'M’L›ºv‰¯SûCSwª@ )w޽oêH@·'©0á`ÿ¯½Fõr¬®®akk gvÏ`ow{{{ØÞÞ1éàëkX]]E¿ß·?*9_€Æ „°?Àh¨Z –¸ œ8ж`˜ô )T7€§žÓѶB†v"—,§ÀeQÒ‹E¸÷E}¾'ZœV}€#ŒÆc¼ù¦¯gú¶>À†MÚØØÄööÖÖÖ°¾¾áp`òè‡Ãà×¹èG¥j»=\·­ùu/­£Ý7a£$ªP¥Ûú=›ÍÜOÅMíöï >@Y™Åï×úæêððÐ-ÆÆæ&LÝš{iïV}€YQàˆ×ÐÚ¦]K¨Dùúy†~o¾>€IÒHÌ/’ãEû„Q¢Jž‰TЮaûCüçäî¥>#nò~¨ç9´öo{"‡Œœþä§>…úáÇðg>þqǺîÒ¶„/eiº5è÷¡” ê”Uiu‚ê]©0mÞ™êÐOÇsÏsî¹>@8Å8WÀ&R^ß»Qàð𳢸¥µþ~·î¤45 ö‹/¼€¯?ñûøîw¾&äÆí/~îsø«?ú£xøáa:ÞÉÕ¸%…x)Ͳ­ý^î`@`ÿ`×Y}“¡C;ߣúÍ×§[ ¦à8EüÝ®0éWJoµ €Û~¿+W®àñßþ_øßø‡s\ÈAƒ~ü¯ÿ~ø±ÇÜ‚u"€”/eiº•ç9ú½zyÃáyÞ 1Oî×8¥úÓÙ Óé“£#L&Ey«mÛN ¾ÿk¿‡¯|ù˘uÂù®"äsŸÿ<þÚý8666ºtƒY¶•gFñëõzŽu%Ò›mMÛ| ëp@g .Ašþê(B ¬*L§3L&Ê¢ò<ÇÁÁþûW¾‚?üƒoܾwõ~ã‰'ðÝ‹ñwîïã?ð˜Íf‘ëÕËIráº>ï×øÞÖB ×ëá™§ŸÆ¿ÿå_ÂþíÛwïñ\Á·o߯¿þù‰ŸøÉŸÄüÈ_q¬ÒyêÈ¡ÂîÚðm®€Ý¯ðîÕ nó»?Ž/ÿæ9v©cÇêºÆ¯ÿê¯â…çŸÇOý­¿ÍÍML§StEïbå@»_à´ëôû}ìïïã?ÿÇßÀÿѤ÷†Ôþï7¿‰·ßz ç§ýèGq)ÚùÏï×ø^Ô‡xùå—ñkÿáWpåÊ•{çÉ¢—/_ÆÏÿ‹ŽŸý{?‡O~ê“AÄÈErÒƒB^v¸"˜u4ce¶ã~}Í®ñ~!ŒGï[ßúø•_þeL&' œxOñd2Á/þÛ_Àx<¶&ûP®M1†´3邈›³ÕÁæÞêuòÜüEõ*RHk×(Ÿ“ÉÄTì11žŒM„Ž´í©q/ª@Z}Wš9µ®è!y&¹âJw¸½Ñ5mÅa"ŒF‡ø¥_üw'>pï Ø)¥h¯œ‘Ó„býÖñ<¯¬± “?ø_¿>ÀÜHÙ[HcGïÿúNDóð¿Ã,·%(€ÍqÛ@tü<ۘ玿l d-ÜcúÎh@´4î1ü‹¼”ÄQ¼ÈaÊ“mÏrQkÝ]ï ¸Òü(cî>†˜À½×`0è‚Ñ]‘¢KèºyøvÉEóÖÀýú‹[ Ò“ÖØî$»±×à•ÁàTÇ ñ8cÌ’ì\F«îµÔˆ¥ëûõÀKXÎâ Dq†pÔLošWý;…@ÇÄvÙ"DŽÁt]KÁÍ¿K{(=+p¿>€fTkäZÇø"i;N?WFHîöÎúB´µ»…g§ü3}§¨‰€øÑ¡ì±ó ±®Ý¯·#÷0´ûuð^Á߉Äõ$ !¡±ƒµ=Zxàs KÌãïB`à ø9€>€-DŠd`þX;Ð}_ä‘dêqG|¿>€¿7ª a`pÀ@ƒ†„àRSáËz:xà§0À_°!¤[NOº íÉ™i^ҧC¾¸žEßK}ÎzçÇðÞÔˆÅR§„ŠKçÂ1 »—‘naK(!°àZpÖ#o-»î8æwbÿÄö9lÒ‹âP-‡+‡‹(Aܯ‹…Í÷FT†MX”*6¼ž rxSà<4Ô!ðv¤ð"`…ú˜«À¤m0RŒ ŠN§>Å"ÞËúÑÈ¢§è«ßPG(lÌBÂÀ “!¬~1¸NãŠEAË ¬»µ–ù‘ø‘O~êSŸúè'>ñ‰­ ÄÊêªÍR‘^ËG¨@}0ë˜,ê7oÞÄ•+WðôÓOßúÎÅ‹/¾òÊ+˲|†âGíß ÌºðkÌ»„uÇášæÖˆ2ÄHAGm0µƒZ°_–å;Ï?ÿÜwŸþ¹½ÕÕÕG|ð¡=òÈ#ß÷}xûÁ‡gΜÁÚú:²lð¬@;ˆêºÆþþ>Þxã \{çýÚåË7/]ºtùõ+W^F—¼ð «Ûµ&À×Y?~,ÿ:ƒAü†ED”ßÀèŒ :²ìÁ(ÞF/>ûì3ðì³Ïìäyþàööö‡ÎŸ¿ðÐC?|öá‡^àÄÞÙ³ØÞÞÆÆú:²4s¹r$#ÿ¤×€0‰GGGš ©Ãƒ}ãæÍƒk×®½}ýÚµ+·nÝz­(Š×Ü€ôÔ®ë й¬Þ¥ü-¤~>»®™ß-ÌcÜ]LŽ¢Ì9 BÐÁ½ˆ[Y–í­¯¯_ØÙÙ9wîÜùÝx`ëX½pá‚:wîvvv°¹iꬬ¬¸Ì£8 Ðêƒd²DÝÔ¨+S˜Á$ˆ”(Š81¤De‹7øß 2yƒe”#Va¤÷¶MƒŠ%Ÿ³f³Y=™LF£ÑèÖh4º6Þ:šLÞ¬êúÖN/, é(`(¨½‹ÊcÀs®£ï¼é€{uÜ;bG÷6u™‰Îkã¦äH‘ÛÏäZîÁ”;YWJm‡Ãíõõõ­­­í3gv7÷öv×Ïž=;ÜÙÙéïîîf›››bccÃáƒÁÀÕà–YqŽí .«ÅÌ›²„(ç?þ<³uвDAõf…ÉlšNQÌfúè訜M§Óét:™ÍfÓéôvQ7‹¢¸QUÕͶmo˜l$»‰šKû™;¦òEÔSúÝ6„€][ôEçº8B—‰¸98R¤ö nÁÿ¦ì/!ÇÀPJ¹ÒëõÖò<_‡«+++«ý~°ºº:‡ý~¿Ÿçyžƒ¬×ë¥iš&2I’DJ)ŒÜºm…ÖZ´Z [@Wu­«ªÒeQ´UUµ³¢hË¢hʲl¦³Y5›Íʲ,‹²(Š¢(¦EQLªª>ªªrTUÕ¨išqÓ4‡Zë±p˦¿eô·Â¼ w Çb¾ðwöÝ®-rñÏÄŸù†Å.äXÄ-¸o›>s“tœ×‹”×infÆÈ½O¦»Ìî«b¡œNö½ô~N³Þ>Â! ­?F¸žõŒÕ?âaá¤æÄ†=5ôø`·©ø5Â_M'¢TqÙ. ñ˜®ýVòJ‚p8Êda€sZHO×Lnøº‡}&ׯâwVQáygÞÔÝïEÚ¯0  š HPEa˜°P@†<14²r?#«“{2u$j»tbD±A{6Ü=·Q¤Ý<þ("q”Cµ’üAþ*¯ÉOåyùË\°ØV÷”­›šºòà;Å噹×ÓÈãsM^|•Ôv“WG–¬yz¼šì?ìW—1æ‚5Äs°ûñ-_•Ì—)ŒÅãUóêK„uZ17ߟl;=â.Ï.µÖs­‰‹7V›—gýjHû“æUùO^õñügÍÄcâ)1&vŠç!‰—Å.ñ’ØK« â`mÇ•†)Òm‘ú$Õ``š¼õ/]?[x½F õQ”ÌÒT‰÷Â*d4¹oúÛÇüä÷ŠçŸ(/làÈ™ºmSqï¡e¥ns®¿Ñ}ð¶nk£~8üX<«­R5Ÿ ¼v‡zè)˜Ó––Í9R‡,Ÿ“ºéÊbRÌPÛCRR×%×eK³™UbévØ™Ón¡9B÷ħJe“ú¯ñ°ý°Rùù¬RÙ~NÖ—úoÀ¼ýEÀx‹‰ pHYs  šœ ·IDATxí\ på>7ɽ\Ä„*Ä!ß:PEDñQµZ¤È(R^ã»Z¬Æ:T¡Sm¥ZÇZhÆWÁŽJëtF Xq-ø@ Í4¨lQ@!!’ÛóíîÙ=÷Ï¿— $1Ú=3{Ïã?çÿÏÎÙÿß»»÷ÆR©EE ' AD *„¨œäeŠC,C¡äò!í#™Ö=Û$gmì_ ¤€ÛAÌvà@œµà#ŸÐ1>ЩtÌd_ƒHÎö³¯Í|4sÞÁûЮ¼"H²FQ¯^½Ž9öØc¯¯¯OÔÔÔlc:µV”ßcDt·HÎP{øø’|4p1´0vÀ¶5àì/:õÔSÏš4iÒC‡¼cÇŽ>%%%²=x¦é+ Qºð ¸È¾óâׯ°gÏž½ÕÕÕ/^¼ø¡-[¶¼Ç©ùç«•ãîœØi…à­¼ ž8qâÂ3fpþKÚ¥3JZç%­]°-‚Cˆ×B¯Ï?ÿü4^åç-X°àN.†½Üµ³M`ˆ´B`†ùcÇŽ:mÚ´#ˆ;ÀF»³2„éš«Edßõñ;ꨣhüøñ7lØpUEEÅFζ \7´+,ÿÉÒÒÒ¹rPEÐq@'N'[Ó6]›LÛhÚ¦k“iMÛtm2m£i›®M¦m4mӵɴ¦mº6™¶Ñ´M×”q^ceeeƒYŽ/þBàž !/‘HôŽÇãÎjùC»©§m4í(z}š´Ö £MðÐ,+Od¬â:œ[J&“…/äÞ¿¨3 ñt¾IÀ+‚VhÝ©†L@lÀ m³A»È#ûÎrÁ€"-¿ÑSöKI’$UË„–„‚Øtm2èÂ6²ÎäΊŸä‘û-Œí$¯µµÕY tbLZxÁޱg«‰n3iáGönä$ìÌøI¬Û¶'y( :YšÓÑrÐÚFÓZ/LÙw|ütÜA‡ª‰„]'èvI"°¦#ûî?'±êÃZh—åIh[1è„k6¢Ù§_'Éõ‘yÂteüB Á¼FÐ…¡÷.‘C&“Ä BËEm‘}pí$qéÊø!&X Éa'5H›È%Ù‚¡ Z@ô„ìÝu‰›`Ä©+â'ù-íˆ$N e"Z0ôD´èH›ÈÅN°Ö-z ]o_Gk—½Hÿ´'M˜>ž¾ÓÏå¿ÄoÁhµh€´É¼ÄN°Ö-z ‡kïö’þi- ŒCŠ›Õ*¼ ‹³j߸ž~zâ8z…;¿ø¡EWŸä¤+ÆÿbÕÃtå¬?8‘ûýú8m|b%xÅÓqÑ~tÊü½ñÐ7ÆÒã™~h|´›`-(™×Xוjòе9(}˜ú&ßÎ…é§Ý"íªñ¿Ø\+nÕn§zþjïêùw`üuÜdbÖB@ÒQ:ùfR…× Z:ïP{öG¥ÚZiÿþý¾¦/=~ù¥3húê:zg ÑØ;Î¥{¿·JÊœe®ðE@dZG|¬Û„î {CpÆBÐŽÙªHOF:4±æ°í[ÕŠÀïRèKY_û-ya)ýõW©ºšhø…WÒE—Ž¥±— £^xÈ® V÷1½ül%ýqù:GÚç˜tõŒ}¸’>ض›¨ôBš=uå¥ò¨°tVœ¤¢ü0®e+½òØÓô¯&¢}O¦³ÖÓK•/Põ 8†¦ßt ?³Ìé³ÃæÏ+¢ ‡] Ò§µÐe›LLÚÄ™0¹ $8L/L.v¼ù$;æoKzüêåÒ„Û+=¦Ö¬X꿼s*½ô»hH{Æ6Ö¾A“GßJœº¸rÖ¬¬ øáƒèÆÉ#)ï³uô»Ê¥Žü“AcèòãˆVTTÒJO3mÄ5¯ÒÏøødÑë4ó죃¾<*lžar³ƒ0½0y˜½)Çcçv€$ËÖ€3Yã™Ð"‡-ÚÀ -º"ákM»ö\˜ž§x»Ê•¹ã€nø÷KéEpÁº{öâÏîšð“gi›ãÿ6zn–.‚!4ñÚ›éÚËÎðµ"'~)ƒÚrÝo `5е9óå!4eölš FO­¢z/â+0æuhówçÜörþ‡|}„œ6U§;1ySßäM}“7õÓxåB`ßDU‹çúêWÜÿ<Ý;4~4-8o2=ní¯èíšÒ÷h=â/WPåÊ{é”"(\O—^LãnY†Á >ÃeùÓ›±/!ºéÓ4n0¿ì=ñ j8{2ýÍióŠTéþºB“WªVÒÔ7y«‘fÒ]ôÙ,´T²ÉKÅ‹¼><û`EàÎýUÇ»…ö6x3<“~<æ¸`üžÇÑõOÝæ‡ãË}û8‰ÁŽ8á×Óè¤ÞnÂáséˆÉtÏ鞺7ŽN:µ[æéwйåIÇŸÔe4ü|±uO&‹Ã›°úIl¥¿ƒ¿ EQB$[ÈTiÙô‘•=ŠËë,Å4&/‹qj¥±wŹM{Kà§.À¶¹ ïmºÐ·çNÑ ¸.ãà¼wÆá U¬hSAœrQ0Ž=o™~ƒëc`)=´ÇYÍ¿½™/9Xû`®~êÔdþÙ¤DY‘ëÙiF{N ãxNZ!pÙºo`¢Ãw eGWì¬õ,ØIËž|À*ž“C±^×sቛÒȪ9t<¿¼…ñÿ»öEzà]¯Ñ[Tv¹`U{Ýë)$éûèÙfSÞhþ}ágŒŸê,ëBÀY€ïéÝ ø4” ¿ùàohî}Ù½ÚÖ0fͽ‘ιâ:¢7Ÿt\~øÚKé³Y÷Ñ™ýX´ä>Zö¾Ìä*öíåæ§;G=ôä/Óô‹>¢Ë§MÉÝëiI ÌÙvïW8K€×EîaèÁÓq£Õ≣š&÷Œ» Ò«©¸º5Ø”Åè+ÁØ›ýß§×^óÚÇ…Û{èÕôàÔ7hÎ35NÃ’ßÞGK¦ÊiþŸn ~|ÅßÖV@—Ýõ8½óÖ-äÔÕвJ×.Í„Gtâ¬÷\,kF ¤¨…ÇwÏü6â[ ¸¶³"ˆåWC/9ôEÉh´kô¡ùÑ™ìƒBСJ:_ñZ[sé¬ë*hñý×Ð ÝÌô ‹¯¡Ç–.¢sûåù¾ÄzLóWü™æÍœBCË]ƒò¡ãèÖÛ•}ªÙIr,¿t!™ä[ë9 ’‡Šó(¦æ˜+ªùyÝ.~’‹¬·(¶´´ø{–Þ{@ c£Ýpí¢'ƒÛlDGluÿÒ–Š ¤»«ªhŽuüN°ëWù9?¢ŠåhçÎÝÔܧDaO*Êïáø+sj®]Eó}òKò)ù­Sè†y/Syß¾Ôh .’6{Ž :¡?Å9¹¥PUÕùŽþc˜É¾Ü&¾°N«C'èûsVðáÍŸ·×/N‡=îpÈñSöâ‹Ó¡÷aÝ ˆ3S’  @KG¦S¦¾ÉK?o§Â>%¾ÿæõN¬øhJ®[MUŽCUôêóˆkixÌ(¾…Èqp÷ÿ ©óýwÇêìø3 ¹¡tðôÄM焌Î5-<0 ÇÖfÊm:jŸ[F7/šKÛošG¡c \yÏãtIYÂúpKN˜‰¯‚µLºEÀœ'db'XË@:Ú^ús{w?­+öyº§'­ ³¡õä²Ñ7u:Ó>Þï»4ÿÅJª^÷!­ÿøSÚ¹·™šøJ¯˜ 6bäpdÂßM¿²å;Óÿl|r¬…E½"˜FÂÛ²ÉDßÄ6]›Ì´Þ¦k“‰¾‰S±|4l¤sH›Ø“çÝ„ÐBhlÄ/¦Ûƒ,oí[I&LmÒC&Lm‘½L1B[Ö… [º=P§8ƒ2AdŸþ NÇ*SlD/“N¦¶Lö¶œ™+²Ê·ãÃï,šƒ /Xæžð‚ÃìDnê /Xô°©'¼à0;‘›z ½0lê /8ÌN䦞ð‚E/ zþYl+l )쑆QZßamZ®é4cfÂÚ´\Ó‘}zÂb£åšÖÖ¼" Ò.l…ÐÄ7^v577SÐx_ùБ¦5oÊÑ& Û4vá‹ÆºMÓ‘ý¡Å÷‡šššê8~ø#-~jâ‚Y¸wÒ´{÷î ¬<‚ÿ,ù- 0±t¢å¡àD^h£  åà#û΋ç5µk×®Mf<.ñï•™…€åbïÚµkŸ-..Õ¿ÿã±*t²$Q mb´ DöÁÍ4‰â"´‰ÑèÈøa»ßºuëÎÕ«W¿À]ã¯öì…Àƒ¦8a7nÜTTTtï°aÃ~^XXØ—ÿw§$777ÏtVópÉ@Ðɯõu›Ö=`­#r-Óý‰¾è /:"ÿ´ç‹ÿýuuu;¶oßþ Ÿä×ÖÖnàx¤B»?Üô؃q!ÿ×â  UPP€×2ùÇ=)dÚÍ6#èîo-\5›7o~{Ó¦Mø7µ|ìã|ú×ÖBÀìøÌÁ«»x¨Š×y€ÁGEÀAøšŠ ç·(œÿUÜǸ‰‹ í[Ch!°2ЉÇÏBp-­„¯! ¤øÕÊ`ÐsÉXZ1¢¿Ù°¾¡ôÍžr4;[þ:°pﹺIEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/red_bullet.png0000644000175000017500000000112511750754334025122 0ustar drazzibdrazzib‰PNG  IHDR Vu\çsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÜ :d7êsiTXtCommentCreated with GIMPd.e¬IDAT(ÏmÎAkÓ`Æñÿ›¾MÓ6M ëÒ®íš2yP†s×}} /ž<ŠßËg?…'©»(ö6p°Ã6d])©d1É—®y½èDðÏñГ‰AQ40ÍO,Oˆ¢i*íyˆJ%Åóΰ¬7KÒÔDˆ÷œŸ·™Ïk ŽÀu¡ß·ûøþk”:–˜æ..|NNúL§‚ €,@4›èím©¶tY®ò³$žruÕd:µ¸¼„<çA£‹U–†ÜÜbYm!:,u‚òÍ¿ŒNªîóÜûÜó»çüÎR°,˲,˲,˲,ËòR™ïÃ=aªÖEä Àá@'Ðì¶©ê#À"2ë%r#ážð`P,ÿNUxfp`pû|Æu‡V="RCTuˆ<ë«Þû7"² Å²÷3íx –hÂAu B¤ÕãÙ܇j ¦¯+9Ç]¨6!¢ö7ET7Ó×5±¼µ—åOA¼óTþcUõÀ{€#TAÕìk÷ÏV÷„¯~ëíš§òž)"×"÷†ºCoŸ-E^ üº|öw¿QÕ·£Uï½sÁhlæy‡olà²xðY ÕP@õ4à[à¿›hâ2àWôu†EûŽeµÿŸN–·ö_¶|ÿ{ßëÈ«®Íårk Åâjã´5ÔÕ­hjn´¬XáYÑÔ$õMMÅ:Ÿ¯àóùRª:V,÷¤’ÉÝ©\n×îmÛvõ®w¥(À„{ÂMÀ?«ê;Eä ÷Ö6ú&ÕʧV9NNTÕ÷„/‹õÇ~8åÍÏð§S€3ÿšÇ|ŠU ¬(àT)N “ša¼ù‚ËÀUÀ_Dö¹,ɪ‹ŽaT¿\F4ñUzƒÓYLv~×ÿ‹Ëêõ—'·Þz«sÌ1ÇœÏçOKg2ÝÉdòȉäDG2™ªK¥Rþ\>ïU|>O±Tqüúý~ÑB>_Êär…L¡Ëd2¾ææçnýÙÏ6çs¹{’ûöÝõwçŸÿÂ’L¨;Ô¬ª¿^5©¯ZF™Aù¤üFU ©êÿ ÷„?ëý[ ÷W²¯‡ºC7 –^Ò»  z±Í|y~û™IFòˆøPý$ª›Û–ÕhYªåÑGuüþÀÉ~¿ï"Çq^ëóùhmi!—Ï“I§™H&Ù76¦ãããRÌçÉe³f«9Ù\Ž´y¦Óéºl.GIµRi£Çã9ÉS_ßÛØÔôÌm·ßþ}GäªÓ^ûÚÑEL¸'¼RUŸ‘Ž2R”Äå~Ô˜öEÀøEÄqcý,ªú¥pOxc¬?öÁZ b•°øð‘õ ì¼ÊÈ8Ó{@Êݸ&t:ªç#2QáÀŒ••E$gŸG]å÷†[ MÜOo0¹¬RËâ–B!È·óùÂa"`5UÅõõÔÕÕÓÒÜ"éLšd*E±X$“ÉÏç)•JK%TUü^/u~?Žãàˆà8Ž:Ž#Àá"r)"-ÀE‹˜pOx%p»ˆtXe—ëð(ðð8ð;àEà98ZU{Dd•˜,Hô…ºC[/_¨ZÚë8ܾ.ÖÛ|Aæ?Edï,®“lr5^âbD2ËÅ€ËD®¨v"rª¯q‘HyTOCõXàe•Z·ìØñÂê¦q(KÆwW•’–PUTÁÁïóÑÐÔHçºõä ¶lyšíÛ¶áõùèho§­­ÆÆFü~?^Çq0E™peïðð±‹r‘BÝ!¯ª^'æô7P¨ê—¯ÇúcÕQ2Gꨪ—‰È)n·Êò!Ÿ ÷„ã±þØ5p ü›%|õ=¯Kbý±­p?jÁå!r½Á{ìÿ7‰ÿ‘[€—[ÔD Ö­z jQJû¹”"µsÑD ½Á}È=¬§¯+½€{Yäè fÈýD¨2g¤nq×ðõôÇÔ%v i¾XÐŽövT•l.K±XÂÁç÷ÑØÐÀŠæ´¶¶ÒÒÜ„#»÷îÁq’©/ìz-)+V˜÷´µ¶ÒÜÜLcc#444ˆßïgb"ÉŽÏ/Žƒ‘“TõóÝž´ªºWD^<<280ø@¸'|ðQ 4î?7 ÷„œ+Œ]e5aqîTà­À-Ký ¬+Wwù—ãQ­³îQy^ã.p1Ò×õÑÄ£¨‰ˆZ›7‹jÐŽsð^;Æ:¦’ºàãD/ZWëô ³ÜÓ!ˆüªoD¤U‡H\$"¿Aõ&úº~;¹½nWŒùà?yªŸC¤øå¬.n4Ñ œê[Në"B4‘·aû«éëzо÷Tà ¢`ªß¢¯kx–ñx7p°É7DâEDžBõ;ôuÝlç³ ‘w¡êµëï®§7øØ<Öâ,à]@È~Nìš>ÈPý>}]{—j[yQŠÅ‚QUG›in^ÁЦ455ÑØØ@ ࣤ011N.›¥. ce¹\ŽÑÑQÆÆÆÈd2ŒÓ¼bÍ--´¶´ÐÜÜLCC™l–’–j˜Pw( ª½Ü„."ò¦X,1ßAcý±ðåPwè(à|7w©ªoÄVœ‹QÕ!µÄqÐêýfp`p”—’~ªÚòò‰¯§¯kêÑм¸`†q>ˆj½µ†J.Àò‹É×iDäÓLF˜ÜJЉȥÀûQÍb¢WerMQmÎ>@$>ŽHŒÞ`i†{zªï·`çî·®ôO?ª^ a…lCä#¨~Ìry“sš…ê©@³µ(ÄE8‹Hü_éëúÔ¬dVy‹›ŸÖšÚî—:D¾e£f«ÜjȇêóˆÜlE5t£Úh-Çþ¬Öš“,‹×X+-Íd$Dñ!2<€j8‘•¨æ+à`´Yu-ÿª¯µkS>4<Öüî6c¢’G'£ºÖ‚˜Úyw¢z‘ø)ôuÕDf—JZ´ëëŸ ™bÒˆ€–&ÑD [b,Ò5Œªîrã?½ºû„ª¦]‡nyü#€»ç"^-qü•pOøƒªz˜ ¨?ê}cp`ðÉ¥Ã}$Ôšõ~Â=áÅúc_«ñ1D¾êÛ§D€Ì<ë€ÀW€ÏM\Dé UYBwX΢‰û€ã+€eçtzƒO3»HE‘ËÏB5‹È€ÑÌT)Ï?¡z" S, x‘øé뜭`ø8½Á[«ò«Ø:å5ÊÇèëúÉ4€ñeT߇HýœŠMÔŸ|®¹‚Hø:½ÁÏLó™> ´ºx­ÙÀåtDÞˆjaŠU©zp!}]¿Ÿæg—Ù|’’}½ ‘Û³jïÅ|á¡L:s ÎdˆyŠU«hEstNH1æÇ!ŸÏ“J¥K¥Rñ—5»H"²ÑmyÛ$ºß-Vk“˜\™)ûOUYàP犋s°áó+—Ð=’¹|NUÍ«ÛÔ^¨ôSÀGÛSÒëÌòÍXBô`Hü­DžnÈ©r‹Äº9û+ÈúеSvD>Goðï÷dW r°¯=•‘ ˆ¼HÜ;ë¾2Š÷ºýÀ%oδ÷Y&•}¨nN¤7ø“ÖîÿJÖÝÐYÔ{€c\œ•X æüiÁÅŒ-"gX®Ç3ëøÑ„‘>ëF‰u뀟Ñ×õÆiÁÅ\ãFTÍšªzì³óo!_]“ âqZ'&&:Š?Äý¿½Ÿg¶laxxˆ|!ÇãÁï÷ãóùñù}x=<c’éÇ’%“SgfžÍdص{7›~˜ûÛþàxáߟKyZªj‹Jªºg‰”w'pBÕïV,Ïé÷„£"ÒëŠpýu¸'|V¬?ö“— ÙÛ%ÿ"·}À«QMR®Ÿt1’¨v rªo#2 —hœ†ªßº! 4 r½ÁoÎq¯Dâ—W3™¶PN·–ÖÐ Ÿ òôŸæoëQ áªx·–ÅEôwÍÁcýœhâràRKÊNgYÔY’¶ÎFsê«èëúÅó}‚hâbà»¶&l¦w‡êÑ.ëÈl³8— ¿Ü®_É®éј¼§Ý }¼©B¾£XÈw&'&ضm›Ž‹ˆ°¢¹™ukײaÃÖ¯_O[[+>¿ßDš&&aïÞ½ìÙ³‡¡¡!öíÛG*•"ŸÏã8>¯Ÿ×K}}=k×®%°~=âñkà¦"”WDŽb j`Tõ¨êÂHàù†º8SDÖ[¾¨ADúBÝ¡»÷½d@¦¯k ¸hâ稾øTÅ|Nšç&âàGä«D÷ÔÖ|™å&ÝCª~qžŸÿ%"ZR²Lâgy°¡N/ª3eÈš @Kî'@|ž›éFàlàài­ ‘VT_‰ª°G˜_±,À6ïæxf.}"6ºTö¶"r>‘xiVrØœŽ‡¢:jT[€cí3^P !àx´·KG{«V­•]»_dllŒt:Å /¼ÈÎ;qDðú|ø|FÝS©###ŒŒŒ0‘L¢ªø|>YÑÔÄŠæfZZZhkkcíš5ttìÞ»WjÙ^0>»‘%¡îÐ* ¹œ\N ³×[hTêñPwè;"ò);”¨êéÀ_×|»ž»å ³¸IYL¦ìþ'æ&i𢉷Ÿ@õÐJ$ǘßET×!òML¢ØB¥Õ6·ÓŽêã®z¨¹Àp‘ø6K„–Ý9“+òØŒ$´ÈÖi¬ ÁTå딈˜ê³3Z$ûË"Û€C§U?ÐQáw ü‚Õyˆ<ƒj×,³†rÞyDNBõ”9#OeòسZáÅ`£0æ;òxÖ¬^C{{;Ç6 j~çñxðz<ž>ŸÏ“L&eïÞ½ íettétš’*~Ÿú†Zš›éèè`õªU¬]»––ÖV2™Ìâ¢Hª‘¿rˆÈ!¡îp`°ÖÚDäåªZ/UZ«†Á¯e¼ˆûe2I^êÝÆbÚ(˜±7ÅúcÏóÇÃUÜJ4ñzT/Aä.K&‹ê›jDΠq o#ò ©§yΞÖb•¶„H矚iG®¢œk‹fÙ±€“;‰êÎÉ2c=­¨d›õÛê|,‹êŽÇĽ¨v0%+[I¥iJ7æ\Y—U³’Ébá>b(•J iooceG;---þJãØØ£££ ³wï^†‡‡e||œt:M±X$_(Ëç)‹ŠEŠÅbÍŠå&yotGnlTï9i‘ªóVi®ZÔµFbý±ç0!ë²Õ¡ªºQD¾Œ©j­à‚SõÍÑ܆HªYW/EÄSSbV9énR_Õ6ËÌWš¦l~cÖçgÝñÓE`&ój¤ê}ÞÌÇAÄ7Ë;Š@zŠ%a¬Ï<µÕÁDôfº~9a®*ðR™Km¯÷mõC(•LR]©d°Îñ8øý~:u>¿¯×‹ÇãJ%cÝd³Y²Ù,ù\ŽR±H­º4-ÀO«êNW”Ƙ×ðÅPw¨¡–ÁÃ=áU½ÀurßsÓƒƒßÀT5»ÛG|DUOtƒäKVzƒ›1Äx¥ý…µ zj8Þ&w7Àp”uçC×£ºÁ•o¢6×f{ óRKdN¶@4Ñ”ƒgŒ”í?Ÿ&L8¿4Ãßó˜H»’=ó *ˆÔ‡ÚTÿéæPöØg3•ƒœµ’þIÙõ\pޕׅq“>ú*ÆœLu/•&2ËQԩ༨­ì>9Ƭûñ/®]“0õ?_]Hs¸'ÜbÇZQž½íi[`~¡sq&ï/÷ŒQ“xv•öŸÈDâ§"rÉÔý ~àuôuÍÔ t&Wh2Œ­º½†«ïDu°ÚæÀ”l!eøÍ<>°É•Ð'˜ú°'k|pOUøc •€cía64X‡êqL¦ãWËð &a°LÂv¢ºùäu©¶"²iF3òT÷!°÷äAõúºNúŸÞZy“6‘?SòƒÄ•î_NìÞ_}§¤)N&n¼QÜëÙq¹%àÙâr“Ê•ÀåážðÆy‚Ë ªú=LXu™‚ˆHTU·-vaŸ®¶95eótµÍgÑë@îƒç-aÞåzÈ›g°<¨ïÚäb]”|å¾®]ˆl¶–G¬2¨^K4Ñ60Š-B<‚ɪ¸ ÕZ õvO»ÌÌ"&Œþ·óüü'1.·Î0ß1D®ÔW•›¢ÀˆÄó°‹€Ã*Q¨éåaD¶»Ê ˆ¼ŠHüÜyX„uDâljo"šØD$¾‰Hü"ñÆšð:—û}6“y(•Jáñ8âñxqlé“̰¯¥Š˜UÊ9a—B¡È¾ÑÑl*™üéb\$bý±­ªúå2·1©{ p‘ªþ2Ü>ßF†ö“PwhC¸'ü9Uý…ˆœ‰«û›c;pÍàÀ`~‰÷j;fu’\MæË,}'}][€t¥xΛT?N4qHÕtP½Üf{ºãvÓ×U[(^õ».^B¬R¯Gõ&¢‰à àÒ‚Hx'TRÄÕ ª·Ìby͵È;P½¯R›cƒ4"Ÿ%šøØ,`×L4q ªovõ-ži¾w£ºÛ•a›GäàZ¢‰õ3(¾—Hüó¨žgó’d–ç¹SòQ²-¨ŽW‰ÿ¯YæÐ ü"77Ú×ùü¬¼Ï,ÒØØ¸&“N¿l` Ÿ»ï¹›­[oCÏà8N%±n²æRªŠ]¿«d+ùB‘‘Ù¼™»î¼“ç¶o4Õ׿©l\êƒÉ8u7›BLdãÀ•ážð>à^à÷ÀqªÚ-&­¼QD¼Ót´ù@¬?öÔRéíàÀà–PwèÛbÜ¥ð‰BÝ¡ÂLþ•m™ùKéõÇ&¨äÿü3ªi××0Žê¯‰&îAõQD6'ÛÔqÕÃ4Ùö µ\‚Hü‡˜ÊíœÝE9T{Pý!‘ø-ˆü?LýÌáÀk€ Pí¬rÑÀÔ×ühüRžhâà¨6ÛÝ]êQý4‘øÛ0½d€g1-^i-±Ñ†íg/è뺟HüwÀ߸¢IDÎDµ›hâ» ôa”Ã9ÃY©qÚ¿J½úy~‘÷¡Ú`•£„j="W‰¿ø&¦4dªAæïĸÕ5v¸“¾®¡Z–3™Ëµ‹Åõ™l–ß?û,cããü~V®\Ɇ 8øàƒY¿~ÍÍÍ8އl.Ëøø8CCC&ÑÎF’öŽ’J¥ÈåÌöxa§ Ôü~:;;9hÃp<¯\4ÀXÅýX¸'¼ZUϙƔ `ò4Z1ÉN.¾nJÿ^\_oR‘Åúc¢quÄÞç‘n@¬Ázh›íãöoÍ5Y_×åDâç˜Zn° Õwï±|ÄÔÖ&¥ÿ^T¯^¤õa¢‰c«ò;ÓõYò¶d݃¼+ó·.FµÞàâ¾w©7x/ÑÄ 6Z6©À&Ä|œµœkå”×$_eåëÏ჈ôcò€J.ÞgðT?o-øò| —Ôp…î¶jK8¦ºb‘øÛ1‰ˆN¥ÿ‹q!{ìAá±c¹×´äÊÿàúºjæ$Žk›¶·µ³fÍvïÚþ±}$“<ùÔS<ùÔSø¼^ü¿TI¥ÓŒŒŒ0<2Âøø8…B¯ÍÚmjj¢¥¥…ÖÖVÚÛÛY³z5ë;;ihl`hïHiIƺKç†{©ê§E¤½Ê¦÷ãÜ=Ê¿Ÿúbý±Û„÷180¸;ÔºBD®=À<ÊRÈùˆü'°Uw¨³XA(op/"C¨~’¾®Å»oªg!rpŠUºÒ”ë»Ëù'®c%ŽÈ§èëZšâÒÞà'‰&Vï¶–QÑÕ7%7å V‘Ç,ÿq̬Im}]/‰¿ßZ1­Ê 1]¿œrev‘§1éûbÙѤ%«¯ñ ÑÄy¨^ ¬­€ {û?ƒ25Q‡Èݨ¾w1ËXðú<¬^µš––V:;BDðù¼x½ÞJ}Q©X¬$ÚŽŽ²wh¨R"µIt¾@€††V45ÑÚÚÊÊU«X³z5mmmd³Y´†n&³&öÄúc_ÎPÕë]Q ™HR-®–h-`úq¼~p`ðö©µƒƒßîw} ÁŸ¦ôu=h;¿=†©™Z´7ÉX ¦³`ÕsìI¼×Åtlûнn ̨º¬¥š·îÀ;è Þ·Ä+òˆ|Âf7¸,‡©Šo¤Þº—FõGÌ'w¦¯ë.àlDî³ëíe®Û³æRàf à ßîÃ|Öt@y+"g[â»ð2•Üî:×çÐ×µ{1 ˜J§ÑR%Ðã8Ô×7°jÕjŽ<âHB'„9ùÕ'sÊ)'sâ‰'ÒÝÝMwO=öu 'pô+^ÁºÎN ¥Rd²Y“`g›U)P,—`¬òÆ€^U=óÕ!{ÊzàrÊA','óë>}vp`p^ýdTÕ[mèt•Á3Ëû¦A©ŸÁí©1kRëe)õuÝœŠÈ§QÝeÄi-À´gÌ úYLûþY²\ëiÄdêš×\Ù ½ÁQT¿€éKû L¶¶ô!RgóAî°÷ð%zƒ³¾ªîa~ëÛ,‚FPíÁ4&Ë[NÃoûÝø,ú€ÇÛŒgeÞ"M˜ês™a½ã¨¾Óö•õ6Ü>{ïu¨Þ‹ê ¨^‹êz&[[0†jz–y o³m3ëÓgOù횀Ÿ¯.¦7¸èÞ¼{÷왢7¥’I|k:ޱf|>?>ŸŸÏ‡ÇVO«*ÅR‰b¡@¡P¨|I©œSµÏ ù¼³Pz &¾"Ü~¹%7ªéߺ Ø!"Æúc;X–0HñW"r,pmYpÿbOµK4q ª‡#²ÕQ›ôu½ÁÜÿøzD¯Bõ(K†ŽÛ¨Ó]Kö}Û‘ø¡ö»À² ¬ž~K_× öú+m‹MÃU™ëDΦ7¸cžshBõd`ÐŽÈà9T‘ØBôÖ øÎ;ÿ¼3ÎxÛ~°nÍo:e"™¤®.@{{;«W­¤­­†ÓÒ'N3666¥’zÏîÝ 3ºoÉdŠR©H `ÕÊ•¬[·ŽuëÖÒÚÚF>_àɧž|ð#^xæk“sÌž+4;3‡ëôðÄ2:,‰Ûò(¦AöOzƒ÷b"‚|é >H-ù>“"˜fV‡T)€÷ÒÜ ÌfUŸ…ÈÉV‰ÊðÒJÁàÿÿ®’c­Þ–;_ÜP*•<2¥ßÔ^YåD»¹MŒiÞd9x×ÃøøDp]¿2Ϥ‹r‘–eY^b€­Öýû6¦çï¨ÞdÛ<Ü@4±ipúª— :QáQD’ÀØ÷3-dœD|pû?O¦’8GÊ®ÑlÅM2ãÿd?¤ëJ=·cÇØ¿½ÿLù“g¾Þ,ïÈeù³”hâç˜>¸î#\lTî. ‘¸-ú<‘³l#¬©)÷ªÿ1Jæ¡·Ë=µ;ÏËßü¦·¼! ž´fíÚ«W¯nX»fwÕª•NGGMM¢j\¤ññqFFFØc]¤Ý{ö0<4Äè¾}LL$) Ôi{{[±­µ5/"ÃÛ·oì¶_ýêWO?ýô½ÀNLm[}Ôe€Y–¿D€9ø°šêdAS;䨱É{&›•—-„ªçÐ×õë?Á:Ö’ð3I²¯;øàƒ8æ˜MGuÔ‘=ôµ´¡cÕª•M@  ªþT:ís†GFÖ¡½{KÃ##ùÑ‘‘ìøÄx:“Jï+‹{ ÅâsûFF¶nÙ²åk™å'ãIDATél6»Ó´+ ÷—s†t>H¸,Ëòç)‘øD®þÊæÍ7Q,€éðøQzƒ?} ÌÔ)÷pÂ’¿˜è[csskãA­klkk¯ohh¨Ç_*<¹\NR™L)“L&R©l2™L§&&RÉTªœó“bò+kJ.@YPu`–åÏÝ’iGõˆœùVŠ,&©oò6MÁTËÅ7#òUzƒý™¬‚ÌS×KâÂ˲,î ã±]ÿÏ@ä\T@d}¥é–IßߊÈO1ßùÄ’dN/˲,˲,˲,˲,ËKPþ_ )“žàHÚIEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/server_icon.png0000644000175000017500000002325511750754334025327 0ustar drazzibdrazzib‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÛ  3’nU• IDATxÚí}[le×yÞ÷¯µ÷>‡‡—!G#‘3KÖñØ–*¥Ž/@l }Ií´iã /RXr.ÖÈ7 yÈC Ô.ÖÒHj $@¤€ƒ>¤$n×îStsÙÆ‚eiFÃ’Cžsö>{¯µú°.{­}9òCÊÃAž ÏçÿÖ÷}ÿe­M¸ûqdW¾ú¯½~í_IÓli}}}s˜¦›ÃÁà•—_~é­“ò;ÒÝ0Íÿã+W¾úèÍ­­ß~à?áþû#¥òøþ׋¢ØÜïw{oó×ý‹[w0Ç/=sù“ýýýçÖ×7>µvö¢ˆƒq¬zòXÀ_éU „«¿ 2U „ƒqr@±À!"EQ ( ¤Ã!öûû;ÃÁ`ó­ŸüäGIœl.--mÞÚ¾õF–¦?º €Yÿ¥g>;¯¬¯o|båÌçÜ­ÞzðC ”ü9(A:øŒqnÙÈc2@¿·ÏÉó;ÛÛø«¿þ«ÍènX'üÖo}é³i:|nyeåÉû/¾Ï§Rc Ì3”RP ÒOS€ù^Aÿ#(y‚R Dæ«"óÒæ‡¡`ž\Þeÿ÷@áƒæGªk[ÿÄÞíÛØÙÙ…TÞº €¶þÊW£Ý_âŒ_>sfí1x<¥È}Õoº½.ê :¨Š¼)e+ƒ_‹“žòçÝwª„]õùTþPæIÃA7oÝ„ QÄÝsî šÃåJ´»»ûK{{{_[_?ÿèââ’^€nÕ"¾þjS% (ÍŠ˜ŽRPD.®Ê¼®]ävm[±„àHÀF)ý€T'(x> ¥)nÞ¼‰Qž#Šb0¦ ¤2¿ç]¸þJ÷öíÝ_ Ooœ¿ðèBwÁ½û áj¯3€þª¯Ü›oi]ßçIƒaT(ßgÎúÚ·¯#¡÷n‡1åØÚº,™Às(e@ªÈÈîàÙg¿ÒÝÛÛýµÁ ecãüF§Û5o|Iߤà@0ž¼Õhä@¿éxRµU'f —¾À{=Ÿí') Ï loßÄþ~qœxU† ×D?½ÿòêÞÞÞSÙ({z}ýÂF§ÛÑo¡¡í2ø!Æ1€õlvÅ—ÔôoYÞ&k (#pt_÷¥/(!D[·vp{wŒspUo™Âøèÿã§—/?»º¿¿÷Y–ýæúúùÕ$IJÃmVx=ø%ô[ÙÌa0-üUî{…Ðù‡ Oü}é€Ç,B*ìîìb{gŒ1p¹¬Â¾–2ÆÐd­¥¼ü4IÀ3Ï<»Ñïï?“çůÞwßùÕ8ŽË7e 6  ¨ø?(@9úö¯ ñÛôÏzò² 6g5+²¾A¿f¿¿‹í[·t ãØ^`!ÂüP?Ïá=€/}éòÆ`°ÿ•¢Èÿå}ë݈G%!Ú *8Œg >àV$Q¸Ú5¼$ ¸'/ý[ð€`ãßËÓá[[7 „D’tÀ˜¿â `RöŸ-ü*#ddñžÀÓOñÑ¢(~CHñ«÷Þ»ÞåQäÌ]S-¦cÏY‚Õ<æ$‚J–°÷ûß±u|¥Pä9nÜxyQ I:ˆ"^®xk0‰Ie‚áäÆT½êÔ{RžzêéG‡Ãáoóˆ~uílÄ4~ÍÛÊŠ/ í @n5—+_#@ù©ŸËॉF ª@y¥CÇ@>a{ûúƒ:.¢( 4L³Inu“+URPg€W¡|OÕžzê©'Ò4½Çñ/®®®EŒq“6MZÅõÇ|I˜ægý•_3‚• Ã9}Ë ÀR­è÷ûàQŒ$I  %ÀÈæÛZu±a­ÁŠ‚zT¿ð…§žÈ²ô¹(J>·±qD,ÌÅ¡ŒošÎèÙÇÚ@Ðø³Êhn›ô‚nË;~à]úgnK%±³³ÝÝ]ÓbŽAÄ %@¤#*Q®öZ-Ù±}Ža*+„ê´g_øÂSÿ`4]Žãäsgά1òJ$•bM“ ÉNüY9 Ä+2à•hÞ·úÍc»»;ØÞÞ#†¤“h€HXCÈ­d˜Çìkûl ÈB1ÊQD„8ŽE18çí àÀ¦ËÓ¹ü)ÒDçàK0p%¡k•Ñ(ÇÍ­-¤Y†^¯‡N'v+^2³ðM@%+3<0ýúD ¾å·«]³Áï2[™ñæ©k%Ig¿·¸ˆ$é¸?„ˆP†Ã²,E>!ÏsB€!ŠbÄq Œ@"ÌáDÐ’&ê!£û(AÏÜÙO) lݸ‰~¿îB Ýžvö`v½KPªÜ6ßkJ(ù2ŒPš<(æ•€½3óû‹§ˆ\…L)¼{ý„ÈAÄ' zX;{"¤T9†Ã†Ã!FY†¢¢c qœ IÝŸ!C—&ZÍu4oç ¤”ØÙ¾…ÝÝ]t: èv{š¢•tµ½ò¥KÓüÛ i9Y^ý§d-”EO¤á1vÊ$ÀBè•$Aİßï#Î2ܺ©‡^;.º bèõzX\\ÂòÊýF`ŒF#ÍiŠl”AŠB€s†8é ‰Mï|Æ4Q* ®LëÕ‚Á°ÁîîŽNé’ ½E8)ÁXËê¶üoµ€•ëÝTÚÉóéç÷ú~c,˜×”§LüƉßä”RG1Š¢@–0Êst’ƒÁ>Þ½þ¢(Âââ¤RèvÐë-âÌ™U`Õ«a4Ê0 0LS¤Ù0FÒé ‰0ΛÓD„^@ƒaÐïc{û¢8ÆBo1X‘ š,EKfW:óÜœ »d¦è#,øµÖT ÓÙˆßôoŸ¶‰ _GaZ¬IÒAÏ®(¥ç#ã ý ¼ÈF9ºÝÒáÛ·¶E’¤B·ÛE¯×ÃÂBÉjg,ÛÆÈ²ÌHÉÃÁBX`pt:$IG{ ”^`”°³} Œqô—‚9 Ë$4 ÌÈ€tN½¤ùª,ˆ€ „õ >(éþ- ªnO[%PI CƒR¢Â=Îy¾y ‘(òE‘#M3À”W ±{=Œ²!vwnsŽnwRJð(ÆòÒ2z=$N«kk”dY†AƒtˆÁ~JJH)5@‰°¸¸F¬5ðÕÛ¾$x^°õ"½Swü”e fDþ”)ûÕ€pª<€ªÖÝ/“nI á éƒñ ¯€¢Ð[­öû},ý®ïíí£·¸ˆˆçöA¤BOÒFXèõ°´´„(Š 0îÁšéÖÁ|}íµW°¼¸ ^ø´ßvÛ‚ÀJCéâ™WØwA5š.!tJ(Ët\vPVþXàKö9=  |ÐH–RBÅÌ/ň!I:!(DQìïï;š„R`ŒaqqNi:ÀíÝmDQ !%éÇ——¤xc›cV{Ûm ræÀÔ²lÀG’Ä8sfÊI„r#Q% º-Rïͳ?-‹QÈN&˜–ö§‘ŸüÚAéÊÂȦŒ De¶`½ÙЍé9œ>(ËbPaªKKKH’F#ýÙï°¼²¢7D2¿p ¤„t+Õè"üŽÊlÒŸ¾•*¤ÙLàX6ðH|6ðûvK˜[;ðGÁJ à”yÏ2Ʊ°ÐA·Û ·Bß¾½‡4ËJú•zí´(>ìh¼ÛÊ%…í˜ÿn:@’%@½Õo7åùÝÇC³RºNàùRd$¡" M¡ë Ø©âÓÆ>Í.¯¬èáh„,Ë ”ÄÚÚZ0[vwo#MÓ)éÞn¤$~oó…_@&ºöÀ*UÕ~é¹ÁÑ¿«"L]6àù¯‹!¬e(žìpJ°5|Þ²P1‰@p@ ³3씄)[ ¤±fÑoÐ’NN·d %u?MA ¬¯¯ƒsæÊ±ƒÁÛÛ;Ri£§Ê×L  AåoýòúóS²ÁÌ@pI‘ º¬òΨRNq3È/’Wš`Ôˆr—„Ëï»ÝÝ:6õ}%²,Å` =Ãúú:¢ˆëÞçØßßÇÎöÃ!¤«û£2έ¼ø–£i³°Á¼²峂e¸Í¦§[‚íÖÊÛÕÂ Š¼½Õõvswa =ÇR ¤iŠ~Î#œ¿pQ9O±¿¿ííÆß­*³á°Ù‚1°Rç:€~6pš$ `€i˜6¯JĸÃB¯§[Φ.¥D:b8LÁ8ÇÆù`P¥ìUTµƒË¤ۭ%e%Ë9ÔýÁ©7#UàºØÃñZ»,Lˆ6 TNÝÐ'k0ôuŸß„á–lã`ƒ‰F¨ÀÙÏÓëÌÇ·’àµû7ñ7?ODÔdá0@h—ÿhS à v¿¿¿ê«ÄÔÄÇ% ö¶@9åi ^aïœ}øÙ]l½¹ %ºÿã;u»Pù¹ ¦Ä4Ò!DÙ­Deµ7³ÁQɤÛ¬§ìn(|üúñ7ßæx<Š)<øÚ«xweÛÿ#uŸ–ü]Ä4‡ÀÛXšK5ŽÓ$Â+ƒŸ:ðǨŸ,Ä“·ttöÚ/üS€3s,K{œÚ€P¥ýéÙ Zùm_ÝÓÈÂ$6˜'Na!Hµ›´å%¸× 6Âr˜®\Mh\݇eƒyÉ‚No ¥Þ l~¨sþ”Ì=¾†PÂx‰PÁï[ÝÃx’dáT1€Þ7o¶`C!Ës]¼I÷œ¢`ŒàN™´´«fnN)dÉ|ßFóó…ƒÔ púÎPnì:1êE¥» îÌE¥”Þ#ÈØøúÑŒÑh„×_}Í=¾°° W]QŽŠ !P˜B ‹c y! „@Lj8ŸÉ(NB9‚úù5Y˜Ž ŽRN ¤”PLƒ Žb<þøãØÛÛÃk¯¼êýØcF§ÓÁ÷ÿ湟[\ZDEȳR=2-FFB|VÈF#(%‘$‰†ª3ÍVKÞôC²ÁQÊ; Áÿå_þB«µ£ ñ+„=ô>ðè™?{ßûÂG?úQÜsîw_¯×ý÷žC¯·ü¼ÙhQˆàþÁp€ýþ¢(¼zó'T(ö ¤­©°U*†Ûel›‹Oð†Sƒÿ¿rûTàçþÓ`Ч<Ï™k¸˜ABŠrHT*¯M«\Í`mm /^Ä‚{Þ… ðÑ} .Ü4qVV–qß}÷¡ÓíA-ŠBï$Ò½Æ0âöíÛ壠H¥¼ïJþ, >tR$R -·1áñpÒðøãS¿¿Ï~üãó·ßþ ³%L© !PTV¤ZÛÃ4XÜ4°RX^ZÂ…óç±´´äM+<ôðCøØÇ?†s[(¥pöìYlll NâàuGynXA¹×¶³fÁJ;V6SÑÀT€¨ êv»l8²k×®ó7Þx=º~ý:«®Ê0ØBHä–¾e á3ƒ…ÏJ*œYYÁÆú::nÀ —>x ÿøÇ°¼´äž¿²²‚÷½ï"z‹‹PÞëÙeÕ¶°Á“…jõ¹XR²ÝÝ]vãÆ {Ô}S¥D‘N«ã7›>ƒûÌb$(ˆ üŒÁÝïzÀê™UÜ{hâØ=ÿÂ… xø‘‡ñê+¯âÚ;ïǯÎZ®W¶0«I<‰•@»-žEÁnܸÁlð5”;âTˆB{/€…( LÞoÿp)м‚m·•WÞ— ÿ(V'-ÞýÝnkkkˆ=PT‹M‡KÆ1×NZ!È“zÚ’üß\ï½c–Ú+ =`ÿP!Š"Vµù¨€ÚØ !!40jÌ E…1ê2R­Ô…˜¥N?Ì'„üóYåvðéNãò³7$ B¢°Àü´ÁS>‘CV@ˆùhÔ £B@ʲ-¥1¡•ç: ?lûvÌK¢ü¦Ï®î86¥Oýr `éÞH@y^„ðWª9`ÑÜgÓ:wÔŠ÷\Ë "×E"ÛŽB"od€pÕZÃ5µ ³,D'(ø¬xTKoÖÝ: ¨yJ€§ëRªÀ4Ñw[((ˆBÔ^C‘ç,T+…îµ×;DûöˆJÊÑ ZùM£*º' õª¬Û¿Ï#$´,xÁRKE)úÉ![Ô=€R²"f P¨t€ î ÔeáÎLÑ€¨>·4v_\Õðyt_j= hf ‚HØû+™D²*{C«×p-âYVÿÊÂ`špŒóN¬ ô œãoÎ êÐY@½P´0@Qö Œ\ÍY@KàÄG( Ç ÃhYý`ü`EXr†Oxu€²@©± PM÷ È+MöUýŸŽHN²@Ì›ßP÷'¢FY° d€æŠŸ½¿¬êMgÒ/Ù4°!cpãÖ^º=Ž ªÙ¼Mâ4@ˆN€þObÏŒ7¥Y·ªKM^j¨+~žÖ7¥’ªn$UŒ›ðŸ{Ôl0YŽ4AãiÌsÜóªz/ª^”«‚àMcUèì+ÀÒÁ.·§;"ÃZ¼:KÛ*­~mMXNJ!h\ú‡&Jºãß›š9>Pœ T &°V -æP&Ð ÕV žœ*#—,TÙ :Æ Ó~ãØÁÃ&•9ıÙÅ׺…~®e†©M K­g½:½R“góp2Lâq@IÿhZýwà ¦8cŸÒìDƒ~ ŠFè ֛A#9fËúÄ]»-—s™‰ „ãb:€Ô¿…[•vŸ[SÀ‡üÕ+dmH„¨ìøÏµµ„Ò”U‡`©Z@¸-jG·…è5~ó×ÊåDPµõ[õÊ3kEs!HÊÐ0¶ŠXsX¾v™6lWó.ûJml€æS=ªlp”²p§ë“jÿi ?ÿ'…h7ýž””™EÑ2)T4‚Œaôj znõS3Læ«H¦(1u/`Vó‡I^ÁÆiX1… cêø“kþýªDº?QÖœTÕO3É‚í€#aƒc˜˜ÕüÑXýÈj°4#a²¡ñSïÈ©§y¬ÖפÁÞï p–EY뮞\•1²ÐÀM)âĆÞÂQ¦šúç 5+€sÎxpn®ì•!2W÷ÀÌ5†ýÄÖ/ â¨DT÷ ¦IÉd'AÙ‹ÓñÍÖüM‚Z3ˆG¼àaP9GEµ@ë‹J—Ò@ ò¾ŠøÀ~y¢Úñ-MÌ‚ÊQ“+u3²Á²àü ŸšÔ¤•;&œÄÍ @!â nç¼"З}áæ0Hû³D- û\ª™MF,ØøÙ–V©†l`švîQÈ‚š¢1Í‘òRí›Ö TÀÒ= ¶p…`€¢( 618±@¿³À€w>@é-\ÀŒÎ–lQfãv™,´ÝöلÂh?0Khl/¢¨lÎ$€1ðŠ ã 4(Êt1†(âA?A™×ÕPÁkpsšhhÕ«Ž tÑŒZç" œv¿ß,,P÷<ª¯vÇÒ]Æ…ˆWÀJ /ô¤% 2:‚(Š"(*W;1BEæÚ@áöðéMà4lpx H[%­‘ €iÌß´Ã SÕìH¸3Uà<â•ÔÐdÕeÁÊEÕ0–,ƒZB›8üêoº}xYP¶þá=~XLcþ&fRÐ.œƒ±*¢š0Y€Õjsé7î$ ¢Z8@#è(eAÀæÍ»rõê ß©ò°… û!u:;àJo†‚ô % ˆ¸gÊ¿‰Æ!IDATòºe3¨.õUÝȪ”€zè>5Ö06µ;,˜À_SPÏ1ÆŸÿæ7ÿc1.€óšðW¾ÿ—°  ©Ò?'Þ-‘5Ýs—¯·˜@¯TO+)cPKà•™‚öZBý -[Å³Ö ¤’R¦JÉßcŒ}ýùo>¿3Mðæ=l™ÀWÀ¦4…Í’Pbaã§: ”žð‰¸)™Œ¹à±zÊU AÊ7’ €¦Ë¾ÍGëlЩd!¥x‘3þ;Ï¿ðµY‚6ï™À&6³Èg¨-øüãÚƒv°ùµ ŒÂQqkàô›š >cM Ý—`d¡¡Lsî¶É‚9´úOˆØ•«W¯¾q€ÕÎ ïŠyÎúŸÑFh5†%èÖhýÍšA‹·ÒÉÓ àçûM«º–ÕX=&†ævp°qe¾ ÿ«Tâ»DtåêÕ«y˜@õù>HÂ|•â–ßaÌI¡ðJÁqÍðE¬š('hí4H@xhøÌ¤pÔÐ8r¹€:šÔN*± àÊÕ«Wÿx:®ƒ"}9ð ¼ßcRÇ0˜H¢È3|¦Gˆ“$[² L ka^‹×3— ceŒXÍZZ&ø…˜ùTø@ê€ßè÷¯^}¡˜WpŽó„*€@â}ޝؽ|Æ2³Úí¤Í׫)\‡óÔÚô© yØZB« 4ÀË‚3‚(¼¶ïÁ*|*ð{¾~õêÕyåNœ¨<ì÷I›'¨Oópx³©:Èb?‡·Â8«zgf¼©Dµ)!ÿ˜8}“BR/Báw®¾xõÚQãNžn™ ÷‚Ÿ0t+fÑÌYØk¸qc ·nÝ _ÃÎ 7»‡p&0$ÀLþpŽ8‰&‚xC;˜«†Á,n£zé–12 aÿ-£ó¯uîôqñUY(Ìgn@Ð1f1 -ìîìà_ÿwXèõ½¿ví²,«hU·{Ù’/«šôP»ý²¼Ë 0l1 ¤ÓÀ(ŽkUC}ÍȆ3‚&° @Œ¾àò‹/ÎÙŸ&ŒB 3’Qzfõ önï!±ùÃ"èøßø÷X][ ò“·ÞÂææ&nïíÛºü¬"(7¤v¼Á°`,\Öû]­#Yá;ŒOÙðµ_|ñŽû?ivþ€s.c9ç[[[[9þüÏÄqüÁû.l\:»vöÑÑhôÁá`ðþ4M‘Sdiêíü¾÷Ýïâ{ßý.:Nè¿û‡µ³gq{÷vPK°€ðÓP"f€ZˆhšÆ!ŒSJÄþRòß¾ôÒK;wò>©ìïïW›KâÑG¡(Šèܹs €x ¯_÷]"|çÝë×ñàûI§#––————/)¨'Iò@—Ò4}Ì#KSdYæ7ðßþ6þâÏ¿]–“ ¿öê«È‹ƒÁ ¸tlžÍ'…¢y1Vðˆýò«/½üⵓðÞï±Çɺrƾÿƒ¨¶ç~æÓŸ^J’ä’Røp§“<Àcøþ,K‘¥²4+·Vû_íŠ&‡{ ?û‘ŸÃ÷¿÷=üŸ7^7ðþ‡vS¸XÄEü[RÊ+/¿üò+'é½{O`ÿäÓŸY“ø€'’Nç.¥éðÉáp¸1J3¤iŠ|”·Âà‘‡Ý\S„ú¾’êòËÿéå¿<‰÷]LŒ$I.艤“\RR^JÓôÉl˜ndY†,Ëç¹ÂC<"†8‰7‰ðÜK/½ôŸOòßw‡F'¹DDOÄqrI)u)MÓ'—W–»žËGùïÿáýazÒÿŽÿÕQ¡vü®IEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/network_icon.png0000644000175000017500000003702211750754334025507 0ustar drazzibdrazzib‰PNG  IHDR€€Ã>aË=ÙIDATxÚí]œTÕÕ?ïMŸÙÝÙÎ.AAD{‰å‹5‚ ±%&öÏh¬X£FcIŒšhLb±wH)ÒûÂî²½ÏNŸyóÞûι÷¾™7³³ uÍ·\~÷¦î›{þ÷´{ïùK°¯õé&õö ìk½Ûö ·ðè“ÿ>§ ?ïjUUWÈyE8ÝÞѨ{è“â½}ãûÚwÓzÀ­øã½M-Y,p:àr¹â.—3àr:ëgÃa¯±Ûl•1E«Æ·×hš^¯ëzs8ÝûõZoÿ¸}mÏ­G\w˯ÔÔÕÿF’%@Á‚ϲ,ƒ$ÉøIP+€Õb»ÝN‡AâÔ]NWÐív5ãã‡ÓQk³Z«ƒ‘ÄI’jñ;êðh †£íÝù{µ·ü¾¶\õû›ÖÔÖŸÀ±<î˜ñà°ËÐØÔ mm­ vBB‰€UJ€Ý `·É`³àð‹9@H{Øl6p@v@€D.§µH>W‹à©±Ym»Z}Ájü\-"­NÓ´–»o¼:ÚÛÓZ·¸äªßKVI«ªolŠÉðÜÓOÁèå(€„¦A(¬@«/õMPÛØ µ ÍPߨ­Ž€¿âÑ Hºv‹N›„ °0 "Éög (¤M Vj[R‹hhf|x݈f§ÎawÔZ­–] m¨Eêðj_­Õ íg¾MïíüooÝà×W]W¢*ñÝ-mmΈ– 3Þxˆ!8@‹‚MRÁapX%°¢ö°ÈÜ´0ó‚™™bá±£A`è òCÚPƒÔ8ìöz43»‚Qe—?©‘¸iªjhkö¡Iû²‡Ö-.»ö¦C~ßÀ/Iî!ðákƒ »T5€ç„éœ0Îh3B%¡âµŠ Ñ@Åçãq"ÑtÃÐî BkG'ž}à÷wB$ä‡D,ÄÀA¦ÅiÕQ{Èhb$Ò(`:ËÂ'!€0-b'€ØutPcŽf®A˜‰© Db•Áp¬½™Ò"~àÁ;nèóŽj·¸æ†Û~ÞÜÒ8=‰@Ñà#`êßî€XBÂZÀ Ò ü¬Ð¡ò÷0@`( ]«'p$ø} |Š>Ebñ8„"Q @üÁ ø‡B̤èèsÈzì². $ä{iá&…i21¡E@¬ÜYuHœÎjÆX$´këöw?ÿÔã«{[½ÕºÀ·ß=©¦¦ö …2æ¨ pÿÍCTÐ %|Cèˆ -ÁAüqÂEBœ5 $Š´ïAM(¨=âxD@"á0„ñˆÇàâs²;ÄÁiQÁš­¸Ð÷p°HEšŠÐ"j,---UOΓÿù·>étv €Iwß7ewMí•qE3Ͻ~uî‰(¨”úçêL e’£^K >¡š4BB¼–Ï )f3¢¦^3Ì 7)Ò #Žg%ƒ( 5‹¢Æˆâk(S56H†¦Ð/׃¥F<4V{GÄrØk“ŸYÓÛÂèÖ-î¾ÿÁ/0<cx¸æÚ›áèCG€Š¡]6$L£žS ¡k)A#ž?rѹ&1À‡bÖ$â} áxÆ…éQ À%UC3‚I ¶àGœ™z^Î)~j mþ`c¦Á¢kЉ&5Âño¼øÜÒÞFo´¬˜tïÃ’ÛaÙÑØÔ<¼-¨Â}wÝ ËŠPZºÀ… ©Ñ¯$5éu Ãq Zü 4v& ¾#m!|•=ÃÏàGÀðÊx:ì7wöÈÎÓa·r§®éyút_ ;¨)péì9 v?¯òë€e÷2æ/PøiGÓ€~†Ž77êí—'oïmaôFË €ÿú¤EQ‹a[Nc§=p;:P³º‡¤º6«ED Öu(°aw6ÔFØu(ÎEÌ„Çl27Í,^“Äí0mº;J,Éü=º$n[J„Àà°qpP®^c` {Ð)I%ÁàX7¼ Zã&–ƒ ä” ÃÊ€?Òt­ì½×¦{[½Ñ²àñ>?JMĶ!¨Øá±{®Cõ+ñÑ¥e^hƒ¸ÐÔÚQk,Ù€ExÔ£Ð鯂ÑQhô6v,´#Á92¸ì2  4!D®þ¹yP’¦!I€…¾[‹@a!íO¸ñû‡¹ ±à ùêpÈ' ÄS ؉þÀþï¼2¥Oæ ²à™©¯Ÿ„æSÕÊ{o¸"qêø `Rõ$²ºö8|°²–ï2{M pÕ®C®Ë ý ì0¨È%èy|´&¬¦ü„„nŠ0˜Jö· ç0š0€RR«æ(Ä¿;¢Ä áï=`ÈËÍeyÀÂÞ|å¤ÞDoµ¬xýÝé×uúýÿÖÐÛîP‹àê OG-1OjÞpɾû£*¼¶¨æoò³Î—Eç.HЇ vÁÈþN(p[™€ ‡/åé ¢CJøBà)G/¥ TãZ8’ôwTû~Æ iü>ŠÝÞỲvàg|8v¶Å4ò!©î¿ØÐ /ÍoEGNeΖ.¾tÌ`7œx`.ôÏ·s'2#0%‹RתIͧƒ@ßpô e ØóÀ5 ËT?“·AÎg¡ÇíAhŸvË&Rʺ¸¨CÆ%™þüÙ¬é÷ô¶ z«eÀœ/æÔÑÙ9¾Ã…²A#aìAñC­IáÑèÆ4xòãøª"Äì-sÐð8jDœq¨¼. D”®á`RØæ°QË>êSÏó¯Š×2a\DIÁ‹k:“)è—k…’x-ø>~$‹ ß› èÿQò²¹Ï|¥·Ñ[-+¾X¸dƒ?SÝà‡ÃÇee%ر&DêÔê–üñ½ZtöÌ›'U<¬Ô —_eù6ô4.X]O&{ŒQ¯˜büdbHKåJr´ë"ùdø†woðh#) @#Ÿ4„¦óPq@ž Ú×A`þŒ:, ¨N» |”:uÁg³çö¶ z«uÀ§ó—º6Km8)XWÑ gò°;=ر2‹©×ïŽÀýïÔ²Îg!ž&S'΃˜bÎý›Ò¾I›œ.ð¤PMªß¬òõ,ªß@–Ñoùl í[5¢k?b> ›ÒF·`w8F.žûiŸÌPë€/—®n³È;E‘¯o€ &œ„#Õ&ºÓ+*‚ðд:ö1êÜ‚ Üø³2èçµAŒMô@·#^ÉBjÔ§F¶¢¥{ýŠº€” H,ÙÍt¦©æaæl|”ªULý;hÝB ôx܃—|ùEGo ¢·Z,Z±æ§8jæ’Eÿ|e \0þDôª­°©6 w½¹[Äñ:ì_î‚ÏìÇM€y´'¸'nžô1F3r ÙÈ È!ˆ¦‚C4É*_áHŠDKI#q·†ÀÉ‘®§T¿ž>}Û.Ã~Å.È[=´Öj>-ÑM]Ín…û‹‹‹÷›÷ÉÇ}vyZ¬^¿ùJ]S§P÷}±ºÎ>õh¨i¸ñåjæÍ“ÆõÀõgôKÅìFd j©™?Mg °k}q¨nCS@…N<} È2ˆ”®¿Y@ ¡§2ƒ| ðÕD²‘Q‰# -ÀÊãóù ìWä€Â•Ï‚ñ†÷‹Fa×΋Ŗ¯]¹üØÞBo¶.غ}Çc‘hôö8JrÅöN8îˆ1𻩵ÐÐXÇ<ăj¿ŸØ1T½IõÓè£Q½­! ëë#PïS˜esz׸ÎöœéyÈxO–T±Î.9$9]KÐãB— à ¬P¶f2èJŒi€` ***@‰Çß]¹tÑ…½-„Þl]°mÛ¶iÑxüüV_V˜³Y‡»ø‹¡%N¸ç¼þ©©[ñKð×HÀ¢AØXaq?zzª¶[ÁŠk¦ÞƒÀ»ý,týùôSFä¨0xë,Z ´·µ@Ue% Ÿóè¢yŸßÝÛBèÍÖÛ·oÿUã¸mÕm°®^‡É‹càÌ+Ó ¾x ËÕsŠ0 a >ÙÐ ëj"|DšR±†€¤$¤Ô_îFÐÉ÷šžë*ü,`Êx?°<×#^û Ÿ•D46ÔAmmíu¸úý·^ŸÒÛBèÍ–€/—¬²—åÔâÈ(Y´®›¾ Ôƒ@rzá¾óÀÀBžÕK&„°Cl Àç›ì9™­Æ’„à9¸C' `;b"'ÃHRÆóÐõ=°W¯óʈÊ[ ìßñ.i€šêJhnn†‚ÂÂ3Ÿ{úÉO{[½ÙÒ°låšù9ÎJt­ÏÏX o~å{Ù!pþqáìÃóÙš@#fo &àµ%m°»=Î&}ÌB4;p†ð“£\6þò7°ÿ‚íIí›?KëçÛà([- oËÙ4¨ÚUpñÅm)ï_îm!d¶H$RWU½ûïÏ¿àûþ[iX´üëãŠòœKdI‡;ž™_5x`ЈƒááK†'cyrò6ÕFàU¾¢AaeªocTK&Í`6)€¤?߭𳂅Î"ïkzö# É·ÃOíU0@m`§C•;  ÂON<Íþ˜Z(ÇCËà8ëÔŸþéûþ{i˜¿då%…¹Ž7h‡Ï¯š µú ¸ïò“`¿~®¤ðl À«}&¯^JÊ a$ãvóèOù.LÙtm¼±;Gšœ”äuúc]F8à\Oé~¦þã±T v´ÃíùÁ»7ÀI Uw(­S|`Âé§þ°Ø°aÃÑXì>zò¼ûçÀþwýêH6©C!àœõ~˜½®39ÏoŰói±{ï>CøÙœ<©;ÁîÉ€®@Àÿòœ2 +°Ã%y;Á1Ðu GXª1him…Ýõ?´Œ{l”Û8`ÿpøacéúsÎ8í‡Àê¯×¼‡.¢… =º¹õb\^Ì„?ws¦ãÈ7 ?éØIÅgŒÎ”Ãé*;ÓØc Cà=½_¼\è²ÀðB\YXIËYühûkkk ®¾¡vGåîÓJà³;Œy€®éœ7þÌ‹—.[†8¦ª1ÿ˜S OºbºVW…á•Å­éj_J%a’gÙÍžìzw¶ß¬æÅ‡öB;>Ë šî¯Ømòe¸²_ËÐ$PKc456@ zìwÜ~ç/çìíœ /ÕÍÀHì_ž3á‡À»3çX r•ÑHtà¢MM²•Á)'M€Çf7&çÖÍË­z©{ºunG¾ÉìÐz?›ÄZB> 0HPê±ÀH¯7'Öê; ½µ"±ØÿÞvë­/ô’¼»´LÄãñ.8÷ì3>êç´YjJÌöî¢ÝpÆi§€Û[ÎiöšæÀI™a}A—k~܃—-äëb  XhKyù|n@LÑ!æ(PŽ8È«ÀÏK:X€>¸eã:ð¡Ð%ùÌý&Ðëxý½™GØem¥®'`Öê˜xÎéðÞZî³}þƻӅŸ ùÒâ}“FOÓi éFøfe±í4²É»§o¬úMM ‰9<ìÊZáHoNÎ÷³Å!tkV­¤¥ààpºF_û¿×léE™§µ^À‹oL›h…ø{ä(­®³ÂˆÑcá‰yA¾-=¤KfìR SþÞH·!ßžòúÂO½N‹;Hø$xTlY¹…¹ú7fé~V Êr,p¢×ãrÂ|¦PUaù²e4 ÎÉÍxí5×ühÖô:Þ~ÿƒ»:;;ÿSThÖËaÞn7ÔŠت¬B¤&KÍ>óÇ{/ؽñ áÓ\;d~pHI°Eø6†–æXáô¼VØÏÅkZE"X´x1 Ÿ³»_yÙ~W]qÅf@¯àÕ·Þ™ÚÑá»ÜV &1>ªp€£`@º°Á¤êŧ•ÀÝ&{²y ùºùqê;HÀ¹™€í²p `ÛÇ$HútÐB"—Îö6B‰Ë¹­½.ZDÓÀKzðÁãp)÷ÐzS^yíKÀÉ >Û]>×°¹sÙ гLÞ˜BÀdXØí¨Þƒ6Èæù‹÷Ðe®ÃÂ÷ZR™Y€/±ëÀ‹ 9ÏÛ _Â^½»–,] šª¾û×Gÿò£ZÐëø× S*Ñ Ýâ˃šƒapY!S§QtŸ£ =¹ÑÂXw§g­+²©úŒÑÞÅ/èª ÈÓ÷ØIÐ|S¨¡l2˜À @`Ò^§ 9VÎË«Ãçy%‘u6ÂÊÕ_Óûþò·ÇûCo ÝÜzýõ‰R5•¡PÈ’ò äžÂ2М…D5‰müˆàFD43kúuxÙ¦x³¥…»Uÿï§—ó©Ñog@¹§OóV ’fÀ"¢‚—ï<g¹k˜ø  ýß´i äæx®xü¯¾ÔÛBÿÑàž?=rR8ù2‰JVeƒC@mª€Z3+Aû&¿øíð>pTÿüý‰Po ýG€Ÿ;±žFÅâ±ÃE9…|¨Õj‚`°B7Ÿº¶¦#ùÙdÙÐ g>hŠšf>IM‘ÚâKî BÕnÈ#ï?)|`EŸ²Áj„…žò¢ï¨\eZ‹ (ðìóS°cc[¿Z¼àÀÞø ™íüK~#:ýåã ‡ÂG¡F8Á0<Ђ^ žl‘ ­ §À`µ¦´CR‹X¸§Žï‘.t.ó™ùPðˆ’£i!MaEí 1MRøúB«ÈìÉÂÉãÂFX ³O`„†.:ÐN$¶,„|=ÄDâÂko¼I‹B>[¶ðË3z[à?jdkãÏ¿ÀªÄ•ÁŠCCÁÐ1(ÜÃQØ[m¶b¸lÖI­!€`M3†o!'ý ÉîBóá…„ISè®<0:‹04¶û‡o=çážE„‚™‘™·—…S×η”`hmm…yóçSU±Ésfͼ¦W¥¥ýè­M8ÿB;Þèþhc …‚?Á~˜Õfe³Úò Mi:l& ðçM>†E˜…Í ‚@Ë)=¯¤Ü°zòXÉXå’Î7¤ÛÈx5>ð Â1´¯g2@Oӎضu+Ä•ø¯½üÒã?”`÷¶ýW [›pþ9Øá£¢Ñèa‘hôhð8Ô#Qàn÷ŒÃ"JnNLÎeÒ´ˆ”<<…3€ÀߥàÉõ‚Ûå@» `)KnêÛü ¬š‰Â·0´µ6CÍîÝ`³;Îû×?žœñ}wì7mÿo­]xée…xGAmqzäÇDcqÄ€E¶ÙmI­`I†œ‘Gæs§ áê6;:š^òJÀQØr‹J¡¼¨šZZ!¼êcfF­MÐØØÆCžý×?7ü¿û›´ÿ·xøÑÇ$еýtM=ÕûÑš¦YßÒvt4§ú-2•%=ŒU'a“¦ ƒl#-a3G–$ ’&…³‘Χˆ5‹b lJ\š‹Õ nkn„––Ö ª©ý_~qJàûþÝß´ý¿ÀSOÿëp8t1 i¼Ûåít:1€°ñâQª +Ö¬_0L{µ˜P©ˆ3©y _£Ú=Šh4Æ™JD¡gú¼lŠ,2} <+Cc0ü§!¡& q~äväBš€ÖÖ¶µ/O2.Ûý¾þδé>g#š¢èè®kióUÝwÛíß·ŒÖ à\ø]´/æÎ“[ÚZÏj¨k¸#'7çxo^žLJ°‚Ï ˆšà¥ãIÐ5 ÿ«4=Ë AÓ¶mtÒØþ=rö(tÑô)˜– jâ4¢­LKŽfJ3Hè \`ƒ¥ò§ø8¢ó°.ò@<€5_¯y.®Æ¯[ºpQZMÀ_\òۜҲ²ZŸ¯ÓKÜHN§‹H+"ÜV—“¸‘µ»£ ?T…·[ƒ®g­¦jõš®wÞyã5±ï?ø¢Ðÿ´}0cæ!8jÿùIQa!/ÆÌÈ$DgpŒŠ9GñZa  Á6µwBŒ ?«ü½*+à ² áñ]SøG€‡ÐÑÖÆ@&Ó 6®%rŽ³Ã‘— B¬zµrªsÐATaÚûïM¬«­]èä´5±‚ÂâDåÎÚ¹\²_nžwG§? ³-æ¤u¨Â¸àG¢#I}ÃÊÍ;ˆú&áâiFíVg·Ûkð'TÄj%vG=~E½¦©-wÝxÍ^e3€Úï‹Î;ç¿ïOŸy-vÐߊ‹ ™§o)b£3‰ €„iØz*ó‰„T>Á+~ã9Îøˆ**„¨#Ëvô–ˆÆØç¶oÙÄ4[ü‰Ë…2x­ô…†Æ–­ºUr¸öw ´Év›Ëç¯'‚¾ö­ÓÞ{÷BMcõí<"x„ÝžœÈÑÇp\~Ié§Ñh4Ç8íN„š†fhjnN_c8‘´š ‚‰E%|EŒˆ,8 8@œ‡JZ’ƒúÍXU$–ØŽÆk±[êÔ„RßáøŸ¸ÿv5PäK'þüÇ€i3gÝãñxÎÍÍaB'Ømܳ§‘˜UÆB£? 3ˆP8„@ˆ0Á’y`f@QÄ㸨úM%á5VõC²ÚA¦ÿFŶ-ÐÚÜÄ*ÛÑ xór¡(¿€MGÇcÑö?úøjY«'7o„· àÐ~¥ýFnݼá_GG­øÍFU;*.wäQç— |Œü‘acN‚g¹‰m†!¬Ä :üh°²®©jZ ®¡ ›Z Ã×ÎXN´'Ïbô76ºrò )©A³‰ÍÂ4”ƒQß8¸Î(jH}KkëÑdú ¼0lèªÊú¯Úúæ‡Ã±xÇ}7]ý½ñ4þG@¿éüôÜœ\™¾ÉŽ·á 5I?’FyëÔ×ÌÛrÐÆLÚI@ ÛNì!Lí'âÌ<Ä©î4–Óä?Ð3þH4N#rÚ:üxt‚¯ÓÇJÔÄ"AДú&•M`QálÓœ‡æÅù>Îrb$Í’¾šìo?:©DâYç°Ù«ñ=»j›}•™æÁµjì”ÖI×^Ö­£ú­0ùåWOv»\_’j§\=zTm¬·Ûåf\tÓÔOÙy´ýdo dT…s©¦Cg"~ˆ3ðD™CH€`@`Ñ„íû3·;¶7-Y¼ø¬½ùãþ‹7ÛÚ;ˆ ¢½éÆ›aÜA# ´¼?‚ÙÍËÏ%«¢‹Pæ hF<Æ™ 1~NŒ¡ñÇäÏ$ÄÁ¢ À#øÛƒ¡øq0øA!Pc«Q° ãFó”& H™^ÂÇȦš‚ƒ±çúª;çtƒ÷?û÷¿&¾üë¹®>pÔÈì8ÒMØè,¦—$#÷Ï=gI,ò á“iôèìô3 @£œ¯)à>³ÉPQ5:E¨58 ¡ÈvÁÜUï®ÖΟ ¾ÞcÒÇíöØOýÙøÛ}¾‚P̺ç6(ïWÌàråˆJæÁd¢µQÓ©nÌuƒ@+ù>A{c äÄÄɳbÉЗœæh4 J,zB}—UMça gd±7ÂzŒ¿¡³½¢ñøï^ŸüÌsß }âÉKÜn÷l'yü`B!:fÄJš€Î¯30°ÎT™ê=g?”øcã ¨ ‹pUø 1zˆ8оƒF@¼‘á`ûÖ­ÑåË—Š@êÑ>8¨ìÈã~2+àHa=``xEÅlSŒ™!ÅLecTLOgF31¥¨USMRSevÒë&(Ô$@¸ÆHæPèHÄ8”x”™ÄX”ó#)xh bTsX$ÈñÀH{8¤Drë\Àç# 3ó½×^úùw€;þpï~( -99¹vcFÎø:]$¾u‹Yp <F´@v „SeŒôhŒƒ‚¢MT%—Åro¶/A{$Ó@¡e£ E$˜kÏ/[ºd]ÅŽ—âÃK€xИ±£;…þ¸ÀSÝ ®œ|±‰!%C`ªª§—¾MVAÕ’œI “Ð5= …-‘ÓÒ5‡©foBZmMhž+Ip0^$ÁDÄYšÕŽ‚r8¨úU°ëQ¾û8„f& ~þþë/þ€Ú¹çO|åÊ+¯øËåâBÔõ”ƒ&œ4~“*K‰#.’AÔá#©­¤£‡gR…d&ȱ¢±Í=±S™ý=ælñÔ1ÒÕÕ•°|é²ñK÷ðõ£Ž9vü𑣤/Í0¾óJìpk’İûiĘ¢4^Š)%p@­h6;k¢Œ.¯ãèvÚ`@.z¾KžBRcŽò$dFÐsÚ/§q#üG¸õö;Jjvï^~ùå—“6à:Y±HMœ ’¹ÃÆßG’ †9„ `o“à¤y¨íˆ Í.rUPšg‡…6è_h¯ËÊb|º ¦ºÕn켉+‘q$Š3‚/œ¥M9 €&íÁ¶Ä£† Òø…mk ¸ì5æÄÒ ýËúÑŽhìÓÐOg¼ýú—ß9ŒvÊ©§ž…2úó 'pè¨Q£YF+aJÜhiæ!]è&sa¼3òŠYÅZbÔ³ŽFÛ‡Û•ÚÝ53 ‹ ïþü“9;{0` ÜáëÑA”EŽ@ÇïÑÊËûkõõu ;·Üy¯eܸ±5¾Îòê¦0üöâ‰PïäXÂÓ7Ùwê­!xea 4 m§Ql•«Ž(sÂ!C\¬ &Ùp2%q³³˜Áªhٹ̜ IJœ$7‚ÄÉ4?s*ÅûC ੘¡ sØ$EQýú•PöU‹E££?zÿímߨÝxó-–榦SwíÚuÝÈ‘#O;pô®²²rÆ;h$Œ’¦F¾#Ū¦‚G´6 Ùð9Ê! ¡¶fwƒ¯£ã=ô³Íœ¾õÛÜëÓϽX^ZZR…£Ã¾¹:¿¿|" ;€Q Wt~{P~Ò _W†Øˆ'µL )B•{¨\8tˆ›ÍDQfbŒ”°{âFÊ”F‹#x4ƒAJe˜øÈiRèiÅTˆV®b£Ÿ|*¯7‚`£…ŸÌœæû^`n^tqYssó©~¿BIIÉÑeååñlõz½àt¹Y~€¼~C•«Fô@3ƒ"?@©ÓÎàhwú|ÛpD/Dõ= ¿cÉë/OýŸ_{wú‘·ký­u»‚pÝoΆ˜jI $ÁGýâ­T4«‘‘bݦÎ/ʳÁ„ÃòáàAî$õmR #ù£A‰F¦°Ó‰2̬(f†4ƒMŒ¨IÓC[⇻ þÙc ´V±ßhk*‚¡PÕ¼ÙËìƒdM µß]ÿ{¹¥¹y`KKËmm­Ë2m>±@o¿ÀfµºP=Û™/§ª †A4mèìíB}°vèÐað÷î˜5ýƒ¶ïòžf}¾`"Ƒ¹vW.›øS´±²Èüñ0ó¥/[áƒmlà #»DUÿ³±^8eŒ7Y)]Ép»Rã˜É±R‚Nã@6ÑÞv%É‚.9=ßnÇ‘Ku‹œ™y/¨!Ó¨´†‚¢£h8ºhÉüÏOì5üÛâ_ߪñÏd’¶Õ'`Â)G¡P,IêÛGgÔÃÒmAfëUAŒuÕOKÀ‹¡í{L¨ÂÍx܆6_5i“­O¢,E°¡0 \úŒ‰…‡’ ÇâZ€vDÍG34ã '`Š ÚÚÚ(óÖª¥ /Éìƒ> €kÖ¿Š¦ñÒp$m'5v$v¨ îïÖÀºêÛ€B‚9sl>œwTç?æÁL—•Iíʃԅ 3ɶnRûäXIV4AÓ3ªC±Û CÜQHÌ~ˆSïP~Í[cc#%Ýþ¼nå².üˆ}_¯ß¼ ‰œX×ìWn 2ãk+<ø~-¬Øâ…1±]uJ)¹Ÿ‡…a| Eq›J§« TÚ6OÜH”$~$bI7æ Š[£ÊªX?"&pøý쫪pÕ¤à´8f’,òMˆqˆÔ Ò¢gØj*zO°³æò®Y±dáäÌ>賘¿lµ¥ ϳ£Œ!ëw4ÁÈ€‚‚Bøçg­0g /‰KB¹e|9ì_îd+ƒ Š[³Ý7Šhš ¨n³ôokˆ×MPÅÓë+KiõÍÕURC)£ü,ê1é’á¤ø‘(2!~ÄÁÑ`ß0ù]55ÔAcSäåyÏ\øÅ']ê"öY,_½¾0Çm¯SŹàë8ùøÃá‹MQxêÓV–“§ž¹ýœrŽv?fž÷7ÍPç'ÒúÚloŽáh×D™šdïv)“QG)kYóµÈšê2I²™—¿F{$‡8`hçpU-âAUU]¹“í‹Ì/(ýùÇv©‹Øg°lÕÚCòÜöu4¦f.ÞãÆŽ…k§ÖàPr1í¦3Ëà¡nnóMY†ª'¡/­B£?!d@ªXÖÞ6k$è¡\@×ùƒÔ{©š %F¶-WëîG #X±}ø|¾H~~AÿY¼ëËì‡> €¥+×ãu[gÒ¦ÒéKª`öf€ÝÑbPeL<ºÆæMyúLèóÄIðŸnôCªx‹%KÝäl‚¥f*“NªY´dBE·¨†â~Ú:¡&Á…€@ P]RÚoøk/>ߥ.bŸÀšõ›n±ÉúßéúƧçÃæÎR° ƒƒ‡æÁ-g•%¾„XÚÜ™€wWv@UkŒÙÛ¬äôÀT<³'6;õ­‹f›ÁÏTcj€ã:¾«b =;+*h`ùûo½‘•±Ï`ûöíÏÅb±ÿÅU÷‡`- ¹Åƒà¯¿ÂF¶á铇=k€e˜)o yí‘#íqö‘œÒ™ß¥ï•v ‡…n ãG<%´Ë×iú}>¨®®¢Øï¿úâ ¿ÌÖ}ŸF£±Óë[pÑ#óÀ9è¸þÜ1pÄðf÷bOÀëKÛ™Ú·È‚%iÍœ|TC÷sý]ÐÉèXz—÷Ó‰Jã/Á™êJ1Ç¢³-ñ¢xâÙ§Ÿ¼=[?ôYlÙ²e[<?`åÖ˜ôâz{Ô pÏE£Ñîó¥Wþˆ ÿžÛMJŠ‘4ëÈïÊ”f¬òIi èf$ôäØí•iƒÑ {8Óº…Óö¢Ùj¬«eÔ8²$]óà­ú$,^žçÍqÕ©ª’3máxæóxôæó`@Iù¾° ÿ¤‰$qµÔ•÷°[¯ºWûÝx÷YÊãw­­Øõ;iYåÀ1Q8ÙQ-¸t wÑ$-%?ówÜ–•¡OàóùKF庬›%Ф'ß_ µ±B¸÷ÊÓØb‹PLƒÇg7€”Am]í<µd!íL0ìÁ?Ø‹ÑÝ#ޏ¦À ¯ N- ÀQ®6‰D9ŠÊÛ Óï×ívÇÁ“núý¦l}Ñ'ðÑgóÏpÛà**5é…¯àgŸ£öqUb#Ÿ’;RœEI&T|¨g£°ËöY)ÃgØ+i0È7$QÙÐL´i„RÏ+õÁ(g€¯°N$ bÛ&Ca§Ó5ø†ë®Í:“Ú'0û³y×j‰Ø³”?¿û•õpÿMƒd÷ÀkKÚaeŸH’ae‹Ù“×Ðc˜Ö­ð’DüÚ"JãYÅÚ?ö’åäÙà%m0Ðe£ŸvQmß´ž"€ZoAá«®¸\ËÖ}s>ûüé`0xyùÓVಉgÀâJÞZÞ!Vûd±Å¦‘ŸPVn£o"Ü= Ÿ„íb»~ŒJè‚Idé:Ð?׿.kk‚­Ÿ ø;aÛæ´pùm“&ÛMWôM|øñìYþ@`BC{ÂÎÁ0pèþðÈœ6Ó¶·#2IVfXøíF{ê5ƒË"2,’™ Ë`GáI ¢Ç¹²¼ 2Ÿjin†Û·Ónìwn»mÒEÝõEŸÀ»ÌØÚÑ‘‡ o¯Ó`K_CŸ 鲄|ÙÌAæs=r!›¯»–¸ö8d¶Í‹ÍZRô8²˜:–Åß&@8e(óHpEiSrƱª²*«ªhYÝ£wÜ~ûÝÝõEŸÀó¯¼åvÛå´…ëâP¶ÿáðì’8ØÜy¦:æÂÕß$t3Ó¡Cž?µn8sDd›`F31 nDYhÃD»Ð¸8?¢&"—õë7@m]-- ½úÖ[n™Ò]ô9üsò+CVØÇäØQþR¨Õúƒlsö@†™ò¸õnU:t/ð¬jÒA<„${î6ß(~äF2´€IÐs%n tÄàœÂ6¶LŒîuáâÅÐØØ…ùgÜ|ÓMŸu×}fÊÉP¿ÔTæî²ÂêÎ2p cÜsºˆíô,‚ív`ÏÏöž,ßC^>©~F‚a•“´8YYÒ„#H[ÄJÝ2 µáä¼N¾< ÛG³çP¥½_ié˜Û&ݺ¹»þèsxô©g.My‰öLÝ9<¥ûAaŽ-úˆ .E,Ö4hp’eÒ>Ý8yÆzé]€"Â:¯KNñd²¦hq( $?¡Äcýå6ç 'ë0¾÷Á üáååîºó_wýѧpç}²”–?ÒÒÖ~'m9k€à,èöÜRˆ[ó ªY¡…Á1.b5¯®'×àñÞËðºÂü¸çÛÆyÙŽ`YêÂ’f74°û†pá…n+ŒÖë`˜#ÊÔ?í~çý¨ˆFå°!CFÜ}çZw}Ò§0éîûŠÜn÷sMÍ-©ˆ•[±Yx‰7 ú’34W ;âÎbˆ(t;ÛôÉOâœ0ËÐÆæMcsF÷´yÐiH½Ÿ–t¼ig ß&NÀ&Af „@À!§ñàXÛV‡¡µ½ f|øm˜]8õ…çOê©Oún˜tçXìü)MM‡§*—[ÓËØeë‰ñĿɑ º»„q#)®bˆ"(b F£5<¢ˆÚ9¤$×ógÑÝ„|$d¢¹#0Ú©ÔœÌwš ‡k«È°p/ÆÖÛª³Í´ÕÕ»)ÙEï{íõ—_úMO}Ò§ðë+ÿ÷Ü`0ô\$-3ŠM¥hR,'&æ?«cÄ4…AšÂ]Ì.ÔQ›¢`g“I%ÁV‡‹ZLM™UO-â4@‰Ô:?Ϥ´pîD _l‘RŒª´zedÛ ¡Í,ðõšµðżùàÍËùã´wÞz¨§>éS8ÿâK]ápd0Úɱ¿ÿÙb9…;…]hM\ðz}FåÏtpdg >Ú‡OšBó (ˆ0‹4…@ášQæ48ªØâ œIMK9šù.Yp!ñ¾§Á”f€lmüùº•x|„¢(‡%Êñ²Å:…| ‚ÂÃý„tÒ¬4 ˜´„Q°š“[sP€3'©)b1ÉÉ@A„YÁÊJ¹~–…q=£Â±rÕî°@H™ƒ:—® D†Ñƒ›V1~DÚp;ëãÙ°~ýFsÐèã_:yiO¿¿Ï [;mÂy^4Û£%qX‚XÔ¬Öq(ðý¬6›³ /RRZ{ƒÛÀ0V"· P1¬8ú1G>XœTË‚oòàüH|^„cp#™£#I„Vƒd×U–õø! «¨²`þ|¨ªÞÿlMO¿uö²>á¼RtæB-q$ãXð¡¨!Yñ¿4þ#‹5E–•ô# ÃD˜EU˜:å…_ìéž÷à;l<úX.šˆ±®+Éò¸P8rz]s«—رh›½¦,•Æ£¤Uï@’îDÚRùˆ4`0-bIVOeËÔQå+NhÖ ¸âÀob•Dëjj¨ŠêƒS_œ|ÿžîyþÃöüäsüþγÑY¼Ðápœèr9 ¨<.«yŒC¿¾© Öm©`{õIEÛY…T+ëx*œMõ#¬*ªÂ*„Ûlv¡)L i™¤›"O¡Û5È=̓€êµ ¯rPâšê¡­£ý¼wß|sôxûð-ÛG³çô¯­­½1_Yï-v»=LÈqEÐሺÆ4éÔáÀî¦vVbF¡úÈâ ­@@¡ÊÞ µ# œEÍÌ”¤ìœ‹Ð_储Z³|8¸ÞïžÚZš•¯V|5œXJV~µ\ïéwìÀ7lÍùÔ ‡nEÛ~WQQažÛåÕÍ×Q\I¸¢2·¼¢¹ÁpÚü!Qç×(¥kÄ ãAåq-Œ{Á5U•L+X¬¼˜$YÝ9­ž–£ÂÑ7ï94hÚ®@Íë>(väÁŽíÛW|8ãƒñx»jž×Å{@ÜŨþR0ìÀ7h3?š]Žù^¾×{1£Vƒ‰±¥¡P¨2:©sòö95ŽàGÂÇ\Ø¢‚º™'Æù‘ ¢,F’AÇîD-P9.Y&E[úµpÁ“;+*¨þ/©!¾©û"ÙQ¡À>ìE{õÍ·¯ÈÉÉy=|f‹©öžÓAüHNv0ØìÌ;WYa†8×ÄŽ"@ ÜL‰“dF£h@p$”8ô¼F…±‚Qn×ÌD­­­-ìE{ä¯OlËóæ@ל¶FæÙ8‹…e󜂉« }ãÜ*cHc!‘@ *âF¢k*{/ ÖQÙƒ‡1­Ä‘v„ÁРsz<âMúrÞÜ©ÍÍÍOCvÛß]#UÜ€½h×üîú)ƒ‡½ EØ`´äh$@°uzœI6­4² Nc ]Oª|ž/àN \Ð,‰]?’àRâ¾™’p(Ìiq„&¢VWS K/¼}ŒÕ°wQáR4ж{Ñ~wý –öë÷õI'žàTÍäâH˜Ô·"B½¸‰IÉ éN¦)ì,÷¯‹êèLÈ ‰‡pÆd0p ÚΟHá!»F­°|Ù²M;+vü?cÙÃÏ0–)R.À/ŽÈ>ìe;kÂÙ“Î8ãŒ'Fâ9œºžù$I~¡ªIòKJó0¨±°ÓºPê˜Õö´x¤þ : ì»UfR¨Õ«Vúׯ[÷Ô ´è#›,Í¡ žF=ñ(FÄsûAߤñ³³î=öØcÿtÌ1GËœø"%t6šWR 0ÒɳHÝGÓWçFR‰š&ø‘È1ä 04^û;;aùÒ¥-k¿^uªþ]À©q9ÿHOþ„ÅAÉŸï†9´¯¶SO?ãùùùÿžpö„~E…ElÄêZ:Ò ±ô)sª`E12|zÚçÔä‚ Ò U•»`Ëæ‹çoÛZZj7oÚèÁ—hMñ#’¬èÀG½!ô}"¾«6é¶Û‹çÎ{zÕqÇç).)IŽZ]œÓyL È Ä!aÓü9ƒ$ î@ZÒ±) ¨«­¡•>UøÝöz½SgÏúUýÜoø 5‚ÜÑÑZ)aÖi[ºkûð´‹.¾¤KkëUúýú 1cö>|8äåå1W^cTóff45KQO€kÎ!œÒΔ¦Õ¾555‰Æ†ú%bN0`à´·^õ?¢ÉÉlûð´n¼ÉÚÔÜ|ÄÖÍ›'äy½'—•—ܯ_Y^aQ!äxrÁîàü‡¬‚¤ü„Tö/Îf ÛÛÛ¡ÓçÓ::Ú›þÀ*·Ç3¿ïÓYÓ§íú¾î}¾‡6ñ—äâiÄ–-›‰é‹Å2Òj³cè—‡Ú‚¼=Žú8 ŠÎ¤½F|¼!?¿`C~Aþ¦¼¼üê×_™ªü÷º}¼í@oÿÀ<ù‚¥UÕrIEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/panel.png0000644000175000017500000001215311750754334024103 0ustar drazzibdrazzib‰PNG  IHDRn 2Ç¿ÃîiCCPICC Profilex…TÏkAþ6n©Ð"Zk²x"IY«hEÔ6ýbk Û¶Ed3IÖn6ëî&µ¥ˆäâÑ*ÞEí¡ÿ€zðd/J…ZE(Þ«(b¡-ñÍnL¶¥êÀÎ~óÞ7ï}ovß rÒ4õ€ä ÇR¢il|BjüˆŽ¢ A4%UÛìN$Aƒsù{çØz[VÃ{ûw²w­šÒ¶š„ý@àGšÙ*°ïq Yˆ<ß¡)ÇtßãØòì9NyxÁµ+=ÄY"|@5-ÎM¸SÍ%Ó@ƒH8”õqR>œ×‹”×infÆÈ½O¦»Ìî«b¡œNö½ô~N³Þ>Â! ­?F¸žõŒÕ?âaá¤æÄ†=5ôø`·©ø5Â_M'¢TqÙ. ñ˜®ýVòJ‚p8Êda€sZHO×Lnøº‡}&ׯâwVQáygÞÔÝïEÚ¯0  š HPEa˜°P@†<14²r?#«“{2u$j»tbD±A{6Ü=·Q¤Ý<þ("q”Cµ’üAþ*¯ÉOåyùË\°ØV÷”­›šºòà;Å噹×ÓÈãsM^|•Ôv“WG–¬yz¼šì?ìW—1æ‚5Äs°ûñ-_•Ì—)ŒÅãUóêK„uZ17ߟl;=â.Ï.µÖs­‰‹7V›—gýjHû“æUùO^õñügÍÄcâ)1&vŠç!‰—Å.ñ’ØK« â`mÇ•†)Òm‘ú$Õ``š¼õ/]?[x½F õQ”ÌÒT‰÷Â*d4¹oúÛÇüä÷ŠçŸ(/làÈ™ºmSqï¡e¥ns®¿Ñ}ð¶nk£~8üX<«­R5Ÿ ¼v‡zè)˜Ó––Í9R‡,Ÿ“ºéÊbRÌPÛCRR×%×eK³™UbévØ™Ón¡9B÷ħJe“ú¯ñ°ý°Rùù¬RÙ~NÖ—úoÀ¼ýEÀx‹‰ pHYs  šœ#IDATxíÛÏ•õõpåÇÈHºhL#¦Å¸m£mìÎEûtÝnmL0º¡+iLL´HX²2îÛÆÄ¿ uÓĦ éBc¬¦ÝØ "0#â ôœËý\/03)ƒ}=ɇç¹÷ž¹÷ø:ÍûûÉsïwûÕ«W·9 @àÞX¸wZÕ)¤€àö¿Üc‚û˜v  pÿíl#þ6ƒ?Ïyäy\Ožð¬+_.Ž•WâûÆòŽÛ¿Bí¶¹°ÎÀ¾/Öïñ8p @€ÀÆ#°¯DÉz+3|Ó/÷4°3¤wÄÊÎúXàù\®±ë¶ó æFç9{mz^^1÷ÜZdwÖ¬{ÜòVÉ4´3œ³6ƒ;×Îéóõ¼Îc„÷µGþ%@€!a<‚;{¬Ï§×y¾+£7_[w÷½ipOC;9wÓ»bíkß¾}K/½ôÒ<øƒ½{÷ˆçwÄ'äÞn;0¸Q 2õêZçÏŸ?ûÞ{ï}øòË/ÿíÂ… +Q÷Ùt»àyLÂûÚå—ÿnx«dÚc§½’¡ýÀSO=õÝ'Nüú±ÇûÅŽ;üò­\ @€ÀW¸|ùòÅÓ§O¿yäÈ‘×âüßøÛ‹±–§+Ã;oŸ¬ÞxÛd³àÎäÏ["ØÜÆÿuøÉ3Ïù³ÅÅÅüáGÞ–·¬s#=ûÅÞMÁ/æsY0ùEIþäϯGBÃA€» °k×®=ñ}ââ£òG!¹ãÎLÎ]÷,¯gñäü‘ÏOn•<úè£ßŸÁ5l­À¡C‡Æ'dhgç®;…é‘/üÚó“s·=‚{aiiÉOÿæp\ @`«öïßÿP|FvÞ²w@f»ÞŽ;‹fá ¿éÿwåì\ @€ÀˆŸ]çN{¬Ìé‘ՙͳy=ŽÜ“süvpR8^t&@€­ˆÜw=2ózäòäƒGŠßØÅ(ZÜ7ÒxL€­˜æî|`_·Þ(¸·¶+ïN€·- ¸o›Î @àë¸Up_·=ÿzZô© ³<Þ,¸gEÈ @àî Ì}·˜9<֬͂{Vä‚úî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PÜ%&Eè# ¸ûÌB'( î“"ôÜ}f¡”w‰Iúî>³Ð J‚»Ä¤ˆ}wŸYè„%Á]bRD€>‚»Ï,tB€’€à.1)"@€@ÁÝg:!@€@I@p—˜ @ €àî3  @ $ ¸KLŠ ÐG@p÷™…N PØ,¸¯Æ;är @€À]ؾ}ûÈÞ‘Ããñ¤‹Í‚û.¶é£ @à³ðÜ·ò2º lÜ“-úÜ–½[ïú!@€À7R`š»³vüGÎ_o[/¸'=-¼Çê7RÆš \¹r%s÷ÊtÍgò¤ãõ‚;_ÈÂü£ÕsçÎ}’O8 @àî|üñÇ⓾ˆ5²8óxv¬Ü£p’òï¿ÿþ?gÕ. @`ËÞ}÷ÝLJä®;Ã{mºâtí–Éö¸’fGÜ[¹/ìŒõ`¬½KKKðÁoîܹsiVä‚¶DàÒ¥K+<òÈá8ÿ+>à?±ò®GîÀ?‹¼Î ßðw¾–«ã8}úô›ù„ƒ¶Và­·Þús„öÅø”Ïb}kìºg»ìn•äÖ<ï©\ŽuéÈ‘#¯­¬¬œkl‘@ì“?}þùçÿoŸÁ})VwÞ2ɵqpÇV<_¡t)vܽòÊ+¿[[[ËǸë««—=z2nMo½k%ÖØqç§mÜùjܹ2ås»¾|âĉ·;vtyyÙ¯LÄA€;%;íçž{î÷¯¿þúßã=3c?•Áw=nºUrÓ—“Q´-¾ Ü§ü’rG¬Ý±öÄÚkÿã?þp„ø¯žx≟ïÞ½ûxÎA€·!_Dþ%Ž^xáÓö¹x›\ÞܹqÎð^›!¹™žëw¾Ù÷¿ïŸ®ÞùË’ ð=‹‹‹>|ø‡‡:xàÀ}Q¼ñB¬|Ï ~L"#¯æŠ[ÎkgΜ9Ÿ?ù;uêÔ?¦_Dæ=í\ù둱ÛÎ{ܓЎó•ÈÕÙ­’ ƒ; çÃ;wÞùÁÅéÊx†y>Îs¾ž;ô\ë}áO; ð­ß!Žßhg0ç}ìÜ]•=B{òC‘ÈìÙn;^›ì¨ó¼Ñ‘’Gþa>Î7ÊÛkú|hÛmŒƒ7ŒsžsM~r==°Îç2È3w× íx~Û¦;îIAìí³.Öçqû$w๻»í¬ÉÇóÁ=/9 ð­¡ÿñy=~r=z„xnŠs“œ¯çÝ‘ëvÚñÜä¸epÏ ¯ÝóṜÞ5”6ÝYoôÿWpoô¦ž'@€­øßQhMÅn™IEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/vnc_off.png0000644000175000017500000000152111750754334024421 0ustar drazzibdrazzib‰PNG  IHDRÄ´l;sRGB®ÎébKGDÿÿÿ ½§“ pHYs „ „ªâcytIMEÛ ŽŒû•ÑIDAT8˵UÍjGþª«{ÿbF‚8 L®9d#‚’Ϻí='È3„¼CŽ!Ç=ÊGÙÒA",0ø’K”ƒ…vM”ïlWuå°³£íH7×eº{ª¾®úê§Ï$tûàììì5mW t£R_€™!¥3Ã9·<¿ð-—mÇãÊ(¥T:çVÀEª f†÷D„m~~î`ggGêžcÈ|3[¹Ù1ƒÙ#%…ªTθRßçyþ‰™ýÉÉ ºÝ.RJ03Ÿò;ùKªH%`ƒ_àüB*žà«Á¼a°µÞü¶­·Ö‡ª á ™¡ðÒömÙZ.?¶ï{½¾ìÍ83"`"˜þ™^Ö%åxåìý¬3ƒ_&ÇÁªÚ[fž˜4¹¼üX£ÁRãŸÖxwf¶’ù¥‚iº—–¶Šùú‹xÃñmeçþþ—±µ®­4Ô½nD€ˆEY·¤¢îµ™-<¶´Zßß^‡cD¿¿ˆØßs€j„÷Ì®ê²N§SéKI™g†ª‚˜«¾­Àˆ!8t:~aPVË”ˆc¬fƒˆÀÌÀD‹tå dK D„,Ëî*À{äÂS…‰€ˆç9Bè÷ûnww×`4ÑæææÏιŸÊáôûx<þa8¶–½xùÒØ9ÄÙ ² @Tçtzzú-3ÿà{OSJ\òhDôÊ9÷JUÝÛÛ»h¿8ž{öa9òÌ "Q‰qfYö'­µÕÌl^Åãýýý7Uƒ<;xÖ)Šâ·Éd‚««+\__£(Š_&ãIw:þc¥”fmTÎl‘çÓéôjå9::ZÕGIµë½Ñ»ÃÃÃiÉmðÞ3 ž„¾sέ©êµˆ¼Íóüã_Ãá°¸÷iºOF£ÕmîJÜg•ÿ†¹¦·ê¹BÂIEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/one-network.png0000644000175000017500000001644611750754334025265 0ustar drazzibdrazzib‰PNG  IHDR(%ƒå•sRGB®ÎébKGDÿÿÿ ½§“ pHYs œ œ“–štIMEÛ WÀ¦IDATxÚíyxÕ™îUÕ‹º[›e˶lÀ»ÍhÆECȲ¶aKB’´'À0—$2æ&„0™É@X“€a7fñ˜½ipaƒ±eË«dIÖÒÝêE½TÝ?ê4*Ê-¹[‹xú{ž~$•ªNå;ïy¿åœ†ªT¥*U©JUªR•›HÕ.¨JU>üòÍï]æ1L Ë[ÔŒßüê³ 0U©JUÆ,—_ýcOOw|YÓä)ó CêȤS]†™ßkò{1ó½õÿ@]m ¹hfsú¯œ–‘jæ0ð©LUªò!—“Ï8½¡eúÜû/úê…§¸Ü5ôô%r=ýñL_,‘ŒÅã‰d*Ï ¦û%3·×,ä:kk”=>¯kO­¯¦½6àë2]þ®3?¾¤cîQ Œñ®›«:#ž/8@ë%®åÈÀµ˜ŠÏ/^<ÀS¦Vô­`V ˆWe9¸É6öà—bÁ9òÈ#›[:¤¡`*´îIóÜú;z²x=2µ~u™$²±œI 1™ÀwÑôe„ƒ… }›¦O¦vØt&+(!QÒ&>4³RÓ¦ 溗p°}ËöŠ…v;áà„ûÈ6·ívNM<ývœØ ‰Ç£¼"ï‹øEÂí‘ð¸êjdæLñC¶~í+¯½þý½½ýýÒ0^Ó4óÈrðÈ£¿eáÂùr¥&Ò§€SÌAŠœD{öWP4ݬ†Ôow˜L~à 5¤¾\H”2ÍN>åtžñ~ ¢ØQË™~›`Jã=¡jïÍ‚©™iM_ÜB8øÄe\&ÆÁå0'M ˆ¦?-ÌÈvÁo‹CQ§bÀ7J‚™¦üÐ"®t×n+q¯_˜ÍÓmý7üŒpP¡þÇßzäýoš>< ü–ppË~úòh¬¨PÒÆ€¯u¹ ˜ ´ß¶U8N €[…>Øå%ÂÁŸ—zd{WW]瀯åÅöAâY²b±I–À%,¿÷·©Høk >·ÌÔ€L³O2;óù®BfÍS,qn~ú¬së%I2M£|CÄ¥†T?p©­Ã‹ ‘¾P¸Ø@&§†ÔG_ ¿‚$Tà…2L†b,ur?TCêêh$:ð`¶.ài¬Ü˜b„.'æØq7p!ðÂ×38 €/NCÓ_.&GcVÚBTìL·8NüÝ&@f2p”M§ê±ÂìëJ”}(pC!ø0a4ývà§„ƒÃ1Ú¬Ô‚âûSÀ?Šç@ã§Ò,yM—D›9æá^1?KÊžÎÞÆ©¥…æÚÒ¦L0d C–MdIB‘0‰·LS­B“O¡¶ÆÅÌ€‰+—2vïéì¼óî{öïS‘*Ï“‘…"|ÖîÇ üA4ÝUi"±í&àmÇ*W4•Ê‘ðÛ eŠI°ô#b:»UB¡¼¶Iuš~ù8K ðà¬h`Æ6Æ¥Uøày4ýkhºRâÓ¡ü8&ª˜‚¥¼a›Ì†X•Ï)QOYøðjÅýºÿsÊ—EY†(»¼A8¸»DÙ' ^±} Ùþ—&þShú #°OûÇü8œ±®ÁJó(ØÚfWnî¡Ö ïø3»×lÓóhÇ1É'3Ç/£º7p”¯ùþ˜ÔÈÒè¿W1ënü.&׺™^çbš/OמöÂÆM›Ú™ 48ÓQ1ÁG%ÑHt§ƒêñ jHu•Y¯kU¶+ÃïÔÚ0ýý@¦ø)°Õfª¦KÑô9c—IÀÍÀ? ?‹|b2׋Ÿ5¶'s¢ïÿS4Ò£;¶v¬Û±mÛ—v·¾½´kSôâøÆU×òî«Ûüà[3¶þ­çÐöGŒˆ­2Ï­‘Ž¡yJ/3krÌlpQofÙÓÑQˆÇí¥ä.‡ï¥([¢‘èXãâ/ŠÁòØQLdÎ^E˜[ßîµ=_'Vå/sœ¢†ÔΔ¢€µM wß+¦Ñôe‚Í$D›„Sý’Q‚‹ ø¬ Ò¼­ïй6ÖG8øœ£ TƒX<$›©Ý…•½JÌa¾O³DV8õÝ31Ä;j€W§€ž2ÇËk3a‹Œ¯¸¸e?¿ú‘¬0%·-üØ ¯ÖÔx”wv¶ÊßXzÎM ž ’©Þ »·lm ÓSƒiœd4M•²3MrÉX¾!àß~Û=û¶lym¦K6»¿xÔÉÅg‡ö‰(™†aŒfrÍÞ'"`)ËXe½˜:€Í®€ ݧ†Ôï·QÒ3ÕzR4]=N½¸« :UøMÆÓùª…¼kOQÁOCÓ'Mhþ aŠæfïÀå%ö ýMÿ¹øÿɶöÖ Úþm77 'k»#ð°”p0»OÙð};É 3Éî°ü¸xWܦ#Ö^·˜¬E9¯hÞ]`/cßLç{ÃŽk é?Œû3 eŒ„ÓùÿW–Ábv_'|­Âñº\°¬„m¼¶?¯0ºÇ¦u¯˜Ë~Äãu»ÿ¹ÆãY–ÏçæîÝÛÖ;ÍÞ¾ÉdJŠõt³}óF©¶>`xOÚݽގW®noï‹~Ȭù¿Ÿ:ejòÞè3—^õï»0Ìí(æV·ìj—yWgGû|Y’Hø/ºø›®C=Rš:¹Ápù]ÆEç^d0³J˜ ëÆ:wٵˬ ‹ú–¨›¡ä»+Õúj4×”ë$ÃÄäÀ@8˜EÓoJVÏPØúb4ýõQl ¼Z°‚´ þuزÂÁ~4ý+À“ÂR4=.BÓÿÍÆb tÄM×óáì·û9>Sº¨¨ƒÀs–8Mñ»4ËJÇ/쵄ƒ¿¶ýp.šþßXìƒ6Sí+hú%}÷/&55¹|>.—\¡@CÀ/Åã úã5¸%³g×ßv¯Zóº~Wb Ï#7Ö{êçÎl:gé?Mݳ76gwg]=ýôöLj$I¥’Ù†™ …là o¶]çºhëöÞLgg|°ÃåvuþðšÿhÝŠGî½þº¼S1JùDrã4}RÃ(cEÀ̾›!?œÆGE,¦òˆmreÄj}â("KÅó’ÍyûcÂÁÜ~ꦕ×Vœ`£m×này‡ßfš¾Ðv×`d1I‰ºgmþA„?¤ÅV77°’pÐiÊŸL²™-`m*-gÛÊeXvísÂ#@q$°X‡•ÒQ®äÑô ´õøáàÝ£íò®®ÎCötvº¶´mãÝÍ­æžÎnÒƒY Y¡Æï§®®Îœ>mþ@@V¹61Ð×x'Mš<½yÊTIRÜÔ54™ϞǜEÇ0eþñ¸:‘Ì´%žþæ%M{?¡ìð-íðÏouqùÚÜœëv¥¼ìëëý]®+Ö\ŠÁìÄ ¯Ù#GOŒÃÔYXâZE‘©h$j¨!õObâÌ·ÙÒ?VCêS%’ÿ&ÊW5чsýkG²}c©&¨~¹òIa¿gl+·GøSÊöŒƒqœ \7†vÝ$üAE_ˆ+ïjš~’´¨÷cÂQd5SÐô£ ׊EÅkN?ð»ïû¢£ 9`á`¼ @L¢é·¿±+¯ðdá`_}¢?lÞ°Y„pðб(Ѷ­­·/X°ð>¯÷SYÓ …<²,ƒ$#I2^ŸO2Lˆ$^ß¾}Û­@zúô鯉K–ÔοPJ šô'sÒK›x¥5Io*Ç-#»dòxI›^Òr=i—IÁrÀÀß½Êeö÷¹²ét¾ÔÄi`Æ$bëNíõí•–D7ª!õ^AÿeQÖbAgocU…&>»ÊަÞ®ö»Ðôß ¿G^|f¡éW–;Áç:Vî¢ÃðÓ•°l‡ Ò2Æ–­}7Y”íÁʧÑämùA0ç‹>Ï ³h­xÆ#Ú§?a©¤Äy‡qŽÊŽFx¹«o@ÓÝ#°ÀJŽ©0…?o–ÄëΫÝpýõÛO=唥‹?þ¼€?p–ÛëW(õÙ|žT*•L%Óm±xÿŠÍ›ß¹wKkë@úý-77Æ2Jc¿NÞÞáÏ/÷Ð=cÑ ?ÇÖ×’)˜Ä ôgL⃉œ’3Iä3G>ÙC<Öב7ŒT)€Y-Ì {òÑ5¤NŠF¢}chëbÀË~e”å]‡¢\`£É7©!õ!Æ–~TIBá‚Ìõhú9X99~—¡éwRÞ!YSyºÝiZ®HŽÉ £éʶ0d°²»—1%™¦O>g˜vafx„Y'‹ûO¬b¾Ãú ¸Ü2’8â÷Žxß;îAR$$YfJ­‹Ùþ©ƒ#½ç¿~ý«}L‘ >‰•Ùhg¦ moª!õLq`öHà2ILþµœLÞŸúü‹h$:L£[PI§¿@blGZþo™7›6Å“ËÐû„éhÚü—Ší#M®húÑô/Ù>ç£éãÔªÇyÿÖû¸m; if|3X»õ‡“'„©Xdr¦`çËFŒ¤Y‡™ÿ‘¡·i3Çw€±ä¬­.Ûû¼À hú¢¡j+V<*w÷ö͈ådßo%,pqɘ²\„i$)Lc@¡¹^a^£BS­/å‘¥îáND#Ñ~‘–¿Š¡d¯â€.ÂJ[þ»RÿGÈÚh$šQC꬈Ó1XÞþ“K€”$âþñè¶¾+?ãð”åŠøÜ~¶ ÈBé7Žê[F'¿~Š)>wV˜×k[õ?ܦÿ²dv°¦¸^Œ¥dÓMXIzã!O'é4§ŸXO8ØkØ]húfàÈ㻇pðùÞÓ‡uÀz‘‰“×.æ¢é?"ìp´VòŸ=œn¾gʽ?Ñp<’64ý;Âj_ ça¥œ5Φپöow·ÒÞ¯Ì|«ŠÔ—µÎê-ȈsdŠlÅS–¨ñÊL¸¨ó)ø<2òäR‰½}½½ÃŒ˜¸kÔz:Ö"É>¬Ä¯/‰TCj1äXü¸‡—6à«ãÄ^ŠuÝ­†Ô[_3ö?Öž‘€Ã+Þu5•åÉh•¯M¿ë[Ò´q+Vbâ5 ÏV¦ðqhú&¬Îœ=V˜ >Þ•±LÏp05Ní1Ðô…ï%ïp –Úöñ²0u<ŽÅàÞý¼§€¦ß%Ãň£!Ê98MoÃJôa…¿ç =°û ýÀmcIz+Sž.…ÛÆ+µ…â¬ý„É‹¯¾é’ýó›k9aRš„ÒH?uÄ ·™2e)gšâ<™F¿BS@¡ÉoùÐ ÷ÒÙÕwS[ÿp+³}⾄µù«¯„Bé[­XU§ :°‹EHÂ[~ôDœáDo~±˜FÅzÃÃ}G”©t/VXß]vÃA¸+Œ‹ì}XGœ~+Eý|¬ðoÃg¦`%È÷žÀv:¬”Í<·Ë*öý&‰}·”fpCQ5»Ž4 P½øgàc6gs±ŸáDþÁãVðcu ³ýl4ýgùúí;v²½mÓʾÏ>l¼ý—w§´Þ×sD×™3ONRtóxÿNóðúsF Ï¿iNòËLò+L (̨s‘õðî–-}ëÖ¯Oì`ÄÄ}k«üJö=˜g$3Ä® Ñi‹£‘èD¥xñL£‹|O¬lr “ÂÊ;ù«¸âqŒS¡ƒÛí׋Œövàªýn/¨|2m^³½GæQ‰{[yÿ¦Jðá`¬Ìw=ƒu¶Ë‹â=öÕŠ,!ï`ÜEð{8¯Ò͆cè—½‚qÆ@WüÖ‰ 'êÕO>úPúñå¹å‘þzö;›7-iۺ崶 o|{§þìuúÃ׿³|çìM÷™ÇìzŽÏH co03ÙJs®Ël*ô3зÇÌeóÝ.ÉH–0dÖc…‚— *Yj›Ãø?îÆ 1~/‰–“?Qj/”§L󊰷mˆg @æÏ׈·F´Q€u½` Å2|#¶ÑšˆË€obàU+ž‘ãWܨؼ+@ûÊΓ•lu°×£Ü¾¹Q°Þâ™,÷pïövû(½5`¤‰ûVvìÄä­-aR#MX yßá'¹DŒ¤kŠx§½¿Ü%ê~£Û8Û}=š~ÒDãÜ[‘Wºžú‰èÓ?vÏ_^ºú3Ÿúd÷a‹åk™t÷N›^§/ú»Ÿ½×l{ò.©uÍ]F»ü¶”l{óõÒ[v\#LÞðRW sè󆃕>^<«£]ÐÉû±’¥bîr~M(}÷k%Çþ/Ö—YÙWøbfd¡íü-•0å”}´ gk°’s¶òž§œ [Ëw¡Ù&ˆ]qוa.=ˆ¦?%ñ_À:½°E(n–¡<¨{h !-|öIºòўŠ'öHNä;„®U~^q88ÜŠ¦?"¾³…ó¸QÔ¡+p±x¶Œ=E;„ÞÞÞ7G¸ÿ Ñ_Y›Sû…aêzŸ8æt¡C×d`šþò¸³Jçà¬xÆ…"ý¨®®ö²@À?©¿¯_nšÜ$uvvÑ×3ãÉ”ÔÕÙ)Å{»éî–ZSµÏõ¬é]#üx1‡Â”M‹ªT¥*•:Éî¾ga½¿öêëZ&Oždæ²9iûŽôõõ‘J§ˆ÷÷Óß3“ )™L&Ÿ{nÕE]›áÈâØ÷åªviUªR•¢ìÚÒšjžÞÒ>8˜iééí“ …<©tš\¾€‰D¿–IŠK’…þx¢s0°1ÛX)û°*U©JU˜yÈÁ‰úºº²D“i3 £à5LL“l>O.—#3˜M¤2égº::®Zÿöº7…YÔ}¦j"U¥*UQ¾»lY­Ï[s¨âq“ÏåäòùúBÞHdó¹M™Lvm:±ñÉåËÕžªJUªR•ªT¥*=ùÿÈI Ûš$+IEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/pbar.gif0000644000175000017500000000755711750754334023725 0ustar drazzibdrazzibGIF89a€òÿÿÿ˜ÃÆçð²ßìB²Ò˜Ã!ÿ NETSCAPE2.0!þCreated with ajaxload.info!ù ,€ç² þ¬=Ťñª|«ö7£™³‘«YI©û–ìkõŒË¹Ýó@ÕN#¶Œ6ZvdútE'´y‹V©Jä49”þžW®5ë]†·èoY ^»Ïj¸™,gÏ»>º¿óÿ~Xxbƒ‚…ˆiw‡Šv ‘’‘”•“˜™›—•Ÿ’¡–š˜£§œ›ž¥ ®¢°¤¦²¨¶ª­´¯»±½³«¬¼ÁúľÇÀÆËµ¿·Î¹ÍÉ©ոÖÐØÓÑÅÒÌÂÊÞâÝäÈßæãèåàÚçáëÏÛíéïê¢Ã¿øÉúÈùûúãp ¨!ù ,€ÿ´ þ"Æ¥ Î^¬1èœåYI£¢L[j[¿&ó©ÊuÎ︞¦Å mF”Nùc¾§¹œTÄÆ5imv¥_ª÷&“£e[–À= ¡ï)zÓ-ë¶~Ëïý}ffyiwrunpŒ‰…€’‚†ˆvŠƒ‡œ¡¢ £¡¥¦¨£ª¢¬§¦¯±¤°±®µ³±ž¸¾¶©À«Â­Ä²´¿ºÁËÃÍ¢¼œÊȷƹÔÌØÎÚÅÏÇÉÖÓ´ÑŸáæÞ×àèâÕëçÜß»ÑìÙêðéí÷ôÛöýò¼ûºé{ç¯^¾‚üÞˆ!Û3¹AÜö°!E‰Vd !ù ,€ÿ´ þ¬='jÔ ôÆ‚šX’–™¢WÄL®”óY¯÷õxzþùޯà òbXÌH#6…L›S Ý­Ï«©tEqSpˆ¥jÃ=ôp¬æB–eñ™MŸÛ³x³Çíà«¿iuyrƒwz~~‚ˆ„†…k‡ŽŠpd˜q’‘€ž£¤¥¤«¬ª­«¯°²­´¬¶±°¹»®º»¸¨£§ÄÂÈÀ³ÊµÌ·Î¼¾É½ÁÐÃÇĦ×ÔÒÖÕËáÍãÏåÑÓÝ×ÛÆ¨Þéç¿ñïàßâöäøæú«ìÚÙóÔÈO^Az÷àôç€áA *œXbÂ`î0d´Åá^¹Žù>bð¨ä>‘!ù ,€ÿ´ þ¬=Ét"ç ô¾žÀ…£Wjç7‘ YIÔ;½ÖªÝ½ê6ù9ÖO4õB´™ ²¨ã³…ân"i•z½%™eXÛ%bwfà™œµ¶¹‚ol< §k÷}›‡ïËx^M ƒr~lo}‹jiH…‘t‡zˆ–•˜”šX†ƒŒ¡|Ž¢¦©ª«ª­®¬´µ¶µ¸¹·³¼»¹À¶Âº¾Áƶ±²ʰ®Ä´Ð½¼ÓÕÒÙÈÅÔ¿Û´Íá̱ÚÝÇçÃßÖØëæ×ÞéµãôôíòÑîûùìñðèªëg¯œ8ƒýÞáÈ¡¾„üúËUðÙA‹3JTøo¡ÇŽ¿0^LÅA¤<O^HÉåÀm.žL!ù ,€ÿ´ þ¬=ɤñÁ¹îÞ Xvg8)YIX5½ô®#ùäºÃã¬]h}9Úìf“53Æ"ò¸FQWU•úË ”OÆÒƒN¥[t÷Œek×évœ.‹Ã0ÓÝ›÷á€V|Drot‚uxSy|zcfކ„A’Yp”€ˆ‹e‰išj‘¡l¢nIŸ§Š©ž7¤–­ƒ¯ ³´µ´·¸¶»¼¾º¸ÅÆÄÇÅÉÊÌÇÎÆÐÅÁ½»Âµ×¹ÕÃÛØÊËßàÒÈâÍæÏèÆÔÀÖÝÚíÜñÞóðàåøäüêáúàØHÐ]½YÙúËwoÜÂ~ÏEÁ$(ú†Áœ’Ã5™1¥3út‘GãÊÄš¤Ðx§³•Çæ%7»Þ®Ú_{„®WÓSñ ŸŸüE€^t{…T‡zˆ<‚qo]>vŠg†‰™‹“n}œrŸŽD•š—–jxa›ž¬Œ€±²³²µ¶´¹º¼¸¶À³ÅÆÄÇÅÉÊÌÇÎÆ¿»¹Â·ÓÁ×ÃÙÖ¾ÔÊËßàÐáàÈâÊÒÝØìÚîÜëòÞð±äèæãéÏüÆøó֣׎à;ƒñæÃÇÐ_9ç”xb 惸O._3ïmi¯B’'M*ìÈñ£Ç~/ÿiD¨¡ ¼šo^°Ió‚K~Æ ú,!ù ,€ÿ´ þ¬=ɤñª|«ö7 $©•æ… 'ºüŠ33URLã„+Ö#(t+Þíç“)›;¦Î¥ƒH×»MJk9po~’Çâ¥ìØÕ^WÙ’9]-çøû—ývøAyNz„†Q‡Vpm%q)}r…ˆ”Šƒ•vk\‘‹~D—–“¢‰™˜h€©›ž%®¯°¯²³±¶·¹µ³½°¿´ÄÅÆÅÈÉÇÃ̼¸¶Á®ÓºÐ»ÒѾÛÀÎÉËàßÆáÆØ×ÚÙÜêÞìÂîÔÝïèëÌÍ÷åÊãÅçÿéèµ8`½súúÛ·Páƒ! (1ÙŸtw_fƒqiyk{~‚€…Ž„d†fˆ–E”“‘›žp•z‰|‹&¨©ª©¬­«°±³¯­·ª¹®²°ÀÁ¿ÂÀÄŶ½¸ÊºÌ¼µ¾Î¨»ÓÒ´ÉÅÆÛÃÝÛÙØÑÐËåÍçÏãæëèíêâÞÇÂóÁâ÷äïÕéûú×øìâm«ÇM[¸|Ý%„‡°aÀ|òÀ#8`a?‹ÿ*ÔÈ]Dƒ%Òc—NÉw&Ý•¼p²¥J!ëi˜˜!ù ,€ÿ´ þ¬=ɤñª|«ö7£ø(ª¥j%aä»ä–ómç¼É¦“І3wF,ÙcH¨C( K©ŒÉÕb·^%ø5®M…Ößw-f7Éî.\LM³âá·¹üœëû{_u'Wm†Q~r‡‹v@„jyމŒˆYŠ”Zƒg? ¡¢¡¤¥£¨©«§¥¯¢±¦ª¨³ º»¹¼º®µ°Â²Ä´­¶Æ¸Ê¬ÁÈÃÐÅ¿º¾¿ÏÎÉÒÇÚÑÞÓàÝÙäÛâËÔÕ×¼åßíáïãæñèçÍÕ½øôÍü·ýóºߺ]þ˜ý[¨°!·z Óý:hí7 Åa wñ BÆ5^˜8’€!ù ,€ÿ´ þ¬=ɤñª|«ö7£™Ž ªÙš•„¹±uÒq‰ïpþ¬Àš®Çc 7¢9[Ê^Lp%LF«Í«/ûÄB»Û¯;–NÞtX]·ËlgùŒ^ÛßG·<¿ïgqZxVzƒd|Š€S‚†}„‰…‘ˆbtš›œ›žŸ¢£¥¡Ÿ©œ« ¤¢­š±¦¶·¨¯ª»¬½®§°¿²Ã´ºÁ¼È¾ÊÀµ¸¶ÇÑÓÂÌÄÖÆÕÒÚÔÉÛÞÏÐÜãÞÝËßçæÍê×èÍá¹äéòëôíìÙåö´ðø³ÿÅbèîÞ¾ ðÜiðÆlṆ*Œøpb+‡Í<!ù ,€ç´ þ¬=ɤñª|«ö7£™³‘«YI©û–ìkõŒË¹Ýó@ÕN#¶Œ6ZvdútE'´y‹V©Jä49”þžW®5ë]†·èoY ^»Ïj¸™,gÏ»>º¿óÿ~Xxbƒ‚…ˆiw‡Šv ‘’‘”•“˜™›—•Ÿ’¡–š˜£§œ›ž¥ ®¢°¤¦²¨¶ª­´¯»±½³«¬¼ÁúľÇÀÆËµ¿·Î¹ÍÉ©ոÖÐØÓÑÅÒÌÂÊÞâÝäÈßæãèåàÚçáëÏÛíéïê¢Ã¿øÉúÈùûúãp ¨;opennebula-3.4.1/src/cloud/occi/lib/ui/public/images/vnc_on.png0000644000175000017500000000217511750754334024271 0ustar drazzibdrazzib‰PNG  IHDRÄ´l;sRGB®ÎébKGDÿÿÿ ½§“ pHYs „ „ªâcytIMEÛ 5.åÜ-"ýIDAT8˽•MlEÇÞ]ÇqÔÊ uã`lLœ¶B"’ËUŠB¢âC¨-¨Ç¸äÊ¡–@¥ H=Vmo¨R>.”Fˆ8ÐF•êÒÖˆ§ÕÊc»¶Câ]{wg†ƒ°Û´p‘Fûæí{ÿ÷æÍæÁ4|÷+òùüe]×' Ã@×ut]§WÖ4 )%RJJ¥år™mÛ¶FB „È››˜žžÆ¶mVWW©Õj!…BD"úŒ‹Å"•J…íÛ·“N§ ƒ?~|ÂPJ>ŸÏPJÑjµFwðë… (¥¨×ë,--°%!ž£Y«P©T¨T*DR»À¶QJaÌ}ý•‰³³³ìÛ·F£A»Ýæâ¹oZ¿õfƒß./> wª&Æè(J)´ÌXÆH§ÓÜ6MFâq”Rü|èJŸƒ5ÓÿÝL¶fàÚÔÒ_õ×:ŽCµÝáÇøÅu!Ä#O»pc=”ëΗÎMrþ基ÀŽÓaÅÄòñÁ„¼½øZ_–C¹Íƒ löSÌçã•^@á8AÈiÐ|! …†ZŸóPîï¬={­ï_µZ@æ8.žç!¥D)…‚ååån¶«wYé¹è.)àyšëº¸n×@)…çy„Ãa"E°fÔ¦eèÕmìÀšé‚¾ºðb7ãN§ƒu{žç±²²‚Ûn=z?`¯¼gv7C9ÐuR©„!„@ö0AJ‰¦iÄã”ÍŒg2<6EJÉòÙl–fs€;å2>|Œìˆ±Rk0ÞA«ÕBÓ4 )%BöSÌ0 &v>ÎÞìNLÓ$8À²,²Ù,­V‹p8Äõë× ‡ÃÝwJX–E, Z­F1\ÏC8.†eá­¯$—Ë=ôÀjµÃÃÃÿô¸å ×uqêuR7¥}ã†ßÏ7gÎ0¾{o¾þ†–H$ÔMOž<ùq8~·ÙlR­V¿œžž>ÈÍ »m³¶u ÅÑ'££$ ƒCo&剄š››KŒŒ¼#„xÎçóíµ,«»íXìðüü|: ^l4§8ï»,Ÿ~þ™ód2åO¥R ´;LÓäfñw·põZüèÑ£7u]iš†Û¶øý~¤”!œ………=SSSW7€õùïϘH&3§OzæØ±cü±¶F­~÷“Þ{ÿùB¡ '''Ÿ ƒ»4M36ÓûØ[–å‹ÅïNœ8ñÅ­[·¬¾2¹È4ÍTue%0–ÉÔüþåÅÅÅÖ=2™=xðà³ãããOÇb±ßï÷•Ëåµb±X8{öì¥B¡pè<²5ý‹VÖë#ù¿ÇŸîöÆEcIEND®B`‚opennebula-3.4.1/src/cloud/occi/lib/OCCIServer.rb0000644000175000017500000005026511750754334021375 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # # Common cloud libs require 'CloudServer' # OCA include OpenNebula # OCCI libs require 'VirtualMachineOCCI' require 'VirtualMachinePoolOCCI' require 'VirtualNetworkOCCI' require 'VirtualNetworkPoolOCCI' require 'ImageOCCI' require 'ImagePoolOCCI' require 'UserOCCI' require 'UserPoolOCCI' require 'OpenNebulaVNC' require 'pp' ############################################################################## # The OCCI Server provides an OCCI implementation based on the # OpenNebula Engine ############################################################################## COLLECTIONS = ["compute", "instance_type", "network", "storage", "user"] # FLAG that will filter the elements retrieved from the Pools POOL_FILTER = Pool::INFO_ALL # Secs to sleep between checks to see if image upload© to repo is finished IMAGE_POLL_SLEEP_TIME = 5 class OCCIServer < CloudServer # Server initializer # config_file:: _String_ path of the config file # template:: _String_ path to the location of the templates def initialize(client, config, logger) super(config, logger) if config[:ssl_server] @base_url=config[:ssl_server] else @base_url="http://#{config[:server]}:#{config[:port]}" end @client = client end # Prepare the OCCI XML Response # resource:: _Pool_ or _PoolElement_ that represents a OCCI resource # [return] _String_,_Integer_ Resource Representation or error, status code def to_occi_xml(resource, opts) xml_response = resource.to_occi(@base_url, opts[:verbose]) return xml_response, 500 if OpenNebula.is_error?(xml_response) return xml_response, opts[:code] end ############################################################################ ############################################################################ # POOL RESOURCE METHODS ############################################################################ ############################################################################ def get_collections(request) xml_resp = "" COLLECTIONS.sort.each { |c| xml_resp << "<#{c.upcase}_COLLECTION href=\"#{@base_url}/#{c}\"/>" } xml_resp << "" return xml_resp, 200 end INSTANCE_TYPE = %q{ <%= name.to_s %> <%= name.to_s %> <% opts.sort{|k1,k2| k1[0].to_s<=>k2[0].to_s}.each { |elem, value| next if elem==:template str = elem.to_s.upcase %> <<%= str %>><%= value %>> <% } %> } def get_instance_types(request) xml_resp = "" @config[:instance_types].sort { |k1,k2| k1[0].to_s<=>k2[0].to_s }.each { |name, opts| if request.params['verbose'] begin occi_it = ERB.new(INSTANCE_TYPE) occi_it = occi_it.result(binding) rescue Exception => e error = OpenNebula::Error.new(e.message) return error, CloudServer::HTTP_ERROR_CODE[error.errno] end xml_resp << occi_it.gsub(/\n\s*/,'') else xml_resp << "" end } xml_resp << "" return xml_resp, 200 end def get_instance_type(request, params) name = params[:id].to_sym unless @config[:instance_types].keys.include?(name) error = OpenNebula::Error.new("INSTANCE_TYPE #{name} not found") return error, 404 else opts = @config[:instance_types][name] begin occi_it = ERB.new(INSTANCE_TYPE) occi_it = occi_it.result(binding) rescue Exception => e error = OpenNebula::Error.new(e.message) return error, CloudServer::HTTP_ERROR_CODE[error.errno] end return occi_it.gsub(/\n\s*/,''), 200 end end # Gets the pool representation of COMPUTES # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ Pool Representation or error, status code def get_computes(request) # --- Get User's VMs --- vmpool = VirtualMachinePoolOCCI.new( @client, POOL_FILTER) # --- Prepare XML Response --- rc = vmpool.info if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end return to_occi_xml(vmpool, :code=>200, :verbose=>request.params['verbose']) end # Gets the pool representation of NETWORKS # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ Network pool representation or error, # => status code def get_networks(request) # --- Get User's VNETs --- network_pool = VirtualNetworkPoolOCCI.new( @client, POOL_FILTER) # --- Prepare XML Response --- rc = network_pool.info if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end return to_occi_xml(network_pool, :code=>200, :verbose=>request.params['verbose']) end # Gets the pool representation of STORAGES # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ Image pool representation or error, # status code def get_storages(request) # --- Get User's Images --- image_pool = ImagePoolOCCI.new( @client, POOL_FILTER) # --- Prepare XML Response --- rc = image_pool.info if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end return to_occi_xml(image_pool, :code=>200, :verbose=>request.params['verbose']) end # Gets the pool representation of USERs # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ User pool representation or error, # status code def get_users(request) # --- Get Users Pool --- user_pool = UserPoolOCCI.new(@client) # --- Prepare XML Response --- rc = user_pool.info if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end return to_occi_xml(user_pool, :code=>200, :verbose=>request.params['verbose']) end ############################################################################ ############################################################################ # ENTITY RESOURCE METHODS ############################################################################ ############################################################################ ############################################################################ # COMPUTE Methods ############################################################################ # Post a new compute to the COMPUTE pool # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ COMPUTE Representation or error, status code def post_compute(request) # --- Create the new Instance --- vm = VirtualMachineOCCI.new( VirtualMachine.build_xml, @client, request.body.read, @config[:instance_types], @config[:template_location]) # --- Generate the template and Allocate the new Instance --- template = vm.to_one_template return template, 500 if OpenNebula.is_error?(template) rc = vm.allocate(template) if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end # --- Prepare XML Response --- vm.info return to_occi_xml(vm, :code=>201) end # Get the representation of a COMPUTE resource # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ COMPUTE representation or error, # status code def get_compute(request, params) # --- Get the VM --- vm = VirtualMachineOCCI.new( VirtualMachine.build_xml(params[:id]), @client) # --- Prepare XML Response --- rc = vm.info if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end return to_occi_xml(vm, :code=>200) end # Deletes a COMPUTE resource # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ Delete confirmation msg or error, # status code def delete_compute(request, params) # --- Get the VM --- vm = VirtualMachineOCCI.new( VirtualMachine.build_xml(params[:id]), @client) # --- Finalize the VM --- result = vm.finalize if OpenNebula.is_error?(result) return result, CloudServer::HTTP_ERROR_CODE[result.errno] end return "", 204 end # Updates a COMPUTE resource # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ Update confirmation msg or error, # status code def put_compute(request, params) # --- Get the VM --- vm = VirtualMachineOCCI.new( VirtualMachine.build_xml(params[:id]), @client) rc = vm.info if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end result, code = vm.update_from_xml(request.body) if OpenNebula.is_error?(result) return result, code else vm.info return to_occi_xml(vm, :code=>code) end end ############################################################################ # NETWORK Methods ############################################################################ # Post a new network to the NETWORK pool # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ Network Representation or error, status code def post_network(request) # --- Create the new Instance --- network = VirtualNetworkOCCI.new( VirtualNetwork.build_xml, @client, request.body, @config[:template_location]) # --- Generate the template and Allocate the new Instance --- template = network.to_one_template return template, 500 if OpenNebula.is_error?(template) rc = network.allocate(template, @config[:cluster_id]||ClusterPool::NONE_CLUSTER_ID) if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end # --- Prepare XML Response --- network.info return to_occi_xml(network, :code=>201) end # Retrieves a NETWORK resource # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ NETWORK occi representation or error, # status code def get_network(request, params) network = VirtualNetworkOCCI.new( VirtualNetwork.build_xml(params[:id]), @client) # --- Prepare XML Response --- rc = network.info if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end return to_occi_xml(network, :code=>200) end # Deletes a NETWORK resource # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ Delete confirmation msg or error, # status code def delete_network(request, params) network = VirtualNetworkOCCI.new( VirtualNetwork.build_xml(params[:id]), @client) # --- Delete the VNET --- rc = network.delete if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end return "", 204 end # Updates a NETWORK resource # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ Update confirmation msg or error, # status code def put_network(request, params) xmldoc = XMLElement.build_xml(request.body, 'NETWORK') vnet_info = XMLElement.new(xmldoc) if xmldoc != nil vnet = VirtualNetworkOCCI.new( VirtualNetwork.build_xml(params[:id]), @client) rc = nil if vnet_info['PUBLIC'] == 'YES' rc = vnet.publish elsif vnet_info['PUBLIC'] == 'NO' rc = vnet.unpublish end if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end # --- Prepare XML Response --- vnet.info return to_occi_xml(vnet, :code=>202) end ############################################################################ # STORAGE Methods ############################################################################ # Post a new image to the STORAGE pool # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ Image representation or error, status code def post_storage(request) # --- Check OCCI XML from POST --- if request.params['occixml'] == nil error_msg = "OCCI XML representation of Image" + " not present in the request" error = OpenNebula::Error.new(error_msg) return error, 400 end # --- Create and Add the new Image --- occixml = request.params['occixml'] occixml = occixml[:tempfile].read if occixml.class == Hash image = ImageOCCI.new( Image.build_xml, @client, occixml, request.params['file']) # --- Generate the template and Allocate the new Instance --- template = image.to_one_template return template, 500 if OpenNebula.is_error?(template) rc = image.allocate(template, @config[:datastore_id]||1) if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end image.info #wait until image is ready to return while (image.state_str == 'LOCKED') && (image['RUNNING_VMS'] == '0') do sleep IMAGE_POLL_SLEEP_TIME image.info end # --- Prepare XML Response --- return to_occi_xml(image, :code=>201) end # Get a STORAGE resource # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ STORAGE occi representation or error, # status code def get_storage(request, params) # --- Get the Image --- image = ImageOCCI.new( Image.build_xml(params[:id]), @client) rc = image.info if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end # --- Prepare XML Response --- return to_occi_xml(image, :code=>200) end # Deletes a STORAGE resource (Not yet implemented) # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ Delete confirmation msg or error, # status code def delete_storage(request, params) # --- Get the Image --- image = ImageOCCI.new( Image.build_xml(params[:id]), @client) # --- Delete the Image --- rc = image.delete if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end return "", 204 end # Updates a STORAGE resource # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ Update confirmation msg or error, # status code def put_storage(request, params) xmldoc = XMLElement.build_xml(request.body, 'STORAGE') image_info = XMLElement.new(xmldoc) if xmldoc != nil image = ImageOCCI.new( Image.build_xml(params[:id]), @client) rc = nil if image_info['PERSISTENT'] && image_info['PUBLIC'] error_msg = "It is not allowed more than one change per request" return OpenNebula::Error.new(error_msg), 400 elsif image_info['PERSISTENT'] == 'YES' rc = image.persistent elsif image_info['PERSISTENT'] == 'NO' rc = image.nonpersistent elsif image_info['PUBLIC'] == 'YES' rc = image.publish elsif image_info['PUBLIC'] == 'NO' rc = image.unpublish end if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end # --- Prepare XML Response --- image.info return to_occi_xml(image, :code=>202) end # Get the representation of a USER # request:: _Hash_ hash containing the data of the request # [return] _String_,_Integer_ USER representation or error, # status code def get_user(request, params) # --- Get the USER --- user = UserOCCI.new( User.build_xml(params[:id]), @client) # --- Prepare XML Response --- rc = user.info if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] end return to_occi_xml(user, :code=>200) end ############################################################################ # VNC Methods ############################################################################ def startvnc(id,config) vm = VirtualMachineOCCI.new(VirtualMachine.build_xml(id), @client) rc = vm.info if OpenNebula.is_error?(rc) error = "Error starting VNC session, " error << "could not retrieve Virtual Machine" return [404, error] end vnc_proxy = OpenNebulaVNC.new(config, logger, {:json_errors => false}) return vnc_proxy.start(vm) end def stopvnc(pipe) begin OpenNebulaVNC.stop(pipe) rescue Exception => e logger.error {e.message} return [500, "Error stopping VNC. Please check server logs."] end return [200,nil] end end opennebula-3.4.1/src/cloud/occi/lib/occi-server.rb0000644000175000017500000002772411750754334021716 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # ############################################################################## # The OCCI Server provides compatible server based on the # OpenNebula Engine ############################################################################## ############################################################################## # Environment Configuration for the Cloud Server ############################################################################## ONE_LOCATION=ENV["ONE_LOCATION"] if !ONE_LOCATION LOG_LOCATION = "/var/log/one" VAR_LOCATION = "/var/lib/one" ETC_LOCATION = "/etc/one" RUBY_LIB_LOCATION = "/usr/lib/one/ruby" else VAR_LOCATION = ONE_LOCATION + "/var" LOG_LOCATION = ONE_LOCATION + "/var" ETC_LOCATION = ONE_LOCATION + "/etc" RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby" end OCCI_AUTH = VAR_LOCATION + "/.one/occi_auth" OCCI_LOG = LOG_LOCATION + "/occi-server.log" CONFIGURATION_FILE = ETC_LOCATION + "/occi-server.conf" TEMPLATE_LOCATION = ETC_LOCATION + "/occi_templates" $: << RUBY_LIB_LOCATION $: << RUBY_LIB_LOCATION+"/cloud/occi" $: << RUBY_LIB_LOCATION+"/cloud" # For the Repository Manager ################################################ # Required libraries ################################################ require 'rubygems' require 'sinatra' require 'yaml' require 'erb' require 'tempfile' require 'fileutils' require 'json' require 'OCCIServer' require 'CloudAuth' include OpenNebula ############################################################################## # Configuration ############################################################################## # Set Configuration settings begin conf = YAML.load_file(CONFIGURATION_FILE) rescue Exception => e STDERR.puts "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}" exit 1 end conf[:template_location] = TEMPLATE_LOCATION conf[:debug_level] ||= 3 CloudServer.print_configuration(conf) set :config, conf # Enable Logger include CloudLogger enable_logging OCCI_LOG, settings.config[:debug_level].to_i # Set Sinatra configuration use Rack::Session::Pool, :key => 'occi' set :public, Proc.new { File.join(root, "ui/public") } set :views, settings.root + '/ui/views' if CloudServer.is_port_open?(settings.config[:server], settings.config[:port]) settings.logger.error { "Port #{settings.config[:port]} busy, please shutdown " << "the service or move occi server port." } exit -1 end set :bind, settings.config[:server] set :port, settings.config[:port] # Create CloudAuth begin ENV["ONE_CIPHER_AUTH"] = OCCI_AUTH cloud_auth = CloudAuth.new(settings.config, settings.logger) rescue => e settings.logger.error {"Error initializing authentication system"} settings.logger.error {e.message} exit -1 end set :cloud_auth, cloud_auth ############################################################################## # Helpers ############################################################################## before do unless request.path=='/ui/login' || request.path=='/ui' if !authorized? begin username = settings.cloud_auth.auth(request.env, params) rescue Exception => e logger.error {e.message} error 500, "" end else username = session[:user] end if username.nil? #unable to authenticate logger.error {"User not authorized"} error 401, "" else client = settings.cloud_auth.client(username) @occi_server = OCCIServer.new(client, settings.config, settings.logger) end end end after do unless request.path=='/ui/login' || request.path=='/ui' unless session[:remember] if params[:timeout] == true env['rack.session.options'][:defer] = true else env['rack.session.options'][:expire_after] = 60*10 end end end end # Response treatment helpers do def authorized? session[:ip] && session[:ip]==request.ip ? true : false end def build_session begin username = settings.cloud_auth.auth(request.env, params) rescue Exception => e logger.error {e.message} error 500, "" end if username.nil? logger.error {"User not authorized"} error 401, "" else client = settings.cloud_auth.client(username) @occi_server = OCCIServer.new(client, settings.config, settings.logger) user_id = OpenNebula::User::SELF user = OpenNebula::User.new_with_id(user_id, client) rc = user.info if OpenNebula.is_error?(rc) logger.error {rc.message} return [500, ""] end session[:ip] = request.ip session[:user] = username session[:remember] = params[:remember] if params[:remember] env['rack.session.options'][:expire_after] = 30*60*60*24 end if params[:lang] session[:lang] = params[:lang] else session[:lang] = settings.config[:lang] end return [204, ""] end end def destroy_session session.clear return [204, ""] end def treat_response(result,rc) if OpenNebula::is_error?(result) logger.error {result.message} halt rc, result.message end status rc result end end ############################################################################## # Actions ############################################################################## get '/' do result,rc = @occi_server.get_collections(request) treat_response(result,rc) end ################################################### # Pool Resources methods ################################################### get '/instance_type' do result,rc = @occi_server.get_instance_types(request) treat_response(result,rc) end post '/compute' do result,rc = @occi_server.post_compute(request) treat_response(result,rc) end get '/compute' do result,rc = @occi_server.get_computes(request) treat_response(result,rc) end post '/network' do result,rc = @occi_server.post_network(request) treat_response(result,rc) end get '/network' do result,rc = @occi_server.get_networks(request) treat_response(result,rc) end post '/storage' do result,rc = @occi_server.post_storage(request) treat_response(result,rc) end get '/storage' do result,rc = @occi_server.get_storages(request) treat_response(result,rc) end get '/user' do result,rc = @occi_server.get_users(request) treat_response(result,rc) end ################################################### # Entity Resources Methods ################################################### get '/compute/:id' do result,rc = @occi_server.get_compute(request, params) treat_response(result,rc) end delete '/compute/:id' do result,rc = @occi_server.delete_compute(request, params) treat_response(result,rc) end put '/compute/:id' do result,rc = @occi_server.put_compute(request, params) treat_response(result,rc) end get '/network/:id' do result,rc = @occi_server.get_network(request, params) treat_response(result,rc) end delete '/network/:id' do result,rc = @occi_server.delete_network(request, params) treat_response(result,rc) end put '/network/:id' do result,rc = @occi_server.put_network(request, params) treat_response(result,rc) end get '/storage/:id' do result,rc = @occi_server.get_storage(request, params) treat_response(result,rc) end delete '/storage/:id' do result,rc = @occi_server.delete_storage(request, params) treat_response(result,rc) end put '/storage/:id' do result,rc = @occi_server.put_storage(request, params) treat_response(result,rc) end get '/user/:id' do result,rc = @occi_server.get_user(request, params) treat_response(result,rc) end get '/instance_type/:id' do result,rc = @occi_server.get_instance_type(request, params) treat_response(result,rc) end ############################################## ## OCCI UI (Self-Service) ############################################## get '/ui/config' do wss = settings.config[:vnc_proxy_support_wss] wss = (wss == true || wss == "yes" || wss == "only" ? "yes" : "no") vnc = settings.config[:vnc_enable] ? "yes" : "no" config = "" config << " #{session[:lang]}" config << " #{wss}" config << " #{vnc}" config << "" return [200, config] end post '/ui/config' do begin body = JSON.parse(request.body.read) rescue [500, "POST Config: Error parsing configuration JSON"] end body.each do | key,value | case key when "lang" then session[:lang]=value end end return 200 end get '/ui/login' do redirect to('ui') end post '/ui/login' do build_session end post '/ui/logout' do destroy_session end get '/ui' do if !authorized? return File.read(File.dirname(__FILE__)+'/ui/templates/login.html') end time = Time.now + 60*10 response.set_cookie("occi-user", :value=>"#{session[:user]}", :expires=>time) erb :index end post '/ui/upload' do #so we can re-use occi post_storage() request.params['file'] = {:tempfile => request.env['rack.input']} result,rc = @occi_server.post_storage(request) treat_response(result,rc) end post '/ui/startvnc/:id' do if !settings.config[:vnc_enable] return [403, "VNC sessions are disabled"] end vm_id = params[:id] vnc_hash = session['vnc'] if !vnc_hash session['vnc'] = {} elsif vnc_hash[vm_id] #return existing information info = vnc_hash[vm_id].clone info.delete(:pipe) return [200, info.to_json] end rc = @occi_server.startvnc(vm_id, settings.config) if rc[0] == 200 info = rc[1] session['vnc'][vm_id] = info.clone info.delete(:pipe) rc = [200, info.to_json] end return rc end post '/ui/stopvnc/:id' do if !settings.config[:vnc_enable] return [403, "VNC sessions are disabled"] end vm_id = params[:id] vnc_hash = session['vnc'] if !vnc_hash || !vnc_hash[vm_id] return [403, "It seems there is no VNC proxy running for this machine"] end rc = @occi_server.stopvnc(vnc_hash[vm_id][:pipe]) if rc[0] == 200 session['vnc'].delete(vm_id) end return rc end opennebula-3.4.1/src/cloud/occi/lib/VirtualMachinePoolOCCI.rb0000644000175000017500000000410011750754334023657 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 'VirtualMachineOCCI' class VirtualMachinePoolOCCI < VirtualMachinePool OCCI_VM_POOL = %q{ <% self.each{ |vm| %> <% if verbose %> <%= vm.to_occi(base_url) %> <% else %> <% end %> <% } %> } # Creates the OCCI representation of a Virtual Machine Pool def to_occi(base_url, verbose=false) begin occi = ERB.new(OCCI_VM_POOL) occi_text = occi.result(binding) rescue Exception => e error = OpenNebula::Error.new(e.message) return error end return occi_text.gsub(/\n\s*/,'') end def factory(element_xml) VirtualMachineOCCI.new(element_xml,@client) end end opennebula-3.4.1/src/cloud/occi/lib/VirtualMachineOCCI.rb0000644000175000017500000002116311750754334023035 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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' include OpenNebula class VirtualMachineOCCI < VirtualMachine OCCI_VM = %q{ <%= self.id.to_s%> <%= self['GNAME'] %> <%= self['TEMPLATE/CPU'] %> <%= self['TEMPLATE/MEMORY'] %> <%= self.name%> <% if self['TEMPLATE/INSTANCE_TYPE'] %> <%= self['TEMPLATE/INSTANCE_TYPE'] %> <% end %> <%= self.state_str %> <% self.each('TEMPLATE/DISK') do |disk| %> <% if disk['SAVE_AS'] %> <% end %> <%= disk['TYPE'] %> <%= disk['TARGET'] %> <% end %> <% self.each('TEMPLATE/NIC') do |nic| %> <% if nic['IP'] %> <%= nic['IP'] %> <% end %> <% if nic['MAC'] %> <%= nic['MAC'] %> <% end %> <% end %> <% if self.has_elements?('TEMPLATE/CONTEXT') %> <% self.each('TEMPLATE/CONTEXT/*') do |cont| %> <% if cont.text %> <<%= cont.name %>><%= cont.text %>> <% end %> <% end %> <% end %> } OCCI_ACTION = { "STOPPED" => { :from => ["ACTIVE"], :action => :stop}, "SUSPENDED" => { :from => ["ACTIVE"], :action => :suspend}, "RESUME" => { :from => ["STOPPED", "SUSPENDED"], :action => :resume}, "CANCEL" => { :from => ["ACTIVE"], :action => :cancel}, "REBOOT" => { :from => ["ACTIVE"], :action => :reboot}, "SHUTDOWN" => { :from => ["ACTIVE"], :action => :shutdown}, "DONE" => { :from => VM_STATE, :action => :finalize} } # Class constructor def initialize(xml, client, xml_info=nil, types=nil, base=nil) super(xml, client) @vm_info = nil @template = nil @common_template = base + '/common.erb' if base if xml_info != nil xmldoc = XMLElement.build_xml(xml_info, 'COMPUTE') @vm_info = XMLElement.new(xmldoc) if xmldoc != nil end if @vm_info != nil if href = @vm_info.attr('INSTANCE_TYPE','href') @itype = href.split('/').last else @itype = @vm_info['INSTANCE_TYPE'] end if @itype != nil and types[@itype.to_sym] != nil @template = base + "/#{types[@itype.to_sym][:template]}" end end end def to_one_template() if @vm_info == nil error_msg = "Missing COMPUTE section in the XML body" return OpenNebula::Error.new(error_msg) end if @template == nil return OpenNebula::Error.new("Bad instance type") end begin template = ERB.new(File.read(@common_template)).result(binding) template << ERB.new(File.read(@template)).result(binding) rescue Exception => e error = OpenNebula::Error.new(e.message) return error end return template end # Creates the VMI representation of a Virtual Machine def to_occi(base_url, verbose=false) begin occi_vm = ERB.new(OCCI_VM) occi_vm_text = occi_vm.result(binding) rescue Exception => e error = OpenNebula::Error.new(e.message) return error end return occi_vm_text.gsub(/\n\s*/,'') end # Update de resource from an XML representation of the COMPUTE # @param [String] xml_compute XML representation of the COMPUTE # @return [[nil, OpenNebula::Error], HTTP_CODE] If there is no error #  the first component is nil. def update_from_xml(xml_compute) xmldoc = XMLElement.build_xml(xml_compute, 'COMPUTE') vm_info = XMLElement.new(xmldoc) if xmldoc != nil action = nil args = [] # Check if a state change is required occi_state = vm_info['STATE'] if occi_state # If a state is provided occi_state.upcase! if OCCI_ACTION.keys.include?(occi_state) # If the requested state is one the OCCI action states shash = OCCI_ACTION[occi_state] if shash[:from].include?(state_str) # Action to be performed action = shash[:action] elsif occi_state != state_str # If the requested state is different from the resource # state but it does not belong to the "from" state array error_msg = "The state of the resource cannot be changed" \ " from #{state_str} to #{occi_state}." error = OpenNebula::Error.new(error_msg) return error, 403 end elsif !VM_STATE.include?(occi_state) # The requested state is not one of the OCCI action states nor # a resource state error_msg = "Invalid state: \"#{occi_state}\"" error = OpenNebula::Error.new(error_msg) return error, 400 end end # Check if a disk image save as is required image_name = nil vm_info.each('DISK/SAVE_AS') { |save_as| image_name = save_as.attr('.', 'name') if image_name if action # Return erro if an action has been defined before if action == :save_as error_msg = "Only one disk can be saved per request" else error_msg = "Changig the state of the resource and" \ " saving a disk is not allowed in the same request" end error = OpenNebula::Error.new(error_msg) return error, 403 else # if no action is defined yet and a save_as is requested action = :save_as disk_id = save_as.attr('..', 'id') # Params for the save_as action: # save_as(disk_id, image_name) args << disk_id.to_i args << image_name end end } # Perform the requested action if action rc = self.send(action, *args) if OpenNebula.is_error?(rc) return rc, CloudServer::HTTP_ERROR_CODE[rc.errno] else return nil, 202 end else # There is no change requested return nil, 200 end end end opennebula-3.4.1/src/cloud/occi/lib/UserPoolOCCI.rb0000644000175000017500000000376611750754334021703 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 'UserOCCI' class UserPoolOCCI < UserPool OCCI_USER_POOL = %q{ <% self.each{ |user| %> <% if verbose %> <%= user.to_occi(base_url) %> <% else %> <% end %> <% } %> } # Creates the OCCI representation of a User Pool def to_occi(base_url, verbose=false) begin occi = ERB.new(OCCI_USER_POOL) occi_text = occi.result(binding) rescue Exception => e error = OpenNebula::Error.new(e.message) return error end return occi_text.gsub(/\n\s*/,'') end def factory(element_xml) UserOCCI.new(element_xml,@client) end endopennebula-3.4.1/src/cloud/occi/test/0000755000175000017500000000000011750754334017345 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/templates/0000755000175000017500000000000011750754334021343 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/templates/image2.template0000644000175000017500000000006611750754334024246 0ustar drazzibdrazzibNAME = second_image PATH = /etc/hosts TYPE = DATABLOCKopennebula-3.4.1/src/cloud/occi/test/templates/vm.template0000644000175000017500000000011611750754334023520 0ustar drazzibdrazzibCPU = 1 MEMORY = 512 DISK = [ IMAGE_ID = 0 ] DISK = [ IMAGE_ID = 1 ]opennebula-3.4.1/src/cloud/occi/test/templates/image1.template0000644000175000017500000000004411750754334024241 0ustar drazzibdrazzibNAME = first_image PATH = /etc/hostsopennebula-3.4.1/src/cloud/occi/test/spec/0000755000175000017500000000000011750754334020277 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/spec/user_spec.rb0000644000175000017500000000556311750754334022625 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 File.expand_path(File.dirname(__FILE__) + '/spec_helper') describe 'OCCI User tests' do before(:all) do @username_1 = "my_first_occi_user" @userpass_1 = "my_first_occi_pass" `oneuser create #{@username_1} #{@userpass_1}` end it "should list the user collection" do basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd') get '/user' last_response.status.should eql(200) xml_body = last_response.body user_collection = File.read(FIXTURES_PATH + '/user/user_collection.xml') xml_body.strip.should eql(user_collection.strip) end it "should check the error if the user collection is retrieved by a non oneadmin user" do basic_authorize('my_first_occi_user','c08c5a6c535b6060b7b2af34e0d2f0ffb7e63b28') get '/user' last_response.status.should eql(403) end it "should show the user information, no quotas and no usage" do basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd') get '/user/0' last_response.status.should eql(200) xml_body = last_response.body user = File.read(FIXTURES_PATH + '/user/user.xml') xml_body.strip.should eql(user.strip) end it "should get a 404 error when trying to get a non existing user" do basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd') get '/user/99' last_response.status.should eql(404) end it "should get a 403 error when trying to get a different user" do basic_authorize('my_first_occi_user','c08c5a6c535b6060b7b2af34e0d2f0ffb7e63b28') get '/user/0' last_response.status.should eql(403) end end opennebula-3.4.1/src/cloud/occi/test/spec/occi_spec.rb0000644000175000017500000002212211750754334022552 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 File.expand_path(File.dirname(__FILE__) + '/spec_helper') # The following methods are helpers defined in spec_helper # - compare_xml # - get_fixture # - network_template # - storage_template # - compute_template describe 'OCCI tests' do before(:all) do @user_oneadmin = "my_first_occi_user" `oneuser create #{@user_oneadmin} my_pass`.scan(/^ID: (\d+)/) { |uid| `oneuser show #{uid.first}`.scan(/PASSWORD\s*:\s*(\w*)/) { |password| @user_pass = password.first.strip } `oneuser chgrp #{uid.first} 0` } @user_users = "my_second_occi_user" `oneuser create #{@user_users} my_pass2`.scan(/^ID: (\d+)/) { |uid| `oneuser show #{uid.first}`.scan(/PASSWORD\s*:\s*(\w*)/) { |password| @user_pass2 = password.first.strip } } # Define BRIDGE attirbute in network.erb, otherwise the NETWORK creation will `sed -i.bck "s%^#\\(BRIDGE = \\).*$%\\1 br0%" $ONE_LOCATION/etc/occi_templates/network.erb` end describe "with a user of the oneadmin group" do before(:each) do basic_authorize(@user_oneadmin, @user_pass) end it "should retrieve the list of collections" do get '/' compare_xml(last_response.body, get_fixture('/root.xml')) last_response.status.should == 200 end it "should retrieve the list of INSTANCE_TYPEs" do get '/instance_type' compare_xml(last_response.body, get_fixture('/instance_type/list.xml')) last_response.status.should == 200 end it "should retrieve the extended list of INSTANCE_TYPEs" do get '/instance_type', {'verbose'=>true} compare_xml(last_response.body, get_fixture('/instance_type/extended.xml')) last_response.status.should == 200 end context "for NETWORK" do it "should retrieve the empty list" do get '/network' compare_xml(last_response.body, get_fixture('/network/empty.xml')) last_response.status.should == 200 end it "should create a new NETWORK" do network = { :name => "Network", :description => "Network of the user #{@user_oneadmin}", :address => "192.168.1.0", :size => "100", :pubic => "YES" } post '/network', network_template(network) compare_xml(last_response.body, get_fixture('/network/first_net.xml')) last_response.status.should == 201 end it "should retrieve the NETWORK with ID 0" do get '/network/0' compare_xml(last_response.body, get_fixture('/network/first_net.xml')) last_response.status.should == 200 end end context "for STORAGE" do it "should retrieve the empty list" do get '/storage' compare_xml(last_response.body, get_fixture('/storage/empty.xml')) last_response.status.should == 200 end it "should create a new STORAGE, type DATABLOCK. This request waits until the IMAGE is ready in OpenNebula" do storage = { :name => "Storage", :description => "Storage of the user #{@user_oneadmin}", :type => "DATABLOCK", :size => "100", :fstype => "ext3" } post '/storage', {'occixml' => storage_template(storage)} compare_xml(last_response.body, get_fixture('/storage/first_storage.xml')) last_response.status.should == 201 end it "should retrieve the STORAGE with ID 0" do get '/storage/0' compare_xml(last_response.body, get_fixture('/storage/first_storage.xml')) last_response.status.should == 200 end end context "for COMPUTE" do it "should retrieve the empty list" do get '/compute' compare_xml(last_response.body, get_fixture('/compute/empty.xml')) last_response.status.should == 200 end it "should create a new COMPUTE using the previous NETWORK (ID=0) and STORAGE(ID=0)" do compute = { :name => "Compute", :instance_type => "small", :disk => [ {:storage => '0'} ], :nic => [ {:network => '0'} ] } post '/compute', compute_template(compute) compare_xml(last_response.body, get_fixture('/compute/first_compute.xml')) last_response.status.should == 201 end it "should retrieve the COMPUTE with ID 0" do get '/compute/0' compare_xml(last_response.body, get_fixture('/compute/first_compute.xml')) last_response.status.should == 200 end it "should terminate (DONE) the COMPUTE with ID 0" do compute = { :id => "0", :state => "DONE" } put '/compute/0', compute_action(compute) compare_xml(last_response.body, get_fixture('/compute/first_compute_done.xml')) last_response.status.should == 202 end end end describe "with a user of the users group" do before(:each) do basic_authorize(@user_users, @user_pass2) end it "should retrieve the list of collections" do get '/' compare_xml(last_response.body, get_fixture('/root.xml')) last_response.status.should == 200 end it "should retrieve the list of INSTANCE_TYPEs" do get '/instance_type' compare_xml(last_response.body, get_fixture('/instance_type/list.xml')) last_response.status.should == 200 end it "should retrieve the extended list of INSTANCE_TYPEs" do get '/instance_type', {'verbose'=>true} compare_xml(last_response.body, get_fixture('/instance_type/extended.xml')) last_response.status.should == 200 end context "for NETWORK" do it "should retrieve the empty list" do get '/network' compare_xml(last_response.body, get_fixture('/network/empty.xml')) last_response.status.should == 200 end it "should create a new NETWORK" do network = { :name => "Network2", :description => "Network of the user #{@user_users}", :address => "192.168.2.0", :size => "100", :pubic => "YES" } post '/network', network_template(network) compare_xml(last_response.body, get_fixture('/network/second_net.xml')) last_response.status.should == 201 end it "should retrieve the NETWORK with ID 1" do get '/network/1' compare_xml(last_response.body, get_fixture('/network/second_net.xml')) last_response.status.should == 200 end end context "for STORAGE" do it "should retrieve the empty list" do get '/storage' compare_xml(last_response.body, get_fixture('/storage/empty.xml')) last_response.status.should == 200 end it "should create a new STORAGE, type DATABLOCK. This request waits until the IMAGE is ready in OpenNebula" do storage = { :name => "Storage2", :description => "Storage of the user #{@user_users}", :type => "DATABLOCK", :size => "100", :fstype => "ext3" } post '/storage', {'occixml' => storage_template(storage)} compare_xml(last_response.body, get_fixture('/storage/second_storage.xml')) last_response.status.should == 201 end it "should retrieve the STORAGE with ID 1" do get '/storage/1' compare_xml(last_response.body, get_fixture('/storage/second_storage.xml')) last_response.status.should == 200 end end context "for COMPUTE" do it "should retrieve the empty list" do get '/compute' compare_xml(last_response.body, get_fixture('/compute/empty.xml')) last_response.status.should == 200 end it "should create a new COMPUTE using the previous NETWORK (ID=1) and STORAGE(ID=1)" do compute = { :name => "Compute2", :instance_type => "small", :disk => [ {:storage => '1'} ], :nic => [ {:network => '1'} ] } post '/compute', compute_template(compute) compare_xml(last_response.body, get_fixture('/compute/second_compute.xml')) last_response.status.should == 201 end it "should retrieve the COMPUTE with ID 1" do get '/compute/1' compare_xml(last_response.body, get_fixture('/compute/second_compute.xml')) last_response.status.should == 200 end it "should terminate (DONE) the COMPUTE with ID 1" do compute = { :id => "1", :state => "DONE" } put '/compute/1', compute_action(compute) compare_xml(last_response.body, get_fixture('/compute/second_compute_done.xml')) last_response.status.should == 202 end end end endopennebula-3.4.1/src/cloud/occi/test/spec/vm_saveas_spec.rb0000644000175000017500000000635711750754334023635 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 File.expand_path(File.dirname(__FILE__) + '/spec_helper') describe 'OCCI User tests' do # PREREQUISITES # OpenNebula installed and running using dummy drivers before(:all) do # Starting the drivers sleep 2 system("onehost create myhost im_dummy vmm_dummy tm_dummy").should == true system("oneimage create #{TEMPLATES_PATH+"/image1.template"}").should == true system("oneimage create #{TEMPLATES_PATH+"/image2.template"}").should == true # Copying the images sleep 1 system("onevm create #{TEMPLATES_PATH+"/vm.template"}").should == true system("onevm deploy 0 0").should == true end it "should show the new compute" do basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd') get '/compute/0' last_response.body.should == File.read(FIXTURES_PATH+"/vm_save_as/newcompute.xml") end it "should get an error when trying to change the resource state and save a disk " do basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd') body = File.read(FIXTURES_PATH+"/vm_save_as/save_a_disk_and_change_state.xml") put '/compute/0', body last_response.status.should == 403 end it "should get an error when trying to save two disks" do basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd') body = File.read(FIXTURES_PATH+"/vm_save_as/save_two_disks.xml") put '/compute/0', body last_response.status.should == 403 end it "should save the first disk" do basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd') body = File.read(FIXTURES_PATH+"/vm_save_as/save_first_disk.xml") put '/compute/0', body last_response.status.should == 202 end it "should save the second disk" do basic_authorize('oneadmin','4478db59d30855454ece114e8ccfa5563d21c9bd') body = File.read(FIXTURES_PATH+"/vm_save_as/save_second_disk.xml") put '/compute/0', body last_response.status.should == 202 end endopennebula-3.4.1/src/cloud/occi/test/spec/spec_helper.rb0000644000175000017500000001204211750754334023114 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # FIXTURES_PATH = File.join(File.dirname(__FILE__),'../fixtures') TEMPLATES_PATH = File.join(File.dirname(__FILE__),'../templates') $: << File.join(File.dirname(__FILE__), '..', '..', 'lib') # Load the testing libraries require 'rubygems' require 'rspec' require 'rack/test' require 'rexml/document' # Load the Sinatra app require 'occi-server' # Make Rack::Test available to all spec contexts RSpec.configure do |conf| conf.include Rack::Test::Methods end # Set the Sinatra environment set :environment, :test # Add an app method for RSpec def app Sinatra::Application end def get_fixture(path) File.read(FIXTURES_PATH + path).strip end def compare_xml(a, b) a = REXML::Document.new(a.to_s) b = REXML::Document.new(b.to_s) normalized = Class.new(REXML::Formatters::Pretty) do def write_text(node, output) super(node.to_s.strip, output) end end normalized.new(indentation=0,ie_hack=false).write(node=a, a_normalized='') normalized.new(indentation=0,ie_hack=false).write(node=b, b_normalized='') a_normalized.should == b_normalized end OCCI_NETWORK = %q{ <% if hash[:name] %> <%= hash[:name] %> <% end %> <% if hash[:description] %> <%= hash[:description] %> <% end %> <% if hash[:address] %>
    <%= hash[:address] %>
    <% end %> <% if hash[:size] %> <%= hash[:size] %> <% end %> <% if hash[:public] %> <%= hash[:public] %> <% end %>
    } def network_template(hash) ERB.new(OCCI_NETWORK).result(binding) end OCCI_IMAGE = %q{ <% if hash[:name] %> <%= hash[:name] %> <% end %> <% if hash[:type] %> <%= hash[:type] %> <% end %> <% if hash[:description] %> <%= hash[:description] %> <% end %> <% if hash[:size] %> <%= hash[:size] %> <% end %> <% if hash[:fstype] %> <%= hash[:fstype] %> <% end %> <% if hash[:public] %> <%= hash[:public] %> <% end %> <% if hash[:persistent] %> <%= hash[:persistent] %> <% end %> } def storage_template(hash) ERB.new(OCCI_IMAGE).result(binding) end OCCI_VM = %q{ <% if hash[:name] %> <%= hash[:name] %> <% end %> <% if hash[:instance_type] %> <% end %> <% if hash[:disk] %> <% hash[:disk].each { |disk| %> <% if disk[:storage] %> <% end %> <% } %> <% end %> <% if hash[:nic] %> <% hash[:nic].each { |nic| %> <% if nic[:network] %> <% end %> <% if nic[:ip] %> <%= nic[:ip] %> <% end %> <% } %> <% end %> <% if hash[:context] %> <% hash[:context].each { |key, value| %> <<%= key.to_s.upcase %>><%= value %>> <% } %> <% end %> } OCCI_VM_ACTION = %q{ <% if hash[:id] %> <%= hash[:id] %> <% end %> <% if hash[:state] %> <%= hash[:state] %> <% end %> } def compute_template(hash) ERB.new(OCCI_VM).result(binding) end def compute_action(hash) ERB.new(OCCI_VM_ACTION).result(binding) end opennebula-3.4.1/src/cloud/occi/test/spec/spec.opts0000644000175000017500000000006311750754334022137 0ustar drazzibdrazzib--colour --format progress --loadby mtime --reverseopennebula-3.4.1/src/cloud/occi/test/test.sh0000755000175000017500000000333011750754334020662 0ustar drazzibdrazzib#!/bin/bash # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # if [ -z $ONE_LOCATION ]; then echo "ONE_LOCATION not defined." exit -1 fi VAR_LOCATION="$ONE_LOCATION/var" if [ "$(ls -A $VAR_LOCATION)" ]; then echo "$VAR_LOCATION is not empty." exit -1 fi for j in `ls ./spec/*_spec.rb` ; do find $VAR_LOCATION -mindepth 1 ! \( -path "$VAR_LOCATION/remotes*" -o -path "$VAR_LOCATION/images" \) -delete PID=$$ oned -f & sleep 2s; rspec $j -f s CODE=$? pkill -P $PID oned sleep 2s; pkill -9 -P $PID oned if [ $CODE != 0 ] ; then exit 1 fi done opennebula-3.4.1/src/cloud/occi/test/fixtures/0000755000175000017500000000000011750754334021216 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/fixtures/vm_save_as/0000755000175000017500000000000011750754334023341 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/fixtures/vm_save_as/save_a_disk_and_change_state.xml0000644000175000017500000000064311750754334031665 0ustar drazzibdrazzib01512one-0SUSPENDEDDISKhdaDISKhdeopennebula-3.4.1/src/cloud/occi/test/fixtures/vm_save_as/save_two_disks.xml0000644000175000017500000000067211750754334027114 0ustar drazzibdrazzib01512one-0ACTIVEDISKhdaDISKhdeopennebula-3.4.1/src/cloud/occi/test/fixtures/vm_save_as/save_second_disk.xml0000644000175000017500000000064011750754334027366 0ustar drazzibdrazzib01512one-0ACTIVEDISKhdaDISKhdeopennebula-3.4.1/src/cloud/occi/test/fixtures/vm_save_as/newcompute.xml0000644000175000017500000000060611750754334026253 0ustar drazzibdrazzib01512one-0ACTIVEDISKhdaDISKhdeopennebula-3.4.1/src/cloud/occi/test/fixtures/vm_save_as/save_first_disk.xml0000644000175000017500000000064011750754334027242 0ustar drazzibdrazzib01512one-0ACTIVEDISKhdaDISKhdeopennebula-3.4.1/src/cloud/occi/test/fixtures/network/0000755000175000017500000000000011750754334022707 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/fixtures/network/first_net.xml0000644000175000017500000000055711750754334025435 0ustar drazzibdrazzib 0 Network oneadmin Network of the user my_first_occi_user
    192.168.1.1
    125 0 NO
    opennebula-3.4.1/src/cloud/occi/test/fixtures/network/empty.xml0000644000175000017500000000005111750754334024563 0ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/fixtures/network/second_net.xml0000644000175000017500000000055711750754334025561 0ustar drazzibdrazzib 1 Network2 users Network of the user my_second_occi_user
    192.168.2.1
    125 0 NO
    opennebula-3.4.1/src/cloud/occi/test/fixtures/compute/0000755000175000017500000000000011750754334022672 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/fixtures/compute/second_compute.xml0000644000175000017500000000117111750754334026423 0ustar drazzibdrazzib 1 users 1 1024 Compute2 small PENDING DISK hde 192.168.2.1 02:00:c0:a8:02:01 opennebula-3.4.1/src/cloud/occi/test/fixtures/compute/first_compute_done.xml0000644000175000017500000000116511750754334027307 0ustar drazzibdrazzib 0 oneadmin 1 1024 Compute small DONE DISK hde 192.168.1.1 02:00:c0:a8:01:01 opennebula-3.4.1/src/cloud/occi/test/fixtures/compute/first_compute.xml0000644000175000017500000000117011750754334026276 0ustar drazzibdrazzib 0 oneadmin 1 1024 Compute small PENDING DISK hde 192.168.1.1 02:00:c0:a8:01:01 opennebula-3.4.1/src/cloud/occi/test/fixtures/compute/second_compute_done.xml0000644000175000017500000000116611750754334027434 0ustar drazzibdrazzib 1 users 1 1024 Compute2 small DONE DISK hde 192.168.2.1 02:00:c0:a8:02:01 opennebula-3.4.1/src/cloud/occi/test/fixtures/compute/empty.xml0000644000175000017500000000005111750754334024546 0ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/fixtures/root.xml0000644000175000017500000000052411750754334022724 0ustar drazzibdrazzib opennebula-3.4.1/src/cloud/occi/test/fixtures/storage/0000755000175000017500000000000011750754334022662 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/fixtures/storage/second_storage.xml0000644000175000017500000000062511750754334026406 0ustar drazzibdrazzib 1 Storage2 users READY DATABLOCK Storage of the user my_second_occi_user 100 ext3 NO NO opennebula-3.4.1/src/cloud/occi/test/fixtures/storage/empty.xml0000644000175000017500000000005111750754334024536 0ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/fixtures/storage/first_storage.xml0000644000175000017500000000062511750754334026262 0ustar drazzibdrazzib 0 Storage oneadmin READY DATABLOCK Storage of the user my_first_occi_user 100 ext3 NO NO opennebula-3.4.1/src/cloud/occi/test/fixtures/instance_type/0000755000175000017500000000000011750754334024063 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/fixtures/instance_type/list.xml0000644000175000017500000000045411750754334025563 0ustar drazzibdrazzib opennebula-3.4.1/src/cloud/occi/test/fixtures/instance_type/extended.xml0000644000175000017500000000114311750754334026404 0ustar drazzibdrazzib large large 8 8192 medium medium 4 4096 small small 1 1024 opennebula-3.4.1/src/cloud/occi/test/fixtures/user/0000755000175000017500000000000011750754334022174 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/occi/test/fixtures/user/user.xml0000644000175000017500000000037211750754334023676 0ustar drazzibdrazzib0oneadmin00000000opennebula-3.4.1/src/cloud/occi/test/fixtures/user/user_collection.xml0000644000175000017500000000024311750754334026106 0ustar drazzibdrazzibopennebula-3.4.1/src/cloud/common/0000755000175000017500000000000011750754334016741 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/common/CloudServer.rb0000644000175000017500000001213111750754334021521 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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' ############################################################################## # This class represents a generic Cloud Server using the OpenNebula Cloud # API (OCA). Any cloud implementation should derive from this class ############################################################################## class CloudServer ########################################################################## # Class Constants. Define the OpenNebula Error and HTTP codes mapping ########################################################################## HTTP_ERROR_CODE = { OpenNebula::Error::EAUTHENTICATION => 401, OpenNebula::Error::EAUTHORIZATION => 403, OpenNebula::Error::ENO_EXISTS => 404, OpenNebula::Error::EACTION => 500, OpenNebula::Error::EXML_RPC_API => 500, OpenNebula::Error::EINTERNAL => 500, OpenNebula::Error::ENOTDEFINED => 500 } ########################################################################## # Public attributes ########################################################################## attr_reader :config # Initializes the Cloud server based on a config file # config_file:: _String_ for the server. MUST include the following # variables: # AUTH # VM_TYPE # XMLRPC def initialize(config, logger=nil) # --- Load the Cloud Server configuration file --- @config = config @@logger = logger end def self.logger return @@logger end def logger return @@logger end # # Prints the configuration of the server # def self.print_configuration(config) puts "--------------------------------------" puts " Server configuration " puts "--------------------------------------" pp config STDOUT.flush end # Finds out if a port is available on ip # ip:: _String_ IP address where the port to check is # port:: _String_ port to find out whether is open # [return] _Boolean_ Newly created image object def self.is_port_open?(ip, port) begin Timeout::timeout(2) do begin s = TCPSocket.new(ip, port) s.close return true rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH return false end end rescue Timeout::Error end return false end end module CloudLogger require 'logger' DEBUG_LEVEL = [ Logger::ERROR, # 0 Logger::WARN, # 1 Logger::INFO, # 2 Logger::DEBUG # 3 ] # Mon Feb 27 06:02:30 2012 [Clo] [E]: Error message example MSG_FORMAT = %{%s [%s]: %s\n} # Mon Feb 27 06:02:30 2012 DATE_FORMAT = "%a %b %d %H:%M:%S %Y" # Patch logger class to be compatible with Rack::CommonLogger class CloudLogger < Logger def initialize(path) super(path) end def write(msg) info msg.chop end def add(severity, message = nil, progname = nil, &block) rc = super(severity, message, progname, &block) @logdev.dev.flush rc end end def enable_logging(path=nil, debug_level=3) path ||= $stdout logger = CloudLogger.new(path) logger.level = DEBUG_LEVEL[debug_level] logger.formatter = proc do |severity, datetime, progname, msg| MSG_FORMAT % [ datetime.strftime(DATE_FORMAT), severity[0..0], msg ] end # Add the logger instance to the Sinatra settings set :logger, logger # The logging will be configured in Rack, not in Sinatra disable :logging # Use the logger instance in the Rack methods use Rack::CommonLogger, logger helpers do def logger settings.logger end end end end opennebula-3.4.1/src/cloud/common/CloudAuth/0000755000175000017500000000000011750754334020631 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/common/CloudAuth/EC2CloudAuth.rb0000644000175000017500000000717511750754334023352 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # module EC2CloudAuth def do_auth(env, params={}) username = params['AWSAccessKeyId'] one_pass = get_password(username, 'core|public') return nil unless one_pass signature = case params['SignatureVersion'] when "1" then signature_v1(params.clone,one_pass) when "2" then signature_v2(params.clone,one_pass,env,true,false) end if params['Signature'] == signature return username elsif params['SignatureVersion']=="2" signature = signature_v2(params.clone,one_pass,env,false,false) if params['Signature'] == signature return username end end return nil end private # Calculates signature version 1 def signature_v1(params, secret_key, digest='sha1') params.delete('Signature') params.delete('econe_host') params.delete('econe_port') params.delete('econe_path') req_desc = params.sort {|x,y| x[0].downcase <=> y[0].downcase}.to_s digest_generator = OpenSSL::Digest::Digest.new(digest) digest = OpenSSL::HMAC.digest(digest_generator, secret_key, req_desc) b64sig = Base64.b64encode(digest) return b64sig.strip end # Calculates signature version 2 def signature_v2(params, secret_key, env, include_port=true, urlencode=true) params.delete('Signature') params.delete('file') server_host = params.delete('econe_host') server_port = params.delete('econe_port') server_path = params.delete('econe_path') || '/' if include_port server_str = "#{server_host}:#{server_port}" else server_str = server_host end canonical_str = AWS.canonical_string( params, server_str, env['REQUEST_METHOD'], server_path) # Use the correct signature strength sha_strength = case params['SignatureMethod'] when "HmacSHA1" then 'sha1' when "HmacSHA256" then 'sha256' else 'sha1' end digest = OpenSSL::Digest::Digest.new(sha_strength) hmac = OpenSSL::HMAC.digest(digest, secret_key, canonical_str) b64hmac = Base64.encode64(hmac).gsub("\n","") if urlencode return CGI::escape(b64hmac) else return b64hmac end end end opennebula-3.4.1/src/cloud/common/CloudAuth/OpenNebulaCloudAuth.rb0000644000175000017500000000350511750754334025022 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # module OpenNebulaCloudAuth def do_auth(env, params={}) auth = Rack::Auth::Basic::Request.new(env) if auth.provided? && auth.basic? username, password = auth.credentials client = OpenNebula::Client.new("#{username}:#{password}") user = OpenNebula::User.new_with_id(OpenNebula::User::SELF, client) rc = user.info if OpenNebula.is_error?(rc) logger.error { "User #{username} could not be authenticated" } logger.error { rc.message } return nil end return username end return nil end endopennebula-3.4.1/src/cloud/common/CloudAuth/SunstoneCloudAuth.rb0000644000175000017500000000310511750754334024604 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # module SunstoneCloudAuth def do_auth(env, params={}) auth = Rack::Auth::Basic::Request.new(env) if auth.provided? && auth.basic? username, password = auth.credentials one_pass = get_password(username, 'core') if one_pass && one_pass == Digest::SHA1.hexdigest(password) return username end end return nil end endopennebula-3.4.1/src/cloud/common/CloudAuth/OCCICloudAuth.rb0000644000175000017500000000306011750754334023503 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # module OCCICloudAuth def do_auth(env, params={}) auth = Rack::Auth::Basic::Request.new(env) if auth.provided? && auth.basic? username, password = auth.credentials one_pass = get_password(username, 'core|public') if one_pass && one_pass == password return username end end return nil end endopennebula-3.4.1/src/cloud/common/CloudAuth/X509CloudAuth.rb0000644000175000017500000000452611750754334023443 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # module X509CloudAuth def do_auth(env, params={}) # For https, the web service should be set to include the user cert in the environment. cert_line = env['HTTP_SSL_CLIENT_CERT'] cert_line = nil if cert_line == '(null)' # For Apache mod_ssl chain_index = 0 # Use the https credentials for authentication unless cert_line.nil? begin m = cert_line.match(/(-+BEGIN CERTIFICATE-+)([^-]*)(-+END CERTIFICATE-+)/) cert_s = "#{m[1]}#{m[2].gsub(' ',"\n")}#{m[3]}" cert = OpenSSL::X509::Certificate.new(cert_s) rescue raise "Could not create X509 certificate from " + cert_line end # Password should be DN with whitespace removed. username = get_username(cert.subject.to_s.delete("\s")) return username if username cert_line = env["HTTP_SSL_CLIENT_CERT_CHAIN_#{chain_index}"] cert_line = nil if cert_line == '(null)' # For Apache mod_ssl chain_index += 1 else raise "Username not found in certificate chain " end return nil end end opennebula-3.4.1/src/cloud/common/CloudAuth.rb0000644000175000017500000001224211750754334021157 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 'thread' class CloudAuth # These are the authentication methods for the user requests AUTH_MODULES = { "occi" => 'OCCICloudAuth', "sunstone" => 'SunstoneCloudAuth' , "ec2" => 'EC2CloudAuth', "x509" => 'X509CloudAuth', "opennebula" => 'OpenNebulaCloudAuth' } # These are the authentication modules for the OpenNebula requests # Each entry is an array with the filename for require and class name # to instantiate the object. AUTH_CORE_MODULES = { "cipher" => [ 'server_cipher_auth', 'ServerCipherAuth' ], "x509" => [ 'server_x509_auth', 'ServerX509Auth' ] } # Default interval for timestamps. Tokens will be generated using the same # timestamp for this interval of time. # THIS VALUE CANNOT BE LOWER THAN EXPIRE_MARGIN EXPIRE_DELTA = 1800 # Tokens will be generated if time > EXPIRE_TIME - EXPIRE_MARGIN EXPIRE_MARGIN = 300 attr_reader :client, :token, :logger # conf a hash with the configuration attributes as symbols def initialize(conf, logger=nil) @conf = conf @logger = logger @lock = Mutex.new @token_expiration_time = Time.now.to_i + EXPIRE_DELTA if AUTH_MODULES.include?(@conf[:auth]) require 'CloudAuth/' + AUTH_MODULES[@conf[:auth]] extend Kernel.const_get(AUTH_MODULES[@conf[:auth]]) else raise "Auth module not specified" end if AUTH_CORE_MODULES.include?(@conf[:core_auth]) core_auth = AUTH_CORE_MODULES[@conf[:core_auth]] else core_auth = AUTH_CORE_MODULES["cipher"] end begin require core_auth[0] @server_auth = Kernel.const_get(core_auth[1]).new_client rescue => e raise e.message end @user_pool = OpenNebula::UserPool.new(client) rc = @user_pool.info raise rc.message if OpenNebula.is_error?(rc) end # Generate a new OpenNebula client for the target User, if the username # is nil the Client is generated for the server_admin # ussername:: _String_ Name of the User # [return] _Client_ def client(username=nil) expiration_time = @lock.synchronize { time_now = Time.now.to_i if time_now > @token_expiration_time - EXPIRE_MARGIN @token_expiration_time = time_now + EXPIRE_DELTA end @token_expiration_time } token = @server_auth.login_token(expiration_time,username) Client.new(token,@conf[:one_xmlrpc]) end # # # def auth(env, params={}) username = do_auth(env, params) if username.nil? update_userpool_cache do_auth(env, params) else username end end protected # Gets the password associated with a username # username:: _String_ the username # driver:: _String_ list of valid drivers for the user, | separated # [return] _Hash_ with the username def get_password(username, driver=nil) xpath = "USER[NAME=\"#{username}\"" if driver xpath << " and (AUTH_DRIVER=\"" xpath << driver.split('|').join("\" or AUTH_DRIVER=\"") << '")' end xpath << "]/PASSWORD" retrieve_from_userpool(xpath) end # Gets the username associated with a password # password:: _String_ the password # [return] _Hash_ with the username def get_username(password) xpath = "USER[contains(PASSWORD, \"#{password}\")]/NAME" retrieve_from_userpool(xpath) end private def retrieve_from_userpool(xpath) @lock.synchronize { @user_pool[xpath] } end def update_userpool_cache oneadmin_client = client @lock.synchronize { @user_pool = OpenNebula::UserPool.new(oneadmin_client) rc = @user_pool.info raise rc.message if OpenNebula.is_error?(rc) } end endopennebula-3.4.1/src/cloud/common/CloudClient.rb0000644000175000017500000001431611750754334021500 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 'rubygems' require 'uri' require 'digest/sha1' require 'net/https' require "rexml/document" begin require 'rexml/formatters/pretty' REXML_FORMATTERS=true rescue LoadError REXML_FORMATTERS=false end begin require 'curb' CURL_LOADED=true rescue LoadError CURL_LOADED=false end begin require 'net/http/post/multipart' MULTIPART_LOADED=true rescue LoadError MULTIPART_LOADED=false end ############################################################################### # The CloudClient module contains general functionality to implement a # Cloud Client ############################################################################### module CloudClient # ######################################################################### # Default location for the authentication file # ######################################################################### DEFAULT_AUTH_FILE = ENV["HOME"]+"/.one/one_auth" # ######################################################################### # Gets authorization credentials from ONE_AUTH or default # auth file. # # Raises an error if authorization is not found # ######################################################################### def self.get_one_auth if ENV["ONE_AUTH"] and !ENV["ONE_AUTH"].empty? and File.file?(ENV["ONE_AUTH"]) one_auth=File.read(ENV["ONE_AUTH"]).strip.split(':') elsif File.file?(DEFAULT_AUTH_FILE) one_auth=File.read(DEFAULT_AUTH_FILE).strip.split(':') else raise "No authorization data present" end raise "Authorization data malformed" if one_auth.length < 2 one_auth end # ######################################################################### # Starts an http connection and calls the block provided. SSL flag # is set if needed. # ######################################################################### def self.http_start(url, timeout, &block) http = Net::HTTP.new(url.host, url.port) if timeout http.read_timeout = timeout.to_i end if url.scheme=='https' http.use_ssl = true http.verify_mode=OpenSSL::SSL::VERIFY_NONE end begin res = http.start do |connection| block.call(connection) end rescue Errno::ECONNREFUSED => e str = "Error connecting to server (#{e.to_s}).\n" str << "Server: #{url.host}:#{url.port}" return CloudClient::Error.new(str,"503") rescue Errno::ETIMEDOUT => e str = "Error timeout connecting to server (#{e.to_s}).\n" str << "Server: #{url.host}:#{url.port}" return CloudClient::Error.new(str,"504") rescue Timeout::Error => e str = "Error timeout while connected to server (#{e.to_s}).\n" str << "Server: #{url.host}:#{url.port}" return CloudClient::Error.new(str,"504") end if res.is_a?(Net::HTTPSuccess) res else CloudClient::Error.new(res.body, res.code) end end # ######################################################################### # The Error Class represents a generic error in the Cloud Client # library. It contains a readable representation of the error. # ######################################################################### class Error attr_reader :message attr_reader :code # +message+ a description of the error def initialize(message=nil, code="500") @message=message @code=code end def to_s() @message end end # ######################################################################### # Returns true if the object returned by a method of the OpenNebula # library is an Error # ######################################################################### def self.is_error?(value) value.class==CloudClient::Error end end # Command line help functions module CloudCLI def print_xml(xml_text) begin doc = REXML::Document.new(xml_text) rescue REXML::ParseException => e return e.message, -1 end xml = doc.root if xml.nil? return xml_text, -1 end str = String.new if REXML_FORMATTERS formatter = REXML::Formatters::Pretty.new formatter.compact = true formatter.write(xml,str) else str = xml.to_s end return str, 0 end # Returns the command name def cmd_name File.basename($0) end def version_text version=<, -K The username of the user --secret-key , -S The password of the user --url , -U Set url as the web service url to use --type , -t OpenNebula template in which is based this instance --user-data, -d Specifies Base64-encoded MIME user data to be made available to the instance --headers, -H Display column headers IMAGE-ID: The image identification as returned by the econe-upload command EOT require 'econe/EC2QueryClient' require 'CloudClient' require 'getoptlong' include CloudCLI opts = GetoptLong.new( ['--help', '-h',GetoptLong::NO_ARGUMENT], ['--version', '-v',GetoptLong::NO_ARGUMENT], ['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT], ['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT], ['--url', '-U',GetoptLong::REQUIRED_ARGUMENT], ['--type', '-t',GetoptLong::REQUIRED_ARGUMENT], ['--user-data', '-d',GetoptLong::REQUIRED_ARGUMENT], ['--headers', '-H',GetoptLong::NO_ARGUMENT] ) headers = false url = nil access = nil secret = nil auth = nil type = nil user_data = nil begin opts.each do |opt, arg| case opt when '--help' puts COMMANDS_HELP return when '--version' puts CloudCLI.version_text exit 0 when '--access-key' access = arg when '--secret-key' secret = arg when '--url' url = arg when '--type' type = arg when '--headers' headers = true when '--user-data' user_data = arg end end rescue Exception => e exit -1 end image_id = ARGV.shift if !image_id puts "#{cmd_name}: missing IMAGE-ID parameter" exit -1 end if !type type = "m1.small" end auth = "#{access}:#{secret}" if secret && access begin ec2_client = EC2QueryClient::Client.new(auth,url) rescue Exception => e puts "#{cmd_name}: #{e.message}" exit -1 end rc = ec2_client.run_instances(image_id,type, user_data) if CloudClient::is_error?(rc) puts "#{cmd_name}: #{rc.message}" exit -1 end images = rc['instancesSet']['item'] fmt = "%-12s %-13s %-14s %s" if headers puts fmt % ["Owner", "ImageId", "InstanceId", "InstanceType"] puts "------------------------------------------------------------------------------" end images.each { |img| puts fmt % [rc['ownerId'],img['imageId'],img['instanceId'],img['instanceType']] } exit 0 opennebula-3.4.1/src/cloud/ec2/bin/econe-describe-instances0000755000175000017500000000731211750754334023457 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 $: << RUBY_LIB_LOCATION+"/cloud" COMMANDS_HELP=<<-EOT econe-describe-instances List and describe running instances Usage: econe-describe-instances [OPTIONS] Options: --help, -h Show help --access-key , -K The username of the user --secret-key , -S The password of the user --url , -U Set url as the web service url to use --headers, -H Display column headers EOT require 'econe/EC2QueryClient' require 'CloudClient' require 'getoptlong' include CloudCLI opts = GetoptLong.new( ['--help', '-h',GetoptLong::NO_ARGUMENT], ['--version', '-v',GetoptLong::NO_ARGUMENT], ['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT], ['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT], ['--url', '-U',GetoptLong::REQUIRED_ARGUMENT], ['--headers', '-H',GetoptLong::NO_ARGUMENT] ) headers = false url = nil access = nil secret = nil auth = nil begin opts.each do |opt, arg| case opt when '--help' puts COMMANDS_HELP return when '--version' puts CloudCLI.version_text exit 0 when '--access-key' access = arg when '--secret-key' secret = arg when '--url' url = arg when '--headers' headers = true end end rescue Exception => e exit -1 end auth = "#{access}:#{secret}" if secret && access begin ec2_client = EC2QueryClient::Client.new(auth,url) rescue Exception => e puts "#{cmd_name}: #{e.message}" exit -1 end rc = ec2_client.describe_instances() if CloudClient::is_error?(rc) puts "#{cmd_name}: #{rc.message}" exit -1 end instances = rc['reservationSet']['item'][0]['instancesSet']['item'] owner = rc['reservationSet']['item'][0]['ownerId'] fmt = "%-10s %-11s %-13s %-11s %-15s %-10s" if headers puts fmt % ["Owner", "Id", "ImageId", "State", "IP", "Type"] puts "-----------------------------------------------------------------------------------" end if instances instances.each { |img| puts fmt % [owner, img['instanceId'],img['imageId'],img['instanceState']['name'],img['dnsName'],img['instanceType']] } end exit 0 opennebula-3.4.1/src/cloud/ec2/bin/econe-register0000755000175000017500000000667111750754334021545 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 $: << RUBY_LIB_LOCATION+"/cloud" COMMANDS_HELP=<<-EOT econe-register Register a previously uploaded image for use with an OpenNebula Cloud. Usage: econe-register [OPTIONS] IMAGE-ID Options: --help, -h Show help --access-key , -K The username of the user --secret-key , -S The password of the user --url , -U Set url as the web service url to use --headers, -H Display column headers IMAGE-ID: The image identification as returned by the econe-upload command EOT require 'econe/EC2QueryClient' require 'CloudClient' require 'getoptlong' include CloudCLI opts = GetoptLong.new( ['--help', '-h',GetoptLong::NO_ARGUMENT], ['--version', '-v',GetoptLong::NO_ARGUMENT], ['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT], ['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT], ['--url', '-U',GetoptLong::REQUIRED_ARGUMENT], ['--headers', '-H',GetoptLong::NO_ARGUMENT] ) headers = false url = nil access = nil secret = nil auth = nil begin opts.each do |opt, arg| case opt when '--help' puts COMMANDS_HELP return when '--version' puts CloudCLI.version_text exit 0 when '--access-key' access = arg when '--secret-key' secret = arg when '--url' url = arg when '--headers' headers = true end end rescue Exception => e exit -1 end image_id = ARGV.shift if !image_id puts "#{cmd_name}: missing ImageId parameter" exit -1 end auth = "#{access}:#{secret}" if secret && access begin ec2_client = EC2QueryClient::Client.new(auth,url) rescue Exception => e puts "#{cmd_name}: #{e.message}" exit -1 end rc = ec2_client.register_image(image_id) if CloudClient::is_error?(rc) puts "#{cmd_name}: #{rc.message}" exit -1 end puts "Success: ImageId #{rc['imageId']}" exit 0 opennebula-3.4.1/src/cloud/ec2/bin/econe-describe-addresses0000755000175000017500000000677211750754334023456 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 $: << RUBY_LIB_LOCATION+"/cloud" COMMANDS_HELP=<<-EOT econe-describe-images List elastic IP addresses Usage: econe-describe-addresses [OPTIONS] Options: --help, -h Show help --access-key , -K The username of the user --secret-key , -S The password of the user --url , -U Set url as the web service url to use --headers, -H Display column headers EOT require 'econe/EC2QueryClient' require 'CloudClient' require 'getoptlong' include CloudCLI opts = GetoptLong.new( ['--help', '-h',GetoptLong::NO_ARGUMENT], ['--version', '-v',GetoptLong::NO_ARGUMENT], ['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT], ['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT], ['--url', '-U',GetoptLong::REQUIRED_ARGUMENT], ['--headers', '-H',GetoptLong::NO_ARGUMENT] ) headers = false url = nil access = nil secret = nil auth = nil begin opts.each do |opt, arg| case opt when '--help' puts COMMANDS_HELP return when '--version' puts CloudCLI.version_text exit 0 when '--access-key' access = arg when '--secret-key' secret = arg when '--url' url = arg when '--headers' headers = true end end rescue Exception => e exit -1 end auth = "#{access}:#{secret}" if secret && access begin ec2_client = EC2QueryClient::Client.new(auth,url) rescue Exception => e puts "#{cmd_name}: #{e.message}" exit -1 end rc = ec2_client.describe_addresses if CloudClient::is_error?(rc) puts "#{cmd_name}: #{rc.message}" exit -1 end addresses = rc['addressesSet']['item'] fmt = "%-12s %s" if headers puts fmt % ["publicIP", "instanceId"] puts "------------------------------------------------------------------------------" end if addresses addresses.each { |addr| puts fmt % [addr['publicIP'],addr['instanceID']] } end exit 0 opennebula-3.4.1/src/cloud/ec2/bin/econe-terminate-instances0000755000175000017500000000664011750754334023672 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 $: << RUBY_LIB_LOCATION+"/cloud" COMMANDS_HELP=<<-EOT econe-terminate-instances Terminate the selected running instance Usage: econe-register [OPTIONS] INSTANCE-ID Options: --help, -h Show help --access-key , -K The username of the user --secret-key , -S The password of the user --url , -U Set url as the web service url to use INSTANCE-ID: The instance identification as returned by the econe-run-instances command EOT require 'econe/EC2QueryClient' require 'CloudClient' require 'getoptlong' include CloudCLI opts = GetoptLong.new( ['--help', '-h',GetoptLong::NO_ARGUMENT], ['--version', '-v',GetoptLong::NO_ARGUMENT], ['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT], ['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT], ['--url', '-U',GetoptLong::REQUIRED_ARGUMENT] ) url = nil access = nil secret = nil auth = nil begin opts.each do |opt, arg| case opt when '--help' puts COMMANDS_HELP return when '--version' puts CloudCLI.version_text exit 0 when '--access-key' access = arg when '--secret-key' secret = arg when '--url' url = arg when '--headers' headers = true end end rescue Exception => e exit -1 end instance = ARGV.shift if !instance puts "#{cmd_name}: missing INSTANCE-ID parameter" exit -1 end auth = "#{access}:#{secret}" if secret && access begin ec2_client = EC2QueryClient::Client.new(auth,url) rescue Exception => e puts "#{cmd_name}: #{e.message}" exit -1 end rc = ec2_client.terminate_instances(instance) if CloudClient::is_error?(rc) puts "#{cmd_name}: #{rc.message}" exit -1 end result = rc['instancesSet']['item'][0] puts "Success: Terminating #{result['instanceId']} in #{result['previousState']['name']} state" exit 0 opennebula-3.4.1/src/cloud/ec2/bin/econe-associate-address0000755000175000017500000000741411750754334023313 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 $: << RUBY_LIB_LOCATION+"/cloud" COMMANDS_HELP=<<-EOT econe-associate-address Associate a publicIP of the user with a given instance Usage: econe-associate-address [OPTIONS] PUBLIC-IP INSTANCE-ID Options: --help, -h Show help --access-key , -K The username of the user --secret-key , -S The password of the user --url , -U Set url as the web service url to use --headers, -H Display column headers PUBLIC-IP: ElasticIP owned by the user. To see the list of ips use econe-describe-addresses INSTANCE-ID: Id of the instance to be associated with the ElasticIP EOT require 'econe/EC2QueryClient' require 'CloudClient' require 'getoptlong' include CloudCLI opts = GetoptLong.new( ['--help', '-h',GetoptLong::NO_ARGUMENT], ['--version', '-v',GetoptLong::NO_ARGUMENT], ['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT], ['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT], ['--url', '-U',GetoptLong::REQUIRED_ARGUMENT], ['--type', '-t',GetoptLong::REQUIRED_ARGUMENT], ['--user-data', '-d',GetoptLong::REQUIRED_ARGUMENT], ['--headers', '-H',GetoptLong::NO_ARGUMENT] ) headers = false url = nil access = nil secret = nil auth = nil begin opts.each do |opt, arg| case opt when '--help' puts COMMANDS_HELP return when '--version' puts CloudCLI.version_text exit 0 when '--access-key' access = arg when '--secret-key' secret = arg when '--url' url = arg when '--headers' headers = true end end rescue Exception => e exit -1 end public_ip = ARGV.shift instance_id = ARGV.shift if !public_ip puts "#{cmd_name}: missing publicIP parameter" exit -1 end if !instance_id puts "#{cmd_name}: missing instanceID parameter" exit -1 end auth = "#{access}:#{secret}" if secret && access begin ec2_client = EC2QueryClient::Client.new(auth,url) rescue Exception => e puts "#{cmd_name}: #{e.message}" exit -1 end rc = ec2_client.associate_address(public_ip, instance_id) if CloudClient::is_error?(rc) puts "#{cmd_name}: #{rc.message}" exit -1 end exit 0 opennebula-3.4.1/src/cloud/ec2/bin/econe-allocate-address0000755000175000017500000000655011750754334023124 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 $: << RUBY_LIB_LOCATION+"/cloud" COMMANDS_HELP=<<-EOT econe-describe-images Allocate a new elastic IP address for the user Usage: econe-allocate-address [OPTIONS] Options: --help, -h Show help --access-key , -K The username of the user --secret-key , -S The password of the user --url , -U Set url as the web service url to use --headers, -H Display column headers EOT require 'econe/EC2QueryClient' require 'CloudClient' require 'getoptlong' include CloudCLI opts = GetoptLong.new( ['--help', '-h',GetoptLong::NO_ARGUMENT], ['--version', '-v',GetoptLong::NO_ARGUMENT], ['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT], ['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT], ['--url', '-U',GetoptLong::REQUIRED_ARGUMENT], ['--headers', '-H',GetoptLong::NO_ARGUMENT] ) headers = false url = nil access = nil secret = nil auth = nil begin opts.each do |opt, arg| case opt when '--help' puts COMMANDS_HELP return when '--version' puts CloudCLI.version_text exit 0 when '--access-key' access = arg when '--secret-key' secret = arg when '--url' url = arg when '--headers' headers = true end end rescue Exception => e exit -1 end auth = "#{access}:#{secret}" if secret && access begin ec2_client = EC2QueryClient::Client.new(auth,url) rescue Exception => e puts "#{cmd_name}: #{e.message}" exit -1 end addr = ec2_client.allocate_address if CloudClient::is_error?(addr) puts "#{cmd_name}: #{addr.message}" exit -1 end if headers puts "publicIP" puts "------------------------------------------------------------------------------" end puts addr['publicIP'] exit 0 opennebula-3.4.1/src/cloud/ec2/bin/econe-upload0000755000175000017500000000703111750754334021174 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 $: << RUBY_LIB_LOCATION+"/cloud" COMMANDS_HELP=<<-EOT econe-upload Uploads an image for use with an OpenNebula Cloud. This image should be later register with econe-register using the returned ImageId Usage: econe-upload [OPTIONS] IMAGE-PATH Options: --help, -h Show help --access-key , -K The username of the user --secret-key , -S The password of the user --url , -U Set url as the web service url to use --multipart, -M Use 'multipart-post' library instead of Curb/Curl IMAGE-PATH: Path to the image to upload EOT require 'econe/EC2QueryClient' require 'CloudClient' require 'getoptlong' include CloudCLI opts = GetoptLong.new( ['--help', '-h',GetoptLong::NO_ARGUMENT], ['--version', '-v',GetoptLong::NO_ARGUMENT], ['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT], ['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT], ['--url', '-U',GetoptLong::REQUIRED_ARGUMENT], ['--multipart', '-M',GetoptLong::NO_ARGUMENT] ) url = nil access = nil secret = nil auth = nil curb = true begin opts.each do |opt, arg| case opt when '--help' puts COMMANDS_HELP return when '--version' puts CloudCLI.version_text exit 0 when '--access-key' access = arg when '--secret-key' secret = arg when '--url' url = arg when '--multipart' curb = false end end rescue Exception => e exit -1 end image = ARGV.shift if !image || !File.exists?(image) puts "#{cmd_name}: missing IMAGE-PATH parameter or file not found" exit -1 end auth = "#{access}:#{secret}" if secret && access begin ec2_client = EC2QueryClient::Client.new(auth,url) rescue Exception => e puts "#{cmd_name}: #{e.message}" exit -1 end rc = ec2_client.upload_image(image, curb) if CloudClient::is_error?(rc) puts "#{cmd_name}: #{rc.message}" exit -1 end puts "Success: ImageId #{rc['imageId']}" exit 0 opennebula-3.4.1/src/cloud/ec2/bin/econe-disassociate-address0000755000175000017500000000713011750754334024006 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 $: << RUBY_LIB_LOCATION+"/cloud" COMMANDS_HELP=<<-EOT econe-disasociate-address Disasociate a publicIP of the user currently associated with an instance Usage: econe-disasociate-address [OPTIONS] PUBLIC-IP Options: --help, -h Show help --access-key , -K The username of the user --secret-key , -S The password of the user --url , -U Set url as the web service url to use --headers, -H Display column headers PUBLIC-IP: ElasticIP owned by the user. To see the list of ips use econe-describe-addresses EOT require 'econe/EC2QueryClient' require 'CloudClient' require 'getoptlong' include CloudCLI opts = GetoptLong.new( ['--help', '-h',GetoptLong::NO_ARGUMENT], ['--version', '-v',GetoptLong::NO_ARGUMENT], ['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT], ['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT], ['--url', '-U',GetoptLong::REQUIRED_ARGUMENT], ['--type', '-t',GetoptLong::REQUIRED_ARGUMENT], ['--user-data', '-d',GetoptLong::REQUIRED_ARGUMENT], ['--headers', '-H',GetoptLong::NO_ARGUMENT] ) headers = false url = nil access = nil secret = nil auth = nil begin opts.each do |opt, arg| case opt when '--help' puts COMMANDS_HELP return when '--version' puts CloudCLI.version_text exit 0 when '--access-key' access = arg when '--secret-key' secret = arg when '--url' url = arg when '--headers' headers = true end end rescue Exception => e exit -1 end public_ip = ARGV.shift if !public_ip puts "#{cmd_name}: missing publicIP parameter" exit -1 end auth = "#{access}:#{secret}" if secret && access begin ec2_client = EC2QueryClient::Client.new(auth,url) rescue Exception => e puts "#{cmd_name}: #{e.message}" exit -1 end rc = ec2_client.disassociate_address(public_ip) if CloudClient::is_error?(rc) puts "#{cmd_name}: #{rc.message}" exit -1 end exit 0 opennebula-3.4.1/src/cloud/ec2/bin/econe-release-address0000755000175000017500000000704111750754334022754 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 $: << RUBY_LIB_LOCATION+"/cloud" COMMANDS_HELP=<<-EOT econe-release-address Release a publicIP of the user Usage: econe-release-address [OPTIONS] PUBLIC-IP Options: --help, -h Show help --access-key , -K The username of the user --secret-key , -S The password of the user --url , -U Set url as the web service url to use --headers, -H Display column headers PUBLIC-IP: ElasticIP owned by the user. To see the list of ips use econe-describe-addresses EOT require 'econe/EC2QueryClient' require 'CloudClient' require 'getoptlong' include CloudCLI opts = GetoptLong.new( ['--help', '-h',GetoptLong::NO_ARGUMENT], ['--version', '-v',GetoptLong::NO_ARGUMENT], ['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT], ['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT], ['--url', '-U',GetoptLong::REQUIRED_ARGUMENT], ['--type', '-t',GetoptLong::REQUIRED_ARGUMENT], ['--user-data', '-d',GetoptLong::REQUIRED_ARGUMENT], ['--headers', '-H',GetoptLong::NO_ARGUMENT] ) headers = false url = nil access = nil secret = nil auth = nil begin opts.each do |opt, arg| case opt when '--help' puts COMMANDS_HELP return when '--version' puts CloudCLI.version_text exit 0 when '--access-key' access = arg when '--secret-key' secret = arg when '--url' url = arg when '--headers' headers = true end end rescue Exception => e exit -1 end public_ip = ARGV.shift if !public_ip puts "#{cmd_name}: missing publicIP parameter" exit -1 end auth = "#{access}:#{secret}" if secret && access begin ec2_client = EC2QueryClient::Client.new(auth,url) rescue Exception => e puts "#{cmd_name}: #{e.message}" exit -1 end rc = ec2_client.release_address(public_ip) if CloudClient::is_error?(rc) puts "#{cmd_name}: #{rc.message}" exit -1 end exit 0 opennebula-3.4.1/src/cloud/ec2/bin/econe-describe-images0000755000175000017500000000745511750754334022745 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 $: << RUBY_LIB_LOCATION+"/cloud" COMMANDS_HELP=<<-EOT econe-describe-images List and describe previously uploaded images of a user to be used with an OpenNebula Cloud. Usage: econe-describe-images [OPTIONS] Options: --help, -h Show help --access-key , -K The username of the user --secret-key , -S The password of the user --url , -U Set url as the web service url to use --headers, -H Display column headers EOT require 'econe/EC2QueryClient' require 'CloudClient' require 'getoptlong' include CloudCLI opts = GetoptLong.new( ['--help', '-h',GetoptLong::NO_ARGUMENT], ['--version', '-v',GetoptLong::NO_ARGUMENT], ['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT], ['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT], ['--url', '-U',GetoptLong::REQUIRED_ARGUMENT], ['--headers', '-H',GetoptLong::NO_ARGUMENT] ) headers = false url = nil access = nil secret = nil auth = nil begin opts.each do |opt, arg| case opt when '--help' puts COMMANDS_HELP return when '--version' puts CloudCLI.version_text exit 0 when '--access-key' access = arg when '--secret-key' secret = arg when '--url' url = arg when '--headers' headers = true end end rescue Exception => e exit -1 end auth = "#{access}:#{secret}" if secret && access begin ec2_client = EC2QueryClient::Client.new(auth,url) rescue Exception => e puts "#{cmd_name}: #{e.message}" exit -1 end rc = ec2_client.describe_images() if CloudClient::is_error?(rc) puts "#{cmd_name}: #{rc.message}" exit -1 end images = rc['imagesSet']['item'] fmt = "%-12s %-13s %-14s %-12s %s" if headers puts fmt % ["Owner", "ImageId", "Status", "Visibility", "Location"] puts "------------------------------------------------------------------------------" end if images images.each { |img| if img['isPublic'] == 'true' visibility = "public" elsif img['isPublic'] == 'false' visibility = "private" end puts fmt % [img['imageOwnerId'],img['imageId'], img['imageState'], visibility,img['imageLocation']] } end exit 0 opennebula-3.4.1/src/cloud/ec2/bin/econe-server0000755000175000017500000000632611750754334021224 0ustar drazzibdrazzib#! /bin/sh # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # if [ -z "$ONE_LOCATION" ]; then ECONE_PID=/var/run/one/econe-server.pid ECONE_SERVER=/usr/lib/one/ruby/cloud/econe/econe-server.rb ECONE_LOCK_FILE=/var/lock/one/.econe.lock ECONE_LOG=/var/log/one/econe-server.log ECONE_LOG_ERROR=/var/log/one/econe-server.error ECONE_ETC=/etc/one/econe.conf else ECONE_PID=$ONE_LOCATION/var/econe-server.pid ECONE_SERVER=$ONE_LOCATION/lib/ruby/cloud/econe/econe-server.rb ECONE_LOCK_FILE=$ONE_LOCATION/var/.econe.lock ECONE_LOG=$ONE_LOCATION/var/econe-server.log ECONE_LOG_ERROR=$ONE_LOCATION/var/econe-server.error ECONE_ETC=$ONE_LOCATION/etc/econe.conf fi setup() { eval `grep ^IMAGE_DIR= $ECONE_ETC` export TMPDIR=$IMAGE_DIR/tmp mkdir -p $TMPDIR if [ -f $ECONE_LOCK_FILE ]; then if [ -f $ECONE_PID ]; then ONEPID=`cat $ECONE_PID` ps $ECONE_PID > /dev/null 2>&1 if [ $? -eq 0 ]; then echo "econe-server is still running (PID:$ECONE_PID). Please try 'occi-server stop' first." exit 1 fi fi echo "Stale .lock detected. Erasing it." rm $LOCK_FILE fi } start() { if [ ! -f "$ECONE_SERVER" ]; then echo "Cannot find $ECONE_SERVER." exit 1 fi # Start the econe-server daemon ruby $ECONE_SERVER >$ECONE_LOG 2>$ECONE_LOG_ERROR & LASTRC=$? LASTPID=$! if [ $LASTRC -ne 0 ]; then echo "Error executing econe-server." echo "Check $ECONE_LOG for more information" exit 1 else echo $LASTPID > $ECONE_PID fi sleep 2 ps $LASTPID > /dev/null 2>&1 if [ $? -ne 0 ]; then echo "Error executing econe-server." echo "Check $ECONE_LOG for more information" exit 1 fi echo "econe-server started" } # # Function that stops the daemon/service # stop() { if [ ! -f $ECONE_PID ]; then echo "Couldn't find econe-server process pid." exit 1 fi # Kill the econe-server daemon kill -INT `cat $ECONE_PID` > /dev/null 2>&1 # Remove pid files rm -f $ECONE_PID > /dev/null 2>&1 echo "econe-server stopped" } case "$1" in start) setup start ;; stop) stop ;; *) echo "Usage: econe-server {start|stop}" >&2 exit 3 ;; esac opennebula-3.4.1/src/cloud/ec2/etc/0000755000175000017500000000000011750754334016675 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/ec2/etc/econe.conf0000644000175000017500000000632711750754334020645 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # ############################################################# # Server Configuration ############################################################# # OpenNebula sever contact information :one_xmlrpc: http://localhost:2633/RPC2 # Host and port where econe server will run :server: localhost :port: 4567 # SSL proxy that serves the API (set if is being used) #:ssl_server: fqdm.of.the.server ############################################################# # Auth ############################################################# # Authentication driver for incomming requests # - ec2, default Acess key and Secret key scheme # - x509, for x509 certificates based authentication :auth: ec2 # Authentication driver to communicate with OpenNebula core # - cipher, for symmetric cipher encryption of tokens # - x509, for x509 certificate encryption of tokens :core_auth: cipher ############################################################# # Log ############################################################# # Log debug level # 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG :debug_level: 3 ############################################################# # Resources ############################################################# # Cluster associated with the EC2 resources, by default no Cluster is defined #:cluster_id: # Datastore in which the Images uploaded through EC2 will be allocated, by # default 1 #:datastore_id: # VM types allowed and its template file (inside templates directory) :instance_types: :m1.small: :template: m1.small.erb ############################################################# # Elastic IP ############################################################# # VirtualNetwork containing the elastic ips to be used with EC2. If no defined # the Elastic IP functionality is disabled #:elasticips_vnet_id: # Script to associate a public IP with a private IP # - arguments: elastic_ip private_ip vnet_template(base64_encoded) :associate_script: /usr/bin/false # Script to disassociate a public IP # - arguments: elastic_ip :disassociate_script: /usr/bin/false opennebula-3.4.1/src/cloud/ec2/etc/templates/0000755000175000017500000000000011750754334020673 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/ec2/etc/templates/m1.small.erb0000644000175000017500000000124211750754334023010 0ustar drazzibdrazzib NAME = eco-vm #Adjust Capacity for this instance type CPU = 0.2 MEMORY = 256 # Put here specific OS configurations for the cloud hypervisors #OS = [ kernel = /vmlinuz, # initrd = /initrd.img, # root = sda1, # kernel_cmd = "ro xencons=tty console=tty1"] DISK = [ IMAGE_ID = <%= erb_vm_info[:img_id] %> ] # Put here the ID of the VNET with the IPs for the EC2 VMs NIC=[NETWORK_ID=] IMAGE_ID = <%= erb_vm_info[:ec2_img_id] %> INSTANCE_TYPE = <%= erb_vm_info[:instance_type ]%> <% if erb_vm_info[:user_data] %> CONTEXT = [ EC2_USER_DATA="<%= erb_vm_info[:user_data] %>", TARGET="hdc" ] <% end %> opennebula-3.4.1/src/cloud/ec2/lib/0000755000175000017500000000000011750754334016670 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/ec2/lib/econe-server.rb0000644000175000017500000001572211750754334021621 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # ############################################################################## # Environment Configuration for the Cloud Server ############################################################################## ONE_LOCATION=ENV["ONE_LOCATION"] if !ONE_LOCATION LOG_LOCATION = "/var/log/one" VAR_LOCATION = "/var/lib/one" ETC_LOCATION = "/etc/one" RUBY_LIB_LOCATION = "/usr/lib/one/ruby" else VAR_LOCATION = ONE_LOCATION + "/var" LOG_LOCATION = ONE_LOCATION + "/var" ETC_LOCATION = ONE_LOCATION + "/etc" RUBY_LIB_LOCATION = ONE_LOCATION+"/lib/ruby" end EC2_AUTH = VAR_LOCATION + "/.one/ec2_auth" EC2_LOG = LOG_LOCATION + "/econe-server.log" CONFIGURATION_FILE = ETC_LOCATION + "/econe.conf" TEMPLATE_LOCATION = ETC_LOCATION + "/ec2query_templates" VIEWS_LOCATION = RUBY_LIB_LOCATION + "/cloud/econe/views" $: << RUBY_LIB_LOCATION $: << RUBY_LIB_LOCATION+"/cloud" $: << RUBY_LIB_LOCATION+"/cloud/econe" ############################################################################### # Libraries ############################################################################### require 'rubygems' require 'sinatra' require 'yaml' require 'uri' require 'EC2QueryServer' require 'CloudAuth' include OpenNebula ############################################################################## # Parse Configuration file ############################################################################## begin conf = YAML.load_file(CONFIGURATION_FILE) rescue Exception => e STDERR.puts "Error parsing config file #{CONFIGURATION_FILE}: #{e.message}" exit 1 end conf[:template_location] = TEMPLATE_LOCATION conf[:views] = VIEWS_LOCATION conf[:debug_level] ||= 3 CloudServer.print_configuration(conf) ############################################################################## # Sinatra Configuration ############################################################################## set :config, conf include CloudLogger enable_logging EC2_LOG, settings.config[:debug_level].to_i if CloudServer.is_port_open?(settings.config[:server], settings.config[:port]) settings.logger.error { "Port #{settings.config[:port]} busy, please shutdown " << "the service or move occi server port." } exit -1 end set :bind, settings.config[:server] set :port, settings.config[:port] begin ENV["ONE_CIPHER_AUTH"] = EC2_AUTH cloud_auth = CloudAuth.new(settings.config, settings.logger) rescue => e settings.logger.error {"Error initializing authentication system"} settings.logger.error {e.message} exit -1 end set :cloud_auth, cloud_auth if conf[:ssl_server] uri = URI.parse(conf[:ssl_server]) econe_host = uri.host econe_port = uri.port econe_path = uri.path else econe_host = conf[:server] econe_port = conf[:port] econe_path = '/' end set :econe_host, econe_host set :econe_port, econe_port set :econe_path, econe_path ############################################################################## # Actions ############################################################################## before do begin params['econe_host'] = settings.econe_host params['econe_port'] = settings.econe_port params['econe_path'] = settings.econe_path username = settings.cloud_auth.auth(request.env, params) rescue Exception => e logger.error {e.message} error 500, error_xml("AuthFailure", 0) end if username.nil? error 401, error_xml("AuthFailure", 0) else client = settings.cloud_auth.client(username) oneadmin_client = settings.cloud_auth.client @econe_server = EC2QueryServer.new(client, oneadmin_client, settings.config, settings.logger) end end helpers do def error_xml(code,id) message = '' case code when 'AuthFailure' message = 'User not authorized' when 'InvalidAMIID.NotFound' message = 'Specified AMI ID does not exist' when 'Unsupported' message = 'The instance type or feature is not supported in your requested Availability Zone.' else message = code end xml = ""+ code + "" + message + "" + id.to_s + "" return xml end end post '/' do do_http_request(params) end get '/' do do_http_request(params) end def do_http_request(params) case params['Action'] when 'UploadImage' result,rc = @econe_server.upload_image(params) when 'RegisterImage' result,rc = @econe_server.register_image(params) when 'DescribeImages' result,rc = @econe_server.describe_images(params) when 'RunInstances' result,rc = @econe_server.run_instances(params) when 'DescribeInstances' result,rc = @econe_server.describe_instances(params) when 'TerminateInstances' result,rc = @econe_server.terminate_instances(params) when 'AllocateAddress' result,rc = @econe_server.allocate_address(params) when 'AssociateAddress' result,rc = @econe_server.associate_address(params) when 'DisassociateAddress' result,rc = @econe_server.disassociate_address(params) when 'ReleaseAddress' result,rc = @econe_server.release_address(params) when 'DescribeAddresses' result,rc = @econe_server.describe_addresses(params) end if OpenNebula::is_error?(result) logger.error(result.message) error rc, error_xml(result.message, 0) end headers['Content-Type'] = 'application/xml' result end opennebula-3.4.1/src/cloud/ec2/lib/elastic_ip.rb0000644000175000017500000001502311750754334021332 0ustar drazzibdrazzibmodule ElasticIP def allocate_address(params) # Get public IP vnet = retrieve_eip_vnet return vnet, 400 if OpenNebula::is_error?(vnet) ips = vnet.retrieve_elements('LEASES/LEASE[USED=0]/IP') if ips.nil? logger.error { "There is no lease available to be allocated" } return OpenNebula::Error.new('AddressLimitExceeded'), 400 end eip = ips.first # Hold IP rc = vnet.hold(eip) if OpenNebula::is_error?(rc) logger.error rc.message return OpenNebula::Error.new('Unsupported'),400 end # Update EC2_ADDRESSES list xml_hash = {'EC2_ADDRESSES' => {'IP' => eip, "UID" => retrieve_uid}} vnet.add_element('TEMPLATE', xml_hash) rc = vnet.update if OpenNebula::is_error?(rc) logger.error rc.message return OpenNebula::Error.new('Unsupported'),400 end response = ERB.new(File.read(@config[:views]+"/allocate_address.erb")) return response.result(binding), 200 end def release_address(params) # Check public IP vnet = retrieve_eip_vnet return vnet, 400 if OpenNebula::is_error?(vnet) eip = params["PublicIp"] unless vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\" and UID=\"#{retrieve_uid}\"]/IP"] logger.error { "address:#{eip} does not exist" } return OpenNebula::Error.new('Unsupported'),400 end # Disassociate address if needed if vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\"]/VMID"] cmd_output = `#{@config[:disassociate_script]} #{eip}` if $?.to_i != 0 logger.error { cmd_output } return OpenNebula::Error.new('Unsupported'),400 end vnet.delete_element("TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\"]/VMID") end # Release IP rc = vnet.release(eip) if OpenNebula::is_error?(rc) logger.error {rc.message} return OpenNebula::Error.new('Unsupported'),400 end # Update EC2_ADDRESSES list vnet.delete_element("TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\"]") rc = vnet.update if OpenNebula::is_error?(rc) logger.error {rc.message} return OpenNebula::Error.new('Unsupported'),400 end response = ERB.new(File.read(@config[:views]+"/release_address.erb")) return response.result(binding), 200 end def describe_addresses(params) vnet = retrieve_eip_vnet return vnet, 400 if OpenNebula::is_error?(vnet) erb_version = params['Version'] user_id = retrieve_uid response = ERB.new(File.read(@config[:views]+"/describe_addresses.erb")) return response.result(binding), 200 end def associate_address(params) # Check public IP vnet = retrieve_eip_vnet return vnet, 400 if OpenNebula::is_error?(vnet) user_id = retrieve_uid eip = params["PublicIp"] vmid = params['InstanceId'] vmid = vmid.split('-')[1] if vmid[0]==?i unless vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\" and UID=\"#{retrieve_uid}\"]/IP"] logger.error { "address:#{eip} does not exist" } return OpenNebula::Error.new('Unsupported'),400 end # Get private IP of the Instance vm = VirtualMachine.new(VirtualMachine.build_xml(vmid), @client) rc = vm.info if OpenNebula::is_error?(rc) logger.error {rc.message} return OpenNebula::Error.new('Unsupported'),400 end ips = vm.retrieve_elements('TEMPLATE/NIC/IP') if ips.nil? logger.error { "The instance does not have any NIC" } return OpenNebula::Error.new('Unsupported'),400 end private_ip = ips.first # Disassociate address if needed if vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\"]/VMID"] cmd_output = `#{@config[:disassociate_script]} #{eip}` if $?.to_i != 0 logger.error { cmd_output } return OpenNebula::Error.new('Unsupported'),400 end vnet.delete_element("TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\"]/VMID") end # Run external script vnet_base64 = Base64.encode64(vnet.to_xml).delete("\n") cmd_output = `#{@config[:associate_script]} #{eip} #{private_ip} \"#{vnet_base64}\"` if $?.to_i != 0 logger.error { "associate_script" << cmd_output } return OpenNebula::Error.new('Unsupported'),400 end # Update EC2_ADDRESSES list vnet.add_element("TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\"]", "VMID" => vmid) rc = vnet.update if OpenNebula::is_error?(rc) logger.error {rc.message} return OpenNebula::Error.new('Unsupported'),400 end response = ERB.new(File.read(@config[:views]+"/associate_address.erb")) return response.result(binding), 200 end def disassociate_address(params) # Check public IP vnet = retrieve_eip_vnet return vnet, 400 if OpenNebula::is_error?(vnet) eip = params["PublicIp"] unless vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\" and UID=\"#{retrieve_uid}\"]/VMID"] logger.error { "address:#{eip} does not exist or is not associated with any instance" } return OpenNebula::Error.new('Unsupported'),400 end # Run external script cmd_output = `#{@config[:disassociate_script]} #{eip}` if $?.to_i != 0 logger.error { cmd_output } return OpenNebula::Error.new('Unsupported'),400 end # Update EC2_ADDRESSES list vnet.delete_element("TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\"]/VMID") rc = vnet.update if OpenNebula::is_error?(rc) logger.error {rc.message} return OpenNebula::Error.new('Unsupported'),400 end response = ERB.new(File.read(@config[:views]+"/disassociate_address.erb")) return response.result(binding), 200 end private def retrieve_eip_vnet vnet = VirtualNetwork.new(VirtualNetwork.build_xml(@config[:elasticips_vnet_id]),@oneadmin_client) rc = vnet.info if OpenNebula::is_error?(rc) logger.error {rc.message} return OpenNebula::Error.new('Unsupported') end vnet end def retrieve_uid user = User.new_with_id(OpenNebula::User::SELF, @client) user.info user.id end endopennebula-3.4.1/src/cloud/ec2/lib/EC2QueryServer.rb0000644000175000017500000002075011750754334022007 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 'rubygems' require 'erb' require 'time' require 'AWS' require 'base64' require 'CloudServer' require 'ImageEC2' ############################################################################### # The EC2Query Server implements a EC2 compatible server based on the # OpenNebula Engine ############################################################################### class EC2QueryServer < CloudServer ########################################################################### # Class Constants. Defined the EC2 and OpenNebula State mapping ########################################################################### EC2_STATES={ :pending => {:code => 0, :name => 'pending'}, :running => {:code => 16,:name => 'running'}, :shutdown => {:code => 32,:name => 'shutting-down'}, :terminated => {:code => 48,:name => 'terminated'} } ONE_STATES={ 'init' => :pending, 'pend' => :pending, 'hold' => :pending, 'stop' => :pending, 'susp' => :pending, 'done' => :terminated, 'fail' => :terminated, 'prol' => :pending, 'boot' => :running, 'runn' => :running, 'migr' => :running, 'save' => :pending, 'epil' => :shutdown, 'shut' => :shutdown, 'clea' => :shutdown, 'fail' => :terminated, 'unkn' => :terminated } ########################################################################### def initialize(client, oneadmin_client, config, logger) super(config, logger) @client = client @oneadmin_client = oneadmin_client if @config[:elasticips_vnet_id].nil? logger.error { 'ElasticIP module not loaded' } else require 'elastic_ip' extend ElasticIP end end ########################################################################### # Repository Interface ########################################################################### def upload_image(params) image = ImageEC2.new(Image.build_xml, @client, params['file']) template = image.to_one_template if OpenNebula.is_error?(template) return OpenNebula::Error.new('Unsupported'), 400 end rc = image.allocate(template, @config[:datastore_id]||1) if OpenNebula.is_error?(rc) return OpenNebula::Error.new('Unsupported'), 400 end erb_version = params['Version'] response = ERB.new(File.read(@config[:views]+"/register_image.erb")) return response.result(binding), 200 end def register_image(params) # Get the Image ID tmp, img=params['ImageLocation'].split('-') image = Image.new(Image.build_xml(img.to_i), @client) # Enable the new Image rc = image.info if OpenNebula.is_error?(rc) return OpenNebula::Error.new('InvalidAMIID.NotFound'), 400 end image.enable erb_version = params['Version'] response = ERB.new(File.read(@config[:views]+"/register_image.erb")) return response.result(binding), 200 end def describe_images(params) user_flag = OpenNebula::Pool::INFO_ALL impool = ImagePool.new(@client, user_flag) impool.info erb_version = params['Version'] response = ERB.new(File.read(@config[:views]+"/describe_images.erb")) return response.result(binding), 200 end ########################################################################### # Instance Interface ########################################################################### def run_instances(params) # Get the instance type and path if params['InstanceType'] != nil instance_type_name = params['InstanceType'] instance_type = @config[:instance_types][instance_type_name.to_sym] if instance_type != nil path = @config[:template_location] + "/#{instance_type[:template]}" end end # Get the image tmp, img=params['ImageId'].split('-') # Build the VM erb_vm_info=Hash.new erb_vm_info[:img_id] = img.to_i erb_vm_info[:ec2_img_id] = params['ImageId'] erb_vm_info[:instance_type] = instance_type_name erb_vm_info[:template] = path erb_vm_info[:user_data] = params['UserData'] template = ERB.new(File.read(erb_vm_info[:template])) template_text = template.result(binding) # Start the VM. vm = VirtualMachine.new(VirtualMachine.build_xml, @client) rc = vm.allocate(template_text) if OpenNebula::is_error?(rc) return OpenNebula::Error.new('Unsupported'),400 end vm.info erb_vm_info[:vm_id]=vm.id erb_vm_info[:vm]=vm erb_user_name = params['AWSAccessKeyId'] erb_version = params['Version'] response = ERB.new(File.read(@config[:views]+"/run_instances.erb")) return response.result(binding), 200 end def describe_instances(params) user_flag = OpenNebula::Pool::INFO_ALL vmpool = VirtualMachinePool.new(@client, user_flag) vmpool.info erb_version = params['Version'] erb_user_name = params['AWSAccessKeyId'] response = ERB.new(File.read(@config[:views]+"/describe_instances.erb")) return response.result(binding), 200 end def terminate_instances(params) # Get the VM ID vmid=params['InstanceId.1'] vmid=params['InstanceId.01'] if !vmid tmp, vmid=vmid.split('-') if vmid[0]==?i vm = VirtualMachine.new(VirtualMachine.build_xml(vmid),@client) rc = vm.info return OpenNebula::Error.new('Unsupported'),400 if OpenNebula::is_error?(rc) if vm.status == 'runn' rc = vm.shutdown else rc = vm.finalize end return OpenNebula::Error.new('Unsupported'),400 if OpenNebula::is_error?(rc) erb_version = params['Version'] response =ERB.new(File.read(@config[:views]+"/terminate_instances.erb")) return response.result(binding), 200 end ########################################################################### # Elastic IP ########################################################################### def allocate_address(params) return OpenNebula::Error.new('Unsupported'),400 end def release_address(params) return OpenNebula::Error.new('Unsupported'),400 end def describe_addresses(params) return OpenNebula::Error.new('Unsupported'),400 end def associate_address(params) return OpenNebula::Error.new('Unsupported'),400 end def disassociate_address(params) return OpenNebula::Error.new('Unsupported'),400 end ########################################################################### # Helper functions ########################################################################### private def render_state(vm) one_state = ONE_STATES[vm.status] ec2_state = EC2_STATES[one_state||:pending] return "#{ec2_state[:code]} #{ec2_state[:name]}" end def render_launch_time(vm) return "#{Time.at(vm["STIME"].to_i).xmlschema}" end end opennebula-3.4.1/src/cloud/ec2/lib/ImageEC2.rb0000644000175000017500000000346511750754334020541 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 'uuidtools' require 'OpenNebula' include OpenNebula 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 = UUIDTools::UUID.random_create.to_s one = ERB.new(ONE_IMAGE) return one.result(binding) end end opennebula-3.4.1/src/cloud/ec2/lib/EC2QueryClient.rb0000644000175000017500000002572211750754334021763 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # $ec2url = nil if ENV["EC2_URL"] $ec2url = ENV["EC2_URL"] ENV["EC2_URL"]=nil end require 'CloudClient' require 'AWS' module EC2QueryClient ########################################################################## # # ########################################################################## class Client API_VERSION = '2008-12-01' ###################################################################### # # ###################################################################### def initialize(secret=nil, endpoint=nil, timeout=nil) # Autentication ec2auth = nil @timeout = nil if secret ec2auth = secret.split(':') elsif ENV["EC2_ACCESS_KEY"] and ENV["EC2_SECRET_KEY"] ec2auth = [ENV["EC2_ACCESS_KEY"], ENV["EC2_SECRET_KEY"]] else ec2auth = CloudClient::get_one_auth ec2auth[1] = Digest::SHA1.hexdigest(ec2auth[1]) end if !ec2auth raise "No authorization data present" end @access_key_id = ec2auth[0] @access_key_secret = ec2auth[1] # Server location if !endpoint if $ec2url endpoint = $ec2url else endpoint = "http://localhost:4567" end end @uri = URI.parse(endpoint) path = @uri.path.empty? ? '/' : @uri.path @ec2_connection = AWS::EC2::Base.new( :access_key_id => @access_key_id, :secret_access_key => @access_key_secret, :server => @uri.host, :port => @uri.port, :use_ssl => @uri.scheme == 'https', :path => path) end ###################################################################### # # ###################################################################### def describe_instances() begin response = @ec2_connection.describe_instances rescue Exception => e error = CloudClient::Error.new(e.message) return error end return response end ###################################################################### # :image_id # :instance_type ###################################################################### def run_instances(ami_id, type, user_data=nil) begin response = @ec2_connection.run_instances( :image_id => ami_id, :min_count => 1, :max_count => 1, :instance_type => type, :user_data => user_data, :base64_encoded => true ) rescue Exception => e error = CloudClient::Error.new(e.message) return error end return response end ###################################################################### # # ###################################################################### def terminate_instances(instance_id) begin response = @ec2_connection.terminate_instances( :instance_id => instance_id ) rescue Exception => e error = CloudClient::Error.new(e.message) return error end return response end ###################################################################### # # Returns true if HTTP code is 200, ###################################################################### def upload_image(file_name, curb=true) params = { "Action" => "UploadImage", "SignatureVersion" => "2", "SignatureMethod" => 'HmacSHA256', "AWSAccessKeyId" => @access_key_id, "Version" => API_VERSION, "Timestamp" => Time.now.getutc.iso8601 } str = AWS.canonical_string(params, @uri.host) sig = AWS.encode(@access_key_secret, str, false) post_fields = Array.new; if curb if !CURL_LOADED error_msg = "curb gem not loaded" error = CloudClient::Error.new(error_msg) return error end params.each { |k,v| post_fields << Curl::PostField.content(k,v) } post_fields << Curl::PostField.content("Signature",sig) post_fields << Curl::PostField.file("file",file_name) connection = Curl::Easy.new(@uri.to_s) connection.multipart_form_post = true connection.http_post(*post_fields) if connection.response_code == 200 return AWS::Response.parse(:xml => connection.body_str) else return CloudClient::Error.new(connection.body_str) end else if !MULTIPART_LOADED error_msg = "multipart-post gem not loaded" error = CloudClient::Error.new(error_msg) return error end params["Signature"]=sig file=File.open(file_name) params["file"]=UploadIO.new(file, 'application/octet-stream', file_name) req = Net::HTTP::Post::Multipart.new('/', params) res = CloudClient.http_start(@uri,@timeout) do |http| http.request(req) end file.close if res.code == '200' return AWS::Response.parse(:xml => res.body) else return CloudClient::Error.new(res.body) end end end ###################################################################### # # ###################################################################### def register_image(image_id) begin response = @ec2_connection.register_image( :image_location => image_id ) rescue Exception => e error = CloudClient::Error.new(e.message) return error end return response end ###################################################################### # :image_id --> ALL # :owner_id --> mine (ALWAYS) # :executable_by --> Always Public (NO ACLS) ###################################################################### def describe_images() begin response = @ec2_connection.describe_images rescue Exception => e error = CloudClient::Error.new(e.message) return error end return response end ###################################################################### ###################################################################### def describe_addresses() begin response = @ec2_connection.describe_addresses rescue Exception => e error = CloudClient::Error.new(e.message) return error end return response end ###################################################################### ###################################################################### def allocate_address() begin response = @ec2_connection.allocate_address rescue Exception => e error = CloudClient::Error.new(e.message) return error end return response end ###################################################################### ###################################################################### def associate_address(public_ip, instance_id) begin response = @ec2_connection.associate_address( :public_ip => public_ip, :instance_id => instance_id) rescue Exception => e error = CloudClient::Error.new(e.message) return error end return response end ###################################################################### ###################################################################### def disassociate_address(public_ip) begin response = @ec2_connection.disassociate_address( :public_ip => public_ip) rescue Exception => e error = CloudClient::Error.new(e.message) return error end return response end ###################################################################### ###################################################################### def release_address(public_ip) begin response = @ec2_connection.release_address( :public_ip => public_ip) rescue Exception => e error = CloudClient::Error.new(e.message) return error end return response end end end opennebula-3.4.1/src/cloud/ec2/lib/views/0000755000175000017500000000000011750754334020025 5ustar drazzibdrazzibopennebula-3.4.1/src/cloud/ec2/lib/views/describe_images.erb0000644000175000017500000000155611750754334023633 0ustar drazzibdrazzib <% impool.each do |im| %> ami-<%= sprintf('%08i', im.id) %> <%= im['SOURCE'].split('/').last %> <% if im['STATE'] == '3' || im['STATE'] == '5' %> failed <% elsif im['STATE'] == '1' || im['STATE'] == '2' %> available <% elsif im['STATE'] == '4'%> pending <% end %> <%= im['UNAME'] %> <% if im['PUBLIC'] == '0' %> false <% elsif im['PUBLIC'] == '1' %> true <% end %> i386 machine <% end %> opennebula-3.4.1/src/cloud/ec2/lib/views/describe_instances.erb0000644000175000017500000000264311750754334024353 0ustar drazzibdrazzib 4ac62eaf-e266-4058-a970-2c01568cd417 default <%= erb_user_name %> default <% vmpool.each do |vm| %> i-<%= vm.id %> <%= vm['TEMPLATE/IMAGE_ID'] %> <%= render_state(vm) %> <%= vm["TEMPLATE/NIC/IP"] %> <%= vm["TEMPLATE/NIC/IP"] %> default 0 <%= vm['TEMPLATE/INSTANCE_TYPE'] %> <%= render_launch_time(vm) %> default eki-EA801065 eri-1FEE1144 false <% end %> opennebula-3.4.1/src/cloud/ec2/lib/views/disassociate_address.erb0000644000175000017500000000033711750754334024702 0ustar drazzibdrazzib 4ac62eaf-e266-4058-a970-2c01568cd417 true opennebula-3.4.1/src/cloud/ec2/lib/views/describe_addresses.erb0000644000175000017500000000135611750754334024341 0ustar drazzibdrazzib 4ac62eaf-e266-4058-a970-2c01568cd417 <% vnet.each("LEASES/LEASE[USED=1 and VID=-1]") do |eip| %> <% if vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip["IP"]}\"]/UID"] == user_id.to_s %> <%= eip["IP"] %> standard <% if vm_id = vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip["IP"]}\"]/VMID"] %> <%= vm_id %> <% else %> <% end %> <% end %> <% end %> opennebula-3.4.1/src/cloud/ec2/lib/views/release_address.erb0000644000175000017500000000033511750754334023645 0ustar drazzibdrazzib 4ac62eaf-e266-4058-a970-2c01568cd417 true opennebula-3.4.1/src/cloud/ec2/lib/views/run_instances.erb0000644000175000017500000000206711750754334023377 0ustar drazzibdrazzib r-47a5402e <%= erb_user_name %> default i-<%= erb_vm_info[:vm_id] %> <%= erb_vm_info[:ec2_img_id] %> 0 pending <%= erb_vm_info[:vm]["TEMPLATE/NIC/IP"]%> <%= erb_vm_info[:vm]["TEMPLATE/NIC/IP"]%> default 0 <%= erb_vm_info[:instance_type] %> <%= render_launch_time(erb_vm_info[:vm]) %> default true opennebula-3.4.1/src/cloud/ec2/lib/views/register_image.erb0000644000175000017500000000024611750754334023507 0ustar drazzibdrazzib ami-<%= sprintf('%08i', image.id) %> opennebula-3.4.1/src/cloud/ec2/lib/views/allocate_address.erb0000644000175000017500000000047111750754334024012 0ustar drazzibdrazzib 4ac62eaf-e266-4058-a970-2c01568cd417 <%= eip %> standard 9090909090 opennebula-3.4.1/src/cloud/ec2/lib/views/terminate_instances.erb0000644000175000017500000000063611750754334024563 0ustar drazzibdrazzib i-<%= vm.id %> 32 shutting-down <%= render_state(vm) %> opennebula-3.4.1/src/cloud/ec2/lib/views/associate_address.erb0000644000175000017500000000037411750754334024203 0ustar drazzibdrazzib 4ac62eaf-e266-4058-a970-2c01568cd417 true opennebula-3.4.1/src/image/0000755000175000017500000000000011750754334015425 5ustar drazzibdrazzibopennebula-3.4.1/src/image/ImagePool.cc0000644000175000017500000002300111750754334017604 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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. */ /* -------------------------------------------------------------------------- */ /* ************************************************************************** */ /* Image Pool */ /* ************************************************************************** */ #include "ImagePool.h" #include "AuthManager.h" #include "Nebula.h" #include "PoolObjectAuth.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ string ImagePool::_default_type; string ImagePool::_default_dev_prefix; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ ImagePool::ImagePool(SqlDB * db, const string& __default_type, const string& __default_dev_prefix, vector& restricted_attrs): PoolSQL(db, Image::table, true) { ostringstream sql; // Init static defaults _default_type = __default_type; _default_dev_prefix = __default_dev_prefix; // Set default type if (_default_type != "OS" && _default_type != "CDROM" && _default_type != "DATABLOCK" ) { NebulaLog::log("IMG", Log::ERROR, "Bad default for type, setting OS"); _default_type = "OS"; } // Set restricted attributes ImageTemplate::set_restricted_attributes(restricted_attrs); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int ImagePool::allocate ( int uid, int gid, const string& uname, const string& gname, ImageTemplate* img_template, int ds_id, const string& ds_name, const string& ds_data, int * oid, string& error_str) { Image * img; Image * img_aux = 0; string name; ostringstream oss; img = new Image(uid, gid, uname, gname, img_template); // ------------------------------------------------------------------------- // Check name & duplicates // ------------------------------------------------------------------------- img->get_template_attribute("NAME", name); if ( name.empty() ) { goto error_name; } if ( name.length() > 128 ) { goto error_name_length; } img_aux = get(name,uid,false); if( img_aux != 0 ) { goto error_duplicated; } img->ds_name = ds_name; img->ds_id = ds_id; // --------------------------------------------------------------------- // Insert the Object in the pool & Register the image in the repository // --------------------------------------------------------------------- *oid = PoolSQL::allocate(img, error_str); if ( *oid != -1 ) { Nebula& nd = Nebula::instance(); ImageManager * imagem = nd.get_imagem(); if ( imagem->register_image(*oid, ds_data) == -1 ) { error_str = "Failed to copy image to repository. " "Image left in ERROR state."; return -1; } } return *oid; error_name: oss << "NAME cannot be empty."; goto error_common; error_name_length: oss << "NAME is too long; max length is 128 chars."; goto error_common; error_duplicated: oss << "NAME is already taken by IMAGE " << img_aux->get_oid() << "."; goto error_common; error_common: delete img; *oid = -1; error_str = oss.str(); return *oid; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ static int get_disk_uid(VectorAttribute * disk, int _uid) { istringstream is; string uid_s ; string uname; int uid; if (!(uid_s = disk->vector_value("IMAGE_UID")).empty()) { is.str(uid_s); is >> uid; if( is.fail() ) { return -1; } } else if (!(uname = disk->vector_value("IMAGE_UNAME")).empty()) { User * user; Nebula& nd = Nebula::instance(); UserPool * upool = nd.get_upool(); user = upool->get(uname,true); if ( user == 0 ) { return -1; } uid = user->get_oid(); user->unlock(); } else { uid = _uid; } return uid; } /* -------------------------------------------------------------------------- */ static int get_disk_id(const string& id_s) { istringstream is; int id; is.str(id_s); is >> id; if( is.fail() ) { return -1; } return id; } /* -------------------------------------------------------------------------- */ int ImagePool::disk_attribute(VectorAttribute * disk, int disk_id, int * index, Image::ImageType * img_type, int uid, int& image_id, string& error_str) { string source; Image * img = 0; int rc = 0; int datastore_id; ostringstream oss; Nebula& nd = Nebula::instance(); ImageManager * imagem = nd.get_imagem(); if (!(source = disk->vector_value("IMAGE")).empty()) { int uiid = get_disk_uid(disk,uid); if ( uiid == -1) { error_str = "Cannot get user set in IMAGE_UID or IMAGE_UNAME."; return -1; } img = imagem->acquire_image(source, uiid, error_str); if ( img == 0 ) { return -1; } } else if (!(source = disk->vector_value("IMAGE_ID")).empty()) { int iid = get_disk_id(source); if ( iid == -1) { error_str = "Wrong ID set in IMAGE_ID"; return -1; } img = imagem->acquire_image(iid, error_str); if ( img == 0 ) { return -1; } } else //Not using the image repository { string type; rc = -2; type = disk->vector_value("TYPE"); transform(type.begin(),type.end(),type.begin(),(int(*)(int))toupper); if( type == "SWAP" ) { string target = disk->vector_value("TARGET"); if ( target.empty() ) { string dev_prefix = _default_dev_prefix; dev_prefix += "d"; disk->replace("TARGET", dev_prefix); } } } if ( img != 0 ) { DatastorePool * ds_pool = nd.get_dspool(); Datastore * ds; img->disk_attribute(disk, index, img_type); image_id = img->get_oid(); datastore_id = img->get_ds_id(); update(img); img->unlock(); ds = ds_pool->get(datastore_id, true); if ( ds == 0 ) { error_str = "Associated datastore for the image does not exist"; return -1; } ds->disk_attribute(disk); ds->unlock(); } oss << disk_id; disk->replace("DISK_ID",oss.str()); return rc; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void ImagePool::authorize_disk(VectorAttribute * disk,int uid, AuthRequest * ar) { string source; Image * img = 0; PoolObjectAuth perm; if (!(source = disk->vector_value("IMAGE")).empty()) { int uiid = get_disk_uid(disk,uid); if ( uiid == -1) { return; } img = get(source , uiid, true); } else if (!(source = disk->vector_value("IMAGE_ID")).empty()) { int iid = get_disk_id(source); if ( iid == -1) { return; } img = get(iid, true); } if (img == 0) { return; } img->get_permissions(perm); img->unlock(); ar->add_auth(AuthRequest::USE, perm); } opennebula-3.4.1/src/image/SConstruct0000644000175000017500000000273611750754334017467 0ustar drazzibdrazzib# SConstruct for src/vm # -------------------------------------------------------------------------- # # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # # a copy of the License at # # # # http://www.apache.org/licenses/LICENSE-2.0 # # # # Unless required by applicable law or agreed to in writing, software # # distributed under the License is distributed on an "AS IS" BASIS, # # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # # See the License for the specific language governing permissions and # # limitations under the License. # #--------------------------------------------------------------------------- # Import('env') lib_name='nebula_image' # Sources to generate the library source_files=[ 'Image.cc', 'ImagePool.cc', 'ImageManagerDriver.cc', 'ImageManager.cc', 'ImageManagerActions.cc', 'ImageTemplate.cc' ] # Build library env.StaticLibrary(lib_name, source_files) opennebula-3.4.1/src/image/ImageManager.cc0000644000175000017500000000761511750754334020262 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 = 0; int rc; NebulaLog::log("ImM",Log::INFO,"Loading Image Manager driver."); if ( mad_conf.size() > 0 ) { 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); } } opennebula-3.4.1/src/image/ImageManagerActions.cc0000644000175000017500000002410411750754334021573 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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" #include "SSLTools.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ Image * ImageManager::acquire_image(int image_id, string& error) { Image * img; int rc; img = ipool->get(image_id,true); if ( img == 0 ) { ostringstream oss; oss << "Image with ID: " << image_id << " does not exists"; error = oss.str(); return 0; } rc = acquire_image(img, error); if ( rc != 0 ) { img->unlock(); img = 0; } return img; } /* -------------------------------------------------------------------------- */ Image * ImageManager::acquire_image(const string& name, int uid, string& error) { Image * img; int rc; img = ipool->get(name,uid,true); if ( img == 0 ) { ostringstream oss; oss << "Image " << name << " does not exists for user " << uid; error = oss.str(); return 0; } rc = acquire_image(img, error); if ( rc != 0 ) { img->unlock(); img = 0; } return img; } /* -------------------------------------------------------------------------- */ int ImageManager::acquire_image(Image *img, string& error) { 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()) { error = "Cannot acquire persistent image, it is already in use"; rc = -1; } else { img->inc_running(); ipool->update(img); } break; case Image::DISABLED: error = "Cannot acquire image, it is disabled"; rc = -1; break; case Image::LOCKED: error = "Cannot acquire image, it is locked"; rc = -1; break; case Image::ERROR: error = "Cannot acquire image, it is in an error state"; rc = -1; break; default: rc = -1; break; } return rc; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void ImageManager::release_image(int iid, bool failed) { int rvms; Image * img; ostringstream disk_file; img = ipool->get(iid,true); if ( img == 0 ) { return; } switch (img->get_state()) { case Image::USED: rvms = img->dec_running(); if (img->isPersistent()) { if (failed == true) { img->set_state(Image::ERROR); } else { img->set_state(Image::READY); } } else if ( rvms == 0 ) { img->set_state(Image::READY); } ipool->update(img); img->unlock(); break; case Image::LOCKED: //SAVE_AS images are LOCKED till released if ( img->isSaving() ) { if (failed == true) { img->set_state(Image::ERROR); } else { img->set_state(Image::READY); } ipool->update(img); } else { NebulaLog::log("ImM",Log::ERROR, "Trying to release image in wrong state."); } img->unlock(); break; case Image::DISABLED: case Image::READY: case Image::ERROR: 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, const string& ds_data) { Image * img; string source; string img_tmpl; string * drv_msg; 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; //Cannot remove images in use } break; case Image::USED: img->unlock(); return -1; //Cannot 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 ) { img->unlock(); return -1; } drv_msg = format_message(img->to_xml(img_tmpl), ds_data); source = img->get_source(); if (source.empty()) { string err_str; int rc; rc = ipool->drop(img, err_str); if ( rc < 0 ) { NebulaLog::log("ImM",Log::ERROR, "Image could not be removed from DB"); } } else { imd->rm(img->get_oid(), *drv_msg); } img->unlock(); delete drv_msg; return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int ImageManager::register_image(int iid, const string& ds_data) { const ImageManagerDriver* imd = get(); ostringstream oss; Image * img; string path; string img_tmpl; string * drv_msg; if ( imd == 0 ) { NebulaLog::log("ImM",Log::ERROR, "Could not get datastore driver"); return -1; } img = ipool->get(iid,true); if (img == 0) { return -1; } drv_msg = format_message(img->to_xml(img_tmpl), ds_data); path = img->get_path(); if ( path.empty() == true ) //NO PATH { string source = img->get_source(); if ( img->isSaving() || img->get_type() == Image::DATABLOCK ) { imd->mkfs(img->get_oid(), *drv_msg); oss << "Creating disk at " << source << " of "<< img->get_size() << "Mb (type: " << img->get_fstype() << ")"; } else if ( !source.empty() ) //Source in Template { img->set_state(Image::READY); ipool->update(img); oss << "Using source " << source << " from template for image " << img->get_name(); } } else //PATH -> COPY TO REPOSITORY AS SOURCE { imd->cp(img->get_oid(), *drv_msg); oss << "Copying " << path <<" to repository for image "<get_oid(); } NebulaLog::log("ImM",Log::INFO,oss); img->unlock(); delete drv_msg; return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ string * ImageManager::format_message( const string& img_data, const string& ds_data) { ostringstream oss; oss << "" << img_data << ds_data << ""; return SSLTools::base64_encode(oss.str()); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ opennebula-3.4.1/src/image/ImageManagerDriver.cc0000644000175000017500000002077311750754334021436 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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& drv_msg) const { ostringstream os; os << "CP " << oid << " " << drv_msg << 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& drv_msg) const { ostringstream os; os << "MKFS " << oid << " " << drv_msg << endl; write(os); } /* -------------------------------------------------------------------------- */ void ImageManagerDriver::rm(int oid, const string& drv_msg) const { ostringstream os; os << "RM " << oid << " " << drv_msg << endl; write(os); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* ************************************************************************** */ /* MAD Interface */ /* ************************************************************************** */ void ImageManagerDriver::protocol( string& message) { istringstream is(message); ostringstream os; string action; string result; int id; Image * image; string source; unsigned int size_mb; 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_type(result[0]), info.c_str()); } return; } } else return; // Parse driver message for CP, MV and MKFS // SUCESS IMAGE_ID SOURCE SIZE if ( (result == "SUCCESS") && (action != "RM") ) { if ( is.good() ) { is >> source >> ws; } if ( is.good() ) { is >> size_mb >> ws; } if ( is.fail() ) { result = "FAILURE"; } } // 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_source(source); image->set_size(size_mb); image->set_state(Image::READY); ipool->update(image); NebulaLog::log("ImM", Log::INFO, "Image copied and ready to use."); } else { goto error_cp; } } else if ( action == "MKFS" ) { if ( result == "SUCCESS" ) { bool is_saving = image->isSaving(); string disk_id; string vm_id; int rc; image->set_source(source); if (is_saving) { image->get_template_attribute("SAVED_DISK_ID",disk_id); image->get_template_attribute("SAVED_VM_ID", vm_id); } else { image->set_size(size_mb); image->set_state(Image::READY); NebulaLog::log("ImM", Log::INFO, "Image created and ready to use"); } ipool->update(image); image->unlock(); if (is_saving) { Nebula& nd = Nebula::instance(); VirtualMachinePool * vmpool = nd.get_vmpool(); VirtualMachine * vm; istringstream iss(vm_id); int vm_id_i; iss >> vm_id_i; vm = vmpool->get(vm_id_i, true); if ( vm == 0 ) { goto error_save_no_vm; } rc = vm->save_disk(disk_id, source, id); if ( rc == -1 ) { vm->unlock(); goto error_save_state_vm; } vmpool->update(vm); vm->unlock(); } return; } else { goto error_mkfs; } } else if ( action == "RM" ) { int rc; string tmp_error; rc = ipool->drop(image, tmp_error); if ( rc < 0 ) { NebulaLog::log("ImM",Log::ERROR,"Image could not be removed from DB"); } if ( result == "SUCCESS" ) { NebulaLog::log("ImM",Log::INFO,"Image successfully removed."); } else { goto error_rm; } } else if (action == "LOG") { getline(is,info); NebulaLog::log("ImM", log_type(result[0]), info.c_str()); } image->unlock(); return; error_cp: os.str(""); os << "Error copying image in the repository"; goto error_common; error_mkfs: os.str(""); os << "Error creating datablock"; goto error_common; error_rm: os.str(""); os << "Error removing image from repository. Remove file " << image->get_source() << " to completely delete image."; image->unlock(); getline(is,info); if (!info.empty() && (info[0] != '-')) { os << ": " << info; } NebulaLog::log("ImM", Log::ERROR, os); return; error_save_no_vm: os.str(""); os << "Image created for SAVE_AS, but the associated VM does not exist."; goto error_save_common; error_save_state_vm: os.str(""); os << "Image created for SAVE_AS, but VM is no longer running"; goto error_save_common; error_save_common: image = ipool->get(id, true); if (image == 0 ) { return; } error_common: getline(is,info); if (!info.empty() && (info[0] != '-')) { os << ": " << info; image->set_template_error_message(os.str()); } 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"); } opennebula-3.4.1/src/image/ImageTemplate.cc0000644000175000017500000000321411750754334020452 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 "ImageTemplate.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ vector ImageTemplate::restricted_attributes; string ImageTemplate::saving_attribute = "SAVE_AS"; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ opennebula-3.4.1/src/image/test/0000755000175000017500000000000011750754334016404 5ustar drazzibdrazzibopennebula-3.4.1/src/image/test/SConstruct0000644000175000017500000000330011750754334020432 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # -------------------------------------------------------------------------- Import('env') env.Prepend(LIBS=[ 'nebula_core_test', 'nebula_vmm', 'nebula_lcm', 'nebula_im', 'nebula_hm', 'nebula_rm', 'nebula_datastore', 'nebula_dm', 'nebula_tm', 'nebula_um', 'nebula_group', 'nebula_authm', 'nebula_acl', 'nebula_mad', 'nebula_template', 'nebula_image', 'nebula_pool', 'nebula_cluster', 'nebula_host', 'nebula_vnm', 'nebula_vm', 'nebula_vmtemplate', 'nebula_common', 'nebula_sql', 'nebula_log', 'nebula_xml', 'crypto' ]) env.Program('test','ImagePoolTest.cc') opennebula-3.4.1/src/image/test/ImagePoolTest.cc0000644000175000017500000010625111750754334021434 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ #include #include #include #include "ImagePool.h" #include "PoolTest.h" using namespace std; const int uids[] = {0,1,2}; const char* unames[] = {"one","two","three"}; const char* gnames[] = {"oneadmin","oneadmin","users"}; const string names[] = {"Image one", "Second Image", "The third image"}; const string templates[] = { "NAME = \"Image one\"\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" "PATH = /tmp/image_second_test\n" "DESCRIPTION = \"This is a rather short description.\"\n", "NAME = \"The third image\"\n" "PATH = /tmp/image_test\n" "# DESCRIPTION = \"An image description\"\n" "BUS = SCSI\n" "PROFILE = STUDENT\n" }; const string xmls[] = { "001oneoneadminImage one110000000010000000000/tmp/image_test0400none", "111twooneadminSecond Image110000000000000000000/tmp/image_second_test0400none", "021threeusersThe third image110000000000000000000/tmp/image_test0400none", }; // This xml dump result has the STIMEs modified to 0000000000 const string xml_dump = "001oneoneadminImage one110000000010000000000/tmp/image_test0400none111twooneadminSecond Image110000000000000000000/tmp/image_second_test0400none221threeusersThe third image110000000000000000000/tmp/image_test0400none"; const string xml_dump_where = "001oneoneadminImage one110000000010000000000/tmp/image_test0400none111twooneadminSecond Image110000000000000000000/tmp/image_second_test0400none"; /* ************************************************************************* */ /* ************************************************************************* */ #include "NebulaTest.h" class NebulaTestImage: public NebulaTest { public: NebulaTestImage():NebulaTest() { NebulaTest::the_tester = this; need_image_pool = true; need_imagem = true; need_datastore_pool = true; } }; class ImagePoolFriend : public ImagePool { public: ImagePoolFriend(SqlDB * db, const string& _default_type, const string& _default_dev_prefix, vector _restricted_attrs): ImagePool( db, _default_type, _default_dev_prefix, _restricted_attrs){}; int allocate(const int& uid, const std::string& stemplate, int* oid) { ImageTemplate * img_template; char * error_msg = 0; int rc; string err; img_template = new ImageTemplate; rc = img_template->parse(stemplate,&error_msg); if( rc == 0 ) { string uname = unames[uid]; string gname = gnames[uid]; return ImagePool::allocate(uid, 1, uname, gname, img_template, 0,"none", "", oid, err); } else { if (error_msg != 0 ) { free(error_msg); } delete img_template; return -2; } }; }; /* ************************************************************************* */ /* ************************************************************************* */ class ImagePoolTest : public PoolTest { CPPUNIT_TEST_SUITE (ImagePoolTest); ALL_POOLTEST_CPPUNIT_TESTS(); CPPUNIT_TEST ( names_initialization ); CPPUNIT_TEST ( update ); CPPUNIT_TEST ( duplicates ); CPPUNIT_TEST ( extra_attributes ); CPPUNIT_TEST ( wrong_templates ); CPPUNIT_TEST ( target_generation ); CPPUNIT_TEST ( bus_source_assignment ); CPPUNIT_TEST ( persistence ); CPPUNIT_TEST ( imagepool_disk_attribute ); CPPUNIT_TEST ( dump ); CPPUNIT_TEST ( dump_where ); CPPUNIT_TEST ( get_using_name ); CPPUNIT_TEST ( wrong_get_name ); CPPUNIT_TEST ( name_index ); CPPUNIT_TEST ( chown_name_index ); CPPUNIT_TEST_SUITE_END (); protected: NebulaTestImage * tester; ImagePool * ipool; ImageManager * imagem; void bootstrap(SqlDB* db) { // setUp overwritten }; PoolSQL* create_pool(SqlDB* db) { // setUp overwritten return ipool; }; int allocate(int index) { int oid; return ((ImagePoolFriend*)pool)->allocate(uids[index], templates[index], &oid); }; void check(int index, PoolObjectSQL* obj) { CPPUNIT_ASSERT( obj != 0 ); string xml_str = ""; // Get the xml and replace the REGTIME to 0, so we can compare // it. ((Image*)obj)->to_xml(xml_str); fix_regtimes(xml_str); //* if( xml_str != xmls[index] ) { cout << endl << xml_str << endl << xmls[index] << endl; } //*/ CPPUNIT_ASSERT( ((Image*)obj)->get_name() == names[index] ); CPPUNIT_ASSERT( xml_str == xmls[index]); }; public: ImagePoolTest(){xmlInitParser();}; ~ImagePoolTest(){xmlCleanupParser();}; void setUp() { create_db(); tester = new NebulaTestImage(); Nebula& neb = Nebula::instance(); neb.start(); ipool = neb.get_ipool(); imagem = neb.get_imagem(); pool = ipool; }; void tearDown() { // ----------------------------------------------------------- // Stop the managers & free resources // ----------------------------------------------------------- imagem->finalize(); pthread_join(imagem->get_thread_id(),0); //XML Library xmlCleanupParser(); delete_db(); delete tester; }; /* ********************************************************************* */ void names_initialization() { ImagePool * imp; Image * img; // Allocate 2 images, so they are written to the DB. allocate(0); allocate(2); // Create a new pool, using the same DB. This new pool should read the // allocated images. vector restricted_attrs; imp = new ImagePool(db,"OS", "hd", restricted_attrs); img = imp->get(0, false); CPPUNIT_ASSERT( img != 0 ); img = imp->get(2, false); CPPUNIT_ASSERT( img == 0 ); img = imp->get(1, false); CPPUNIT_ASSERT( img != 0 ); delete imp; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void update() { string description_name = "DESCRIPTION"; string description_val = ""; string new_description = "A new description"; string attr_name = "NEW_ATTRIBUTE"; string attr_val = ""; string new_attr_value = "New value"; string no_value = "Some random value"; ImagePool * ip; Image * img; int oid_1; ip = static_cast(pool); oid_1 = allocate(0); img = ip->get(oid_1, true); CPPUNIT_ASSERT( img != 0 ); // 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("PATH"); ip->update(img); img->unlock(); img = ip->get(oid_1,false); CPPUNIT_ASSERT( img != 0 ); img->get_template_attribute("DESCRIPTION", description_val); img->get_template_attribute("NEW_ATTRIBUTE", attr_val); img->get_template_attribute("PATH", no_value); CPPUNIT_ASSERT( description_val == new_description ); CPPUNIT_ASSERT( attr_val == new_attr_value ); CPPUNIT_ASSERT( no_value == "" ); //Now force access to DB pool->clean(); img = ip->get(oid_1,false); CPPUNIT_ASSERT( img != 0 ); description_val = ""; attr_val = ""; no_value = "Random value"; img->get_template_attribute("DESCRIPTION", description_val); img->get_template_attribute("NEW_ATTRIBUTE", attr_val); img->get_template_attribute("PATH", no_value); CPPUNIT_ASSERT( description_val == new_description ); CPPUNIT_ASSERT( attr_val == new_attr_value ); CPPUNIT_ASSERT( no_value == "" ); }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void duplicates() { int rc, oid; ImagePoolFriend * imp = static_cast(pool); // Allocate an image. rc = imp->allocate(uids[0], templates[0], &oid); CPPUNIT_ASSERT( oid == 0 ); CPPUNIT_ASSERT( oid == rc ); // Try to allocate twice the same image, shouldn't work rc = imp->allocate(uids[0], templates[0], &oid); CPPUNIT_ASSERT( rc == -1 ); CPPUNIT_ASSERT( oid == -1 ); // Try again, this time with different uid. Should be allowed rc = imp->allocate(uids[1], templates[0], &oid); CPPUNIT_ASSERT( rc >= 0 ); CPPUNIT_ASSERT( oid == 1 ); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void extra_attributes() { int oid; string value = ""; Image * img; // The third template doen't have a description, but has some // extra attibutes oid = allocate(2); CPPUNIT_ASSERT( oid == 0 ); pool->clean(); img = ((ImagePool*)pool)->get(oid, false); check(2, img); img->get_template_attribute("DESCRIPTION", value); CPPUNIT_ASSERT( value == "" ); img->get_template_attribute("PROFILE", value); CPPUNIT_ASSERT( value == "STUDENT" ); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void wrong_templates() { int rc; ImagePoolFriend * imp = static_cast(pool); string templates[] = { "PATH = /tmp/image_test\n" "DESCRIPTION = \"This template lacks name!\"\n", "NAME = \"name A\"\n" "PATH = /tmp/image_test\n" "TYPE = WRONG\n", "NAME \"PARSE ERROR\"\n" "TYPE = WRONG\n", "END" }; int results[] = { -1, -1, -1 }; int i = 0; while( templates[i] != "END" ) { imp->allocate(0, templates[i], &rc); //cout << endl << i << " - rc: " << rc << " expected: " // << results[i] << endl; CPPUNIT_ASSERT( rc == results[i] ); i++; } } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void target_generation() { ImagePoolFriend * imp = static_cast(pool); Image * img; VectorAttribute * disk; int oid; string value; int index=0; Image::ImageType img_type; disk = new VectorAttribute("DISK"); // Allocate an OS type image oid = allocate(0); img = imp->get(oid, false); CPPUNIT_ASSERT( img != 0 ); CPPUNIT_ASSERT( oid == 0 ); img->set_state(Image::READY); img->disk_attribute(disk, &index, &img_type); value = disk->vector_value("TARGET"); CPPUNIT_ASSERT( value == "hda" ); CPPUNIT_ASSERT( img_type == Image::OS ); // clean up delete disk; value = ""; disk = new VectorAttribute("DISK"); // Allocate a CDROM type image string templ = "NAME = \"name A\" TYPE = CDROM PATH = /tmp"; imp->allocate(0, templ, &oid); CPPUNIT_ASSERT(oid >= 0); img = imp->get(oid, false); CPPUNIT_ASSERT( img != 0 ); img->set_state(Image::READY); img->disk_attribute(disk, &index, &img_type); value = disk->vector_value("TARGET"); CPPUNIT_ASSERT(value == "hdc"); CPPUNIT_ASSERT( img_type == Image::CDROM ); // clean up delete disk; value = ""; disk = new VectorAttribute("DISK"); // Allocate a DATABLOCK type image templ = "NAME = \"name B\" TYPE = DATABLOCK PATH=\"/dev/null\""; imp->allocate(0, templ, &oid); CPPUNIT_ASSERT(oid >= 0); img = imp->get(oid, false); CPPUNIT_ASSERT( img != 0 ); img->set_state(Image::READY); img->disk_attribute(disk, &index, &img_type); value = disk->vector_value("TARGET"); CPPUNIT_ASSERT(value == "hde"); CPPUNIT_ASSERT( img_type == Image::DATABLOCK ); // clean up delete disk; value = ""; disk = new VectorAttribute("DISK"); // Allocate a DATABLOCK type image templ = "NAME = \"name C\" TYPE = DATABLOCK DEV_PREFIX = \"sd\"" " SIZE=4 FSTYPE=ext3"; imp->allocate(0, templ, &oid); CPPUNIT_ASSERT(oid >= 0); img = imp->get(oid, false); CPPUNIT_ASSERT( img != 0 ); img->set_state(Image::READY); img->disk_attribute(disk, &index, &img_type); value = disk->vector_value("TARGET"); CPPUNIT_ASSERT(value == "sdf"); // clean up delete disk; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void bus_source_assignment() { ImagePool * imp = static_cast(pool); Image * img; VectorAttribute * disk; int rc, oid; string value; int index = 0; Image::ImageType img_type; // Allocate an OS type image oid = allocate(0); img = imp->get(oid, false); CPPUNIT_ASSERT( img != 0 ); // --------------------------------------------------------------------- // A disk without a BUS attribute should not have it added. disk = new VectorAttribute("DISK"); img->set_state(Image::READY); rc = img->disk_attribute(disk, &index, &img_type); CPPUNIT_ASSERT( rc == 0 ); value = ""; value = disk->vector_value("BUS"); CPPUNIT_ASSERT( value == "" ); value = ""; value = disk->vector_value("SOURCE"); CPPUNIT_ASSERT( value == "" ); // clean up //img->release_image(); delete disk; // --------------------------------------------------------------------- // A disk with a BUS attribute should not have it overwritten. disk = new VectorAttribute("DISK"); disk->replace("BUS", "SCSI"); img->set_state(Image::READY); rc = img->disk_attribute(disk, &index, &img_type); CPPUNIT_ASSERT( rc == 0 ); value = disk->vector_value("BUS"); CPPUNIT_ASSERT( value == "SCSI" ); value = ""; value = disk->vector_value("SOURCE"); CPPUNIT_ASSERT( value == "" ); // clean up delete disk; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void imagepool_disk_attribute() { ImagePoolFriend * imp = static_cast(pool); Image * img; VectorAttribute * disk; int oid_0, oid_1, index, img_id; string value, error; Image::ImageType img_type; // --------------------------------------------------------------------- // Allocate 2 images, with different dev_prefix string template_0 = "NAME = \"Image 0\"\n" "DEV_PREFIX = \"hd\"\n" "PATH = /dev/null\n"; string template_1 = "NAME = \"Image 1\"\n" "DEV_PREFIX = \"sd\"\n" "PATH = /dev/null\n"; imp->allocate(0, template_0, &oid_0); CPPUNIT_ASSERT( oid_0 == 0 ); imp->allocate(0, template_1, &oid_1); CPPUNIT_ASSERT( oid_1 == 1 ); img = imp->get(oid_0, false); CPPUNIT_ASSERT( img != 0 ); img->set_state(Image::READY); img = imp->get(oid_1, false); CPPUNIT_ASSERT( img != 0 ); img->set_state(Image::READY); // Disk using image 0 disk = new VectorAttribute("DISK"); disk->replace("IMAGE_ID", "0"); ((ImagePool*)imp)->disk_attribute(disk, 0, &index, &img_type,0, img_id,error); value = ""; value = disk->vector_value("TARGET"); CPPUNIT_ASSERT( value == "hda" ); delete disk; // Disk using image 1 index disk = new VectorAttribute("DISK"); disk->replace("IMAGE_ID", "1"); ((ImagePool*)imp)->disk_attribute(disk, 0, &index, &img_type,0, img_id,error); value = ""; value = disk->vector_value("TARGET"); CPPUNIT_ASSERT( value == "sda" ); value = ""; value = disk->vector_value("IMAGE"); CPPUNIT_ASSERT( value == "Image 1" ); delete disk; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void persistence() { int oid; int success; string error_msg; ImagePoolFriend * imp = static_cast(pool); Image * img; string templates [] = { "NAME = \"Image 1\"\n" "PERSISTENT = NO\n" "PATH = /dev/null\n", "NAME = \"Image 2\"\n" "PERSISTENT = NO\n" "PATH = /dev/null\n", "NAME = \"Image 3\"\n" "PERSISTENT = YES\n" "PATH = /dev/null\n", "END" }; bool persistent[] = { false, false, true }; int i = 0; while( templates[i] != "END" ) { imp->allocate(0, templates[i], &oid); CPPUNIT_ASSERT( oid >= 0 ); img = imp->get( oid, false ); CPPUNIT_ASSERT( img != 0 ); CPPUNIT_ASSERT( img->isPersistent() == persistent[i] ); i++; } // img 0 is not persistent img = imp->get( 0, false ); CPPUNIT_ASSERT( img != 0 ); // make it persistent success = img->persistent(true, error_msg); CPPUNIT_ASSERT( success == 0 ); CPPUNIT_ASSERT( img->isPersistent() == true ); // it isn't public, try to unpublish success = img->set_permissions(1,1,0, 0,0,0, 0,0,0, error_msg); CPPUNIT_ASSERT( success == 0 ); CPPUNIT_ASSERT( img->isPublic() == false ); // try to publish, should fail because it is persistent success = img->set_permissions(1,1,0, 1,0,0, 0,0,0, error_msg); CPPUNIT_ASSERT( success == -1 ); CPPUNIT_ASSERT( img->isPublic() == false ); // make it non-persistent success = img->persistent(false, error_msg); CPPUNIT_ASSERT( success == 0 ); CPPUNIT_ASSERT( img->isPersistent() == false ); // it isn't public, try to unpublish success = img->set_permissions(1,1,0, 0,0,0, 0,0,0, error_msg); CPPUNIT_ASSERT( success == 0 ); CPPUNIT_ASSERT( img->isPublic() == false ); // try to publish, now it should be possible success = img->set_permissions(1,1,0, 1,0,0, 0,0,0, error_msg); CPPUNIT_ASSERT( success == 0 ); CPPUNIT_ASSERT( img->isPublic() == true ); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void dump() { ImagePool * imp = static_cast(pool); ostringstream oss; int rc; string nan; allocate(0); allocate(1); allocate(2); rc = imp->dump(oss,nan); CPPUNIT_ASSERT(rc == 0); string result = oss.str(); fix_regtimes(result); //* if( result != xml_dump ) { cout << endl << result << endl << xml_dump << endl; } //*/ CPPUNIT_ASSERT( result == xml_dump ); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void dump_where() { ImagePool * imp = static_cast(pool); int rc; ostringstream oss; ostringstream where; allocate(0); allocate(1); allocate(2); where << "uid < 2"; rc = imp->dump(oss, where.str()); CPPUNIT_ASSERT(rc == 0); string result = oss.str(); fix_regtimes(result); //* if( result != xml_dump_where ) { cout << endl << result << endl << xml_dump_where << endl; } //*/ CPPUNIT_ASSERT( result == xml_dump_where ); } /* ********************************************************************* */ void get_using_name() { int oid_0, oid_1; ImagePool * imp = static_cast(pool); // Allocate two objects oid_0 = allocate(0); oid_1 = allocate(1); // --------------------------------- // Get first object and check its integrity obj = pool->get(oid_0, false); CPPUNIT_ASSERT( obj != 0 ); check(0, obj); // Get using its name obj = imp->get(names[1], uids[1], true); CPPUNIT_ASSERT( obj != 0 ); obj->unlock(); check(1, obj); // --------------------------------- // Clean the cache, forcing the pool to read the objects from the DB pool->clean(); // Get first object and check its integrity obj = imp->get(names[0], uids[0], false); check(0, obj); // Get using its name obj = imp->get(oid_1, false); check(1, obj); }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void wrong_get_name() { ImagePool * imp = static_cast(pool); // The pool is empty // Non existing name obj = imp->get("Wrong name", 0, true); CPPUNIT_ASSERT( obj == 0 ); // Allocate an object allocate(0); // Ask again for a non-existing name obj = imp->get("Non existing name",uids[0], true); CPPUNIT_ASSERT( obj == 0 ); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void name_index() { Image *img_oid, *img_name; int oid_0; int uid_0; string name_0; oid_0 = allocate(0); CPPUNIT_ASSERT(oid_0 != -1); // --------------------------------- // Get by oid img_oid = ipool->get(oid_0, true); CPPUNIT_ASSERT(img_oid != 0); name_0 = img_oid->get_name(); uid_0 = img_oid->get_uid(); img_oid->unlock(); // Get by name and check it is the same object img_name = ipool->get(name_0, uid_0, true); CPPUNIT_ASSERT(img_name != 0); img_name->unlock(); CPPUNIT_ASSERT(img_oid == img_name); // --------------------------------- // Clean the cache, forcing the pool to read the objects from the DB ipool->clean(); // Get by oid img_oid = ipool->get(oid_0, true); CPPUNIT_ASSERT(img_oid != 0); img_oid->unlock(); // Get by name and check it is the same object img_name = ipool->get(name_0, uid_0, true); CPPUNIT_ASSERT(img_name != 0); img_name->unlock(); CPPUNIT_ASSERT(img_oid == img_name); // --------------------------------- // Clean the cache, forcing the pool to read the objects from the DB ipool->clean(); // Get by name img_name = ipool->get(name_0, uid_0, true); CPPUNIT_ASSERT(img_name != 0); img_name->unlock(); // Get by oid and check it is the same object img_oid = ipool->get(oid_0, true); CPPUNIT_ASSERT(img_oid != 0); img_oid->unlock(); CPPUNIT_ASSERT(img_oid == img_name); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void chown_name_index() { Image *img_oid, *img_name; int oid; int old_uid; int new_uid = 3456; string name; oid = allocate(0); CPPUNIT_ASSERT(oid != -1); // --------------------------------- // Get by oid img_oid = ipool->get(oid, true); CPPUNIT_ASSERT(img_oid != 0); name = img_oid->get_name(); old_uid = img_oid->get_uid(); // Change owner and update cache index img_oid->set_user(new_uid, "new_username"); ipool->update(img_oid); img_oid->unlock(); ipool->update_cache_index(name, old_uid, name, new_uid); // Get by name, new_uid and check it is the same object img_name = ipool->get(name, new_uid, true); CPPUNIT_ASSERT(img_name != 0); img_name->unlock(); CPPUNIT_ASSERT(img_oid == img_name); // Get by name, old_uid and check it does not exist img_name = ipool->get(name, old_uid, true); CPPUNIT_ASSERT(img_name == 0); // --------------------------------- // Clean the cache, forcing the pool to read the objects from the DB ipool->clean(); // Get by name, old_uid and check it does not exist img_name = ipool->get(name, old_uid, true); CPPUNIT_ASSERT(img_name == 0); // Get by oid img_oid = ipool->get(oid, true); CPPUNIT_ASSERT(img_oid != 0); img_oid->unlock(); // Get by name, new_uid and check it is the same object img_name = ipool->get(name, new_uid, true); CPPUNIT_ASSERT(img_name != 0); img_name->unlock(); CPPUNIT_ASSERT(img_oid == img_name); } }; /* ************************************************************************* */ /* ************************************************************************* */ int main(int argc, char ** argv) { return PoolTest::main(argc, argv, ImagePoolTest::suite()); } opennebula-3.4.1/src/image/test/one_auth0000644000175000017500000000002711750754334020130 0ustar drazzibdrazzibone_user_test:password opennebula-3.4.1/src/image/Image.cc0000644000175000017500000003734211750754334016767 0ustar drazzibdrazzib/* ------------------------------------------------------------------------ */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* ------------------------------------------------------------------------ */ #include #include #include #include #include #include #include "Image.h" #include "ImagePool.h" #include "AuthManager.h" #include "UserPool.h" #define TO_UPPER(S) transform(S.begin(),S.end(),S.begin(),(int(*)(int))toupper) /* ************************************************************************ */ /* Image :: Constructor/Destructor */ /* ************************************************************************ */ Image::Image(int _uid, int _gid, const string& _uname, const string& _gname, ImageTemplate * _image_template): PoolObjectSQL(-1,IMAGE,"",_uid,_gid,_uname,_gname,table), type(OS), regtime(time(0)), source(""), path(""), fs_type(""), size_mb(0), state(INIT), running_vms(0), ds_id(-1), ds_name("") { if (_image_template != 0) { obj_template = _image_template; } else { obj_template = new ImageTemplate; } } Image::~Image() { if (obj_template != 0) { delete obj_template; } } /* ************************************************************************ */ /* Image :: Database Access Functions */ /* ************************************************************************ */ const char * Image::table = "image_pool"; const char * Image::db_names = "oid, name, body, uid, gid, owner_u, group_u, other_u"; const char * Image::db_bootstrap = "CREATE TABLE IF NOT EXISTS image_pool (" "oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, " "gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, " "UNIQUE(name,uid) )"; /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ int Image::insert(SqlDB *db, string& error_str) { int rc; string path_attr; string type_att; string persistent_attr; string dev_prefix; string source_attr; string saved_id; ostringstream oss; // --------------------------------------------------------------------- // Check default image attributes // --------------------------------------------------------------------- // ------------ NAME -------------------- erase_template_attribute("NAME", name); // ------------ TYPE -------------------- erase_template_attribute("TYPE", type_att); if ( type_att.empty() == true ) { type_att = ImagePool::default_type(); } if (set_type(type_att) != 0) { goto error_type; } // ------------ PERSISTENT -------------------- erase_template_attribute("PERSISTENT", persistent_attr); TO_UPPER(persistent_attr); persistent_img = (persistent_attr == "YES"); // ------------ PREFIX -------------------- get_template_attribute("DEV_PREFIX", dev_prefix); if( dev_prefix.empty() ) { SingleAttribute * dev_att = new SingleAttribute("DEV_PREFIX", ImagePool::default_dev_prefix()); obj_template->set(dev_att); } // ------------ PATH & SOURCE -------------------- erase_template_attribute("PATH", path); erase_template_attribute("SOURCE", source); if (!isSaving()) //Not a saving image { if ( source.empty() && path.empty() ) { string size_attr; istringstream iss; erase_template_attribute("SIZE", size_attr); erase_template_attribute("FSTYPE", fs_type); // DATABLOCK image needs SIZE and FSTYPE if (type != DATABLOCK || size_attr.empty() || fs_type.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.empty() ) { goto error_path_and_source; } } else { string size_attr; istringstream iss; fs_type = "save_as"; erase_template_attribute("SIZE", size_attr); iss.str(size_attr); iss >> size_mb; if (iss.fail() == true) { goto error_size_format; } } state = LOCKED; //LOCKED till the ImageManager copies it to the Repository //-------------------------------------------------------------------------- // Insert the Image //-------------------------------------------------------------------------- rc = insert_replace(db, false, error_str); return rc; error_type: error_str = "Incorrect TYPE in template."; goto error_common; error_no_path: if ( type == DATABLOCK ) { error_str = "A DATABLOCK type IMAGE has to declare a PATH, or both " "SIZE and FSTYPE."; } else { error_str = "No PATH in template."; } 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 mutually exclusive."; goto error_common; error_common: NebulaLog::log("IMG", Log::ERROR, error_str); return -1; } /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ int Image::update(SqlDB *db) { string error_str; return insert_replace(db, true, error_str); } /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ int Image::insert_replace(SqlDB *db, bool replace, string& error_str) { ostringstream oss; int rc; string xml_body; char * sql_name; char * sql_xml; // Update the Image sql_name = db->escape_str(name.c_str()); if ( sql_name == 0 ) { goto error_name; } sql_xml = db->escape_str(to_xml(xml_body).c_str()); if ( sql_xml == 0 ) { goto error_body; } if ( validate_xml(sql_xml) != 0 ) { goto error_xml; } if(replace) { oss << "REPLACE"; } else { oss << "INSERT"; } // Construct the SQL statement to Insert or Replace oss <<" INTO "<< table <<" ("<< db_names <<") VALUES (" << oid << "," << "'" << sql_name << "'," << "'" << sql_xml << "'," << uid << "," << gid << "," << owner_u << "," << group_u << "," << other_u << ")"; rc = db->exec(oss); db->free_str(sql_name); db->free_str(sql_xml); return rc; error_xml: db->free_str(sql_name); db->free_str(sql_xml); error_str = "Error transforming the Image to XML."; goto error_common; error_body: db->free_str(sql_name); goto error_generic; error_name: goto error_generic; error_generic: error_str = "Error inserting Image in DB."; error_common: return -1; } /* ************************************************************************ */ /* Image :: Misc */ /* ************************************************************************ */ string& Image::to_xml(string& xml) const { string template_xml; string perms_xml; ostringstream oss; oss << "" << "" << oid << "" << "" << uid << "" << "" << gid << "" << "" << uname << "" << "" << gname << "" << "" << name << "" << perms_to_xml(perms_xml) << "" << type << "" << "" << persistent_img << "" << "" << regtime << "" << "" << source << "" << "" << path << "" << "" << fs_type << "" << "" << size_mb << "" << "" << state << "" << "" << running_vms << "" << "" << ds_id << ""<< "" << ds_name << "" << obj_template->to_xml(template_xml) << ""; xml = oss.str(); return xml; } /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ int Image::from_xml(const string& xml) { vector content; int int_state; int int_type; int rc = 0; // Initialize the internal XML object update_from_str(xml); // Get class base attributes rc += xpath(oid, "/IMAGE/ID", -1); rc += xpath(uid, "/IMAGE/UID", -1); rc += xpath(gid, "/IMAGE/GID", -1); rc += xpath(uname, "/IMAGE/UNAME", "not_found"); rc += xpath(gname, "/IMAGE/GNAME", "not_found"); rc += xpath(name, "/IMAGE/NAME", "not_found"); rc += xpath(int_type, "/IMAGE/TYPE", 0); rc += xpath(persistent_img, "/IMAGE/PERSISTENT", 0); rc += xpath(regtime, "/IMAGE/REGTIME", 0); rc += xpath(source, "/IMAGE/SOURCE", "not_found"); rc += xpath(size_mb, "/IMAGE/SIZE", 0); rc += xpath(int_state, "/IMAGE/STATE", 0); rc += xpath(running_vms, "/IMAGE/RUNNING_VMS", -1); rc += xpath(ds_id, "/IMAGE/DATASTORE_ID", -1); rc += xpath(ds_name,"/IMAGE/DATASTORE", "not_found"); // Permissions rc += perms_from_xml(); //Optional image attributes xpath(path,"/IMAGE/PATH", ""); xpath(fs_type,"/IMAGE/FSTYPE",""); type = static_cast(int_type); state = static_cast(int_state); // Get associated classes ObjectXML::get_nodes("/IMAGE/TEMPLATE", content); if (content.empty()) { return -1; } rc += obj_template->from_xml_node(content[0]); ObjectXML::free_nodes(content); if (rc != 0) { return -1; } return 0; } /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ int Image::disk_attribute( VectorAttribute * disk, int * index, ImageType* img_type) { string bus; string target; string driver; ostringstream iid; *img_type = type; bus = disk->vector_value("BUS"); target = disk->vector_value("TARGET"); driver = disk->vector_value("DRIVER"); iid << oid; string template_bus; string template_target; string prefix; string template_driver; get_template_attribute("BUS", template_bus); get_template_attribute("TARGET", template_target); get_template_attribute("DRIVER", template_driver); get_template_attribute("DEV_PREFIX", prefix); if (prefix.empty())//Removed from image template, get it again from defaults { prefix = ImagePool::default_dev_prefix(); } //--------------------------------------------------------------------------- // BASE DISK ATTRIBUTES //--------------------------------------------------------------------------- disk->replace("IMAGE", name); disk->replace("IMAGE_ID", iid.str()); disk->replace("SOURCE", source); if (bus.empty() && !template_bus.empty()) //BUS in Image, not in DISK { disk->replace("BUS",template_bus); } if (driver.empty() && !template_driver.empty())//DRIVER in Image,not in DISK { disk->replace("DRIVER",template_driver); } //--------------------------------------------------------------------------- // TYPE, READONLY, CLONE, and SAVE attributes //--------------------------------------------------------------------------- if ( persistent_img ) { disk->replace("CLONE","NO"); disk->replace("SAVE","YES"); disk->replace("PERSISTENT","YES"); } else { disk->replace("CLONE","YES"); disk->replace("SAVE","NO"); } switch(type) { case OS: case DATABLOCK: disk->replace("TYPE","DISK"); disk->replace("READONLY","NO"); break; case CDROM: disk->replace("TYPE","CDROM"); disk->replace("READONLY","YES"); break; } //--------------------------------------------------------------------------- // TARGET attribute //--------------------------------------------------------------------------- if (target.empty()) //No TARGET in DISK attribute { if (!template_target.empty()) { disk->replace("TARGET", template_target); } else { switch(type) { case OS: prefix += "a"; break; case CDROM: prefix += "c"; // b is for context break; case DATABLOCK: prefix += static_cast(('e'+ *index)); *index = *index + 1; break; } disk->replace("TARGET", prefix); } } return 0; } /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ int Image::set_type(string& _type) { int rc = 0; TO_UPPER(_type); if ( _type == "OS" ) { type = OS; } else if ( _type == "CDROM" ) { type = CDROM; } else if ( _type == "DATABLOCK" ) { type = DATABLOCK; } else { rc = -1; } return rc; } /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ opennebula-3.4.1/src/dm/0000755000175000017500000000000011750754334014743 5ustar drazzibdrazzibopennebula-3.4.1/src/dm/SConstruct0000644000175000017500000000265111750754334017001 0ustar drazzibdrazzib# SConstruct for src/vm # -------------------------------------------------------------------------- # # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # # a copy of the License at # # # # http://www.apache.org/licenses/LICENSE-2.0 # # # # Unless required by applicable law or agreed to in writing, software # # distributed under the License is distributed on an "AS IS" BASIS, # # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # # See the License for the specific language governing permissions and # # limitations under the License. # #--------------------------------------------------------------------------- # Import('env') lib_name='nebula_dm' # Sources to generate the library source_files=[ 'DispatchManager.cc', 'DispatchManagerActions.cc', 'DispatchManagerStates.cc', ] # Build library env.StaticLibrary(lib_name, source_files) opennebula-3.4.1/src/dm/DispatchManagerStates.cc0000644000175000017500000001257211750754334021477 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 "DispatchManager.h" #include "NebulaLog.h" void DispatchManager::suspend_success_action(int vid) { VirtualMachine * vm; vm = vmpool->get(vid,true); if ( vm == 0 ) { return; } if ((vm->get_state() == VirtualMachine::ACTIVE) && (vm->get_lcm_state() == VirtualMachine::SAVE_SUSPEND)) { vm->set_state(VirtualMachine::SUSPENDED); vm->set_state(VirtualMachine::LCM_INIT); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is SUSPENDED"); } else { ostringstream oss; oss << "suspend_success action received but VM " << vid << " not in ACTIVE state"; NebulaLog::log("DiM",Log::ERROR,oss); } vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void DispatchManager::stop_success_action(int vid) { VirtualMachine * vm; vm = vmpool->get(vid,true); if ( vm == 0 ) { return; } if ((vm->get_state() == VirtualMachine::ACTIVE) && (vm->get_lcm_state() == VirtualMachine::EPILOG_STOP)) { vm->set_state(VirtualMachine::STOPPED); vm->set_state(VirtualMachine::LCM_INIT); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is STOPPED"); } else { ostringstream oss; oss << "stop_success action received but VM " << vid << " not in ACTIVE state"; NebulaLog::log("DiM",Log::ERROR,oss); } vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void DispatchManager::done_action(int vid) { VirtualMachine * vm; VirtualMachine::LcmState lcm_state; VirtualMachine::VmState dm_state; vm = vmpool->get(vid,true); if ( vm == 0 ) { return; } lcm_state = vm->get_lcm_state(); dm_state = vm->get_state(); if ((dm_state == VirtualMachine::ACTIVE) && (lcm_state == VirtualMachine::EPILOG || lcm_state == VirtualMachine::CANCEL || lcm_state == VirtualMachine::CLEANUP )) { vm->set_state(VirtualMachine::DONE); vm->set_state(VirtualMachine::LCM_INIT); vm->set_exit_time(time(0)); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is DONE"); vm->release_network_leases(); vm->release_disk_images(); } else { ostringstream oss; oss << "done action received but VM " << vid << " not in ACTIVE state"; NebulaLog::log("DiM",Log::ERROR,oss); } vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void DispatchManager::failed_action(int vid) { VirtualMachine * vm; vm = vmpool->get(vid,true); if ( vm == 0 ) { return; } if (vm->get_lcm_state() == VirtualMachine::FAILURE) { vm->set_state(VirtualMachine::LCM_INIT); vm->set_state(VirtualMachine::FAILED); vm->set_exit_time(time(0)); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is FAILED"); vm->unlock(); } return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void DispatchManager::resubmit_action(int vid) { VirtualMachine * vm; vm = vmpool->get(vid,true); if ( vm == 0 ) { return; } if (vm->get_lcm_state() == VirtualMachine::CLEANUP) { vm->set_state(VirtualMachine::LCM_INIT); vm->set_state(VirtualMachine::PENDING); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is PENDING"); vm->unlock(); } return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ opennebula-3.4.1/src/dm/DispatchManager.cc0000644000175000017500000000774011750754334020314 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 "DispatchManager.h" #include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ extern "C" void * dm_action_loop(void *arg) { DispatchManager * dm; if ( arg == 0 ) { return 0; } dm = static_cast(arg); NebulaLog::log("DiM",Log::INFO,"Dispatch Manager started."); dm->am.loop(0,0); NebulaLog::log("DiM",Log::INFO,"Dispatch Manager stopped."); return 0; } /* -------------------------------------------------------------------------- */ int DispatchManager::start() { int rc; pthread_attr_t pattr; pthread_attr_init (&pattr); pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); NebulaLog::log("DiM",Log::INFO,"Starting Dispatch Manager..."); rc = pthread_create(&dm_thread,&pattr,dm_action_loop,(void *) this); return rc; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void DispatchManager::trigger(Actions action, int _vid) { int * vid; string aname; vid = new int(_vid); switch (action) { case SUSPEND_SUCCESS: aname = "SUSPEND_SUCCESS"; break; case STOP_SUCCESS: aname = "STOP_SUCCESS"; break; case DONE: aname = "DONE"; break; case FAILED: aname = "FAILED"; break; case RESUBMIT: aname = "RESUBMIT"; break; case FINALIZE: aname = ACTION_FINALIZE; break; default: delete vid; return; } am.trigger(aname,vid); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void DispatchManager::do_action(const string &action, void * arg) { int vid; ostringstream oss; if (arg == 0) { return; } vid = *(static_cast(arg)); delete static_cast(arg); if (action == "SUSPEND_SUCCESS") { suspend_success_action(vid); } else if (action == "STOP_SUCCESS") { stop_success_action(vid); } else if (action == "DONE") { done_action(vid); } else if (action == "FAILED") { failed_action(vid); } else if (action == "RESUBMIT") { resubmit_action(vid); } else if (action == ACTION_FINALIZE) { NebulaLog::log("DiM",Log::INFO,"Stopping Dispatch Manager..."); } else { ostringstream oss; oss << "Unknown action name: " << action; NebulaLog::log("DiM", Log::ERROR, oss); } } opennebula-3.4.1/src/dm/DispatchManagerActions.cc0000644000175000017500000003736311750754334021641 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 "DispatchManager.h" #include "NebulaLog.h" #include "Nebula.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::deploy ( VirtualMachine * vm) { ostringstream oss; int vid; if ( vm == 0 ) { return -1; } vid = vm->get_oid(); oss << "Deploying VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if ( vm->get_state() == VirtualMachine::PENDING ) { Nebula& nd = Nebula::instance(); LifeCycleManager * lcm = nd.get_lcm(); vm->set_state(VirtualMachine::ACTIVE); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is ACTIVE."); lcm->trigger(LifeCycleManager::DEPLOY,vid); } else { goto error; } vm->unlock(); return 0; error: oss.str(""); oss << "Could not deploy VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -1; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::migrate( VirtualMachine * vm) { ostringstream oss; int vid; if ( vm == 0 ) { return -1; } vid = vm->get_oid(); oss << "Migrating VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) { Nebula& nd = Nebula::instance(); LifeCycleManager * lcm = nd.get_lcm(); lcm->trigger(LifeCycleManager::MIGRATE,vid); } else { goto error; } vm->unlock(); return 0; error: oss.str(""); oss << "Could not migrate VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -1; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::live_migrate( VirtualMachine * vm) { ostringstream oss; int vid; if ( vm == 0 ) { return -1; } vid = vm->get_oid(); oss << "Live-migrating VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) { Nebula& nd = Nebula::instance(); LifeCycleManager * lcm = nd.get_lcm(); lcm->trigger(LifeCycleManager::LIVE_MIGRATE,vid); } else { goto error; } vm->unlock(); return 0; error: oss.str(""); oss << "Could not live-migrate VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -1; } /* ************************************************************************** */ /* ************************************************************************** */ int DispatchManager::shutdown ( int vid) { ostringstream oss; VirtualMachine * vm; vm = vmpool->get(vid,true); if ( vm == 0 ) { return -1; } oss << "Shutting down VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) { Nebula& nd = Nebula::instance(); LifeCycleManager * lcm = nd.get_lcm(); lcm->trigger(LifeCycleManager::SHUTDOWN,vid); } else { goto error; } vm->unlock(); return 0; error: oss.str(""); oss << "Could not shutdown VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::hold( int vid) { VirtualMachine * vm; ostringstream oss; vm = vmpool->get(vid,true); if ( vm == 0 ) { return -1; } oss << "Holding VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::PENDING) { vm->set_state(VirtualMachine::HOLD); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is HOLD."); } else { goto error; } vm->unlock(); return 0; error: oss.str(""); oss << "Could not hold VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::release( int vid) { VirtualMachine * vm; ostringstream oss; vm = vmpool->get(vid,true); if ( vm == 0 ) { return -1; } oss << "Releasing VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::HOLD) { vm->set_state(VirtualMachine::PENDING); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is PENDING."); } else { goto error; } vm->unlock(); return 0; error: oss.str(""); oss << "Could not release VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::stop( int vid) { VirtualMachine * vm; ostringstream oss; vm = vmpool->get(vid,true); if ( vm == 0 ) { return -1; } oss << "Stopping VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) { Nebula& nd = Nebula::instance(); LifeCycleManager * lcm = nd.get_lcm(); lcm->trigger(LifeCycleManager::STOP,vid); } else { goto error; } vm->unlock(); return 0; error: oss.str(""); oss << "Could not stop VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::cancel( int vid) { VirtualMachine * vm; ostringstream oss; vm = vmpool->get(vid,true); if ( vm == 0 ) { return -1; } oss << "Cancelling VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) { Nebula& nd = Nebula::instance(); LifeCycleManager * lcm = nd.get_lcm(); vm->unlock(); lcm->trigger(LifeCycleManager::CANCEL,vid); } else { goto error; } return 0; error: oss.str(""); oss << "Could not cancel VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::suspend( int vid) { VirtualMachine * vm; ostringstream oss; vm = vmpool->get(vid,true); if ( vm == 0 ) { return -1; } oss << "Suspending VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) { Nebula& nd = Nebula::instance(); LifeCycleManager * lcm = nd.get_lcm(); lcm->trigger(LifeCycleManager::SUSPEND,vid); } else { goto error; } vm->unlock(); return 0; error: oss.str(""); oss << "Could not suspend VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::resume( int vid) { VirtualMachine * vm; ostringstream oss; vm = vmpool->get(vid,true); if ( vm == 0 ) { return -1; } oss << "Resuming VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::STOPPED ) { vm->set_state(VirtualMachine::PENDING); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is PENDING."); } else if (vm->get_state() == VirtualMachine::SUSPENDED) { Nebula& nd = Nebula::instance(); LifeCycleManager * lcm = nd.get_lcm(); vm->set_state(VirtualMachine::ACTIVE); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is ACTIVE."); lcm->trigger(LifeCycleManager::RESTORE,vid); } else { goto error; } vm->unlock(); return 0; error: oss.str(""); oss << "Could not resume VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::restart(int vid) { VirtualMachine * vm; ostringstream oss; vm = vmpool->get(vid,true); if ( vm == 0 ) { return -1; } oss << "Restarting VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && (vm->get_lcm_state() == VirtualMachine::UNKNOWN || vm->get_lcm_state() == VirtualMachine::BOOT)) { Nebula& nd = Nebula::instance(); LifeCycleManager * lcm = nd.get_lcm(); lcm->trigger(LifeCycleManager::RESTART,vid); } else { goto error; } vm->unlock(); return 0; error: oss.str(""); oss << "Could not restart VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::reboot(int vid) { VirtualMachine * vm; ostringstream oss; vm = vmpool->get(vid,true); if ( vm == 0 ) { return -1; } oss << "Rebooting VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); if (vm->get_state() == VirtualMachine::ACTIVE && vm->get_lcm_state() == VirtualMachine::RUNNING ) { Nebula& nd = Nebula::instance(); LifeCycleManager * lcm = nd.get_lcm(); lcm->trigger(LifeCycleManager::REBOOT,vid); } else { goto error; } vm->unlock(); return 0; error: oss.str(""); oss << "Could not reboot VM " << vid << ", wrong state."; NebulaLog::log("DiM",Log::ERROR,oss); vm->unlock(); return -2; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::finalize( int vid) { VirtualMachine * vm; ostringstream oss; VirtualMachine::VmState state; vm = vmpool->get(vid,true); if ( vm == 0 ) { return -1; } state = vm->get_state(); oss << "Finalizing VM " << vid; NebulaLog::log("DiM",Log::DEBUG,oss); Nebula& nd = Nebula::instance(); TransferManager * tm = nd.get_tm(); LifeCycleManager * lcm = nd.get_lcm(); switch (state) { case VirtualMachine::SUSPENDED: case VirtualMachine::FAILED: tm->trigger(TransferManager::EPILOG_DELETE,vid); case VirtualMachine::INIT: case VirtualMachine::PENDING: case VirtualMachine::HOLD: case VirtualMachine::STOPPED: vm->release_network_leases(); vm->release_disk_images(); vm->set_exit_time(time(0)); vm->set_state(VirtualMachine::LCM_INIT); vm->set_state(VirtualMachine::DONE); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is DONE."); break; case VirtualMachine::ACTIVE: lcm->trigger(LifeCycleManager::DELETE,vid); break; case VirtualMachine::DONE: break; } vm->unlock(); return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int DispatchManager::resubmit(int vid) { VirtualMachine * vm; ostringstream oss; int rc = 0; Nebula& nd = Nebula::instance(); LifeCycleManager * lcm = nd.get_lcm(); TransferManager * tm = nd.get_tm(); vm = vmpool->get(vid,true); if ( vm == 0 ) { return -1; } switch (vm->get_state()) { case VirtualMachine::SUSPENDED: NebulaLog::log("DiM",Log::ERROR, "Cannot resubmit a suspended VM. Resume it first"); rc = -2; break; case VirtualMachine::INIT: // No need to do nothing here case VirtualMachine::PENDING: break; case VirtualMachine::FAILED: //Cleanup VM host files tm->trigger(TransferManager::EPILOG_DELETE,vid); case VirtualMachine::HOLD: // Move the VM to PENDING in any of these case VirtualMachine::STOPPED: vm->set_state(VirtualMachine::LCM_INIT); vm->set_state(VirtualMachine::PENDING); vmpool->update(vm); vm->log("DiM", Log::INFO, "New VM state is PENDING."); break; case VirtualMachine::ACTIVE: //Cleanup VM resources before PENDING lcm->trigger(LifeCycleManager::CLEAN,vid); break; case VirtualMachine::DONE: NebulaLog::log("DiM",Log::ERROR, "Cannot resubmit a VM already in DONE state"); rc = -2; break; } vm->unlock(); return rc; } opennebula-3.4.1/src/authm_mad/0000755000175000017500000000000011750754334016302 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/0000755000175000017500000000000011750754334017760 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/quota/0000755000175000017500000000000011750754334021111 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/quota/onequota0000755000175000017500000001346011750754334022676 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 $: << RUBY_LIB_LOCATION+"/cli" require 'command_parser' require 'cli_helper' require 'one_helper' require 'quota' require 'pp' QUOTA_KEYS = Quota::DB_QUOTA_SCHEMA.keys def show_table(values, usage=nil) size = usage ? 12 : 8 values.sort!{|v1, v2| v1[:UID]<=>v2[:UID] } table=CLIHelper::ShowTable.new(nil, self) do column :UID, "ONE identifier for the User", :size=>4 do |d| d[:UID] end QUOTA_KEYS.each { |key| column key, "#{key} quota", :size=>size do |d| if usage "#{usage[key].to_i}/#{d[key].to_i}" else "#{d[key].to_i}" end end } default :UID, *QUOTA_KEYS end table.show(values) end cmd=CommandParser::CmdParser.new(ARGV) do usage "`onequota` [] []" version OpenNebulaHelper::ONE_VERSION quota = Quota.new ######################################################################## # Global Options ######################################################################## set :option, CommandParser::OPTIONS ######################################################################## # Argument Formats ######################################################################## quota_list_desc = <<-EOT.unindent List of quota keys, comma separated. Available quotas: #{QUOTA_KEYS.join(', ')} EOT set :format, :quota_list, quota_list_desc do |arg| arg_list = arg.split(',') rc = nil arg_list.collect! do |elem| sym = elem.upcase.to_sym if !QUOTA_KEYS.include?(sym) rc = -1, "#{elem} is not a valid quota" break end sym end rc ? rc : [0, arg_list] end set :format, :value_list, "List of quota values, comma separated." do |arg| arg_list = arg.split(',') arg_list.map! {|a| a.to_i } [0, arg_list] end set :format, :userid, OpenNebulaHelper.rname_to_id_desc("USER") do |arg| OpenNebulaHelper.rname_to_id(arg, "USER") end ######################################################################## # Commands ######################################################################## set_desc = <<-EOT.unindent Set a quota for a given user. Examples: onequota set 3 cpu 12 onequota set 4 cpu,memory,storage 8,4096,10000 EOT command :set, set_desc, :userid, :quota_list, :value_list do user_id, keys, values = args if keys.length != values.length exit_with_code -1, "The number of keys and values does not match" end values_hash = Hash.new keys.each_with_index { |k,i| values_hash[k] = values[i] } quota.set_quota(user_id, values_hash) exit_with_code 0 end ######################################################################## unset_desc = <<-EOT.unindent Unset a quota for a given user. Examples: onequota unset 3 cpu onequota unset 4 cpu,memory,storage EOT command :unset, unset_desc, :userid, :quota_list do user_id, keys = args values_hash = Hash.new keys.each_with_index { |k,i| values_hash[k] = 0 } quota.set_quota(user_id, values_hash) exit_with_code 0 end ######################################################################## delete_desc = "Delete the defined quotas for the given user" command :delete, delete_desc, :userid do quota.delete_quota(args[0]) exit_with_code 0 end ######################################################################## show_desc = "Show the user's quota and usage. (usage/quota)" FORCE={ :name => "force", :short => "-f", :large => "--force", :description => "Force the usage calculation instead of using the cache" } command :show, show_desc, :userid, :options=>[FORCE] do user_usage = quota.get_usage(args[0],nil,options[:force]) user_quota = quota.get_quota(args[0]) show_table([user_quota], user_usage) exit_with_code 0 end ######################################################################## list_desc = "List the defined quotas for all the users" command :list, list_desc do show_table(quota.get_quota) exit_with_code 0 end endopennebula-3.4.1/src/authm_mad/remotes/quota/test/0000755000175000017500000000000011750754334022070 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/quota/test/quota_spec.rb0000644000175000017500000002471211750754334024566 0ustar drazzibdrazzib$: << '.' require 'helper/test_helper' describe "Quota testing" do before(:all) do @mock_client = MockClient.new @quota = Quota.new @quota.set_client(@mock_client) @quota.rm_and_set_testdb @uid1 = 0 @quota1 = { :CPU => 2.4, :MEMORY => 1024, :NUM_VMS => 4, :STORAGE => 10000 } @uid2 = 1 @quota2 = { :CPU => 1.2, :MEMORY => 512, :NUM_VMS => 2, :STORAGE => 5000 } # Generate VM ACL request vm_template = <<-EOT EOT vm_base64 = Base64::encode64(vm_template) @acl_vm_create = "VM:#{vm_base64}:CREATE:0:1:1" # Generate IMAGE ACL request image_template = <<-EOT EOT image_base64 = Base64::encode64(image_template) @acl_image_create = "IMAGE:#{image_base64}:CREATE:0:1:1" # Generate TEMPLATE ACL request temp_template = <<-EOT EOT temp_base64 = Base64::encode64(temp_template) @acl_template_instantiate = "TEMPLATE:#{temp_base64}:INSTANTIATE:0:1:1" end it "should check default quotas" do quota1 = @quota.get_quota(@uid1) quota1[:UID].should eql(0) quota1[:NUM_VMS].should eql(nil) quota1[:CPU].should eql(nil) quota1[:MEMORY].should eql(nil) quota1[:STORAGE].should eql(nil) end it "should check default usage cache" do usage1cache = @quota.get_usage(@uid1) usage1cache[:UID].should eql(0) usage1cache[:NUM_VMS].should eql(nil) usage1cache[:CPU].should eql(nil) usage1cache[:MEMORY].should eql(nil) usage1cache[:STORAGE].should eql(nil) end it "should check default cache (force)" do usage1force = @quota.get_usage(@uid1, nil, true) usage1force[:UID].should eql(0) usage1force[:NUM_VMS].should eql(0) usage1force[:CPU].should eql(0) usage1force[:MEMORY].should eql(0) usage1force[:STORAGE].should eql(0) end it "should authorize the user because there is no quota defined" do @quota.authorize(@uid1, @acl_vm_create).should eql(false) @quota.authorize(@uid1, @acl_image_create).should eql(false) @quota.authorize(@uid1, @acl_template_instantiate).should eql(false) end it "should add a new VM" do values = { :CPU => 2, :MEMORY => 128, :UID => 2, :GID => 4, } @mock_client.add_vm(0, values) end it "should check the usage cache is not updated" do usage1cache = @quota.get_usage(@uid1) usage1cache[:UID].should eql(0) usage1cache[:NUM_VMS].should eql(0) usage1cache[:CPU].should eql(0.0) usage1cache[:MEMORY].should eql(0) usage1cache[:STORAGE].should eql(0) end it "should check the cache (force)" do usage1force = @quota.get_usage(@uid1, nil, true) usage1force[:UID].should eql(0) usage1force[:NUM_VMS].should eql(1) usage1force[:CPU].should eql(2.0) usage1force[:MEMORY].should eql(128) usage1force[:STORAGE].should eql(0) end it "should check the usage cache is updated and contains the last usage" do usage1cache = @quota.get_usage(@uid1) usage1cache[:UID].should eql(0) usage1cache[:NUM_VMS].should eql(1) usage1cache[:CPU].should eql(2.0) usage1cache[:MEMORY].should eql(128) usage1cache[:STORAGE].should eql(0) end it "should add a new Image" do values = { :UID => 2, :GID => 4, :SIZE => 1000 } @mock_client.add_image(0, values) end it "should check the usage cache is not updated" do usage1cache = @quota.get_usage(@uid1) usage1cache[:UID].should eql(0) usage1cache[:NUM_VMS].should eql(1) usage1cache[:CPU].should eql(2.0) usage1cache[:MEMORY].should eql(128) usage1cache[:STORAGE].should eql(0) end it "should check the cache (force)" do usage1force = @quota.get_usage(@uid1, nil, true) usage1force[:UID].should eql(0) usage1force[:NUM_VMS].should eql(1) usage1force[:CPU].should eql(2.0) usage1force[:MEMORY].should eql(128) usage1force[:STORAGE].should eql(1000) end it "should check the usage cache is updated and contains the last usage" do usage1cache = @quota.get_usage(@uid1) usage1cache[:UID].should eql(0) usage1cache[:NUM_VMS].should eql(1) usage1cache[:CPU].should eql(2.0) usage1cache[:MEMORY].should eql(128) usage1cache[:STORAGE].should eql(1000) end it "should add a second VM" do values = { :CPU => 2, :MEMORY => 128, :UID => 2, :GID => 4, } @mock_client.add_vm(1, values) end it "should check the usage cache is not updated" do usage1cache = @quota.get_usage(@uid1) usage1cache[:UID].should eql(0) usage1cache[:NUM_VMS].should eql(1) usage1cache[:CPU].should eql(2.0) usage1cache[:MEMORY].should eql(128) usage1cache[:STORAGE].should eql(1000) end it "should check the cache (force)" do usage1force = @quota.get_usage(@uid1, nil, true) usage1force[:UID].should eql(0) usage1force[:NUM_VMS].should eql(1*2) usage1force[:CPU].should eql(2.0*2) usage1force[:MEMORY].should eql(128*2) usage1force[:STORAGE].should eql(1000) end it "should check the usage cache is updated and contains the last usage" do usage1cache = @quota.get_usage(@uid1) usage1cache[:UID].should eql(0) usage1cache[:NUM_VMS].should eql(1*2) usage1cache[:CPU].should eql(2.0*2) usage1cache[:MEMORY].should eql(128*2) usage1cache[:STORAGE].should eql(1000) end it "should add a second Image" do values = { :UID => 2, :GID => 4, :SIZE => 1000 } @mock_client.add_image(1, values) end it "should check the usage cache is not updated" do usage1cache = @quota.get_usage(@uid1) usage1cache[:UID].should eql(0) usage1cache[:NUM_VMS].should eql(1*2) usage1cache[:CPU].should eql(2.0*2) usage1cache[:MEMORY].should eql(128*2) usage1cache[:STORAGE].should eql(1000) end it "should check the cache (force)" do usage1force = @quota.get_usage(@uid1, nil, true) usage1force[:UID].should eql(0) usage1force[:NUM_VMS].should eql(1*2) usage1force[:CPU].should eql(2.0*2) usage1force[:MEMORY].should eql(128*2) usage1force[:STORAGE].should eql(1000*2) end it "should check the usage cache is updated and contains the last usage" do usage1cache = @quota.get_usage(@uid1) usage1cache[:UID].should eql(0) usage1cache[:NUM_VMS].should eql(1*2) usage1cache[:CPU].should eql(2.0*2) usage1cache[:MEMORY].should eql(128*2) usage1cache[:STORAGE].should eql(1000*2) end it "should add a new quota and check it" do @quota.set_quota(@uid1, @quota1) quota = @quota.get_quota(@uid1) @quota1.each{ |key,value| quota[key].should eql(value) } end it "should not authorize the user because the vm quota is spent" do err_msg = "CPU quota exceeded (Quota: 2.4, Used: 4.0, Requested: 2.0)" @quota.authorize(@uid1, @acl_vm_create).should eql(err_msg) @quota.authorize(@uid1, @acl_template_instantiate).should eql(err_msg) @quota.authorize(@uid1, @acl_image_create).should eql(false) end it "should add a new quota for another user and check it" do @quota.set_quota(@uid2, @quota2) quota = @quota.get_quota(@uid2) @quota2.each{ |key,value| quota[key].should eql(value) } end it "should list all the defined quotas" do quotas = @quota.get_quota quotas.each { |quota| if quota[:UID] == @uid1 @quota1.each{ |key,value| quota[key].should eql(value) } elsif quota[:UID] == @uid2 @quota2.each{ |key,value| quota[key].should eql(value) } end } end it "should update the first user quota and check it" do new_quota = Hash.new @quota1.each { |key,value| new_quota[key] = value*3 } @quota.set_quota(@uid1, new_quota) quota = @quota.get_quota(@uid1) new_quota.each{ |key,value| quota[key] == value } end it "should authorize the user because the quota is not spent" do @quota.authorize(@uid1, @acl_vm_create).should eql(false) @quota.authorize(@uid1, @acl_image_create).should eql(false) @quota.authorize(@uid1, @acl_template_instantiate).should eql(false) end it "should update the first user quota and check it" do new_quota = { :STORAGE => 0 } @quota.set_quota(@uid1, new_quota) quota = @quota.get_quota(@uid1) quota[:STORAGE].should eql(new_quota[:STORAGE]) end it "should not authorize the user because the image quota is spent" do @quota.authorize(@uid1, @acl_vm_create).should eql(false) @quota.authorize(@uid1, @acl_template_instantiate).should eql(false) err_msg = "STORAGE quota exceeded (Quota: 0, Used: 2000, Requested: 271)" @quota.authorize(@uid1, @acl_image_create).should eql(err_msg) end it "should delete the quota and check it" do @quota.delete_quota(@uid1) quota1 = @quota.get_quota(@uid1) quota1[:UID].should eql(0) quota1[:NUM_VMS].should eql(nil) quota1[:CPU].should eql(nil) quota1[:MEMORY].should eql(nil) quota1[:STORAGE].should eql(nil) end it "should authorize the user because the quota was deleted" do @quota.authorize(@uid1, @acl_vm_create).should eql(false) @quota.authorize(@uid1, @acl_image_create).should eql(false) @quota.authorize(@uid1, @acl_template_instantiate).should eql(false) end endopennebula-3.4.1/src/authm_mad/remotes/quota/test/helper/0000755000175000017500000000000011750754334023347 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/quota/test/helper/test_helper.rb0000644000175000017500000000105311750754334026211 0ustar drazzibdrazzib 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 $: << './helper' $: << '.' $: << '..' require 'mock_client' require 'OpenNebula' require 'quota' class Quota def set_client(client) @client = client end def rm_and_set_testdb `rm -f /tmp/onequota_test.db` @db=Sequel.connect("sqlite:///tmp/onequota_test.db") create_table(QUOTA_TABLE) create_table(USAGE_TABLE) end end opennebula-3.4.1/src/authm_mad/remotes/quota/test/helper/mock_client.rb0000644000175000017500000000242211750754334026163 0ustar drazzibdrazzibrequire 'erb' FPATH = "./fixtures/" class MockClient def initialize @vms = Hash.new @done_vms = Hash.new @images = Hash.new end def call(action, *args) xmlrpc_action = "one."+action case xmlrpc_action when "one.vm.info" id = args[0] vm = @vms[id] return ERB.new(File.read(FPATH+'vm.xml')).result(binding) when "one.vmpool.info" case args[3] when -1 vms = @vms return ERB.new(File.read(FPATH+'vmpool.xml')).result(binding) when 6 then vms = @done_vms return ERB.new(File.read(FPATH+'vmpool.xml')).result(binding) end when "one.imagepool.info" images = @images return ERB.new(File.read(FPATH+'imagepool.xml')).result(binding) end end def add_vm(id, values) if values[:state] == 6 @done_vms[id] = values.clone else @vms[id] = values.clone end end def delete_vm(id) @vms.delete(id) @vms_done.delete(id) end def add_image(id, values) @images[id] = values end endopennebula-3.4.1/src/authm_mad/remotes/quota/test/fixtures/0000755000175000017500000000000011750754334023741 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/quota/test/fixtures/vmpool.xml0000644000175000017500000000360711750754334026005 0ustar drazzibdrazzib <% vms.each do |id,vm| %> <%= id %> <%= vm[:uid] ? vm[:uid] : 0 %> <%= vm[:gid] ? vm[:gid] : 0 %> <%= vm[:name] ? vm[:uid] : 'pepe' %> <%= vm[:last_poll] ? vm[:last_poll] : '1309275256' %> <%= vm[:state] ? vm[:state] : 3 %> 3 1309275252 0 dummy <%= vm[:memory] ? vm[:memory] : 128 %> <%= vm[:cpu] ? vm[:cpu] : 1 %> <%= vm[:net_tx] ? vm[:net_tx] : 0 %> <%= vm[:net_rx] ? vm[:net_rx] : 0 %> <% if history = vm[:history] %> <% h = history.last %> <%= h[:seq] ? h[:seq] : 0 %> <%= h[:hostname] ? h[:hostname] : "kvxen" %> /Users/dmolina/trabajo/acctmoni/install/var/ <%= h[:hid] ? h[:hid] : 0 %> 1309275256 0 vmm_dummy tm_dummy <%= h[:pstime] ? h[:pstime] : 0 %> <%= h[:petime] ? h[:petime] : 0 %> <%= h[:rstime] ? h[:rstime] : 0 %> <%= h[:retime] ? h[:retime] : 0 %> <%= h[:estime] ? h[:estime] : 0 %> <%= h[:eetime] ? h[:eetime] : 0 %> <%= h[:reason] ? h[:reason] : 0 %> <% end %> <% end %> opennebula-3.4.1/src/authm_mad/remotes/quota/test/fixtures/imagepool.xml0000644000175000017500000000205211750754334026436 0ustar drazzibdrazzib <% images.each do |id,image| %> <%= id %> <%= image[:uid] ? image[:uid] : 0 %> <%= image[:gid] ? image[:gid] : 0 %> <%= image[:uname] ? image[:uname] : 'oneadmin' %> <%= image[:gname] ? image[:gname] : 'oneadmin' %> <%= image[:name] ? image[:name] : 'ttylinux' %> <%= image[:type] ? image[:type] : 0 %> <%= image[:pub] ? image[:pub] : 0 %> <%= image[:persistent] ? image[:persistent] : 0 %> 1314875019 <%= image[:source] ? image[:source] : '/etc/hosts' %> <%= image[:state] ? image[:state] : 1 %> <%= image[:size] ? image[:size] : 100 %> 0 <% end %> opennebula-3.4.1/src/authm_mad/remotes/quota/test/fixtures/vm.xml0000644000175000017500000000330111750754334025102 0ustar drazzibdrazzib <%= id %> <%= vm[:uid] ? vm[:uid] : 0 %> <%= vm[:gid] ? vm[:gid] : 0 %> <%= vm[:name] ? vm[:uid] : 'pepe' %> <%= vm[:last_poll] ? vm[:last_poll] : '1309275256' %> <%= vm[:state] ? vm[:state] : 3 %> 3 1309275252 0 dummy <%= vm[:memory] ? vm[:memory] : 128 %> <%= vm[:cpu] ? vm[:cpu] : 1 %> <%= vm[:net_tx] ? vm[:net_tx] : 0 %> <%= vm[:net_rx] ? vm[:net_rx] : 0 %> <% if history = vm[:history] %> <% history.each do |h| %> <%= h[:seq] ? h[:seq] : 0 %> <%= h[:hostname] ? h[:hostname] : "kvxen" %> /Users/dmolina/trabajo/acctmoni/install/var/ <%= h[:hid] ? h[:hid] : 0 %> 1309275256 0 vmm_dummy tm_dummy <%= h[:pstime] ? h[:pstime] : 0 %> <%= h[:petime] ? h[:petime] : 0 %> <%= h[:rstime] ? h[:rstime] : 0 %> <%= h[:retime] ? h[:retime] : 0 %> <%= h[:estime] ? h[:estime] : 0 %> <%= h[:eetime] ? h[:eetime] : 0 %> <%= h[:reason] ? h[:reason] : 0 %> <% end %> <% end %> opennebula-3.4.1/src/authm_mad/remotes/quota/authorize0000755000175000017500000000416511750754334023057 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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" ETC_LOCATION="/etc/one/" else RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" ETC_LOCATION=ONE_LOCATION+"/etc/" end $: << RUBY_LIB_LOCATION require 'scripts_common' require 'OpenNebula' require 'quota' user_id = ARGV.shift overall_evalutation = ARGV.pop exit -1 if overall_evalutation.to_i == 0 quota = Quota.new #q = { # :cpu => 10, # :memory => 2048, # :storage => 100000, # :num_vms => 5 #} # #quota.set(1, q) #OpenNebula.log_debug("quotas: #{quota.get(1)}") ARGV.each {|request| obj, template_or_id, op, owner, acl_eval = request.split(':') if ( obj == "TEMPLATE" && op == "USE" && ARGV.size == 1 ) rc = false else rc = quota.authorize(user_id, request) end if rc OpenNebula.error_message rc exit -1 end } #OpenNebula.log_debug("AUTHORIZE ARGS: #{ARGV.join(' ')}") exit 0opennebula-3.4.1/src/authm_mad/remotes/quota/quota.rb0000644000175000017500000002714711750754334022602 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 'sequel' require 'base64' require 'yaml' require 'uri' require 'net/http' class Quota ########################################################################### # Constants with paths to relevant files and defaults ########################################################################### ONE_LOCATION=ENV["ONE_LOCATION"] if !ONE_LOCATION VAR_LOCATION = "/var/lib/one" ETC_LOCATION = "/etc/one" else VAR_LOCATION = ONE_LOCATION + "/var" ETC_LOCATION = ONE_LOCATION + "/etc" end CONF_FILE = ETC_LOCATION + "/auth/quota.conf" CONF = { :db => "sqlite://#{VAR_LOCATION}/onequota.db", :defaults => { :CPU => nil, :MEMORY => nil, :NUM_VMS => nil, :STORAGE => nil } } ########################################################################### # Schema for the USAGE and QUOTA tables ########################################################################### DB_QUOTA_SCHEMA = { :CPU => Float, :MEMORY => Integer, :NUM_VMS => Integer, :STORAGE => Integer } QUOTA_TABLE = :quotas USAGE_TABLE = :usage ########################################################################### # Usage params to calculate each quota ########################################################################### VM_USAGE = { :CPU => { :proc_info => lambda {|template| template['CPU']}, :xpath => 'TEMPLATE/CPU' }, :MEMORY => { :proc_info => lambda {|template| template['MEMORY']}, :xpath => 'TEMPLATE/MEMORY' }, :NUM_VMS => { :proc_info => lambda {|template| 1 }, :xpath => 'ID', :count => true } } IMAGE_USAGE = { :STORAGE => { :proc_info => lambda {|template| if template['TYPE'] == 'DATABLOCK' template['SIZE'].to_i elsif template['PATH'] uri = URI.parse(template['PATH']) size = if uri.scheme.nil? File.size(template['PATH']) else Net::HTTP.start(uri.host,uri.port) { |http| http.head(uri.path) }.content_length end (size.to_f / 2**20).round elsif template['SAVED_VM_ID'] vm_id = template['SAVED_VM_ID'].to_i disk_id = template['SAVED_DISK_ID'].to_i client = OpenNebula::Client.new vm = OpenNebula::VirtualMachine.new_with_id(vm_id, client) vm.info im_id = vm["DISK[DISK_ID=#{disk_id}]/IMAGE_ID"].to_i im = OpenNebula::Image.new_with_id(im_id, client) im.info im['SIZE'].to_i else 0 end }, :xpath => 'SIZE' } } RESOURCES = ["VM", "IMAGE"] ########################################################################### # DB handling ########################################################################### def initialize conf = YAML.load_file(CONF_FILE) @conf=CONF.merge(conf) {|key,h1,h2| if h1.instance_of?(Hash) && h2.instance_of?(Hash) h1.merge(h2) else if h2 h2 else h1 end end } @client = OpenNebula::Client.new @db=Sequel.connect(@conf[:db]) create_table(QUOTA_TABLE) create_table(USAGE_TABLE) end # Creates database quota table if it does not exist def create_table(table) @db.create_table?(table) do Integer :UID DB_QUOTA_SCHEMA.each { |key,value| column key, value } primary_key :UID index :UID end end # Adds new user limits def set(table, uid, quota={}) data=quota.delete_if{|key,value| !DB_QUOTA_SCHEMA.keys.include?(key)} quotas=@db[table].filter(:UID => uid) if quotas.first quotas.update(data) else @db[table].insert(data.merge!(:UID => uid)) end end # Gets user limits def get(table, uid=nil) if uid @db[table].filter(:UID => uid).first else @db[table].all end end # Delete user limits def delete(table, uid) quotas=@db[table].filter(:UID => uid) if quotas.first quotas.delete end end ########################################################################### # Quota Client ########################################################################### def set_quota(uid, quota={}) set(QUOTA_TABLE, uid, quota) end # Retrieves quota information for a given user # # @param [Integer, nil] uid the user id from which get the quota # information, if nil will retrieve the quotas for all users. # @return [Hash] Hash containing the quota information and the user id # # { # :uid => 4, # :cpu => 8, # :memory => 8064, # :num_vms => 4, # :storage => 1240019 # } def get_quota(uid=nil) limit = get(QUOTA_TABLE, uid) limit ? limit : @conf[:defaults].merge!(:UID => uid) end def delete_quota(uid) delete(QUOTA_TABLE, uid) end ########################################################################### # Authorization ########################################################################### def authorize(user_id, request) obj, template_or_id, op, owner, acl_eval = request.split(':') if acl_eval.to_i == 0 return "ACL evaluation denied" end # Check if this op needs to check the quota return false unless with_quota?(obj, op) template = "" if ( obj == "TEMPLATE" ) obj = "VM" vm_template = OpenNebula::Template.new_with_id(template_or_id, @client) vm_template.info vm_template.each("TEMPLATE") { |xml_elem| template = xml_elem.to_xml } else template = Base64::decode64(template_or_id) end check_quotas(user_id.to_i, obj, template) end def check_quotas(user_id, obj, template) info = get_resources(obj, template) total = get_usage(user_id, obj, true) quota = get_quota(user_id) msg = "" separator = "" info.each { |qname, quota_requested| unless quota[qname] || quota[qname]==0 next end type = DB_QUOTA_SCHEMA[qname].name.to_sym used = send(type, total[qname]) request = send(type, quota_requested) limit = send(type, quota[qname]) spent = used + request if spent > limit msg << separator msg << " #{qname.to_s.upcase} quota exceeded " msg << "(Quota: #{limit}, " msg << "Used: #{used}, " msg << "Requested: #{request})" separator = ";" end } if msg=="" return false else return msg.strip end end def with_quota?(obj, op) return (obj == "VM" && op == "CREATE") || (obj == "IMAGE" && op == "CREATE") || (obj == "TEMPLATE" && op == "USE") end ########################################################################### # Usage ########################################################################### # Retrieves usage information for a given user # # @param [Integer] uid the user id from which get the usage information. # @param ["VM", "IMAGE"] resource kind of resource. If nil will return # the usage for all kinds of resources # @param [true, false] force If true will force the usage calculation # instead of retrieving it from the cache # @return [Hash] Hash containing the usage information and the user id # # { # :uid => 4, # :cpu => 8, # :memory => 8064, # :num_vms => 4, # :storage => 1240019 # } def get_usage(user_id, resource=nil, force=false) if force if RESOURCES.include?(resource) resources = [resource] else resources = RESOURCES end usage = Hash.new resources.each{ |res| pool = get_pool(res, user_id) base_xpath = "/#{res}_POOL/#{resource}" Quota.const_get("#{res}_USAGE".to_sym).each { |key, params| usage[key] ||= 0 pool.each_xpath("#{base_xpath}/#{params[:xpath]}") { |elem| if elem if params[:count] usage[key] += 1 else usage[key] += send(DB_QUOTA_SCHEMA[key].name.to_sym, elem) end end } } set(USAGE_TABLE, user_id, usage) unless usage.empty? usage.merge!(:UID => user_id) } else usage = get(USAGE_TABLE, user_id) usage ||= {:UID => user_id} end usage end # Retrieve the useful information of the template for the specified # kind of resource def get_resources(resource, xml_template) template = OpenNebula::XMLElement.new template.initialize_xml(xml_template, 'TEMPLATE') info = Hash.new self.class.const_get("#{resource}_USAGE").each { |key, params| info[key] = params[:proc_info].call(template).to_i } info end # Returns a an Array than contains the elements of the resource Pool def get_pool(resource, user_id) pool = case resource when "VM" then OpenNebula::VirtualMachinePool.new(@client, user_id) when "IMAGE" then OpenNebula::ImagePool.new(@client, user_id) end rc = pool.info return pool end end opennebula-3.4.1/src/authm_mad/remotes/quota/quota.conf0000644000175000017500000000301711750754334023112 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # # Database URI #:db: sqlite:///var/one/onequota.db #------------------------------------------------------------------------------- # Default quotas, these apply to all users. Leave empty to disable quota for # a given metric. #------------------------------------------------------------------------------- :defaults: :CPU: :MEMORY: :NUM_VMS: :STORAGE: opennebula-3.4.1/src/authm_mad/remotes/server_x509/0000755000175000017500000000000011750754334022053 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/server_x509/authenticate0000755000175000017500000000377411750754334024472 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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" ETC_LOCATION="/etc/one/" else RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" ETC_LOCATION=ONE_LOCATION+"/etc/" end $: << RUBY_LIB_LOCATION require 'server_x509_auth' require 'scripts_common' user = ARGV[0] # username as registered in OpenNebula pass = ARGV[1] # password for this user secret = ARGV[2] # Base64 encoded secret as obtained from login_token #OpenNebula.log_debug("Authenticating #{user}, with password #{pass} (#{secret})") begin server_auth = ServerX509Auth.new dsecret = Base64::decode64(secret) rc = server_auth.authenticate(user, pass, dsecret) rescue => e OpenNebula.error_message e.message exit -1 end if rc == true exit 0 else OpenNebula.error_message rc exit -1 end opennebula-3.4.1/src/authm_mad/remotes/server_x509/server_x509_auth.conf0000644000175000017500000000036311750754334026040 0ustar drazzibdrazzib# User to be used for x509 server authentication #:srv_user: serveradmin # Path to the certificate used by the OpenNebula Services # Certificates must be in PEM format #:one_cert: "/etc/one/auth/cert.pem" #:one_key: "/etc/one/auth/pk.pem" opennebula-3.4.1/src/authm_mad/remotes/server_x509/server_x509_auth.rb0000644000175000017500000000757111750754334025526 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 'openssl' require 'base64' require 'fileutils' require 'x509_auth' # Server authentication class. This authmethod can be used by opennebula services # to let access authenticated users by other means. It is based on x509 server # certificates class ServerX509Auth < X509Auth ########################################################################### #Constants with paths to relevant files and defaults ########################################################################### SERVER_AUTH_CONF_PATH = ETC_LOCATION + "/auth/server_x509_auth.conf" SERVER_DEFAULTS = { :one_cert => ETC_LOCATION + "/auth/cert.pem", :one_key => ETC_LOCATION + "/auth/key.pem" } ########################################################################### def initialize() @options = SERVER_DEFAULTS load_options(SERVER_AUTH_CONF_PATH) begin certs = [ File.read(@options[:one_cert]) ] key = File.read(@options[:one_key]) super(:certs_pem => certs, :key_pem => key) rescue raise end if @options[:srv_user] == nil || @options[:srv_user].empty? raise "User for x509 server not defined" end end ########################################################################### # Client side ########################################################################### # Creates a ServerCipher for client and driver sage class << ServerX509Auth alias :new_client :new alias :new_driver :new end # Generates a login token in the form: # - server_user:target_user:time_expires def login_token(expire, target_user=nil) target_user ||= @options[:srv_user] token_txt = "#{@options[:srv_user]}:#{target_user}:#{expire}" token = encrypt(token_txt) token64 = Base64::encode64(token).strip.delete("\n") return "#{@options[:srv_user]}:#{target_user}:#{token64}" end ########################################################################### # Server side ########################################################################### # auth method for auth_mad def authenticate(server_user, server_pass, signed_text) begin s_user, t_user, expires = decrypt(signed_text).split(':') return "Server password missmatch" if server_pass != password return "User name missmatch" if ( s_user != server_user || s_user != @options[:srv_user] ) return "login token expired" if Time.now.to_i >= expires.to_i return true rescue => e return e.message end end endopennebula-3.4.1/src/authm_mad/remotes/ldap/0000755000175000017500000000000011750754334020700 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/ldap/authenticate0000755000175000017500000000403211750754334023303 0ustar drazzibdrazzib#!/usr/bin/ruby # ---------------------------------------------------------------------------- # # Copyright 2002-2012, C12G Labs S.L # # # # 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" ETC_LOCATION="/etc/one/" else RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" ETC_LOCATION=ONE_LOCATION+"/etc/" end $: << RUBY_LIB_LOCATION require 'yaml' require 'ldap_auth' user=ARGV[0] pass=ARGV[1] secret=ARGV[2] options=YAML.load(File.read(ETC_LOCATION+'/auth/ldap_auth.conf')) ldap=LdapAuth.new(options) user_name=ldap.find_user(user) if !user_name STDERR.puts "User #{user} not found" exit(-1) end if options[:group] if !ldap.is_in_group?(user_name, options[:group]) STDERR.puts "User #{user} is not in group #{options[:group]}" exit(-1) end end if ldap.authenticate(user_name, secret) puts "ldap #{user} #{user_name}" exit(0) else STDERR.puts "Bad user/password" exit(-1) end opennebula-3.4.1/src/authm_mad/remotes/ldap/ldap_auth.conf0000644000175000017500000000320711750754334023512 0ustar drazzibdrazzib# ---------------------------------------------------------------------------- # # Copyright 2002-2012, C12G Labs S.L # # # # 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. # # ---------------------------------------------------------------------------- # # Ldap user able to query, if not set connects as anonymous #:user: 'admin' #:password: 'password' # Ldap authentication method :auth_method: :simple # Ldap server :host: localhost :port: 389 # base hierarchy where to search for users and groups :base: 'dc=domain' # group the users need to belong to. If not set any user will do :group: 'cn=cloud,ou=groups,dc=domain' # field that holds the user name, if not set 'cn' will be used :user_field: 'cn' opennebula-3.4.1/src/authm_mad/remotes/ldap/test/0000755000175000017500000000000011750754334021657 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/ldap/test/ldap_auth_spec.rb0000644000175000017500000000500611750754334025160 0ustar drazzibdrazzib# ---------------------------------------------------------------------------- # # Copyright 2002-2012, C12G Labs S.L # # # # 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 'ldap_auth' options={ :host => 'ubuntu-test', :base => 'dc=localdomain' } describe LdapAuth do before(:all) do @ldap=LdapAuth.new(options) end it 'should find user dn' do name=@ldap.find_user('user01') name.should=='cn=user01,dc=localdomain' name=@ldap.find_user('user02') name.should=='cn=user02,dc=localdomain' name=@ldap.find_user('user03') name.should==nil name=@ldap.find_user('cn=user01,dc=localdomain') name.should=='cn=user01,dc=localdomain' end it 'should tell if a user is in a group' do group='cn=cloud,ou=groups,dc=localdomain' result=@ldap.is_in_group?('cn=user01,dc=localdomain', group) result.should==true result=@ldap.is_in_group?('cn=user02,dc=localdomain', group) result.should==false end it 'should authenticate user' do result=@ldap.authenticate('cn=user01,dc=localdomain', 'password01') result.should==true result=@ldap.authenticate('cn=user02,dc=localdomain', 'password02') result.should==true result=@ldap.authenticate('cn=user01,dc=localdomain', 'password02') result.should==false result=@ldap.authenticate('user01,dc=localdomain', 'password01') result.should==false end end opennebula-3.4.1/src/authm_mad/remotes/ldap/ldap_auth.rb0000644000175000017500000000564711750754334023202 0ustar drazzibdrazzib# ---------------------------------------------------------------------------- # # Copyright 2002-2012, C12G Labs S.L # # # # 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 'rubygems' require 'net/ldap' class LdapAuth def initialize(options) @options={ :host => 'localhost', :port => 389, :user => nil, :password => nil, :base => nil, :auth_method => :simple, :user_field => 'cn' }.merge(options) ops={} if @options[:user] ops[:auth] = { :method => @options[:auth_method], :username => @options[:user], :password => @options[:password] } end ops[:host]=@options[:host] if @options[:host] ops[:port]=@options[:port].to_i if @options[:port] @ldap=Net::LDAP.new(ops) end def find_user(name) begin result=@ldap.search( :base => @options[:base], :filter => "#{@options[:user_field]}=#{name}") if result && result.first result.first.dn else result=@ldap.search(:base => name) if result && result.first name else nil end end rescue nil end end def is_in_group?(user, group) result=@ldap.search(:base => group, :filter => "(member=#{user})") if result && result.first true else false end end def authenticate(user, password) ldap=@ldap.clone auth={ :method => @options[:auth_method], :username => user, :password => password } if ldap.bind(auth) true else false end end end opennebula-3.4.1/src/authm_mad/remotes/plain/0000755000175000017500000000000011750754334021063 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/plain/authenticate0000755000175000017500000000326111750754334023471 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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" ETC_LOCATION="/etc/one/" else RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" ETC_LOCATION=ONE_LOCATION+"/etc/" end $: << RUBY_LIB_LOCATION require 'scripts_common' user = ARGV[0] pass = ARGV[1] secret = ARGV[2] #OpenNebula.log_debug("Authenticating #{user}, with password #{pass} (#{secret})") if pass == secret exit 0 else OpenNebula.error_message "Invalid credentials" exit -1 end opennebula-3.4.1/src/authm_mad/remotes/x509/0000755000175000017500000000000011750754334020465 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/x509/authenticate0000755000175000017500000000416511750754334023077 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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" ETC_LOCATION="/etc/one/" else RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" ETC_LOCATION=ONE_LOCATION+"/etc/" end $: << RUBY_LIB_LOCATION require 'x509_auth' require 'scripts_common' user = ARGV[0] # username as registered in OpenNebula pass = ARGV[1] # DN registered for this user secret = ARGV[2] # Base64 encoded text and certificate chain text:cert_0:cert_1:..., certs in pem format #OpenNebula.log_debug("Authenticating #{user}, with password #{pass} (#{secret})") begin dsecret = Base64::decode64(secret) asecret = dsecret.split(':') token = asecret[0] certs = asecret[1..-1] x509_auth = X509Auth.new(:certs_pem=>certs) rc = x509_auth.authenticate(user, pass, token) rescue => e OpenNebula.error_message e.message exit -1 end if rc == true exit 0 else OpenNebula.error_message rc exit -1 end opennebula-3.4.1/src/authm_mad/remotes/x509/x509_auth.rb0000644000175000017500000002111611750754334022541 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 'openssl' require 'base64' require 'fileutils' require 'yaml' # X509 authentication class. It can be used as a driver for auth_mad # as auth method is defined. It also holds some helper methods to be used # by oneauth command class X509Auth ########################################################################### #Constants with paths to relevant files and defaults ########################################################################### if !ENV["ONE_LOCATION"] ETC_LOCATION = "/etc/one" else ETC_LOCATION = ENV["ONE_LOCATION"] + "/etc" end LOGIN_PATH = ENV['HOME']+'/.one/one_x509' X509_AUTH_CONF_PATH = ETC_LOCATION + "/auth/x509_auth.conf" X509_DEFAULTS = { :ca_dir => ETC_LOCATION + "/auth/certificates" } ########################################################################### # Initialize x509Auth object # # @param [Hash] default options for path # @option options [String] :certs_pem # cert chain array in colon-separated pem format # @option options [String] :key_pem # key in pem format # @option options [String] :ca_dir # directory of trusted CA's. Needed for auth method, not for login. def initialize(options={}) @options ||= X509_DEFAULTS @options.merge!(options) load_options(X509_AUTH_CONF_PATH) @cert_chain = @options[:certs_pem].collect do |cert_pem| OpenSSL::X509::Certificate.new(cert_pem) end if @options[:key_pem] @key = OpenSSL::PKey::RSA.new(@options[:key_pem]) end end ########################################################################### # Client side ########################################################################### # Creates the login file for x509 authentication at ~/.one/one_x509. # By default it is valid as long as the certificate is valid. It can # be changed to any number of seconds with expire parameter (sec.) def login(user, expire=0) write_login(login_token(user,expire)) end # Returns a valid password string to create a user using this auth driver. # In this case the dn of the user certificate. def password @cert_chain[0].subject.to_s.delete("\s") end # Generates a login token in the form: # user_name:x509:user_name:time_expires:cert_chain # - user_name:time_expires is encrypted with the user certificate # - user_name:time_expires:cert_chain is base64 encoded def login_token(user, expire) if expire != 0 expires = Time.now.to_i + expire.to_i else expires = @cert_chain[0].not_after.to_i end text_to_sign = "#{user}:#{expires}" signed_text = encrypt(text_to_sign) certs_pem = @cert_chain.collect{|cert| cert.to_pem}.join(":") token = "#{signed_text}:#{certs_pem}" token64 = Base64::encode64(token).strip.delete("\n") login_out = "#{user}:#{token64}" login_out end ########################################################################### # Server side ########################################################################### # auth method for auth_mad def authenticate(user, pass, signed_text) begin # Decryption demonstrates that the user posessed the private key. _user, expires = decrypt(signed_text).split(':') return "User name missmatch" if user != _user return "x509 proxy expired" if Time.now.to_i >= expires.to_i # Some DN in the chain must match a DN in the password dn_ok = @cert_chain.each do |cert| if pass.split('|').include?(cert.subject.to_s.delete("\s")) break true end end unless dn_ok == true return "Certificate subject missmatch" end validate return true rescue => e return e.message end end private # Writes a login_txt to the login file as defined in LOGIN_PATH # constant def write_login(login_txt) # Inits login file path and creates ~/.one directory if needed # Set instance variables login_dir = File.dirname(LOGIN_PATH) begin FileUtils.mkdir_p(login_dir) rescue Errno::EEXIST end file = File.open(LOGIN_PATH, "w") file.write(login_txt) file.close File.chmod(0600,LOGIN_PATH) end # Load class options form a configuration file (yaml syntax) def load_options(conf_file) if File.readable?(conf_file) conf_txt = File.read(conf_file) conf_opt = YAML::load(conf_txt) @options.merge!(conf_opt) if conf_opt != false end end ########################################################################### # Methods to encrpyt/decrypt keys ########################################################################### # Encrypts data with the private key of the user and returns # base 64 encoded output in a single line def encrypt(data) return nil if !@key Base64::encode64(@key.private_encrypt(data)).delete("\n").strip end # Decrypts base 64 encoded data with pub_key (public key) def decrypt(data) @cert_chain[0].public_key.public_decrypt(Base64::decode64(data)) end ########################################################################### # Validate the user certificate ########################################################################### def validate now = Time.now failed = "Could not validate user credentials: " # Check start time and end time of certificates @cert_chain.each do |cert| if cert.not_before > now || cert.not_after < now raise failed + "Certificate not valid. Current time is " + now.localtime.to_s + "." end end begin # Validate the proxy certifcates signee = @cert_chain[0] @cert_chain[1..-1].each do |cert| if !((signee.issuer.to_s == cert.subject.to_s) && (signee.verify(cert.public_key))) raise failed + signee.subject.to_s + " with issuer " + signee.issuer.to_s + " was not verified by " + cert.subject.to_s + "." end signee = cert end # Validate the End Entity certificate if !@options[:ca_dir] raise failed + "No certifcate authority directory was specified." end begin ca_hash = signee.issuer.hash.to_s(16) ca_path = @options[:ca_dir] + '/' + ca_hash + '.0' ca_cert = OpenSSL::X509::Certificate.new(File.read(ca_path)) if !((signee.issuer.to_s == ca_cert.subject.to_s) && (signee.verify(ca_cert.public_key))) raise failed + signee.subject.to_s + " with issuer " + signee.issuer.to_s + " was not verified by " + ca_cert.subject.to_s + "." end signee = ca_cert end while ca_cert.subject.to_s != ca_cert.issuer.to_s rescue raise end end end opennebula-3.4.1/src/authm_mad/remotes/x509/x509_auth.conf0000644000175000017500000000025511750754334023064 0ustar drazzibdrazzib# Path to the trusted CA directory. It should contain the trusted CA's for # the server, each CA certificate shoud be name CA_hash.0 #:ca_dir: "/etc/one/auth/certificates" opennebula-3.4.1/src/authm_mad/remotes/dummy/0000755000175000017500000000000011750754334021113 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/dummy/authenticate0000755000175000017500000000243611750754334023524 0ustar drazzibdrazzib#!/usr/bin/env bash # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # # $1 = username # $2 = "-" if user is not registered in opennebula # $3 = password echo core $1 $3 opennebula-3.4.1/src/authm_mad/remotes/server_cipher/0000755000175000017500000000000011750754334022620 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/server_cipher/authenticate0000755000175000017500000000373011750754334025227 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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" ETC_LOCATION="/etc/one/" else RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" ETC_LOCATION=ONE_LOCATION+"/etc/" end $: << RUBY_LIB_LOCATION require 'server_cipher_auth' require 'scripts_common' user = ARGV[0] # username as registered in OpenNebula pass = ARGV[1] # password for this user secret = ARGV[2] # Base64 encoded secret as obtained from login_token #OpenNebula.log_debug("Authenticating #{user}, with password #{pass} (#{secret})") begin server_auth = ServerCipherAuth.new_driver rc = server_auth.authenticate(user, pass, secret) rescue => e OpenNebula.error_message e.message exit -1 end if rc == true exit 0 else OpenNebula.error_message rc exit -1 endopennebula-3.4.1/src/authm_mad/remotes/server_cipher/server_cipher_auth.rb0000644000175000017500000001141011750754334027023 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 'openssl' require 'digest/sha1' require 'base64' require 'fileutils' # Server authentication class. This method can be used by OpenNebula services # to let access authenticated users by other means. It is based on OpenSSL # symmetric ciphers class ServerCipherAuth ########################################################################### #Constants with paths to relevant files and defaults ########################################################################### CIPHER = "aes-256-cbc" ########################################################################### def initialize(srv_user, srv_passwd) @srv_user = srv_user @srv_passwd = srv_passwd if !srv_passwd.empty? @key = Digest::SHA1.hexdigest(@srv_passwd) else @key = "" end @cipher = OpenSSL::Cipher::Cipher.new(CIPHER) end ########################################################################### # Client side ########################################################################### # Creates a ServerCipher for client usage def self.new_client(srv_user=nil, srv_passwd=nil) if ( srv_user == nil || srv_passwd == nil ) begin if ENV["ONE_CIPHER_AUTH"] and !ENV["ONE_CIPHER_AUTH"].empty? one_auth = File.read(ENV["ONE_CIPHER_AUTH"]) else raise "ONE_CIPHER_AUTH environment variable not set" end one_auth.rstrip! rc = one_auth.match(/(.*?):(.*)/) if rc.nil? raise "Bad format for one_auth token (:)" else srv_user = rc[1] srv_passwd = rc[2] end rescue => e raise e.message end end self.new(srv_user, srv_passwd) end # Generates a login token in the form: # - server_user:target_user:time_expires # The token is then encrypted with the contents of one_auth def login_token(expire, target_user=nil) target_user ||= @srv_user token_txt = "#{@srv_user}:#{target_user}:#{expire}" token = encrypt(token_txt) token64 = Base64::encode64(token).strip.delete("\n") return "#{@srv_user}:#{target_user}:#{token64}" end # Returns a valid password string to create a user using this auth driver def password return @srv_passwd end ########################################################################### # Driver side ########################################################################### # Creates a ServerCipher for driver usage def self.new_driver() self.new("","") end # auth method for auth_mad def authenticate(srv_user,srv_pass, signed_text) begin @key = srv_pass s_user, t_user, expires = decrypt(signed_text).split(':') return "User name missmatch" if s_user != srv_user return "login token expired" if Time.now.to_i >= expires.to_i return true rescue => e return e.message end end private def encrypt(data) @cipher.encrypt @cipher.key = @key rc = @cipher.update(data) rc << @cipher.final return rc end def decrypt(data) @cipher.decrypt @cipher.key = @key rc = @cipher.update(Base64::decode64(data)) rc << @cipher.final return rc end endopennebula-3.4.1/src/authm_mad/remotes/ssh/0000755000175000017500000000000011750754334020555 5ustar drazzibdrazzibopennebula-3.4.1/src/authm_mad/remotes/ssh/authenticate0000755000175000017500000000353011750754334023162 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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" ETC_LOCATION="/etc/one/" else RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" ETC_LOCATION=ONE_LOCATION+"/etc/" end $: << RUBY_LIB_LOCATION require 'ssh_auth' require 'scripts_common' user = ARGV[0] pass = ARGV[1] secret = ARGV[2] #OpenNebula.log_debug("Authenticating #{user}, with password #{pass} (#{secret})") begin ssh_auth = SshAuth.new(:public_key=>pass) rescue Exception => e OpenNebula.error_message e.message exit -1 end rc = ssh_auth.authenticate(user,secret) if rc == true exit 0 else OpenNebula.error_message rc exit -1 end opennebula-3.4.1/src/authm_mad/remotes/ssh/ssh_auth.rb0000644000175000017500000001160411750754334022722 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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 'pp' require 'openssl' require 'base64' require 'fileutils' # SSH key authentication class. It can be used as a driver for auth_mad # as auth method is defined. It also holds some helper methods to be used # by oneauth command class SshAuth LOGIN_PATH = ENV['HOME']+'/.one/one_ssh' # Initialize SshAuth object # # @param [Hash] default options for path # @option options [String] :public_key public key for the user # @option options [String] :private_key key private key for the user. def initialize(options={}) @private_key = nil @public_key = nil if options[:private_key] begin @private_key = File.read(options[:private_key]) rescue Exception => e raise "Cannot read #{options[:private_key]}" end end if options[:public_key] @public_key = options[:public_key] elsif @private_key != nil # Init ssh keys using private key. public key is extracted in a # format compatible with openssl. The public key does not contain # "---- BEGIN/END RSA PUBLIC KEY ----" and is in a single line key = OpenSSL::PKey::RSA.new(@private_key) @public_key = key.public_key.to_pem.split("\n") @public_key = @public_key.reject {|l| l.match(/RSA PUBLIC KEY/) }.join('') end if @private_key.nil? && @public_key.nil? raise "You have to define at least one of the keys" end end # Creates the login file for ssh authentication at ~/.one/one_ssh. # By default it is valid for 1 hour but it can be changed to any number # of seconds with expire parameter (in seconds) def login(user, expire=3600) expire ||= 3600 # Init proxy file path and creates ~/.one directory if needed proxy_dir = File.dirname(LOGIN_PATH) begin FileUtils.mkdir_p(proxy_dir) rescue Errno::EEXIST end # Generate security token time = Time.now.to_i + expire.to_i secret_plain = "#{user}:#{time}" secret_crypted = encrypt(secret_plain) proxy = "#{user}:#{secret_crypted}" file = File.open(LOGIN_PATH, "w") file.write(proxy) file.close File.chmod(0600,LOGIN_PATH) secret_crypted end # Returns a valid password string to create a user using this auth driver. # In this case the ssh public key. def password @public_key end # Checks the proxy created with the login method def authenticate(user, token) begin token_plain = decrypt(token) _user, time = token_plain.split(':') if user == _user if Time.now.to_i >= time.to_i return "ssh proxy expired, login again to renew it" else return true end else return "invalid credentials" end rescue return "error" end end private ########################################################################### # Methods to handle ssh keys ########################################################################### # Encrypts data with the private key of the user and returns # base 64 encoded output in a single line def encrypt(data) rsa=OpenSSL::PKey::RSA.new(@private_key) Base64::encode64(rsa.private_encrypt(data)).gsub!(/\n/, '').strip end # Decrypts base 64 encoded data with pub_key (public key) def decrypt(data) rsa=OpenSSL::PKey::RSA.new(Base64::decode64(@public_key)) rsa.public_decrypt(Base64::decode64(data)) end end opennebula-3.4.1/src/authm_mad/one_auth_mad0000755000175000017500000000314011750754334020651 0ustar drazzibdrazzib#!/bin/bash # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # if [ -z "${ONE_LOCATION}" ]; then DRIVERRC=/etc/one/auth/authrc MADCOMMON=/usr/lib/one/mads/madcommon.sh VAR_LOCATION=/var/lib/one else DRIVERRC=$ONE_LOCATION/etc/auth/authrc MADCOMMON=$ONE_LOCATION/lib/mads/madcommon.sh VAR_LOCATION=$ONE_LOCATION/var fi . $MADCOMMON # Export the vmm_mad specific rc export_rc_vars $DRIVERRC # Go to ONE_LOCATION cd $VAR_LOCATION # Execute the actual MAD execute_mad $* opennebula-3.4.1/src/authm_mad/one_auth_mad.rb0000755000175000017500000001475511750754334021271 0ustar drazzibdrazzib#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2012, 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" ETC_LOCATION="/etc/one/" else RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" ETC_LOCATION=ONE_LOCATION+"/etc/" end $: << RUBY_LIB_LOCATION require 'scripts_common' require 'OpenNebulaDriver' require 'getoptlong' # This is a generic AuthZ/AuthN driver able to manage multiple authentication # protocols (simultaneosly). It also supports the definition of custom # authorization methods class AuthDriver < OpenNebulaDriver # Auth Driver Protocol constants ACTION = { :authN => "AUTHENTICATE", :authZ => "AUTHORIZE" } # Initialize an AuthDriver # # @param [String] the authorization method to be used, nil to use the # built-in ACL engine # @param [Array] authentication modules enabled, nil will use any # any method existing in remotes directory def initialize(authZ, authN, nthreads) super( "auth", :concurrency => nthreads, :threaded => nthreads > 0, :local_actions => {ACTION[:authN] => nil, ACTION[:authZ] => nil} ) register_action(ACTION[:authN].to_sym, method("authN")) register_action(ACTION[:authZ].to_sym, method("authZ")) if authZ != nil @authZ_cmd = File.join(@local_scripts_path, authZ) @authZ_cmd = File.join(@authZ_cmd, ACTION[:authZ].downcase) else @authZ_cmd = nil end if authN == nil # get the directories from remotes dir that have an authenticate # script @authN_protocols=Dir[@local_scripts_path+"/*/authenticate"].map do |d| d.split('/')[-2] end else if authN.class==String @authN_protocols=[authN] else @authN_protocols=authN end end end # Authenticate a user based in a string of the form user:secret when using the # driver secret is protocol:token # @param [String] the id for this request, used by OpenNebula core # to identify the request # @param [String] id of the user, "-1" if not in defined in OpenNebula # @param [String] driver to be used # @param [Strgin] user filed of the auth string # @param [String] password of the user registered in OpenNebula "-" if none # @param [String] secret filed of the auth string def authN(request_id, user_id, driver, user, password, secret) #OpenNebula.log_debug("authN: #{request_id} #{user_id} #{driver} #{password} #{secret}") unless @authN_protocols.include?(driver) return send_message( ACTION[:authN], RESULT[:failure], request_id, "Authentication driver '#{driver}' not available") end #build path for the auth action #/var/lib/one/remotes/auth//authenticate authN_path = File.join(@local_scripts_path, driver) command = File.join(authN_path, ACTION[:authN].downcase) command << " '" << user.gsub("'", '\'"\'"\'') << "' '" << password.gsub("'", '\'"\'"\'') << "' " << secret rc = LocalCommand.run(command, log_method(request_id)) result , info = get_info_from_execution(rc) send_message(ACTION[:authN], result, request_id, info) end # Authenticate a user based in a string of the form user:secret when using the # driver secret is protocol:token # @param [String] the id for this request, used by OpenNebula core # to identify the request # @param [String] id of the user, "-1" if not in defined in OpenNebula # @param [Array] of auth strings, last element is the ACL evaluation of # the overall request (0 = denied, 1 = granted). Each request is in # the form: # OBJECT::OPERATION:OWNER:ACL_EVAL def authZ(request_id, user_id, *requests) requests.flatten! #OpenNebula.log_debug("authZ: #{request_id} #{user_id} #{requests}") if @authZ_cmd == nil if requests[-1] == "1" result = RESULT[:success] else result = RESULT[:failure] end send_message(ACTION[:authZ], result, request_id, "-") else command = @authZ_cmd.clone command << ' ' << user_id << ' ' << requests.join(' ') rc = LocalCommand.run(command, log_method(request_id)) result , info = get_info_from_execution(rc) send_message(ACTION[:authZ], result, request_id, info) end end end # Auth Driver Main program opts = GetoptLong.new( [ '--threads', '-t', GetoptLong::REQUIRED_ARGUMENT ], [ '--authz', '-z', GetoptLong::REQUIRED_ARGUMENT ], [ '--authn', '-n', GetoptLong::REQUIRED_ARGUMENT ] ) threads = 15 authz = nil authn = nil begin opts.each do |opt, arg| case opt when '--threads' threads = arg.to_i when '--authz' authz = arg when '--authn' authn = arg.split(',').map {|a| a.strip } end end rescue Exception => e exit(-1) end auth_driver = AuthDriver.new(authz, authn, threads) auth_driver.start_driver opennebula-3.4.1/src/vm_template/0000755000175000017500000000000011750754334016660 5ustar drazzibdrazzibopennebula-3.4.1/src/vm_template/VMTemplatePool.cc0000644000175000017500000000607511750754334022047 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ /* ************************************************************************** */ /* Template Pool */ /* ************************************************************************** */ #include "VMTemplatePool.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int VMTemplatePool::allocate ( int uid, int gid, const string& uname, const string& gname, VirtualMachineTemplate * template_contents, int * oid, string& error_str) { VMTemplate * vm_template; VMTemplate * vm_template_aux = 0; string name; ostringstream oss; // ------------------------------------------------------------------------ // Build a new VMTemplate object // ------------------------------------------------------------------------ vm_template = new VMTemplate(-1, uid, gid, uname, gname,template_contents); // Check name vm_template->get_template_attribute("NAME", name); if ( !name.empty() ) { // Check for duplicates vm_template_aux = get(name,uid,false); if( vm_template_aux != 0 ) { goto error_duplicated; } } // ------------------------------------------------------------------------ // Insert the Object in the pool // ------------------------------------------------------------------------ *oid = PoolSQL::allocate(vm_template, error_str); return *oid; error_duplicated: oss << "NAME is already taken by TEMPLATE " << vm_template_aux->get_oid() << "."; delete vm_template; *oid = -1; error_str = oss.str(); return *oid; } opennebula-3.4.1/src/vm_template/SConstruct0000644000175000017500000000260311750754334020713 0ustar drazzibdrazzib# SConstruct for src/vm # -------------------------------------------------------------------------- # # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # # a copy of the License at # # # # http://www.apache.org/licenses/LICENSE-2.0 # # # # Unless required by applicable law or agreed to in writing, software # # distributed under the License is distributed on an "AS IS" BASIS, # # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # # See the License for the specific language governing permissions and # # limitations under the License. # #--------------------------------------------------------------------------- # Import('env') lib_name='nebula_vmtemplate' # Sources to generate the library source_files=[ 'VMTemplate.cc', 'VMTemplatePool.cc' ] # Build library env.StaticLibrary(lib_name, source_files) opennebula-3.4.1/src/vm_template/test/0000755000175000017500000000000011750754334017637 5ustar drazzibdrazzibopennebula-3.4.1/src/vm_template/test/SConstruct0000644000175000017500000000306111750754334021671 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # -------------------------------------------------------------------------- Import('env') env.Prepend(LIBS=[ 'nebula_image', 'nebula_um', 'nebula_vm', 'nebula_vmtemplate', 'nebula_hm', 'nebula_cluster', 'nebula_datastore', 'nebula_vnm', 'nebula_authm', 'nebula_acl', 'nebula_template', 'nebula_pool', 'nebula_mad', 'nebula_common', 'nebula_core', 'nebula_sql', 'nebula_log', 'nebula_xml', 'crypto' ]) env.Program('test','VMTemplatePoolTest.cc') opennebula-3.4.1/src/vm_template/test/VMTemplatePoolTest.cc0000644000175000017500000005136211750754334023665 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ #include #include #include #include "VMTemplatePool.h" #include "PoolTest.h" using namespace std; const int uids[] = {0,1,2}; const string names[] = {"Template one", "Second Template", "Third Template"}; const string templates[] = { "NAME = \"Template one\"\n" "MEMORY = 128\n" "CPU = 1", "NAME = \"Second Template\"\n" "MEMORY = 256\n" "CPU = 2", "NAME = \"Third Template\"\n" "MEMORY = 1024\n" "CPU = 3" }; const string xmls[] = { "000the_useroneadminTemplate one1100000000000000000", "110the_useroneadminSecond Template1100000000000000000", "220the_useroneadminThird Template00000000000" }; // This xml dump result has the STIMEs modified to 0000000000 const string xml_dump = "000the_useroneadminTemplate one1100000000000000000110the_useroneadminSecond Template1100000000000000000220the_useroneadminThird Template1100000000000000000"; const string xml_dump_where = "000the_useroneadminTemplate one1100000000000000000110the_useroneadminSecond Template1100000000000000000"; class VMTemplatePoolFriend : public VMTemplatePool { public: VMTemplatePoolFriend(SqlDB * db) : VMTemplatePool(db){}; int allocate(int uid, const string& stemplate, int * oid) { VirtualMachineTemplate * template_contents; char * error_msg = 0; int rc; string err; template_contents = new VirtualMachineTemplate(); rc = template_contents->parse(stemplate,&error_msg); if( rc == 0 ) { return VMTemplatePool::allocate(uid, 0,"the_user","oneadmin",template_contents, oid, err); } else { if (error_msg != 0 ) { free(error_msg); } delete template_contents; return -2; } }; }; /* ************************************************************************* */ /* ************************************************************************* */ class VMTemplatePoolTest : public PoolTest { CPPUNIT_TEST_SUITE (VMTemplatePoolTest); ALL_POOLTEST_CPPUNIT_TESTS(); CPPUNIT_TEST ( names_initialization ); CPPUNIT_TEST ( clone_template ); CPPUNIT_TEST ( update ); CPPUNIT_TEST ( get_using_name ); CPPUNIT_TEST ( wrong_get_name ); CPPUNIT_TEST ( duplicates ); CPPUNIT_TEST ( dump ); CPPUNIT_TEST ( dump_where ); CPPUNIT_TEST ( name_index ); CPPUNIT_TEST ( chown_name_index ); CPPUNIT_TEST_SUITE_END (); protected: void bootstrap(SqlDB* db) { VMTemplatePool::bootstrap(db); }; PoolSQL* create_pool(SqlDB* db) { return new VMTemplatePoolFriend(db); }; int allocate(int index) { int oid; return ((VMTemplatePoolFriend*)pool)->allocate(uids[index], templates[index], &oid); }; void check(int index, PoolObjectSQL* obj) { CPPUNIT_ASSERT( obj != 0 ); string xml_str = ""; // Get the xml and replace the REGTIME to 0, so we can compare // it. ((VMTemplate*)obj)->to_xml(xml_str); fix_regtimes( xml_str ); //* if( xml_str != xmls[index] ) { cout << endl << xml_str << endl << xmls[index] << endl; } //*/ CPPUNIT_ASSERT( obj->get_name() == names[index] ); CPPUNIT_ASSERT( xml_str == xmls[index]); }; public: VMTemplatePoolTest(){xmlInitParser();}; ~VMTemplatePoolTest(){xmlCleanupParser();}; /* ********************************************************************* */ void names_initialization() { VMTemplatePoolFriend * tpool; VMTemplate * temp; // Allocate 2 Templates, so they are written to the DB. allocate(0); allocate(2); // Create a new pool, using the same DB. This new pool should read the // allocated Templates. tpool = new VMTemplatePoolFriend(db); temp = tpool->get(names[0], uids[0], false); CPPUNIT_ASSERT( temp != 0 ); temp = tpool->get(names[1], uids[1], false); CPPUNIT_ASSERT( temp == 0 ); temp = tpool->get(names[2], uids[2], false); CPPUNIT_ASSERT( temp != 0 ); delete tpool; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void clone_template() { string attr_temp; string attr_vmt; string name1 = "NAME"; string name2 = "MEMORY"; VMTemplatePoolFriend * tpool; VMTemplate * temp; VirtualMachineTemplate * vmt; int oid_1; tpool = static_cast(pool); oid_1 = allocate(0); temp = tpool->get(oid_1, true); CPPUNIT_ASSERT( temp != 0 ); vmt = temp->clone_template(); vmt->get(name1,attr_vmt); CPPUNIT_ASSERT( attr_vmt == "Template one"); temp->get_template_attribute(name1.c_str(), attr_temp); CPPUNIT_ASSERT( attr_temp == "Template one"); temp->replace_template_attribute(name2.c_str(), "1024"); vmt->get(name2,attr_vmt); CPPUNIT_ASSERT( attr_vmt == "128"); temp->get_template_attribute(name2.c_str(), attr_temp); CPPUNIT_ASSERT( attr_temp == "1024"); delete vmt; temp->get_template_attribute(name2.c_str(), attr_temp); CPPUNIT_ASSERT( attr_temp == "1024"); tpool->update(temp); temp->unlock(); }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void update() { string description_name = "DESCRIPTION"; string description_val = ""; string new_description = "A new description"; string attr_name = "NEW_ATTRIBUTE"; string attr_val = ""; string new_attr_value = "New value"; string no_value = "Some random value"; VMTemplatePoolFriend * tpool; VMTemplate * temp; int oid_1; tpool = static_cast(pool); oid_1 = allocate(0); temp = tpool->get(oid_1, true); CPPUNIT_ASSERT( temp != 0 ); // Object should be cached. Let's change some template attributes temp->replace_template_attribute(description_name, new_description); temp->replace_template_attribute(attr_name, new_attr_value); temp->remove_template_attribute("ORIGINAL_PATH"); tpool->update(temp); temp->unlock(); temp = tpool->get(oid_1,false); CPPUNIT_ASSERT( temp != 0 ); temp->get_template_attribute("DESCRIPTION", description_val); temp->get_template_attribute("NEW_ATTRIBUTE", attr_val); temp->get_template_attribute("ORIGINAL_PATH", no_value); CPPUNIT_ASSERT( description_val == new_description ); CPPUNIT_ASSERT( attr_val == new_attr_value ); CPPUNIT_ASSERT( no_value == "" ); //Now force access to DB pool->clean(); temp = tpool->get(oid_1,false); CPPUNIT_ASSERT( temp != 0 ); description_val = ""; attr_val = ""; no_value = "Random value"; temp->get_template_attribute("DESCRIPTION", description_val); temp->get_template_attribute("NEW_ATTRIBUTE", attr_val); temp->get_template_attribute("ORIGINAL_PATH", no_value); CPPUNIT_ASSERT( description_val == new_description ); CPPUNIT_ASSERT( attr_val == new_attr_value ); CPPUNIT_ASSERT( no_value == "" ); }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void get_using_name() { int oid_0, oid_1; // Allocate two objects oid_0 = allocate(0); oid_1 = allocate(1); // --------------------------------- // Get first object and check its integrity obj = pool->get(oid_0, false); CPPUNIT_ASSERT( obj != 0 ); check(0, obj); // Get using its name obj = pool->get(names[1], uids[1], true); CPPUNIT_ASSERT( obj != 0 ); obj->unlock(); check(1, obj); // --------------------------------- // Clean the cache, forcing the pool to read the objects from the DB pool->clean(); // Get first object and check its integrity obj = pool->get(names[0], uids[0], false); check(0, obj); // Get using its name obj = pool->get(oid_1, false); check(1, obj); }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void wrong_get_name() { // The pool is empty // Non existing name obj = pool->get("Wrong name", 0, true); CPPUNIT_ASSERT( obj == 0 ); // Allocate an object allocate(0); // Ask again for a non-existing name obj = pool->get("Non existing name",uids[0], true); CPPUNIT_ASSERT( obj == 0 ); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void duplicates() { int rc, oid; VMTemplatePoolFriend * tpool = static_cast(pool); // Allocate a template rc = tpool->allocate(uids[0], templates[0], &oid); CPPUNIT_ASSERT( oid == 0 ); CPPUNIT_ASSERT( oid == rc ); // Try to allocate twice the same template, should fail rc = tpool->allocate(uids[0], templates[0], &oid); CPPUNIT_ASSERT( rc == -1 ); CPPUNIT_ASSERT( oid == rc ); // Try again, this time with different uid. Should be allowed rc = tpool->allocate(uids[1], templates[0], &oid); CPPUNIT_ASSERT( rc >= 0 ); CPPUNIT_ASSERT( oid == rc ); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void dump() { VMTemplatePool * tpool = static_cast(pool); ostringstream oss; int rc; string nan; allocate(0); allocate(1); allocate(2); rc = tpool->dump(oss,nan); CPPUNIT_ASSERT(rc == 0); string result = oss.str(); fix_regtimes(result); //* if( result != xml_dump ) { cout << endl << result << endl << xml_dump << endl; } //*/ CPPUNIT_ASSERT( result == xml_dump ); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void dump_where() { VMTemplatePool * tpool = static_cast(pool); int rc; ostringstream oss; ostringstream where; allocate(0); allocate(1); allocate(2); where << "uid < 2"; rc = tpool->dump(oss, where.str()); CPPUNIT_ASSERT(rc == 0); string result = oss.str(); fix_regtimes(result); //* if( result != xml_dump_where ) { cout << endl << result << endl << xml_dump_where << endl; } //*/ CPPUNIT_ASSERT( result == xml_dump_where ); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void name_index() { VMTemplatePool *tpool = static_cast(pool); VMTemplate *vnet_oid, *vnet_name; int oid_0; int uid_0; string name_0; oid_0 = allocate(0); CPPUNIT_ASSERT(oid_0 != -1); // --------------------------------- // Get by oid vnet_oid = tpool->get(oid_0, true); CPPUNIT_ASSERT(vnet_oid != 0); name_0 = vnet_oid->get_name(); uid_0 = vnet_oid->get_uid(); vnet_oid->unlock(); // Get by name and check it is the same object vnet_name = tpool->get(name_0, uid_0, true); CPPUNIT_ASSERT(vnet_name != 0); vnet_name->unlock(); CPPUNIT_ASSERT(vnet_oid == vnet_name); // --------------------------------- // Clean the cache, forcing the pool to read the objects from the DB tpool->clean(); // Get by oid vnet_oid = tpool->get(oid_0, true); CPPUNIT_ASSERT(vnet_oid != 0); vnet_oid->unlock(); // Get by name and check it is the same object vnet_name = tpool->get(name_0, uid_0, true); CPPUNIT_ASSERT(vnet_name != 0); vnet_name->unlock(); CPPUNIT_ASSERT(vnet_oid == vnet_name); // --------------------------------- // Clean the cache, forcing the pool to read the objects from the DB tpool->clean(); // Get by name vnet_name = tpool->get(name_0, uid_0, true); CPPUNIT_ASSERT(vnet_name != 0); vnet_name->unlock(); // Get by oid and check it is the same object vnet_oid = tpool->get(oid_0, true); CPPUNIT_ASSERT(vnet_oid != 0); vnet_oid->unlock(); CPPUNIT_ASSERT(vnet_oid == vnet_name); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void chown_name_index() { VMTemplatePool *tpool = static_cast(pool); VMTemplate *obj_oid, *obj_name; int oid; int old_uid; int new_uid = 3456; string name; oid = allocate(0); CPPUNIT_ASSERT(oid != -1); // --------------------------------- // Get by oid obj_oid = tpool->get(oid, true); CPPUNIT_ASSERT(obj_oid != 0); name = obj_oid->get_name(); old_uid = obj_oid->get_uid(); // Change owner and update cache index obj_oid->set_user(new_uid, "new_username"); tpool->update(obj_oid); obj_oid->unlock(); tpool->update_cache_index(name, old_uid, name, new_uid); // Get by name, new_uid and check it is the same object obj_name = tpool->get(name, new_uid, true); CPPUNIT_ASSERT(obj_name != 0); obj_name->unlock(); CPPUNIT_ASSERT(obj_oid == obj_name); // Get by name, old_uid and check it does not exist obj_name = tpool->get(name, old_uid, true); CPPUNIT_ASSERT(obj_name == 0); // --------------------------------- // Clean the cache, forcing the pool to read the objects from the DB tpool->clean(); // Get by name, old_uid and check it does not exist obj_name = tpool->get(name, old_uid, true); CPPUNIT_ASSERT(obj_name == 0); // Get by oid obj_oid = tpool->get(oid, true); CPPUNIT_ASSERT(obj_oid != 0); obj_oid->unlock(); // Get by name, new_uid and check it is the same object obj_name = tpool->get(name, new_uid, true); CPPUNIT_ASSERT(obj_name != 0); obj_name->unlock(); CPPUNIT_ASSERT(obj_oid == obj_name); } /* ********************************************************************* */ }; /* ************************************************************************* */ /* ************************************************************************* */ int main(int argc, char ** argv) { return PoolTest::main(argc, argv, VMTemplatePoolTest::suite()); } opennebula-3.4.1/src/vm_template/VMTemplate.cc0000644000175000017500000001723111750754334021211 0ustar drazzibdrazzib/* ------------------------------------------------------------------------ */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* ------------------------------------------------------------------------ */ #include "VMTemplate.h" #define TO_UPPER(S) transform(S.begin(),S.end(),S.begin(),(int(*)(int))toupper) /* ************************************************************************ */ /* VMTemplate :: Constructor/Destructor */ /* ************************************************************************ */ VMTemplate::VMTemplate(int id, int _uid, int _gid, const string& _uname, const string& _gname, VirtualMachineTemplate * _template_contents): PoolObjectSQL(id,TEMPLATE,"",_uid,_gid,_uname,_gname,table), regtime(time(0)) { if (_template_contents != 0) { obj_template = _template_contents; } else { obj_template = new VirtualMachineTemplate; } } /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ VMTemplate::~VMTemplate() { if ( obj_template != 0 ) { delete obj_template; } } /* ************************************************************************ */ /* VMTemplate :: Database Access Functions */ /* ************************************************************************ */ const char * VMTemplate::table = "template_pool"; const char * VMTemplate::db_names = "oid, name, body, uid, gid, owner_u, group_u, other_u"; const char * VMTemplate::db_bootstrap = "CREATE TABLE IF NOT EXISTS template_pool (oid INTEGER PRIMARY KEY, " "name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, " "owner_u INTEGER, group_u INTEGER, other_u INTEGER)"; /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ int VMTemplate::insert(SqlDB *db, string& error_str) { int rc; ostringstream oss; // --------------------------------------------------------------------- // Check default attributes // --------------------------------------------------------------------- // ------------ NAME & TEMPLATE_ID -------------------- oss << oid; replace_template_attribute("TEMPLATE_ID",oss.str()); get_template_attribute("NAME", name); if ( name.empty() == true ) { oss.str(""); oss << "template-" << oid; name = oss.str(); } else if ( name.length() > 128 ) { error_str = "NAME is too long; max length is 128 chars."; return -1; } // ------------------------------------------------------------------------ // Insert the Template // ------------------------------------------------------------------------ rc = insert_replace(db, false, error_str); return rc; } /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ int VMTemplate::insert_replace(SqlDB *db, bool replace, string& error_str) { ostringstream oss; int rc; string xml_body; char * sql_name; char * sql_xml; // Update the Object sql_name = db->escape_str(name.c_str()); if ( sql_name == 0 ) { goto error_name; } sql_xml = db->escape_str(to_xml(xml_body).c_str()); if ( sql_xml == 0 ) { goto error_body; } if ( validate_xml(sql_xml) != 0 ) { goto error_xml; } if(replace) { oss << "REPLACE"; } else { oss << "INSERT"; } // Construct the SQL statement to Insert or Replace oss <<" INTO " << table <<" ("<< db_names <<") VALUES (" << oid << "," << "'" << sql_name << "'," << "'" << sql_xml << "'," << uid << "," << gid << "," << owner_u << "," << group_u << "," << other_u << ")"; rc = db->exec(oss); db->free_str(sql_name); db->free_str(sql_xml); return rc; error_xml: db->free_str(sql_name); db->free_str(sql_xml); error_str = "Error transforming the Template to XML."; goto error_common; error_body: db->free_str(sql_name); goto error_generic; error_name: goto error_generic; error_generic: error_str = "Error inserting Template in DB."; error_common: return -1; } /* ************************************************************************ */ /* VMTemplate :: Misc */ /* ************************************************************************ */ string& VMTemplate::to_xml(string& xml) const { ostringstream oss; string template_xml; string perm_str; oss << "" << "" << oid << "" << "" << uid << "" << "" << gid << "" << "" << uname << "" << "" << gname << "" << "" << name << "" << perms_to_xml(perm_str) << "" << regtime << "" << obj_template->to_xml(template_xml) << ""; xml = oss.str(); return xml; } /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ int VMTemplate::from_xml(const string& xml) { vector content; int rc = 0; // Initialize the internal XML object update_from_str(xml); // Get class base attributes rc += xpath(oid, "/VMTEMPLATE/ID", -1); rc += xpath(uid, "/VMTEMPLATE/UID", -1); rc += xpath(gid, "/VMTEMPLATE/GID", -1); rc += xpath(uname, "/VMTEMPLATE/UNAME", "not_found"); rc += xpath(gname, "/VMTEMPLATE/GNAME", "not_found"); rc += xpath(name, "/VMTEMPLATE/NAME", "not_found"); rc += xpath(regtime, "/VMTEMPLATE/REGTIME", 0); // Permissions rc += perms_from_xml(); // Get associated classes ObjectXML::get_nodes("/VMTEMPLATE/TEMPLATE", content); if (content.empty()) { return -1; } // Template contents rc += obj_template->from_xml_node(content[0]); ObjectXML::free_nodes(content); if (rc != 0) { return -1; } return 0; } opennebula-3.4.1/src/pool/0000755000175000017500000000000011750754334015314 5ustar drazzibdrazzibopennebula-3.4.1/src/pool/SConstruct0000644000175000017500000000265711750754334017360 0ustar drazzibdrazzib# SConstruct for src/pool # -------------------------------------------------------------------------- # # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # # a copy of the License at # # # # http://www.apache.org/licenses/LICENSE-2.0 # # # # Unless required by applicable law or agreed to in writing, software # # distributed under the License is distributed on an "AS IS" BASIS, # # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # # See the License for the specific language governing permissions and # # limitations under the License. # #--------------------------------------------------------------------------- # Import('env') lib_name='nebula_pool' # Sources to generate the library source_files=[ 'PoolSQL.cc', 'PoolObjectSQL.cc', 'ObjectCollection.cc', 'PoolObjectAuth.cc' ] # Build library env.StaticLibrary(lib_name, source_files) opennebula-3.4.1/src/pool/PoolObjectSQL.cc0000644000175000017500000002136411750754334020251 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 "PoolObjectSQL.h" #include "PoolObjectAuth.h" #include "SSLTools.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ string& PoolObjectSQL::to_xml64(string &xml64) { string *str64; to_xml(xml64); str64 = SSLTools::base64_encode(xml64); xml64 = *str64; delete str64; return xml64; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int PoolObjectSQL::select(SqlDB *db) { ostringstream oss; int rc; int boid; set_callback( static_cast(&PoolObjectSQL::select_cb)); oss << "SELECT body FROM " << table << " WHERE oid = " << oid; boid = oid; oid = -1; rc = db->exec(oss, this); unset_callback(); if ((rc != 0) || (oid != boid )) { return -1; } return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int PoolObjectSQL::select(SqlDB *db, const string& _name, int _uid) { ostringstream oss; int rc; char * sql_name; sql_name = db->escape_str(_name.c_str()); if ( sql_name == 0 ) { return -1; } set_callback( static_cast(&PoolObjectSQL::select_cb)); oss << "SELECT body FROM " << table << " WHERE name = '" << sql_name << "'"; if ( _uid != -1 ) { oss << " AND uid = " << _uid; } name = ""; uid = -1; rc = db->exec(oss, this); unset_callback(); db->free_str(sql_name); if ((rc != 0) || (_name != name) || (_uid != -1 && _uid != uid)) { return -1; } return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int PoolObjectSQL::drop(SqlDB *db) { ostringstream oss; int rc; oss << "DELETE FROM " << table << " WHERE oid=" << oid; rc = db->exec(oss); if ( rc == 0 ) { set_valid(false); } return rc; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ const char * PoolObjectSQL::error_attribute_name = "ERROR"; void PoolObjectSQL::set_template_error_message(const string& message) { VectorAttribute * attr; map error_value; char str[26]; time_t the_time; the_time = time(NULL); #ifdef SOLARIS ctime_r(&(the_time),str,sizeof(char)*26); #else ctime_r(&(the_time),str); #endif str[24] = '\0'; // Get rid of final enter character error_value.insert(make_pair("TIMESTAMP",str)); error_value.insert(make_pair("MESSAGE",message)); //Replace previous error message and insert the new one attr = new VectorAttribute(error_attribute_name,error_value); obj_template->erase(error_attribute_name); obj_template->set(attr); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int PoolObjectSQL::replace_template(const string& tmpl_str, string& error) { Template * new_tmpl = get_new_template(); if ( new_tmpl == 0 ) { error = "Cannot allocate a new template"; return -1; } if ( new_tmpl->parse_str_or_xml(tmpl_str, error) != 0 ) { return -1; } delete obj_template; obj_template = new_tmpl; return 0; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ string& PoolObjectSQL::perms_to_xml(string& xml) const { ostringstream oss; oss << "" << "" << owner_u << "" << "" << owner_m << "" << "" << owner_a << "" << "" << group_u << "" << "" << group_m << "" << "" << group_a << "" << "" << other_u << "" << "" << other_m << "" << "" << other_a << "" << ""; xml = oss.str(); return xml; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int PoolObjectSQL::perms_from_xml() { int rc = 0; rc += xpath(owner_u, "/*/PERMISSIONS/OWNER_U", 0); rc += xpath(owner_m, "/*/PERMISSIONS/OWNER_M", 0); rc += xpath(owner_a, "/*/PERMISSIONS/OWNER_A", 0); rc += xpath(group_u, "/*/PERMISSIONS/GROUP_U", 0); rc += xpath(group_m, "/*/PERMISSIONS/GROUP_M", 0); rc += xpath(group_a, "/*/PERMISSIONS/GROUP_A", 0); rc += xpath(other_u, "/*/PERMISSIONS/OTHER_U", 0); rc += xpath(other_m, "/*/PERMISSIONS/OTHER_M", 0); rc += xpath(other_a, "/*/PERMISSIONS/OTHER_A", 0); return rc; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void PoolObjectSQL::get_permissions(PoolObjectAuth& auth) { auth.obj_type = obj_type; auth.oid = oid; auth.uid = uid; auth.gid = gid; auth.owner_u = owner_u; auth.owner_m = owner_m; auth.owner_a = owner_a; auth.group_u = group_u; auth.group_m = group_m; auth.group_a = group_a; auth.other_u = other_u; auth.other_m = other_m; auth.other_a = other_a; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int PoolObjectSQL::set_permissions( int _owner_u, int _owner_m, int _owner_a, int _group_u, int _group_m, int _group_a, int _other_u, int _other_m, int _other_a, string& error_str) { if ( _owner_u < -1 || _owner_u > 1 ) goto error_value; if ( _owner_m < -1 || _owner_m > 1 ) goto error_value; if ( _owner_a < -1 || _owner_a > 1 ) goto error_value; if ( _group_u < -1 || _group_u > 1 ) goto error_value; if ( _group_m < -1 || _group_m > 1 ) goto error_value; if ( _group_a < -1 || _group_a > 1 ) goto error_value; if ( _other_u < -1 || _other_u > 1 ) goto error_value; if ( _other_m < -1 || _other_m > 1 ) goto error_value; if ( _other_a < -1 || _other_a > 1 ) goto error_value; set_perm(owner_u, _owner_u); set_perm(owner_m, _owner_m); set_perm(owner_a, _owner_a); set_perm(group_u, _group_u); set_perm(group_m, _group_m); set_perm(group_a, _group_a); set_perm(other_u, _other_u); set_perm(other_m, _other_m); set_perm(other_a, _other_a); return 0; error_value: error_str = "New permission values must be -1, 0 or 1"; return -1; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ opennebula-3.4.1/src/pool/PoolSQL.cc0000644000175000017500000003142611750754334017122 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ #include #include #include #include #include #include "PoolSQL.h" #include /* ************************************************************************** */ /* PoolSQL constructor/destructor */ /* ************************************************************************** */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ const unsigned int PoolSQL::MAX_POOL_SIZE = 15000; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int PoolSQL::init_cb(void *nil, int num, char **values, char **names) { lastOID = -1; if ( values[0] != 0 ) { lastOID = atoi(values[0]); } return 0; } /* -------------------------------------------------------------------------- */ PoolSQL::PoolSQL(SqlDB * _db, const char * _table, bool cache_by_name): db(_db), lastOID(-1), table(_table), uses_name_pool(cache_by_name) { ostringstream oss; pthread_mutex_init(&mutex,0); set_callback(static_cast(&PoolSQL::init_cb)); oss << "SELECT last_oid FROM pool_control WHERE tablename='" << table <<"'"; db->exec(oss,this); unset_callback(); }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ PoolSQL::~PoolSQL() { map::iterator it; pthread_mutex_lock(&mutex); for ( it = pool.begin(); it != pool.end(); it++) { it->second->lock(); delete it->second; } pthread_mutex_unlock(&mutex); pthread_mutex_destroy(&mutex); } /* ************************************************************************** */ /* PoolSQL public interface */ /* ************************************************************************** */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int PoolSQL::allocate( PoolObjectSQL *objsql, string& error_str) { int rc; lock(); if (lastOID == INT_MAX) { lastOID = -1; } objsql->lock(); objsql->oid = ++lastOID; rc = objsql->insert(db,error_str); if ( rc != 0 ) { lastOID--; rc = -1; } else { rc = lastOID; do_hooks(objsql, Hook::ALLOCATE); } objsql->unlock(); delete objsql; if( rc != -1 ) { update_lastOID(); } unlock(); return rc; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void PoolSQL::update_lastOID() { // db->escape_str is not used for 'table' since its name can't be set in // any way by the user, it is hardcoded. ostringstream oss; oss << "REPLACE INTO pool_control (tablename, last_oid) VALUES (" << "'" << table << "'," << lastOID << ")"; db->exec(oss); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ PoolObjectSQL * PoolSQL::get( int oid, bool olock) { map::iterator index; PoolObjectSQL * objectsql; int rc; lock(); index = pool.find(oid); if ( index != pool.end() ) { if ( index->second->isValid() == false ) { objectsql = 0; } else { objectsql = index->second; if ( olock == true ) { objectsql->lock(); if ( objectsql->isValid() == false ) { objectsql->unlock(); objectsql = 0; } } } unlock(); return objectsql; } else { objectsql = create(); objectsql->oid = oid; rc = objectsql->select(db); if ( rc != 0 ) { delete objectsql; unlock(); return 0; } if ( uses_name_pool ) { map::iterator name_index; string okey; okey = key(objectsql->name,objectsql->uid); name_index = name_pool.find(okey); if ( name_index != name_pool.end() ) { name_index->second->lock(); PoolObjectSQL * tmp_ptr = name_index->second; name_pool.erase(okey); pool.erase(tmp_ptr->oid); delete tmp_ptr; } name_pool.insert(make_pair(okey, objectsql)); } pool.insert(make_pair(objectsql->oid,objectsql)); if ( olock == true ) { objectsql->lock(); } oid_queue.push(objectsql->oid); if ( pool.size() > MAX_POOL_SIZE ) { replace(); } unlock(); return objectsql; } } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ PoolObjectSQL * PoolSQL::get(const string& name, int ouid, bool olock) { map::iterator index; PoolObjectSQL * objectsql; int rc; lock(); if ( uses_name_pool == false ) { unlock(); return 0; } index = name_pool.find(key(name,ouid)); if ( index != name_pool.end() && index->second->isValid() == true ) { objectsql = index->second; if ( olock == true ) { objectsql->lock(); if ( objectsql->isValid() == false ) { objectsql->unlock(); objectsql = 0; } } unlock(); return objectsql; } else { objectsql = create(); rc = objectsql->select(db,name,ouid); if ( rc != 0 ) { delete objectsql; unlock(); return 0; } if ( index != name_pool.end() && index->second->isValid() == false ) { index->second->lock(); PoolObjectSQL * tmp_ptr = index->second; string tmp_okey = key(tmp_ptr->name,tmp_ptr->uid); pool.erase(tmp_ptr->oid); name_pool.erase(tmp_okey); delete tmp_ptr; } string okey = key(objectsql->name,objectsql->uid); pool.insert(make_pair(objectsql->oid, objectsql)); name_pool.insert(make_pair(okey, objectsql)); if ( olock == true ) { objectsql->lock(); } oid_queue.push(objectsql->oid); if ( pool.size() > MAX_POOL_SIZE ) { replace(); } unlock(); return objectsql; } } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void PoolSQL::update_cache_index(string& old_name, int old_uid, string& new_name, int new_uid) { map::iterator index; lock(); if ( uses_name_pool == false ) { unlock(); return; } string old_key = key(old_name, old_uid); string new_key = key(new_name, new_uid); index = name_pool.find(old_key); if ( index != name_pool.end() ) { name_pool.erase(old_key); if ( name_pool.find(new_key) == name_pool.end()) { name_pool.insert(make_pair(new_key, index->second)); } } unlock(); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void PoolSQL::replace() { bool removed = false; int oid; int rc; map::iterator index; while (!removed) { oid = oid_queue.front(); index = pool.find(oid); if ( index == pool.end()) { oid_queue.pop(); continue; } rc = pthread_mutex_trylock(&(index->second->mutex)); if ( rc == EBUSY ) // In use by other thread, move to back { oid_queue.pop(); oid_queue.push(oid); } else { PoolObjectSQL * tmp_ptr = index->second; pool.erase(index); if ( uses_name_pool ) { string okey = key(tmp_ptr->name,tmp_ptr->uid); name_pool.erase(okey); } delete tmp_ptr; oid_queue.pop(); removed = true; } } } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void PoolSQL::clean() { map::iterator it; lock(); for ( it = pool.begin(); it != pool.end(); it++) { it->second->lock(); delete it->second; } pool.clear(); name_pool.clear(); unlock(); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int PoolSQL::dump_cb(void * _oss, int num, char **values, char **names) { ostringstream * oss; oss = static_cast(_oss); if ( (!values[0]) || (num != 1) ) { return -1; } *oss << values[0]; return 0; } /* -------------------------------------------------------------------------- */ int PoolSQL::dump(ostringstream& oss, const string& elem_name, const char * table, const string& where) { int rc; ostringstream cmd; oss << "<" << elem_name << ">"; set_callback(static_cast(&PoolSQL::dump_cb), static_cast(&oss)); cmd << "SELECT body FROM " << table; if ( !where.empty() ) { cmd << " WHERE " << where; } cmd << " ORDER BY oid"; rc = db->exec(cmd, this); oss << ""; unset_callback(); return rc; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int PoolSQL:: search_cb(void * _oids, int num, char **values, char **names) { vector * oids; oids = static_cast *>(_oids); if ( num == 0 || values == 0 || values[0] == 0 ) { return -1; } oids->push_back(atoi(values[0])); return 0; } /* -------------------------------------------------------------------------- */ int PoolSQL::search( vector& oids, const char * table, const string& where) { ostringstream sql; int rc; set_callback(static_cast(&PoolSQL::search_cb), static_cast(&oids)); sql << "SELECT oid FROM " << table << " WHERE " << where; rc = db->exec(sql, this); unset_callback(); return rc; } opennebula-3.4.1/src/pool/PoolObjectAuth.cc0000644000175000017500000000657011750754334020515 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 "PoolObjectAuth.h" #include "AuthManager.h" #include "AclRule.h" void PoolObjectAuth::get_acl_rules(AclRule& owner_rule, AclRule& group_rule, AclRule& other_rule) const { long long perm_user, perm_resource, perm_rights; perm_resource = obj_type | AclRule::INDIVIDUAL_ID | oid; // ------------------------------------------------------------------------- // Rule "#uid ob_type/#oid user_rights" // ------------------------------------------------------------------------- perm_user = AclRule::INDIVIDUAL_ID | uid; perm_rights = 0; if ( owner_u == 1 ) { perm_rights = perm_rights | AuthRequest::USE; } if ( owner_m == 1 ) { perm_rights = perm_rights | AuthRequest::MANAGE; } if ( owner_a == 1 ) { perm_rights = perm_rights | AuthRequest::ADMIN; } owner_rule.set(0, perm_user, perm_resource, perm_rights); // ------------------------------------------------------------------------- // Rule "@gid ob_type/#oid group_rights" // ------------------------------------------------------------------------- perm_user = AclRule::GROUP_ID | gid; perm_rights = 0; if ( group_u == 1 ) { perm_rights = perm_rights | AuthRequest::USE; } if ( group_m == 1 ) { perm_rights = perm_rights | AuthRequest::MANAGE; } if ( group_a == 1 ) { perm_rights = perm_rights | AuthRequest::ADMIN; } group_rule.set(0, perm_user, perm_resource, perm_rights); // ------------------------------------------------------------------------- // Rule "* ob_type/#oid others_rights" // ------------------------------------------------------------------------- perm_user = AclRule::ALL_ID; perm_rights = 0; if ( other_u == 1 ) { perm_rights = perm_rights | AuthRequest::USE; } if ( other_m == 1 ) { perm_rights = perm_rights | AuthRequest::MANAGE; } if ( other_a == 1 ) { perm_rights = perm_rights | AuthRequest::ADMIN; } other_rule.set(0, perm_user, perm_resource, perm_rights); }; opennebula-3.4.1/src/pool/test/0000755000175000017500000000000011750754334016273 5ustar drazzibdrazzibopennebula-3.4.1/src/pool/test/SConstruct0000644000175000017500000000272311750754334020331 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # -------------------------------------------------------------------------- Import('env') # Library dirs env.Append(LIBPATH=[ '.' ]) env.Prepend(LIBS=[ 'nebula_pool', 'nebula_template', 'nebula_xml', 'nebula_common', 'nebula_log', 'nebula_core', 'nebula_sql', 'test_object', 'crypto' ]) env.StaticLibrary('test_object', ['TestPoolSQL.cc', 'TestPoolSQL.h']) env.Program('test','pool.cc') opennebula-3.4.1/src/pool/test/TestPoolSQL.h0000644000175000017500000001027111750754334020576 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ #ifndef TESTSQL_H_ #define TESTSQL_H_ #include #include "PoolSQL.h" using namespace std; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // THE OBJECT class TestObjectSQL : public PoolObjectSQL { public: //OBJECT ATTRIBUTES TestObjectSQL(int n=-1, string t="default"):PoolObjectSQL(-1,VM,t,0,0,"","",table),number(n),text(t){}; ~TestObjectSQL(){}; int number; string text; // OBJECTSQL INTERFACE int unmarshall(void * nil, int num, char **names, char ** values); int insert(SqlDB *db, string& err); int update(SqlDB *db); int insert_replace(SqlDB *db, bool replace); int drop(SqlDB *db) { return PoolObjectSQL::drop(db); } static const char * db_names; static const char * db_bootstrap; static const char * table; static void bootstrap(SqlDB * db) { ostringstream oss; oss.str(TestObjectSQL::db_bootstrap); db->exec(oss,0); }; string& to_xml(string& xml) const { ostringstream oss; oss << "" << "" << oid << "" << "" << uid << "" << "" << gid << "" << "" << uname << "" << "" << gname << "" << "" << name << "" << "" << number << "" << "" << text << "" << ""; xml = oss.str(); return xml; }; int from_xml(const string &xml_str) { int rc = 0; // Initialize the internal XML object update_from_str(xml_str); // Get class base attributes rc += xpath(oid, "/TEST/ID", -1); rc += xpath(uid, "/TEST/UID", -1); rc += xpath(gid, "/TEST/GID", -1); rc += xpath(uname, "/TEST/UNAME", "not_found"); rc += xpath(gname, "/TEST/GNAME", "not_found"); rc += xpath(name, "/TEST/NAME", "not_found"); rc += xpath(number, "/TEST/NUMBER", -1); rc += xpath(text, "/TEST/TEXT", "not_found"); if ( rc != 0 ) { return -1; } return 0; }; }; // THE POOL class TestPool : public PoolSQL { public: TestPool(SqlDB *db):PoolSQL(db,"test_pool",true){}; ~TestPool(){}; TestObjectSQL * get( int oid, bool lock) { return static_cast(PoolSQL::get(oid,lock)); } TestObjectSQL * get( const string& name, int ouid, bool olock) { return static_cast(PoolSQL::get(name, ouid, olock)); } int dump(std::ostringstream&, const std::string&){return -1;}; private: TestObjectSQL * create() { return new TestObjectSQL; }; }; #endif opennebula-3.4.1/src/pool/test/pool.cc0000644000175000017500000002042311750754334017554 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ #include #include #include #include "test/OneUnitTest.h" #include "PoolSQL.h" #include "TestPoolSQL.h" using namespace std; /* ************************************************************************* */ /* ************************************************************************* */ class PoolTest : public OneUnitTest { CPPUNIT_TEST_SUITE (PoolTest); CPPUNIT_TEST (allocate_get); CPPUNIT_TEST (wrong_get); CPPUNIT_TEST (search); CPPUNIT_TEST (cache_test); CPPUNIT_TEST (cache_name_test); CPPUNIT_TEST_SUITE_END (); private: TestPool * pool; int create_allocate(int n, string st) { string err; TestObjectSQL *obj = new TestObjectSQL(n,st); return pool->allocate(obj, err); }; public: PoolTest(){}; ~PoolTest(){}; void setUp() { create_db(); TestObjectSQL::bootstrap(db); pool = new TestPool(db); }; void tearDown() { delete pool; delete_db(); }; /* ********************************************************************* */ /* ********************************************************************* */ // Try to allocate two objects, and retrieve them void allocate_get() { int n1 = 3; int n2 = 7; string st1 = "text number one"; string st2 = "another text"; TestObjectSQL *obj; int oid; oid = create_allocate(n1,st1); // first element in the pool should have oid=0 CPPUNIT_ASSERT(oid == 0); oid = create_allocate(n2,st2); // second element in the pool should have oid=1 CPPUNIT_ASSERT(oid == 1); // --------------------------------- obj = pool->get(0, false); CPPUNIT_ASSERT(obj != 0); CPPUNIT_ASSERT(obj->number == n1); CPPUNIT_ASSERT(obj->text == st1); // --------------------------------- obj = pool->get(1, true); CPPUNIT_ASSERT(obj != 0); CPPUNIT_ASSERT(obj->number == n2); CPPUNIT_ASSERT(obj->text == st2); obj->unlock(); }; void wrong_get() { int n1 = 2; string st1 = "object 2"; TestObjectSQL *obj; int oid; oid = create_allocate(n1,st1); obj = pool->get(oid,true); CPPUNIT_ASSERT(obj != 0); obj->drop(db); obj->unlock(); obj = pool->get(oid,true); CPPUNIT_ASSERT(obj == 0); pool->clean(); obj = pool->get(oid,true); CPPUNIT_ASSERT(obj == 0); }; void search() { int nA = 13; int nB = 17; string stA = "String value for number 13"; string stB = "String value for number 17"; int oidA = create_allocate(nA, stA); int oidB = create_allocate(nB, stB); vector results; const char * table = "test_pool"; string where = "name = '" + stB + "'"; int ret; ret = pool->search(results, table, where); CPPUNIT_ASSERT(ret == 0); CPPUNIT_ASSERT(results.size() == 1); CPPUNIT_ASSERT(results.at(0) == oidB); results.erase(results.begin(), results.end()); where = "number < 18"; ret = pool->search(results, table, where); CPPUNIT_ASSERT(ret == 0); CPPUNIT_ASSERT(results.size() == 2); CPPUNIT_ASSERT(results.at(0) == oidA); CPPUNIT_ASSERT(results.at(1) == oidB); }; void cache_test() { TestObjectSQL *obj; TestObjectSQL *obj_lock; //pin object in the cache, it can't be removed - //Should be set to MAX_POOL -1 for (int i=0 ; i < 14999 ; i++) { ostringstream name; name << "A Test object " << i; create_allocate(i,name.str()); obj_lock = pool->get(i, true); CPPUNIT_ASSERT(obj_lock != 0); } for (int i=14999 ; i < 15200 ; i++) //Works with just 1 cache line { ostringstream name; name << "A Test object " << i; create_allocate(i,name.str()); } for (int i=14999; i < 15200 ; i++) { ostringstream name; name << "A Test object " << i; obj = pool->get(i, true); CPPUNIT_ASSERT(obj != 0); CPPUNIT_ASSERT(obj->number == i); CPPUNIT_ASSERT(obj->text == name.str()); obj->unlock(); } for (int i=0 ; i < 14999 ; i++) { obj_lock = pool->get(i, false); obj_lock->unlock(); } }; void cache_name_test() { TestObjectSQL *obj; TestObjectSQL *obj_lock; ostringstream oss; string err_str; //pin object in the cache, it can't be removed - //Should be set to MAX_POOL -1 for (int i=0 ; i < 14999 ; i++) { oss.str(""); oss << "obj_" << i; create_allocate(i, oss.str()); obj_lock = pool->get(oss.str(), 0, true); CPPUNIT_ASSERT(obj_lock != 0); } for (int i=14999 ; i < 15200 ; i++) //Works with just 1 cache line { oss.str(""); oss << "obj_" << i; create_allocate(i, oss.str()); } for (int i=14999; i < 15200 ; i++) { oss.str(""); oss << "obj_" << i; obj = pool->get(oss.str(), 0, true); CPPUNIT_ASSERT(obj != 0); CPPUNIT_ASSERT(obj->number == i); CPPUNIT_ASSERT(obj->get_name() == obj->text); CPPUNIT_ASSERT(obj->get_name() == oss.str()); obj->unlock(); } // Delete some of the locked objects, and create new with the same name for (int i=10 ; i < 21 ; i++) { oss.str(""); oss << "obj_" << i; obj_lock = pool->get(oss.str(), 0, false); CPPUNIT_ASSERT(obj_lock != 0); pool->drop(obj_lock, err_str); obj_lock->unlock(); create_allocate(i, oss.str()); } // Try to get the new objects for (int i=10 ; i < 21 ; i++) { oss.str(""); oss << "obj_" << i; obj = pool->get(oss.str(), 0, true); CPPUNIT_ASSERT(obj != 0); CPPUNIT_ASSERT(obj->number == i); CPPUNIT_ASSERT(obj->get_oid() >= 15200); CPPUNIT_ASSERT(obj->get_name() == oss.str()); obj->unlock(); } for (int i=0 ; i < 14999 ; i++) { obj_lock = pool->get(i, false); if ( obj_lock != 0 ) { obj_lock->unlock(); } } }; }; /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ int main(int argc, char ** argv) { return OneUnitTest::main(argc, argv, PoolTest::suite()); } opennebula-3.4.1/src/pool/test/TestPoolSQL.cc0000644000175000017500000000644011750754334020737 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not use this file except in compliance with the License. You may obtain */ /* a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* See the License for the specific language governing permissions and */ /* limitations under the License. */ /* -------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include "TestPoolSQL.h" /* ************************************************************************** */ /* Database Access Functions */ /* ************************************************************************** */ const char * TestObjectSQL::table = "test_pool"; const char * TestObjectSQL::db_names = "oid,name,body,uid,number"; const char * TestObjectSQL::db_bootstrap = "CREATE TABLE test_pool (" "oid INTEGER PRIMARY KEY, name VARCHAR(256), body TEXT, uid INTEGER, " "number INTEGER)"; /* -------------------------------------------------------------------------- */ int TestObjectSQL::insert(SqlDB *db, string& str) { return insert_replace(db, false); } /* -------------------------------------------------------------------------- */ int TestObjectSQL::update(SqlDB *db) { return insert_replace(db, true); } /* -------------------------------------------------------------------------- */ int TestObjectSQL::insert_replace(SqlDB *db, bool replace) { ostringstream oss; int rc; string xml_body; char * sql_name; char * sql_xml; // Update the User sql_name = db->escape_str(name.c_str()); if ( sql_name == 0 ) { goto error_name; } sql_xml = db->escape_str(to_xml(xml_body).c_str()); if ( sql_xml == 0 ) { goto error_body; } // Construct the SQL statement to Insert or Replace if(replace) { oss << "REPLACE"; } else { oss << "INSERT"; } oss << " INTO " << table << " ("<< db_names <<") VALUES (" << oid << "," << "'" << sql_name << "'," << "'" << sql_xml << "'," << uid << "," << number << ")"; rc = db->exec(oss); db->free_str(sql_name); db->free_str(sql_xml); return rc; error_body: db->free_str(sql_name); error_name: return -1; } opennebula-3.4.1/src/pool/ObjectCollection.cc0000644000175000017500000000670711750754334021057 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 "ObjectCollection.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int ObjectCollection::from_xml_node(const xmlNodePtr node) { xmlNodePtr cur_node = 0; istringstream iss; int id; int rc = 0; for (cur_node = node->children; cur_node != 0; cur_node = cur_node->next) { if ((cur_node->type == XML_ELEMENT_NODE) && (cur_node->children != 0) && ((cur_node->children->type == XML_TEXT_NODE ) || (cur_node->children->type == XML_CDATA_SECTION_NODE))) { iss.clear(); iss.str(reinterpret_cast(cur_node->children->content)); iss >> dec >> id; if ( iss.fail() ) { rc = -1; break; } else { collection_set.insert(id); } } else { rc = -1; break; } } return rc; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ string& ObjectCollection::to_xml(string& xml) const { ostringstream oss; set::iterator it; oss << "<" << collection_name << ">"; for ( it = collection_set.begin(); it != collection_set.end(); it++ ) { oss << "" << *it << ""; } oss << ""; xml = oss.str(); return xml; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int ObjectCollection::add_collection_id(int id) { pair::iterator,bool> ret; ret = collection_set.insert(id); if( !ret.second ) { return -1; } return 0; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int ObjectCollection::del_collection_id(int id) { if( collection_set.erase(id) != 1 ) { return -1; } return 0; }; opennebula-3.4.1/src/tm/0000755000175000017500000000000011750754334014763 5ustar drazzibdrazzibopennebula-3.4.1/src/tm/TransferManagerDriver.cc0000644000175000017500000001336711750754334021537 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 "TransferManagerDriver.h" #include "NebulaLog.h" #include "LifeCycleManager.h" #include "Nebula.h" #include /* ************************************************************************** */ /* Driver ASCII Protocol Implementation */ /* ************************************************************************** */ void TransferManagerDriver::transfer ( const int oid, const string& xfr_file) const { ostringstream os; os << "TRANSFER " << oid << " " << xfr_file << endl; write(os); }; /* ************************************************************************** */ /* MAD Interface */ /* ************************************************************************** */ void TransferManagerDriver::protocol( string& message) { istringstream is(message); ostringstream os; string action; string result; int id; VirtualMachine * vm; os << "Message received: " << message; NebulaLog::log("TM", 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("TM",log_type(result[0]), info.c_str()); } return; } } else return; // Get the VM from the pool vm = vmpool->get(id,true); if ( vm == 0 ) { return; } if ( vm->get_lcm_state() == VirtualMachine::CLEANUP || vm->get_lcm_state() == VirtualMachine::FAILURE || vm->get_lcm_state() == VirtualMachine::LCM_INIT ) { os.str(""); os << "Ignored: " << message; vm->log("TM",Log::WARNING,os); vm->unlock(); return; } // Driver Actions if (action == "TRANSFER") { Nebula &ne = Nebula::instance(); LifeCycleManager * lcm = ne.get_lcm(); LifeCycleManager::Actions lcm_action; if (result == "SUCCESS") { switch (vm->get_lcm_state()) { case VirtualMachine::PROLOG: case VirtualMachine::PROLOG_MIGRATE: case VirtualMachine::PROLOG_RESUME: lcm_action = LifeCycleManager::PROLOG_SUCCESS; break; case VirtualMachine::EPILOG: case VirtualMachine::EPILOG_STOP: lcm_action = LifeCycleManager::EPILOG_SUCCESS; break; default: goto error_state; } } else { string info; getline(is,info); os.str(""); os << "Error executing image transfer script"; if (!info.empty() && info[0] != '-') { os << ": " << info; vm->set_template_error_message(os.str()); vmpool->update(vm); } vm->log("TM",Log::ERROR,os); switch (vm->get_lcm_state()) { case VirtualMachine::PROLOG: case VirtualMachine::PROLOG_MIGRATE: case VirtualMachine::PROLOG_RESUME: lcm_action = LifeCycleManager::PROLOG_FAILURE; break; case VirtualMachine::EPILOG: case VirtualMachine::EPILOG_STOP: lcm_action = LifeCycleManager::EPILOG_FAILURE; break; default: goto error_state; } } lcm->trigger(lcm_action, id); } else if (action == "LOG") { string info; getline(is,info); vm->log("TM",log_type(result[0]),info.c_str()); } vm->unlock(); return; error_state: os.str(""); os << "Wrong state in TM answer for VM " << id; vm->log("TM",Log::ERROR,os); vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManagerDriver::recover() { NebulaLog::log("TM",Log::INFO,"Recovering TM drivers"); } opennebula-3.4.1/src/tm/SConstruct0000644000175000017500000000260711750754334017022 0ustar drazzibdrazzib# SConstruct for src/vm # -------------------------------------------------------------------------- # # Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) # # # # Licensed under the Apache License, Version 2.0 (the "License"); you may # # not use this file except in compliance with the License. You may obtain # # a copy of the License at # # # # http://www.apache.org/licenses/LICENSE-2.0 # # # # Unless required by applicable law or agreed to in writing, software # # distributed under the License is distributed on an "AS IS" BASIS, # # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # # See the License for the specific language governing permissions and # # limitations under the License. # #--------------------------------------------------------------------------- # Import('env') lib_name='nebula_tm' # Sources to generate the library source_files=[ 'TransferManager.cc', 'TransferManagerDriver.cc' ] # Build library env.StaticLibrary(lib_name, source_files) opennebula-3.4.1/src/tm/TransferManager.cc0000644000175000017500000010172111750754334020353 0ustar drazzibdrazzib/* -------------------------------------------------------------------------- */ /* Copyright 2002-2012, 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 "TransferManager.h" #include "NebulaLog.h" #include "Nebula.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ const char * TransferManager::transfer_driver_name = "transfer_exe"; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ extern "C" void * tm_action_loop(void *arg) { TransferManager * tm; if ( arg == 0 ) { return 0; } tm = static_cast(arg); NebulaLog::log("TrM",Log::INFO,"Transfer Manager started."); tm->am.loop(0,0); NebulaLog::log("TrM",Log::INFO,"Transfer Manager stopped."); return 0; } /* -------------------------------------------------------------------------- */ int TransferManager::start() { int rc; pthread_attr_t pattr; rc = MadManager::start(); if ( rc != 0 ) { return -1; } NebulaLog::log("TrM",Log::INFO,"Starting Transfer Manager..."); pthread_attr_init (&pattr); pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); rc = pthread_create(&tm_thread,&pattr,tm_action_loop,(void *) this); return rc; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManager::trigger(Actions action, int _vid) { int * vid; string aname; vid = new int(_vid); switch (action) { case PROLOG: aname = "PROLOG"; break; case PROLOG_MIGR: aname = "PROLOG_MIGR"; break; case PROLOG_RESUME: aname = "PROLOG_RESUME"; break; case EPILOG: aname = "EPILOG"; break; case EPILOG_STOP: aname = "EPILOG_STOP"; break; case EPILOG_DELETE: aname = "EPILOG_DELETE"; break; case EPILOG_DELETE_PREVIOUS: aname = "EPILOG_DELETE_PREVIOUS"; break; case CHECKPOINT: aname = "CHECKPOINT"; break; case DRIVER_CANCEL: aname = "DRIVER_CANCEL"; break; case FINALIZE: aname = ACTION_FINALIZE; break; default: delete vid; return; } am.trigger(aname,vid); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManager::do_action(const string &action, void * arg) { int vid; if (arg == 0) { return; } vid = *(static_cast(arg)); delete static_cast(arg); if (action == "PROLOG") { prolog_action(vid); } else if (action == "PROLOG_MIGR") { prolog_migr_action(vid); } else if (action == "PROLOG_RESUME") { prolog_resume_action(vid); } else if (action == "EPILOG") { epilog_action(vid); } else if (action == "EPILOG_STOP") { epilog_stop_action(vid); } else if (action == "EPILOG_DELETE") { epilog_delete_action(vid); } else if (action == "EPILOG_DELETE_PREVIOUS") { epilog_delete_previous_action(vid); } else if (action == "CHECKPOINT") { checkpoint_action(vid); } else if (action == "DRIVER_CANCEL") { driver_cancel_action(vid); } else if (action == ACTION_FINALIZE) { NebulaLog::log("TrM",Log::INFO,"Stopping Transfer Manager..."); MadManager::stop(); } else { ostringstream oss; oss << "Unknown action name: " << action; NebulaLog::log("TrM", Log::ERROR, oss); } } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManager::prolog_action(int vid) { ofstream xfr; ostringstream os; string xfr_name; const VectorAttribute * disk; string source; string type; string clon; string files; string size; string format; string tm_mad, system_tm_mad; VirtualMachine * vm; Nebula& nd = Nebula::instance(); const TransferManagerDriver * tm_md; vector attrs; int num; int context_result; // ------------------------------------------------------------------------ // Setup & Transfer script // ------------------------------------------------------------------------ system_tm_mad = nd.get_system_ds_tm_mad(); vm = vmpool->get(vid,true); if (vm == 0) { return; } if (!vm->hasHistory()) { goto error_history; } tm_md = get(); if ( tm_md == 0 ) { goto error_driver; } xfr_name = vm->get_transfer_file() + ".prolog"; xfr.open(xfr_name.c_str(), ios::out | ios::trunc); if (xfr.fail() == true) { goto error_file; } // ------------------------------------------------------------------------ // Swap and image Commands // ------------------------------------------------------------------------ num = vm->get_template_attribute("DISK",attrs); for (int i=0; i < num ;i++, source="", type="", clon="", tm_mad="") { disk = dynamic_cast(attrs[i]); if ( disk == 0 ) { continue; } type = disk->vector_value("TYPE"); if ( type.empty() == false) { transform(type.begin(),type.end(),type.begin(), (int(*)(int))toupper); } if ( type == "SWAP" ) { // ----------------------------------------------------------------- // Generate a swap disk image // ----------------------------------------------------------------- size = disk->vector_value("SIZE"); if (size.empty()==true) { vm->log("TM",Log::WARNING,"No size in swap image, skipping"); continue; } //MKSWAP tm_mad size host:remote_system_dir/disk.i xfr << "MKSWAP " << system_tm_mad << " " << size << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << i << endl; } else if ( type == "FS" ) { // ----------------------------------------------------------------- // Create a clean file system disk image // ----------------------------------------------------------------- size = disk->vector_value("SIZE"); format = disk->vector_value("FORMAT"); if ( size.empty() || format.empty()) { vm->log("TM",Log::WARNING,"No size or format in plain FS image," " skipping"); continue; } //MKIMAGE tm_mad size format host:remote_system_dir/disk.i xfr << "MKIMAGE " << system_tm_mad << " " << size << " " << format << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << i << endl; } else { tm_mad = disk->vector_value("TM_MAD"); if ( tm_mad.empty() ) { goto error_tm_mad; } // ----------------------------------------------------------------- // CLONE or LINK disk images // ----------------------------------------------------------------- clon = disk->vector_value("CLONE"); size = disk->vector_value("SIZE"); if ( clon.empty() == true ) { clon = "YES"; //Clone by default } else { transform(clon.begin(),clon.end(),clon.begin(), (int(*)(int))toupper); } // tm_mad fe:SOURCE host:remote_system_ds/disk.i size if (clon == "YES") { xfr << "CLONE "; } else { xfr << "LN "; } xfr << tm_mad << " "; // ----------------------------------------------------------------- // Get the disk image, and set source URL // ----------------------------------------------------------------- source = disk->vector_value("SOURCE"); if ( source.empty() ) { goto error_empty_disk; } if ( source.find(":") == string::npos ) //Regular file { xfr << nd.get_nebula_hostname() << ":" << source << " "; } else //TM Plugin specific protocol { xfr << source << " "; } xfr << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << i; if (!size.empty()) //Add size for dev based disks { xfr << " " << size; } xfr << endl; } } // ------------------------------------------------------------------------ // Generate context file (There are 0...num-1 disks, constext is disk.num) // ------------------------------------------------------------------------ context_result = vm->generate_context(files); if ( context_result == -1 ) { goto error_context; } if ( context_result ) { //CONTEXT tm_mad files hostname:remote_system_dir/disk.i xfr << "CONTEXT " << system_tm_mad << " " << vm->get_context_file() << " "; if (!files.empty()) { xfr << files << " "; } xfr << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << num << endl; } xfr.close(); tm_md->transfer(vid,xfr_name); vm->unlock(); return; error_context: os.str(""); os << "prolog, could not write context file for VM " << vid; goto error_common; error_history: os.str(""); os << "prolog, VM " << vid << " has no history"; goto error_common; error_file: os.str(""); os << "prolog, could not open file: " << xfr_name; goto error_common; error_driver: os.str(""); os << "prolog, error getting Transfer Manager driver."; goto error_common; error_tm_mad: os.str(""); os << "prolog, undefined TM_MAD for disk image in VM template"; xfr.close(); error_empty_disk: os.str(""); os << "prolog, undefined source disk image in VM template"; xfr.close(); error_common: (nd.get_lcm())->trigger(LifeCycleManager::PROLOG_FAILURE,vid); vm->log("TM", Log::ERROR, os); vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManager::prolog_migr_action(int vid) { ofstream xfr; ostringstream os; string xfr_name; const VectorAttribute * disk; string tm_mad; string system_tm_mad; vector attrs; int num; VirtualMachine * vm; Nebula& nd = Nebula::instance(); const TransferManagerDriver * tm_md; // ------------------------------------------------------------------------ // Setup & Transfer script // ------------------------------------------------------------------------ system_tm_mad = nd.get_system_ds_tm_mad(); vm = vmpool->get(vid,true); if (vm == 0) { return; } if (!vm->hasHistory()) { goto error_history; } tm_md = get(); if ( tm_md == 0 ) { goto error_driver; } xfr_name = vm->get_transfer_file() + ".migrate"; xfr.open(xfr_name.c_str(), ios::out | ios::trunc); if (xfr.fail() == true) { goto error_file; } // ------------------------------------------------------------------------ // Move system directory and disks // ------------------------------------------------------------------------ num = vm->get_template_attribute("DISK",attrs); for (int i=0 ; i < num ; i++, tm_mad="") { disk = dynamic_cast(attrs[i]); if ( disk == 0 ) { continue; } tm_mad = disk->vector_value("TM_MAD"); if ( tm_mad.empty() ) { continue; } //MV tm_mad prev_host:remote_system_dir/disk.i host:remote_system_dir/disk.i xfr << "MV " << tm_mad << " " << vm->get_previous_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << i << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << i << endl; } //MV tm_mad prev_host:remote_system_dir host:remote_system_dir xfr << "MV " << system_tm_mad << " " << vm->get_previous_hostname() << ":" << vm->get_remote_system_dir() << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << endl; xfr.close(); tm_md->transfer(vid,xfr_name); vm->unlock(); return; error_history: os.str(""); os << "prolog_migr, VM " << vid << " has no history"; goto error_common; error_file: os.str(""); os << "prolog_migr, could not open file: " << xfr_name; goto error_common; error_driver: os.str(""); os << "prolog_migr, error getting Transfer Manager driver."; error_common: (nd.get_lcm())->trigger(LifeCycleManager::PROLOG_FAILURE,vid); vm->log("TM", Log::ERROR, os); vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManager::prolog_resume_action(int vid) { ofstream xfr; ostringstream os; string xfr_name; const VectorAttribute * disk; string tm_mad; string system_tm_mad; vector attrs; int num; VirtualMachine * vm; Nebula& nd = Nebula::instance(); const TransferManagerDriver * tm_md; // ------------------------------------------------------------------------ // Setup & Transfer script // ------------------------------------------------------------------------ system_tm_mad = nd.get_system_ds_tm_mad(); vm = vmpool->get(vid,true); if (vm == 0) { return; } if (!vm->hasHistory()) { goto error_history; } tm_md = get(); if ( tm_md == 0 ) { goto error_driver; } xfr_name = vm->get_transfer_file() + ".resume"; xfr.open(xfr_name.c_str(), ios::out | ios::trunc); if (xfr.fail() == true) { goto error_file; } // ------------------------------------------------------------------------ // Move system directory and disks // ------------------------------------------------------------------------ num = vm->get_template_attribute("DISK",attrs); for (int i=0 ; i < num ; i++, tm_mad="") { disk = dynamic_cast(attrs[i]); if ( disk == 0 ) { continue; } tm_mad = disk->vector_value("TM_MAD"); if ( tm_mad.empty() ) { continue; } //MV tm_mad fe:system_dir/disk.i host:remote_system_dir/disk.i xfr << "MV " << tm_mad << " " << nd.get_nebula_hostname() << ":" << vm->get_system_dir() << "/disk." << i << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << i << endl; } //MV tm_mad fe:system_dir host:remote_system_dir xfr << "MV " << system_tm_mad << " " << nd.get_nebula_hostname() << ":"<< vm->get_system_dir() << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << endl; xfr.close(); tm_md->transfer(vid,xfr_name); vm->unlock(); return; error_history: os.str(""); os << "prolog_resume, VM " << vid << " has no history"; goto error_common; error_file: os.str(""); os << "prolog_resume, could not open file: " << xfr_name; goto error_common; error_driver: os.str(""); os << "prolog_resume, error getting Transfer Manager driver."; error_common: (nd.get_lcm())->trigger(LifeCycleManager::PROLOG_FAILURE,vid); vm->log("TM", Log::ERROR, os); vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManager::epilog_action(int vid) { ofstream xfr; ostringstream os; string xfr_name; string system_tm_mad; string tm_mad; const VectorAttribute * disk; string save; VirtualMachine * vm; Nebula& nd = Nebula::instance(); const TransferManagerDriver * tm_md; vector attrs; int num; // ------------------------------------------------------------------------ // Setup & Transfer script // ------------------------------------------------------------------------ system_tm_mad = nd.get_system_ds_tm_mad(); vm = vmpool->get(vid,true); if (vm == 0) { return; } if (!vm->hasHistory()) { goto error_history; } tm_md = get(); if ( tm_md == 0 ) { goto error_driver; } xfr_name = vm->get_transfer_file() + ".epilog"; xfr.open(xfr_name.c_str(), ios::out | ios::trunc); if (xfr.fail() == true) { goto error_file; } // ------------------------------------------------------------------------ // copy back VM image (DISK with SAVE="yes") // ------------------------------------------------------------------------ num = vm->get_template_attribute("DISK",attrs); for (int i=0; i < num ;i++,save="") { disk = dynamic_cast(attrs[i]); if ( disk == 0 ) { continue; } save = disk->vector_value("SAVE"); if ( save.empty() == true) { continue; } transform(save.begin(),save.end(),save.begin(),(int(*)(int))toupper); tm_mad = disk->vector_value("TM_MAD"); if ( save == "YES" ) //TODO SAVE_SOURCE { string source; string save_source; source = disk->vector_value("SOURCE"); save_source = disk->vector_value("SAVE_AS_SOURCE"); if ( source.empty() && save_source.empty() ) { vm->log("TM", Log::ERROR, "No SOURCE to save disk image"); continue; } if (!save_source.empty()) //Use the save as source instead { source = save_source; } //MVDS tm_mad hostname:remote_system_dir/disk.0 xfr << "MVDS " << tm_mad << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << i << " " << source << endl; } else if ( !tm_mad.empty() ) //No saving disk and no system_ds disk { //DELETE tm_mad hostname:remote_system_dir/disk.i xfr << "DELETE " << tm_mad << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << i << endl; } } //DELETE system_tm_mad hostname:remote_system_dir xfr << "DELETE " << system_tm_mad << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << endl; xfr.close(); tm_md->transfer(vid,xfr_name); vm->unlock(); return; error_history: os.str(""); os << "epilog, VM " << vid << " has no history"; goto error_common; error_file: os.str(""); os << "epilog, could not open file: " << xfr_name; goto error_common; error_driver: os.str(""); os << "epilog, error getting Transfer Manager driver."; error_common: (nd.get_lcm())->trigger(LifeCycleManager::EPILOG_FAILURE,vid); vm->log("TM", Log::ERROR, os); vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManager::epilog_stop_action(int vid) { ofstream xfr; ostringstream os; string xfr_name; string tm_mad; string system_tm_mad; VirtualMachine * vm; Nebula& nd = Nebula::instance(); const TransferManagerDriver * tm_md; vector attrs; const VectorAttribute * disk; int num; // ------------------------------------------------------------------------ // Setup & Transfer script // ------------------------------------------------------------------------ system_tm_mad = nd.get_system_ds_tm_mad(); vm = vmpool->get(vid,true); if (vm == 0) { return; } if (!vm->hasHistory()) { goto error_history; } tm_md = get(); if ( tm_md == 0 ) { goto error_driver; } xfr_name = vm->get_transfer_file() + ".stop"; xfr.open(xfr_name.c_str(), ios::out | ios::trunc); if (xfr.fail() == true) { goto error_file; } // ------------------------------------------------------------------------ // Move system directory and disks // ------------------------------------------------------------------------ num = vm->get_template_attribute("DISK",attrs); for (int i=0 ; i < num ; i++, tm_mad="") { disk = dynamic_cast(attrs[i]); if ( disk == 0 ) { continue; } tm_mad = disk->vector_value("TM_MAD"); if ( tm_mad.empty() ) { continue; } //MV tm_mad host:remote_system_dir/disk.i fe:system_dir/disk.i xfr << "MV " << tm_mad << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << i << " " << nd.get_nebula_hostname() << ":" << vm->get_system_dir() << "/disk." << i << endl; } //MV system_tm_mad hostname:remote_system_dir fe:system_dir xfr << "MV " << system_tm_mad << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << " " << nd.get_nebula_hostname() << ":" << vm->get_system_dir() << endl; xfr.close(); tm_md->transfer(vid,xfr_name); vm->unlock(); return; error_history: os.str(""); os << "epilog_stop, VM " << vid << " has no history"; goto error_common; error_file: os.str(""); os << "epilog_stop, could not open file: " << xfr_name; goto error_common; error_driver: os.str(""); os << "epilog_stop, error getting Transfer Manager driver."; error_common: (nd.get_lcm())->trigger(LifeCycleManager::EPILOG_FAILURE,vid); vm->log("TM", Log::ERROR, os); vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManager::epilog_delete_action(int vid) { ofstream xfr; ostringstream os; string xfr_name; string system_tm_mad; string tm_mad; VirtualMachine * vm; Nebula& nd = Nebula::instance(); const TransferManagerDriver * tm_md; const VectorAttribute * disk; vector attrs; int num; // ------------------------------------------------------------------------ // Setup & Transfer script // ------------------------------------------------------------------------ system_tm_mad = nd.get_system_ds_tm_mad(); vm = vmpool->get(vid,true); if (vm == 0) { return; } if (!vm->hasHistory()) { goto error_history; } tm_md = get(); if ( tm_md == 0 ) { goto error_driver; } xfr_name = vm->get_transfer_file() + ".delete"; xfr.open(xfr_name.c_str(), ios::out | ios::trunc); if (xfr.fail() == true) { goto error_file; } // ------------------------------------------------------------------------- // Delete disk images and the remote system Directory // ------------------------------------------------------------------------- num = vm->get_template_attribute("DISK",attrs); for (int i=0 ; i < num ; i++, tm_mad="") { disk = dynamic_cast(attrs[i]); if ( disk == 0 ) { continue; } tm_mad = disk->vector_value("TM_MAD"); if ( tm_mad.empty() ) { continue; } //DELETE tm_mad host:remote_system_dir/disk.i xfr << "DELETE " << tm_mad << " " << vm->get_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << i << endl; } //DELETE system_tm_mad hostname:remote_system_dir xfr << "DELETE " << system_tm_mad << " " << vm->get_hostname() <<":"<< vm->get_remote_system_dir() << endl; xfr.close(); tm_md->transfer(vid,xfr_name); vm->unlock(); return; error_history: os.str(""); os << "epilog_delete, VM " << vid << " has no history"; goto error_common; error_file: os.str(""); os << "epilog_delete, could not open file: " << xfr_name; os << ". You may need to manually clean " << vm->get_hostname() << ":" << vm->get_remote_system_dir(); goto error_common; error_driver: os.str(""); os << "epilog_delete, error getting driver Transfer Manager driver."; os << ". You may need to manually clean " << vm->get_hostname() << ":" << vm->get_remote_system_dir(); error_common: vm->log("TM", Log::ERROR, os); vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManager::epilog_delete_previous_action(int vid) { ofstream xfr; ostringstream os; string xfr_name; string system_tm_mad; string tm_mad; VirtualMachine * vm; Nebula& nd = Nebula::instance(); const TransferManagerDriver * tm_md; const VectorAttribute * disk; vector attrs; int num; // ------------------------------------------------------------------------ // Setup & Transfer script // ------------------------------------------------------------------------ system_tm_mad = nd.get_system_ds_tm_mad(); vm = vmpool->get(vid,true); if (vm == 0) { return; } if (!vm->hasHistory() || !vm->hasPreviousHistory()) { goto error_history; } tm_md = get(); if ( tm_md == 0 ) { goto error_driver; } xfr_name = vm->get_transfer_file() + ".delete_prev"; xfr.open(xfr_name.c_str(),ios::out | ios::trunc); if (xfr.fail() == true) { goto error_file; } // ------------------------------------------------------------------------ // Delete the remote VM Directory // ------------------------------------------------------------------------ num = vm->get_template_attribute("DISK",attrs); for (int i=0 ; i < num ; i++, tm_mad="") { disk = dynamic_cast(attrs[i]); if ( disk == 0 ) { continue; } tm_mad = disk->vector_value("TM_MAD"); if ( tm_mad.empty() ) { continue; } //DELETE tm_mad prev_host:remote_system_dir/disk.i xfr << "DELETE " << tm_mad << " " << vm->get_previous_hostname() << ":" << vm->get_remote_system_dir() << "/disk." << i << endl; } //DELTE system_tm_mad prev_host:remote_system_dir xfr << "DELETE " << system_tm_mad << " " << vm->get_previous_hostname() <<":"<< vm->get_remote_system_dir() << endl; xfr.close(); tm_md->transfer(vid,xfr_name); vm->unlock(); return; error_history: os.str(""); os << "epilog_delete_previous, VM " << vid << " has no history"; goto error_common; error_file: os.str(""); os << "epilog_delete, could not open file: " << xfr_name; os << ". You may need to manually clean " << vm->get_previous_hostname() << ":" << vm->get_remote_system_dir(); goto error_common; error_driver: os.str(""); os << "epilog_delete, error getting driver Transfer Manager driver."; os << ". You may need to manually clean " << vm->get_previous_hostname() << ":" << vm->get_remote_system_dir(); error_common: vm->log("TM", Log::ERROR, os); vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManager::driver_cancel_action(int vid) { ofstream xfr; ostringstream os; string xfr_name; VirtualMachine * vm; const TransferManagerDriver * tm_md; // ------------------------------------------------------------------------ // Get the Driver for this host // ------------------------------------------------------------------------ vm = vmpool->get(vid,true); if (vm == 0) { return; } tm_md = get(); if ( tm_md == 0 ) { goto error_driver; } // ------------------------------------------------------------------------ // Cancel the current operation // ------------------------------------------------------------------------ tm_md->driver_cancel(vid); vm->unlock(); return; error_driver: os.str(""); os << "driver_cancel, error getting driver Transfer Manager driver."; vm->log("TM", Log::ERROR, os); vm->unlock(); return; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void TransferManager::checkpoint_action(int vid) { } /* ************************************************************************** */ /* MAD Loading */ /* ************************************************************************** */ void TransferManager::load_mads(int uid) { ostringstream oss; int rc; string name; const VectorAttribute * vattr = 0; TransferManagerDriver * tm_driver = 0; oss << "Loading Transfer Manager driver."; NebulaLog::log("TM",Log::INFO,oss); if ( mad_conf.size() > 0 ) { vattr = static_cast(mad_conf[0]); } if ( vattr == 0 ) { NebulaLog::log("TM",Log::ERROR,"Failed to load Transfer Manager driver."); return; } VectorAttribute tm_conf("TM_MAD",vattr->value()); tm_conf.replace("NAME",transfer_driver_name); tm_driver = new TransferManagerDriver(uid, tm_conf.value(), (uid != 0), vmpool); rc = add(tm_driver); if ( rc == 0 ) { oss.str(""); oss << "\tTransfer manager driver loaded"; NebulaLog::log("TM",Log::INFO,oss); } } opennebula-3.4.1/src/oca/0000755000175000017500000000000011750754334015105 5ustar drazzibdrazzibopennebula-3.4.1/src/oca/ruby/0000755000175000017500000000000011750754334016066 5ustar drazzibdrazzibopennebula-3.4.1/src/oca/ruby/test/0000755000175000017500000000000011750754334017045 5ustar drazzibdrazzibopennebula-3.4.1/src/oca/ruby/test/HostPool_spec.rb0000644000175000017500000000605311750754334022157 0ustar drazzibdrazzib$: << '../' \ << './' require 'OpenNebula' require 'helpers/MockClient' module OpenNebula describe "Host using NOKOGIRI" do before(:all) do NOKOGIRI=true client = MockClient.new() @host_pool = HostPool.new(client) end it "should update the HOST_POOL info" do rc = @host_pool.info() rc.nil?.should eql(true) end it "should iterate the HOST_POOL elements and get info from them" do rc = @host_pool.each{ |host| host.class.to_s.should eql("OpenNebula::Host") if host.id == 0 host.name.should eql('dummyhost') host['STATE'].should eql('2') host['IM_MAD'].should eql('im_dummy') host['HOST_SHARE/MEM_USAGE'].should eql('1572864') host['HOST_SHARE/CPU_USAGE'].should eql('300') host['HOST_SHARE/FREE_MEM'].should eql('16777216') host['HOST_SHARE/RUNNING_VMS'].should eql('3') elsif host.id == 1 host.name.should eql('thost') host['STATE'].should eql('2') host['IM_MAD'].should eql('im_dummy') host['HOST_SHARE/MEM_USAGE'].should eql('0') host['HOST_SHARE/CPU_USAGE'].should eql('0') host['HOST_SHARE/FREE_MEM'].should eql('16777216') host['HOST_SHARE/RUNNING_VMS'].should eql('0') end } end end describe "Host using REXML" do before(:all) do NOKOGIRI=false client = MockClient.new() @host_pool = HostPool.new(client) end it "should update the HOST_POOL info" do rc = @host_pool.info() rc.nil?.should eql(true) end it "should iterate the HOST_POOL elements and get info from them" do rc = @host_pool.each{ |host| host.class.to_s.should eql("OpenNebula::Host") if host.id == 0 host.name.should eql('dummyhost') host['STATE'].should eql('2') host['IM_MAD'].should eql('im_dummy') host['HOST_SHARE/MEM_USAGE'].should eql('1572864') host['HOST_SHARE/CPU_USAGE'].should eql('300') host['HOST_SHARE/FREE_MEM'].should eql('16777216') host['HOST_SHARE/RUNNING_VMS'].should eql('3') elsif host.id == 1 host.name.should eql('thost') host['STATE'].should eql('2') host['IM_MAD'].should eql('im_dummy') host['HOST_SHARE/MEM_USAGE'].should eql('0') host['HOST_SHARE/CPU_USAGE'].should eql('0') host['HOST_SHARE/FREE_MEM'].should eql('16777216') host['HOST_SHARE/RUNNING_VMS'].should eql('0') end } end end end opennebula-3.4.1/src/oca/ruby/test/VirtualNetwork_spec.rb0000644000175000017500000001024111750754334023402 0ustar drazzibdrazzib$: << '../' \ << './' require 'OpenNebula' require 'helpers/MockClient' module OpenNebula describe "VirtualNetwork using NOKOGIRI" do before(:all) do NOKOGIRI=true @xml = VirtualNetwork.build_xml(3) client = MockClient.new() @vnet = VirtualNetwork.new(@xml,client) end it "should create a Nokogiri Node" do @xml.class.to_s.should eql('Nokogiri::XML::NodeSet') end it "should allocate the new VNET" do @vnet.allocate(nil) @vnet.id.should eql(3) end it "should update the VNET info" do @vnet.info() @vnet.id.should eql(3) @vnet.name.should eql('Red LAN') end it "should delete the VNET" do rc = @vnet.delete() rc.should eql(nil) end it "should access an attribute using []" do @vnet['ID'].should eql('3') @vnet['NAME'].should eql('Red LAN') @vnet['BRIDGE'].should eql('vbr0') @vnet['TEMPLATE/NETWORK_ADDRESS'].should eql('192.168.0.0') @vnet['TEMPLATE/TYPE'].should eql('RANGED') @vnet['LEASES/LEASE/IP'].should eql('192.168.0.1') @vnet['LEASES/LEASE/USED'].should eql('1') end end describe "VirtualNetwork using REXML" do before(:all) do NOKOGIRI=false @xml = VirtualNetwork.build_xml(3) client = MockClient.new() @vnet = VirtualNetwork.new(@xml,client) end it "should create a REXML Element" do @xml.class.to_s.should eql('REXML::Element') end it "should allocate the new VNET" do @vnet.allocate(nil) @vnet.id.should eql(3) end it "should update the VNET info" do @vnet.info() @vnet.id.should eql(3) @vnet.name.should eql('Red LAN') end it "should delete the VNET" do rc = @vnet.delete() rc.should eql(nil) end it "should access an attribute using []" do @vnet['ID'].should eql('3') @vnet['NAME'].should eql('Red LAN') @vnet['BRIDGE'].should eql('vbr0') @vnet['TEMPLATE/NETWORK_ADDRESS'].should eql('192.168.0.0') @vnet['TEMPLATE/TYPE'].should eql('RANGED') @vnet['LEASES/LEASE/IP'].should eql('192.168.0.1') @vnet['LEASES/LEASE/USED'].should eql('1') end end describe "VirtualNetwork using NOKOGIRI without id" do before(:all) do NOKOGIRI=true @xml = VirtualNetwork.build_xml() client = MockClient.new() @vnet = VirtualNetwork.new(@xml,client) end it "should create a Nokogiri Node" do @xml.class.to_s.should eql('Nokogiri::XML::NodeSet') end it "should get Error getting info" do rc = @vnet.info() OpenNebula.is_error?(rc).should eql(true) @vnet.id.should eql(nil) @vnet.name.should eql(nil) end it "should get Error deleting the VNET" do rc = @vnet.delete() OpenNebula.is_error?(rc).should eql(true) end end describe "VirtualNetwork using REXML without id" do before(:all) do NOKOGIRI=false @xml = VirtualNetwork.build_xml() client = MockClient.new() @vnet = VirtualNetwork.new(@xml,client) end it "should create a REXML Element" do @xml.class.to_s.should eql('REXML::Element') end it "should get Error getting info" do rc = @vnet.info() OpenNebula.is_error?(rc).should eql(true) @vnet.id.should eql(nil) @vnet.name.should eql(nil) end it "should get Error deleting the VNET" do rc = @vnet.delete() OpenNebula.is_error?(rc).should eql(true) end end end opennebula-3.4.1/src/oca/ruby/test/VirtualMachinePool_spec.rb0000644000175000017500000001121611750754334024152 0ustar drazzibdrazzib$: << '../' \ << './' require 'OpenNebula' require 'helpers/MockClient' module OpenNebula describe "VirtualMachinePool using NOKOGIRI" do before(:all) do NOKOGIRI=true client = MockClient.new() @vm_pool = VirtualMachinePool.new(client) end it "should update the VM_POOL info" do rc = @vm_pool.info() rc.nil?.should eql(true) end it "should iterate the VM_POOL elements and get info from them using to_hash" do vm_pool = @vm_pool.to_hash vm_pool['VM_POOL']['VM'].each{ |vm| if vm['ID'] == 6 vm.name.should eql('vm-example') vm.state.should eql(3) vm.state_str.should eql('ACTIVE') vm['UID'].should eql('0') vm['USERNAME'].should eql('oneadmin') vm['LAST_POLL'].should eql('1277910006') vm['HISTORY']['HOSTNAME'].should eql('dummyhost') vm['HISTORY']['STIME'].should eql('1277375186') vm['HISTORY']['REASON'].should eql('0') elsif vm['ID'] == 8 vm.name.should eql('vmext') vm.state.should eql(4) vm.state_str.should eql('STOPPED') vm['UID'].should eql('0') vm['USERNAME'].should eql('oneadmin') vm['LAST_POLL'].should eql('1277910006') vm['HISTORY']['HOSTNAME'].should eql('thost') vm['HISTORY']['STIME'].should eql('1277377556') vm['HISTORY']['REASON'].should eql('0') end } end it "should iterate the VM_POOL elements and get info from them" do rc = @vm_pool.each{ |vm| vm.class.to_s.should eql("OpenNebula::VirtualMachine") if vm.id == 6 vm.name.should eql('vm-example') vm.state.should eql(3) vm.state_str.should eql('ACTIVE') vm['UID'].should eql('0') vm['USERNAME'].should eql('oneadmin') vm['LAST_POLL'].should eql('1277910006') vm['HISTORY/HOSTNAME'].should eql('dummyhost') vm['HISTORY/STIME'].should eql('1277375186') vm['HISTORY/REASON'].should eql('0') elsif vm.id == 8 vm.name.should eql('vmext') vm.state.should eql(4) vm.state_str.should eql('STOPPED') vm['UID'].should eql('0') vm['USERNAME'].should eql('oneadmin') vm['LAST_POLL'].should eql('1277910006') vm['HISTORY/HOSTNAME'].should eql('thost') vm['HISTORY/STIME'].should eql('1277377556') vm['HISTORY/REASON'].should eql('0') end } end end describe "VirtualMachinePool using REXML" do before(:all) do NOKOGIRI=false client = MockClient.new() @vm_pool = VirtualMachinePool.new(client) end it "should update the VM_POOL info" do rc = @vm_pool.info() rc.nil?.should eql(true) end it "should iterate the VM_POOL elements and get info from them" do rc = @vm_pool.each{ |vm| vm.class.to_s.should eql("OpenNebula::VirtualMachine") if vm.id == 6 vm.name.should eql('vm-example') vm.state.should eql(3) vm.state_str.should eql('ACTIVE') vm['UID'].should eql('0') vm['USERNAME'].should eql('oneadmin') vm['LAST_POLL'].should eql('1277910006') vm['HISTORY/HOSTNAME'].should eql('dummyhost') vm['HISTORY/STIME'].should eql('1277375186') vm['HISTORY/REASON'].should eql('0') elsif vm.id == 8 vm.name.should eql('vmext') vm.state.should eql(4) vm.state_str.should eql('STOPPED') vm['UID'].should eql('0') vm['USERNAME'].should eql('oneadmin') vm['LAST_POLL'].should eql('1277910006') vm['HISTORY/HOSTNAME'].should eql('thost') vm['HISTORY/STIME'].should eql('1277377556') vm['HISTORY/REASON'].should eql('0') end } end end end opennebula-3.4.1/src/oca/ruby/test/VirtualMachine_spec.rb0000644000175000017500000003105411750754334023322 0ustar drazzibdrazzib$: << '../' \ << './' require 'OpenNebula' require 'helpers/MockClient' module OpenNebula describe "VirtualMachine using NOKOGIRI" do before(:all) do NOKOGIRI=true @xml = VirtualMachine.build_xml(6) client = MockClient.new() @vm = VirtualMachine.new(@xml,client) end it "should create a Nokogiri Node" do @xml.class.to_s.should eql('Nokogiri::XML::NodeSet') end it "should allocate the new VM" do @vm.allocate(nil) @vm.id.should eql(6) end it "should update the VM info" do @vm.info() @vm.id.should eql(6) @vm.name.should eql('vm-example') @vm.state.should eql(3) @vm.state_str.should eql('ACTIVE') @vm.lcm_state.should eql(3) @vm.lcm_state_str.should eql('RUNNING') @vm.status.should eql('runn') end it "should deploy the VNET" do rc = @vm.deploy(nil) rc.should eql(nil) end it "should migrate the VNET" do rc = @vm.migrate(nil) rc.should eql(nil) end it "should live_migrate the VNET" do rc = @vm.live_migrate(nil) rc.should eql(nil) end it "should shutdown the VNET" do rc = @vm.shutdown() rc.should eql(nil) end it "should cancel the VNET" do rc = @vm.cancel() rc.should eql(nil) end it "should hold the VNET" do rc = @vm.hold() rc.should eql(nil) end it "should release the VNET" do rc = @vm.release() rc.should eql(nil) end it "should stop the VNET" do rc = @vm.stop() rc.should eql(nil) end it "should suspend the VNET" do rc = @vm.suspend() rc.should eql(nil) end it "should resume the VNET" do rc = @vm.resume() rc.should eql(nil) end it "should finalize the VNET" do rc = @vm.finalize() rc.should eql(nil) end it "should restart the VNET" do rc = @vm.restart() rc.should eql(nil) end it "should access an attribute using []" do @vm['NAME'].should eql('vm-example') @vm['DEPLOY_ID'].should eql('dummy') @vm['TEMPLATE/MEMORY'].should eql('512') @vm['ID'].should eql('6') @vm['NAME'].should eql('vm-example') @vm['LCM_STATE'].should eql('3') @vm['DEPLOY_ID'].should eql('dummy') @vm['TEMPLATE/MEMORY'].should eql('512') @vm['TEMPLATE/CONTEXT/DNS'].should eql('192.169.1.4') @vm['TEMPLATE/DISK/SIZE'].should eql('1024') @vm['HISTORY/HOSTNAME'].should eql('dummyhost') @vm['HISTORY/PSTIME'].should eql('1277375186') end it "should access an attribute using to_hash" do vm_hash = @vm.to_hash vm_hash['VM']['NAME'].should eql('vm-example') vm_hash['VM']['DEPLOY_ID'].should eql('dummy') vm_hash['VM']['TEMPLATE']['MEMORY'].should eql('512') vm_hash['VM']['ID'].should eql('6') vm_hash['VM']['NAME'].should eql('vm-example') vm_hash['VM']['LCM_STATE'].should eql('3') vm_hash['VM']['DEPLOY_ID'].should eql('dummy') vm_hash['VM']['TEMPLATE']['MEMORY'].should eql('512') vm_hash['VM']['TEMPLATE']['CONTEXT']['DNS'].should eql('192.169.1.4') vm_hash['VM']['TEMPLATE']['DISK'][1]['SIZE'].should eql('1024') vm_hash['VM']['HISTORY']['HOSTNAME'].should eql('dummyhost') vm_hash['VM']['HISTORY']['PSTIME'].should eql('1277375186') end end describe "VirtualMachine using REXML" do before(:all) do NOKOGIRI=false @xml = VirtualMachine.build_xml(6) client = MockClient.new() @vm = VirtualMachine.new(@xml,client) end it "should create a REXML Element" do @xml.class.to_s.should eql('REXML::Element') end it "should allocate the new VM" do @vm.allocate(nil) @vm.id.should eql(6) end it "should update the VM info" do @vm.info() @vm.id.should eql(6) @vm.name.should eql('vm-example') @vm.state.should eql(3) @vm.state_str.should eql('ACTIVE') @vm.lcm_state.should eql(3) @vm.lcm_state_str.should eql('RUNNING') @vm.status.should eql('runn') end it "should deploy the VNET" do rc = @vm.deploy(nil) rc.should eql(nil) end it "should migrate the VNET" do rc = @vm.migrate(nil) rc.should eql(nil) end it "should live_migrate the VNET" do rc = @vm.live_migrate(nil) rc.should eql(nil) end it "should shutdown the VNET" do rc = @vm.shutdown() rc.should eql(nil) end it "should cancel the VNET" do rc = @vm.cancel() rc.should eql(nil) end it "should hold the VNET" do rc = @vm.hold() rc.should eql(nil) end it "should release the VNET" do rc = @vm.release() rc.should eql(nil) end it "should stop the VNET" do rc = @vm.stop() rc.should eql(nil) end it "should suspend the VNET" do rc = @vm.suspend() rc.should eql(nil) end it "should resume the VNET" do rc = @vm.resume() rc.should eql(nil) end it "should finalize the VNET" do rc = @vm.finalize() rc.should eql(nil) end it "should restart the VNET" do rc = @vm.restart() rc.should eql(nil) end it "should access an attribute using []" do @vm['NAME'].should eql('vm-example') @vm['DEPLOY_ID'].should eql('dummy') @vm['TEMPLATE/MEMORY'].should eql('512') @vm['ID'].should eql('6') @vm['NAME'].should eql('vm-example') @vm['LCM_STATE'].should eql('3') @vm['DEPLOY_ID'].should eql('dummy') @vm['TEMPLATE/MEMORY'].should eql('512') @vm['TEMPLATE/CONTEXT/DNS'].should eql('192.169.1.4') @vm['TEMPLATE/DISK/SIZE'].should eql('1024') @vm['HISTORY/HOSTNAME'].should eql('dummyhost') @vm['HISTORY/PSTIME'].should eql('1277375186') end it "should access an attribute using to_hash" do vm_hash = @vm.to_hash vm_hash['VM']['NAME'].should eql('vm-example') vm_hash['VM']['DEPLOY_ID'].should eql('dummy') vm_hash['VM']['TEMPLATE']['MEMORY'].should eql('512') vm_hash['VM']['ID'].should eql('6') vm_hash['VM']['NAME'].should eql('vm-example') vm_hash['VM']['LCM_STATE'].should eql('3') vm_hash['VM']['DEPLOY_ID'].should eql('dummy') vm_hash['VM']['TEMPLATE']['MEMORY'].should eql('512') vm_hash['VM']['TEMPLATE']['CONTEXT']['DNS'].should eql('192.169.1.4') vm_hash['VM']['TEMPLATE']['DISK'][1]['SIZE'].should eql('1024') vm_hash['VM']['HISTORY']['HOSTNAME'].should eql('dummyhost') vm_hash['VM']['HISTORY']['PSTIME'].should eql('1277375186') end end describe "VirtualMachine using NOKOGIRI without id" do before(:all) do NOKOGIRI=true @xml = VirtualMachine.build_xml() client = MockClient.new() @vm = VirtualMachine.new(@xml,client) end it "should create a Nokogiri Node" do @xml.class.to_s.should eql('Nokogiri::XML::NodeSet') end it "should deploy the VNET" do rc = @vm.deploy(nil) OpenNebula.is_error?(rc).should eql(true) end it "should migrate the VNET" do rc = @vm.migrate(nil) OpenNebula.is_error?(rc).should eql(true) end it "should live_migrate the VNET" do rc = @vm.live_migrate(nil) OpenNebula.is_error?(rc).should eql(true) end it "should shutdown the VNET" do rc = @vm.shutdown() OpenNebula.is_error?(rc).should eql(true) end it "should cancel the VNET" do rc = @vm.cancel() OpenNebula.is_error?(rc).should eql(true) end it "should hold the VNET" do rc = @vm.hold() OpenNebula.is_error?(rc).should eql(true) end it "should release the VNET" do rc = @vm.release() OpenNebula.is_error?(rc).should eql(true) end it "should stop the VNET" do rc = @vm.stop() OpenNebula.is_error?(rc).should eql(true) end it "should suspend the VNET" do rc = @vm.suspend() OpenNebula.is_error?(rc).should eql(true) end it "should resume the VNET" do rc = @vm.resume() OpenNebula.is_error?(rc).should eql(true) end it "should finalize the VNET" do rc = @vm.finalize() OpenNebula.is_error?(rc).should eql(true) end it "should restart the VNET" do rc = @vm.restart() OpenNebula.is_error?(rc).should eql(true) end it "should get Error getting info" do rc = @vm.info() OpenNebula.is_error?(rc).should eql(true) @vm.id.should eql(nil) @vm.name.should eql(nil) end end describe "VirtualMachine using REXML without id" do before(:all) do NOKOGIRI=false @xml = VirtualMachine.build_xml() client = MockClient.new() @vm = VirtualMachine.new(@xml,client) end it "should create a REXML Element" do @xml.class.to_s.should eql('REXML::Element') end it "should deploy the VNET" do rc = @vm.deploy(nil) OpenNebula.is_error?(rc).should eql(true) end it "should migrate the VNET" do rc = @vm.migrate(nil) OpenNebula.is_error?(rc).should eql(true) end it "should live_migrate the VNET" do rc = @vm.live_migrate(nil) OpenNebula.is_error?(rc).should eql(true) end it "should shutdown the VNET" do rc = @vm.shutdown() OpenNebula.is_error?(rc).should eql(true) end it "should cancel the VNET" do rc = @vm.cancel() OpenNebula.is_error?(rc).should eql(true) end it "should hold the VNET" do rc = @vm.hold() OpenNebula.is_error?(rc).should eql(true) end it "should release the VNET" do rc = @vm.release() OpenNebula.is_error?(rc).should eql(true) end it "should stop the VNET" do rc = @vm.stop() OpenNebula.is_error?(rc).should eql(true) end it "should suspend the VNET" do rc = @vm.suspend() OpenNebula.is_error?(rc).should eql(true) end it "should resume the VNET" do rc = @vm.resume() OpenNebula.is_error?(rc).should eql(true) end it "should finalize the VNET" do rc = @vm.finalize() OpenNebula.is_error?(rc).should eql(true) end it "should restart the VNET" do rc = @vm.restart() OpenNebula.is_error?(rc).should eql(true) end it "should get Error getting info" do rc = @vm.info() OpenNebula.is_error?(rc).should eql(true) @vm.id.should eql(nil) @vm.name.should eql(nil) end end end opennebula-3.4.1/src/oca/ruby/test/helpers/0000755000175000017500000000000011750754334020507 5ustar drazzibdrazzibopennebula-3.4.1/src/oca/ruby/test/helpers/MockClient.rb0000644000175000017500000000305611750754334023070 0ustar drazzibdrazzibclass MockClient def call(action, *args) xmlrpc_action = "one."+action case xmlrpc_action when "one.vn.info" return File.read("fixtures/vnet.xml") when "one.vn.allocate" return 3 when "one.vn.delete" return nil when "one.vm.info" return File.read("fixtures/vm.xml") when "one.vm.allocate" return 6 when "one.vm.delete" return nil when "one.vm.action" return nil when "one.vm.deploy" return nil when "one.vm.migrate" return nil when "one.host.info" return File.read("fixtures/host.xml") when "one.host.allocate" return 7 when "one.host.delete" return nil when "one.host.enable" return nil when "one.user.allocate" return 3 when "one.user.info" return File.read("fixtures/user.xml") when "one.user.delete" return nil when "one.vnpool.info" return File.read("fixtures/vnetpool.xml") when "one.vmpool.info" return File.read("fixtures/vmpool.xml") when "one.hostpool.info" return File.read("fixtures/hostpool.xml") when "one.userpool.info" return File.read("fixtures/userpool.xml") end end endopennebula-3.4.1/src/oca/ruby/test/VirtualNetworkPool_spec.rb0000644000175000017500000000577311750754334024252 0ustar drazzibdrazzib$: << '../' \ << './' require 'OpenNebula' require 'helpers/MockClient' module OpenNebula describe "VirtualNetwork using NOKOGIRI" do before(:all) do NOKOGIRI=true client = MockClient.new() @vnet_pool = VirtualNetworkPool.new(client) end #it "should get nil, trying to get a hash, if the info method was not called before" do # vnet_hash = @vnet_pool.to_hash # vnet_hash.nil?.should eql(true) #end it "should update the VNET_POOL info" do rc = @vnet_pool.info() rc.nil?.should eql(true) end it "should iterate the VNET_POOL elements and get info from them" do rc = @vnet_pool.each{ |vn| vn.class.to_s.should eql("OpenNebula::VirtualNetwork") if vn.id == 4 vn.name.should eql('Red LAN') vn['UID'].should eql('0') vn['USERNAME'].should eql('oneadmin') vn['TYPE'].should eql('0') vn['BRIDGE'].should eql('vbr0') vn['TOTAL_LEASES'].should eql('0') elsif vn.id == 5 vn.name.should eql('Public') vn['UID'].should eql('0') vn['USERNAME'].should eql('oneadmin') vn['TYPE'].should eql('0') vn['BRIDGE'].should eql('vbr0') vn['TOTAL_LEASES'].should eql('1') end } end end describe "VirtualNetwork using REXML" do before(:all) do NOKOGIRI=false client = MockClient.new() @vnet_pool = VirtualNetworkPool.new(client) end #it "should get nil, trying to get a hash, if the info method was not called before" do # vnet_hash = @vnet_pool.to_hash # vnet_hash.nil?.should eql(true) #end it "should update the VNET_POOL info" do rc = @vnet_pool.info() rc.nil?.should eql(true) end it "should iterate the VNET_POOL elements and get info from them" do rc = @vnet_pool.each{ |vn| vn.class.to_s.should eql("OpenNebula::VirtualNetwork") if vn.id == 4 vn.name.should eql('Red LAN') vn['UID'].should eql('0') vn['USERNAME'].should eql('oneadmin') vn['TYPE'].should eql('0') vn['BRIDGE'].should eql('vbr0') vn['TOTAL_LEASES'].should eql('0') elsif vn.id == 5 vn.name.should eql('Public') vn['UID'].should eql('0') vn['USERNAME'].should eql('oneadmin') vn['TYPE'].should eql('0') vn['BRIDGE'].should eql('vbr0') vn['TOTAL_LEASES'].should eql('1') end } end end end opennebula-3.4.1/src/oca/ruby/test/Host_spec.rb0000644000175000017500000001365311750754334021331 0ustar drazzibdrazzib$: << '../' \ << './' require 'OpenNebula' require 'helpers/MockClient' module OpenNebula describe "Host using NOKOGIRI" do before(:all) do NOKOGIRI=true @xml = Host.build_xml(7) client = MockClient.new() @host = Host.new(@xml,client) end it "should create a Nokogiri Node" do @xml.class.to_s.should eql('Nokogiri::XML::NodeSet') end it "should allocate the new HOST" do @host.allocate(nil,nil,nil,nil) @host.id.should eql(7) end it "should update the HOST info" do @host.info() @host.id.should eql(7) @host.name.should eql('dummyhost') @host.state.should eql(2) @host.state_str.should eql('MONITORED') @host.short_state_str.should eql('on') end it "should enable the HOST" do rc = @host.enable() rc.should eql(nil) end it "should disable the HOST" do rc = @host.disable() rc.should eql(nil) end it "should delete the HOST" do rc = @host.delete() rc.should eql(nil) end it "should access an attribute using []" do @host['ID'].should eql('7') @host['NAME'].should eql('dummyhost') @host['STATE'].should eql('2') @host['IM_MAD'].should eql('im_dummy') @host['LAST_MON_TIME'].should eql('1277733596') @host['HOST_SHARE/MEM_USAGE'].should eql('1572864') @host['HOST_SHARE/CPU_USAGE'].should eql('300') @host['HOST_SHARE/FREE_CPU'].should eql('800') @host['HOST_SHARE/RUNNING_VMS'].should eql('3') @host['TEMPLATE/CPUSPEED'].should eql('2.2GHz') @host['TEMPLATE/HYPERVISOR'].should eql('dummy') @host['TEMPLATE/TOTALMEMORY'].should eql('16777216') end end describe "Host using REXML" do before(:all) do NOKOGIRI=false @xml = Host.build_xml(7) client = MockClient.new() @host = Host.new(@xml,client) end it "should create a REXML Element" do @xml.class.to_s.should eql('REXML::Element') end it "should allocate the new HOST" do @host.allocate(nil,nil,nil,nil) @host.id.should eql(7) end it "should update the HOST info" do @host.info() @host.id.should eql(7) @host.name.should eql('dummyhost') @host.state.should eql(2) @host.state_str.should eql('MONITORED') @host.short_state_str.should eql('on') end it "should enable the HOST" do rc = @host.enable() rc.should eql(nil) end it "should disable the HOST" do rc = @host.disable() rc.should eql(nil) end it "should delete the HOST" do rc = @host.delete() rc.should eql(nil) end it "should access an attribute using []" do @host['ID'].should eql('7') @host['NAME'].should eql('dummyhost') @host['STATE'].should eql('2') @host['IM_MAD'].should eql('im_dummy') @host['LAST_MON_TIME'].should eql('1277733596') @host['HOST_SHARE/MEM_USAGE'].should eql('1572864') @host['HOST_SHARE/CPU_USAGE'].should eql('300') @host['HOST_SHARE/FREE_CPU'].should eql('800') @host['HOST_SHARE/RUNNING_VMS'].should eql('3') @host['TEMPLATE/CPUSPEED'].should eql('2.2GHz') @host['TEMPLATE/HYPERVISOR'].should eql('dummy') @host['TEMPLATE/TOTALMEMORY'].should eql('16777216') end end describe "Host using NOKOGIRI without id" do before(:all) do NOKOGIRI=true @xml = Host.build_xml() client = MockClient.new() @host = Host.new(@xml,client) end it "should create a Nokogiri Node" do @xml.class.to_s.should eql('Nokogiri::XML::NodeSet') end it "should get Error getting info" do rc = @host.info() OpenNebula.is_error?(rc).should eql(true) @host.id.should eql(nil) @host.name.should eql(nil) end it "should enable the HOST" do rc = @host.enable() OpenNebula.is_error?(rc).should eql(true) end it "should disable the HOST" do rc = @host.disable() OpenNebula.is_error?(rc).should eql(true) end it "should get Error deleting the HOST" do rc = @host.delete() OpenNebula.is_error?(rc).should eql(true) end end describe "Host using REXML without id" do before(:all) do NOKOGIRI=false @xml = Host.build_xml() client = MockClient.new() @host = Host.new(@xml,client) end it "should create a REXML Element" do @xml.class.to_s.should eql('REXML::Element') end it "should get Error getting info" do rc = @host.info() OpenNebula.is_error?(rc).should eql(true) @host.id.should eql(nil) @host.name.should eql(nil) end it "should enable the HOST" do rc = @host.enable() OpenNebula.is_error?(rc).should eql(true) end it "should disable the HOST" do rc = @host.disable() OpenNebula.is_error?(rc).should eql(true) end it "should get Error deleting the HOST" do rc = @host.delete() OpenNebula.is_error?(rc).should eql(true) end end end opennebula-3.4.1/src/oca/ruby/test/UserPool_spec.rb0000644000175000017500000000416711750754334022164 0ustar drazzibdrazzib$: << '../' \ << './' require 'OpenNebula' require 'helpers/MockClient' module OpenNebula describe "User using NOKOGIRI" do before(:all) do NOKOGIRI=true client = MockClient.new() @user_pool = UserPool.new(client) end it "should update the USER_POOL info" do rc = @user_pool.info() rc.nil?.should eql(true) end it "should iterate the USER_POOL elements and get info from them" do rc = @user_pool.each{ |user| user.class.to_s.should eql("OpenNebula::User") if user.id == 0 user.name.should eql('oneadmin') user['PASSWORD'].should eql('f13a1234833436f71ab846572d251c0d40391e72') user['ENABLED'].should eql('1') elsif user.id == 1 user.name.should eql('dan') user['PASSWORD'].should eql('d22a12348334v33f71ba846572d25250d40701e72') user['ENABLED'].should eql('0') end } end end describe "User using REXML" do before(:all) do NOKOGIRI=false client = MockClient.new() @user_pool = UserPool.new(client) end it "should update the USER_POOL info" do rc = @user_pool.info() rc.nil?.should eql(true) end it "should iterate the USER_POOL elements and get info from them" do rc = @user_pool.each{ |user| user.class.to_s.should eql("OpenNebula::User") if user.id == 0 user.name.should eql('oneadmin') user['PASSWORD'].should eql('f13a1234833436f71ab846572d251c0d40391e72') user['ENABLED'].should eql('1') elsif user.id == 1 user.name.should eql('dan') user['PASSWORD'].should eql('d22a12348334v33f71ba846572d25250d40701e72') user['ENABLED'].should eql('0') end } end end end opennebula-3.4.1/src/oca/ruby/test/User_spec.rb0000644000175000017500000000703111750754334021323 0ustar drazzibdrazzib$: << '../' \ << './' require 'OpenNebula' require 'helpers/MockClient' module OpenNebula describe "User using NOKOGIRI" do before(:all) do NOKOGIRI=true @xml = User.build_xml(3) client = MockClient.new() @user = User.new(@xml,client) end it "should create a Nokogiri Node" do @xml.class.to_s.should eql('Nokogiri::XML::NodeSet') end it "should allocate the new USER" do @user.allocate(nil,nil) @user.id.should eql(3) end it "should update the USER info" do @user.info() @user.id.should eql(3) @user.name.should eql('dan') end it "should delete the USER" do rc = @user.delete() rc.should eql(nil) end it "should access an attribute using []" do @user['ID'].should eql('3') @user['NAME'].should eql('dan') @user['PASSWORD'].should eql('d22a12348334v33f71ba846572d25250d40701e72') @user['ENABLED'].should eql('0') end end describe "User using REXML" do before(:all) do NOKOGIRI=false @xml = User.build_xml(3) client = MockClient.new() @user = User.new(@xml,client) end it "should create a REXML Element" do @xml.class.to_s.should eql('REXML::Element') end it "should allocate the new USER" do @user.allocate(nil,nil) @user.id.should eql(3) end it "should update the USER info" do @user.info() @user.id.should eql(3) @user.name.should eql('dan') end it "should delete the USER" do rc = @user.delete() rc.should eql(nil) end it "should access an attribute using []" do @user['ID'].should eql('3') @user['NAME'].should eql('dan') @user['PASSWORD'].should eql('d22a12348334v33f71ba846572d25250d40701e72') @user['ENABLED'].should eql('0') end end describe "User using NOKOGIRI without id" do before(:all) do NOKOGIRI=true @xml = User.build_xml() client = MockClient.new() @user = User.new(@xml,client) end it "should create a Nokogiri Node" do @xml.class.to_s.should eql('Nokogiri::XML::NodeSet') end it "should get Error getting info" do rc = @user.info() OpenNebula.is_error?(rc).should eql(true) end it "should get Error deleting the USER" do rc = @user.delete() OpenNebula.is_error?(rc).should eql(true) end end describe "User using REXML without id" do before(:all) do NOKOGIRI=false @xml = User.build_xml() client = MockClient.new() @user = User.new(@xml,client) end it "should create a REXML Element" do @xml.class.to_s.should eql('REXML::Element') end it "should get Error getting info" do rc = @user.info() OpenNebula.is_error?(rc).should eql(true) end it "should get Error deleting the USER" do rc = @user.delete() OpenNebula.is_error?(rc).should eql(true) end end end opennebula-3.4.1/src/oca/ruby/test/fixtures/0000755000175000017500000000000011750754334020716 5ustar drazzibdrazzibopennebula-3.4.1/src/oca/ruby/test/fixtures/vmpool.xml0000644000175000017500000000423511750754334022760 0ustar drazzibdrazzib 6 0 oneadmin vm-example 1277910006 3 3 1277375180 0 dummy 512 1 12345 0 0 dummyhost 0 1277375186 0 1277375186 1277375186 1277375186 0 0 0 0 7 0 oneadmin vm-in 1277910006 3 3 1277377464 0 dummy 1024 2 12345 0 0 thost 0 1277377466 0 1277377466 1277377466 1277377466 0 0 0 0 8 0 oneadmin vmext 1277910006 4 5 1277377533 0 thost 256 1 12345 0 0 thost 0 1277377556 0 1277377556 1277377556 1277377556 0 0 0 0 opennebula-3.4.1/src/oca/ruby/test/fixtures/hostpool.xml0000644000175000017500000000256011750754334023312 0ustar drazzibdrazzib 0 dummyhost 2 im_dummy vmm_dummy tm_dummy 1277912461 0 0 1572864 300 0 16777216 800 0 16777216 800 0 0 0 3 1 thost 2 im_dummy vmm_dummy tm_dummy 1277912461 1 0 0 0 0 16777216 800 0 16777216 800 0 0 0 0 opennebula-3.4.1/src/oca/ruby/test/fixtures/vnet.xml0000644000175000017500000000075411750754334022422 0ustar drazzibdrazzib 3 0 Red LAN 0 vbr0 192.168.0.1 00:03:c0:a8:00:01 1 18 opennebula-3.4.1/src/oca/ruby/test/fixtures/user.xml0000644000175000017500000000020611750754334022414 0ustar drazzibdrazzib 3 dan d22a12348334v33f71ba846572d25250d40701e72 0 opennebula-3.4.1/src/oca/ruby/test/fixtures/vnetpool.xml0000644000175000017500000000062311750754334023307 0ustar drazzibdrazzib 4 0 oneadmin Red LAN 0 vbr0 0 5 0 oneadmin Public 0 vbr0 1 opennebula-3.4.1/src/oca/ruby/test/fixtures/userpool.xml0000644000175000017500000000050211750754334023305 0ustar drazzibdrazzib 0 oneadmin f13a1234833436f71ab846572d251c0d40391e72 1 1 dan d22a12348334v33f71ba846572d25250d40701e72 0 opennebula-3.4.1/src/oca/ruby/test/fixtures/host.xml0000644000175000017500000000177211750754334022424 0ustar drazzibdrazzib 7 dummyhost 2 im_dummy vmm_dummy tm_dummy 1277733596 0 0 1572864 300 0 16777216 800 0 16777216 800 0 0 0 3 opennebula-3.4.1/src/oca/ruby/test/fixtures/vm.xml0000644000175000017500000000245211750754334022065 0ustar drazzibdrazzib 6 0 vm-example 1277729095 3 3 1277375180 0 dummy 512 1 12345 0 0 dummyhost 0 1277375186 0 1277375186 1277375186 1277375186 0 0 0 0 opennebula-3.4.1/src/oca/ruby/OpenNebula/0000755000175000017500000000000011750754334020116 5ustar drazzibdrazzibopennebula-3.4.1/src/oca/ruby/OpenNebula/XMLUtils.rb0000644000175000017500000003015711750754334022132 0ustar drazzibdrazzib# -------------------------------------------------------------------------- # # Copyright 2002-2012, 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. # #--------------------------------------------------------------------------- # module OpenNebula begin require 'nokogiri' NOKOGIRI=true rescue LoadError NOKOGIRI=false end begin require 'rexml/formatters/pretty' REXML_FORMATTERS=true rescue LoadError REXML_FORMATTERS=false end # The XMLElement class provides an abstraction of the underlying # XML parser engine. It provides XML-related methods for the Pool and # PoolElement classes class XMLElement # xml:: _opaque xml object_ an xml object as returned by build_xml def initialize(xml=nil) @xml = xml end # Initialize a XML document for the element # xml:: _String_ the XML document of the object # root_element:: _String_ Base xml element def initialize_xml(xml, root_element) @xml = XMLElement.build_xml(xml, root_element) if OpenNebula.is_error?(@xml) @xml = nil else if NOKOGIRI if @xml.size == 0 @xml = nil end else if @xml.name != root_element @xml = nil end end end end # Builds a XML document # xml:: _String_ the XML document of the object # root_element:: _String_ Base xml element # [return] _XML_ object for the underlying XML engine def self.build_xml(xml, root_element) begin if NOKOGIRI doc = Nokogiri::XML(xml).xpath("/#{root_element}") else doc = REXML::Document.new(xml).root end rescue Exception => e return OpenNebula::Error.new(e.message) end return doc end # Extract an element from the XML description of the PoolElement. # key::_String_ The name of the element # [return] _String_ the value of the element # Examples: # ['VID'] # gets VM id # ['HISTORY/HOSTNAME'] # get the hostname from the history def [](key) if NOKOGIRI element=@xml.xpath(key.to_s) if element.size == 0 return nil end else element=@xml.elements[key.to_s] end if element element.text end end def delete_element(xpath) if NOKOGIRI @xml.xpath(xpath.to_s).remove else @xml.delete_element(xpath.to_s) end end def add_element(xpath, elems) elems.each { |key, value| if value.instance_of?(Hash) if NOKOGIRI elem = Nokogiri::XML::Node.new key, @xml.document value.each { |k2, v2| child = Nokogiri::XML::Node.new k2, elem child.content = v2 elem.add_child(child) } @xml.xpath(xpath.to_s).first.add_child(elem) else elem = REXML::Element.new(key) value.each { |k2, v2| elem.add_element(k2).text = v2 } @xml.elements[xpath].add_element(elem) end else if NOKOGIRI elem = Nokogiri::XML::Node.new key, @xml.document elem.content = value @xml.xpath(xpath.to_s).first.add_child(elem) else @xml.elements[xpath].add_element(key).text = value end end } end # Gets an array of text from elemenets extracted # using the XPATH expression passed as filter def retrieve_elements(filter) elements_array = Array.new if NOKOGIRI @xml.xpath(filter.to_s).each { |pelem| elements_array << pelem.text if pelem.text } else @xml.elements.each(filter.to_s) { |pelem| elements_array << pelem.text if pelem.text } end if elements_array.size == 0 return nil else return elements_array end end # Gets an attribute from an elemenT # key:: _String_ xpath for the element # name:: _String_ name of the attribute def attr(key,name) value = nil if NOKOGIRI element=@xml.xpath(key.to_s.upcase) if element.size == 0 return nil end attribute = element.attr(name) value = attribute.text if attribute != nil else element=@xml.elements[key.to_s.upcase] value = element.attributes[name] if element != nil end return value end # Iterates over every Element in the XPath and calls the block with a # a XMLElement # block:: _Block_ def each(xpath_str,&block) if NOKOGIRI @xml.xpath(xpath_str).each { |pelem| block.call XMLElement.new(pelem) } else @xml.elements.each(xpath_str) { |pelem| block.call XMLElement.new(pelem) } end end def each_xpath(xpath_str,&block) if NOKOGIRI @xml.xpath(xpath_str).each { |pelem| block.call pelem.text } else @xml.elements.each(xpath_str) { |pelem| block.call pelem.text } end end def name @xml.name end def text if NOKOGIRI @xml.content else @xml.text end end # Returns wheter there are elements for a given XPath # xpath_str:: _String_ XPath expression to locate the element def has_elements?(xpath_str) if NOKOGIRI element = @xml.xpath(xpath_str.to_s.upcase) return element != nil && element.children.size > 0 else element = @xml.elements[xpath_str.to_s] return element != nil && element.has_elements? end end # Returns the