From 1c826bced52fb82932d09a0e76dab786099087cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Mon, 17 Dec 2012 14:43:23 +0100 Subject: [PATCH 01/79] Bug #1694: Rollback cluster id when system DS is added to any cluster --- src/rm/RequestManagerCluster.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/rm/RequestManagerCluster.cc b/src/rm/RequestManagerCluster.cc index 73bcd3da75..6107511910 100644 --- a/src/rm/RequestManagerCluster.cc +++ b/src/rm/RequestManagerCluster.cc @@ -149,6 +149,18 @@ void RequestManagerCluster::add_generic( request_error("Cannot add object to cluster", err_msg), att); + // Rollback + get(object_id, true, &object, &cluster_obj); + + if ( object != 0 ) + { + cluster_obj->set_cluster(old_cluster_id, old_cluster_name); + + pool->update(object); + + object->unlock(); + } + return; } From cdab2668d13a438b4f95c3374725d1d423fd5eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Mon, 17 Dec 2012 16:23:16 +0100 Subject: [PATCH 02/79] Bug #1694: Add new attribute system_ds to Cluster. Template attribute is now ignored --- include/Cluster.h | 56 ++++++-------------------- src/cluster/Cluster.cc | 89 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 95 insertions(+), 50 deletions(-) diff --git a/include/Cluster.h b/include/Cluster.h index 2aa93e5e8d..274720ff3f 100644 --- a/include/Cluster.h +++ b/include/Cluster.h @@ -32,20 +32,13 @@ class Cluster : public PoolObjectSQL public: /** - * Returns the SYSTEM_DS attribute, or the system DS id if it is not defined + * Returns the SYSTEM_DS attribute * - * @return the SYSTEM_DS attribute, or the system DS id if it is not defined + * @return the SYSTEM_DS attribute */ int get_ds_id() { - int ds_id; - - if ( obj_template->get("SYSTEM_DS", ds_id) == false ) - { - ds_id = DatastorePool::SYSTEM_DS_ID; - } - - return ds_id; + return system_ds; } /** @@ -103,29 +96,7 @@ public: * @param error_msg Error message, if any * @return 0 on success */ - int add_datastore(int id, string& error_msg) - { - // TODO: should fail for any system DS? - if ( id == DatastorePool::SYSTEM_DS_ID ) - { - ostringstream oss; - oss << "Datastore '"<< DatastorePool::SYSTEM_DS_NAME - << "' cannot be added to any cluster."; - - error_msg = oss.str(); - - return -1; - } - - int rc = datastores.add_collection_id(id); - - if ( rc < 0 ) - { - error_msg = "Datastore ID is already in the cluster set."; - } - - return rc; - } + int add_datastore(int id, string& error_msg); /** * Deletes this datastore ID from the set. @@ -133,17 +104,7 @@ public: * @param error_msg Error message, if any * @return 0 on success */ - int del_datastore(int id, string& error_msg) - { - int rc = datastores.del_collection_id(id); - - if ( rc < 0 ) - { - error_msg = "Datastore ID is not part of the cluster set."; - } - - return rc; - } + int del_datastore(int id, string& error_msg); /** * Adds this vnet ID to the set. @@ -219,13 +180,18 @@ private: virtual ~Cluster(){}; // ************************************************************************* - // Object Collections (Private) + // Attributes (Private) // ************************************************************************* ObjectCollection hosts; ObjectCollection datastores; ObjectCollection vnets; + /** + * System datastore id + */ + int system_ds; + // ************************************************************************* // DataBase implementation (Private) // ************************************************************************* diff --git a/src/cluster/Cluster.cc b/src/cluster/Cluster.cc index 8c25673843..cc220f55e3 100644 --- a/src/cluster/Cluster.cc +++ b/src/cluster/Cluster.cc @@ -45,7 +45,8 @@ Cluster::Cluster( PoolObjectSQL(id,CLUSTER,name,-1,-1,"","",table), hosts("HOSTS"), datastores("DATASTORES"), - vnets("VNETS") + vnets("VNETS"), + system_ds(DatastorePool::SYSTEM_DS_ID) { if (cl_template != 0) { @@ -113,6 +114,82 @@ string& Cluster::get_ds_location(string &ds_location) return ds_location; } +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int Cluster::add_datastore(int id, string& error_msg) +{ + if ( id == DatastorePool::SYSTEM_DS_ID ) + { + ostringstream oss; + oss << "Datastore '"<< DatastorePool::SYSTEM_DS_NAME + << "' cannot be added to any cluster."; + + error_msg = oss.str(); + + return -1; + } + + // TODO: Do not lock DS here, take ds_type as an argument + + Datastore *ds = Nebula::instance().get_dspool()->get(id, true); + + if ( ds == 0 ) + { + return -1; + } + + Datastore::DatastoreType ds_type = ds->get_type(); + + ds->unlock(); + + if ( ds_type == Datastore::SYSTEM_DS ) + { + if ( system_ds != DatastorePool::SYSTEM_DS_ID ) + { + ostringstream oss; + oss << "Cluster " << oid << " already contains the System Datastore " + << system_ds << "."; + + error_msg = oss.str(); + + return -1; + } + } + + int rc = datastores.add_collection_id(id); + + if ( rc < 0 ) + { + error_msg = "Datastore ID is already in the cluster set."; + } + else if ( ds_type == Datastore::SYSTEM_DS ) + { + system_ds = id; + } + + return rc; +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +int Cluster::del_datastore(int id, string& error_msg) +{ + int rc = datastores.del_collection_id(id); + + if ( rc < 0 ) + { + error_msg = "Datastore ID is not part of the cluster set."; + } + else if ( system_ds == id ) + { + system_ds = DatastorePool::SYSTEM_DS_ID; + } + + return rc; +} + /* ************************************************************************ */ /* Cluster :: Database Access Functions */ /* ************************************************************************ */ @@ -215,8 +292,9 @@ string& Cluster::to_xml(string& xml) const oss << "" << - "" << oid << "" << - "" << name << "" << + "" << oid << "" << + "" << name << "" << + "" << system_ds << "" << hosts.to_xml(host_collection_xml) << datastores.to_xml(ds_collection_xml) << @@ -241,8 +319,9 @@ int Cluster::from_xml(const string& xml) update_from_str(xml); // Get class base attributes - rc += xpath(oid, "/CLUSTER/ID", -1); - rc += xpath(name,"/CLUSTER/NAME", "not_found"); + rc += xpath(oid, "/CLUSTER/ID", -1); + rc += xpath(name, "/CLUSTER/NAME", "not_found"); + rc += xpath(system_ds, "/CLUSTER/SYSTEM_DS", -1); // Set oneadmin as the owner set_user(0,""); From 3c6871b2c02f80cfea1dda115030b10389fd8580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Mon, 17 Dec 2012 16:54:17 +0100 Subject: [PATCH 03/79] Bug #1694: Remove potential deadlock --- include/Cluster.h | 3 ++- include/RequestManagerAllocate.h | 45 ++++++++++++++++++++++++++++---- include/RequestManagerCluster.h | 44 +++++++++++++++++++++++++++---- src/cluster/Cluster.cc | 15 +---------- src/rm/RequestManagerAllocate.cc | 4 ++- src/rm/RequestManagerCluster.cc | 6 ++++- 6 files changed, 90 insertions(+), 27 deletions(-) diff --git a/include/Cluster.h b/include/Cluster.h index 274720ff3f..9f47652c07 100644 --- a/include/Cluster.h +++ b/include/Cluster.h @@ -93,10 +93,11 @@ public: /** * Adds this datastore ID to the set. * @param id to be added to the cluster + * @param ds_type Datastore type * @param error_msg Error message, if any * @return 0 on success */ - int add_datastore(int id, string& error_msg); + int add_datastore(int id, Datastore::DatastoreType ds_type, string& error_msg); /** * Deletes this datastore ID from the set. diff --git a/include/RequestManagerAllocate.h b/include/RequestManagerAllocate.h index 4957ded508..3dbe8da1c7 100644 --- a/include/RequestManagerAllocate.h +++ b/include/RequestManagerAllocate.h @@ -86,11 +86,20 @@ protected: return ClusterPool::NONE_CLUSTER_ID; }; - virtual int add_to_cluster(Cluster* cluster, int id, string& error_msg) + virtual int add_to_cluster( + Cluster* cluster, + int id, + Datastore::DatastoreType ds_type, + string& error_msg) { return -1; }; + virtual Datastore::DatastoreType get_ds_type(int oid) + { + return Datastore::FILE_DS; + }; + protected: ClusterPool * clpool; @@ -176,7 +185,11 @@ public: return xmlrpc_c::value_int(paramList.getInt(2)); }; - int add_to_cluster(Cluster* cluster, int id, string& error_msg) + int add_to_cluster( + Cluster* cluster, + int id, + Datastore::DatastoreType ds_type, + string& error_msg) { return cluster->add_vnet(id, error_msg); }; @@ -274,7 +287,11 @@ public: return xmlrpc_c::value_int(paramList.getInt(5)); }; - int add_to_cluster(Cluster* cluster, int id, string& error_msg) + int add_to_cluster( + Cluster* cluster, + int id, + Datastore::DatastoreType ds_type, + string& error_msg) { return cluster->add_host(id, error_msg); }; @@ -376,9 +393,27 @@ public: return xmlrpc_c::value_int(paramList.getInt(2)); }; - int add_to_cluster(Cluster* cluster, int id, string& error_msg) + virtual Datastore::DatastoreType get_ds_type(int oid) { - return cluster->add_datastore(id, error_msg); + Datastore::DatastoreType ds_type = Datastore::FILE_DS; + Datastore *ds = static_cast(pool)->get(oid, true); + + if ( ds != 0 ) + { + ds_type = ds->get_type(); + ds->unlock(); + } + + return ds_type; + }; + + int add_to_cluster( + Cluster* cluster, + int id, + Datastore::DatastoreType ds_type, + string& error_msg) + { + return cluster->add_datastore(id, ds_type, error_msg); }; }; diff --git a/include/RequestManagerCluster.h b/include/RequestManagerCluster.h index 22ab693207..ec424ffefe 100644 --- a/include/RequestManagerCluster.h +++ b/include/RequestManagerCluster.h @@ -65,7 +65,24 @@ protected: PoolSQL * pool, PoolObjectSQL::ObjectType type); - virtual int add_object(Cluster* cluster, int id, string& error_msg) = 0; + virtual Datastore::DatastoreType get_ds_type(PoolObjectSQL *obj) + { + return Datastore::FILE_DS; + }; + + /** + * Add object to cluster id collection + * @param cluster where to add the object + * @param id of the object + * @param ds_type Datastore type, will be ignored for different objects + * @param error_msg Error reason, if any + * @return 0 on success + */ + virtual int add_object( + Cluster* cluster, + int id, + Datastore::DatastoreType ds_type, + string& error_msg) = 0; virtual int del_object(Cluster* cluster, int id, string& error_msg) = 0; @@ -86,7 +103,11 @@ public: ~RequestManagerClusterHost(){}; - virtual int add_object(Cluster* cluster, int id, string& error_msg) + virtual int add_object( + Cluster* cluster, + int id, + Datastore::DatastoreType ds_type, + string& error_msg) { return cluster->add_host(id, error_msg); }; @@ -169,9 +190,18 @@ public: ~RequestManagerClusterDatastore(){}; - virtual int add_object(Cluster* cluster, int id, string& error_msg) + virtual Datastore::DatastoreType get_ds_type(PoolObjectSQL *obj) { - return cluster->add_datastore(id, error_msg); + return static_cast(obj)->get_type(); + }; + + virtual int add_object( + Cluster* cluster, + int id, + Datastore::DatastoreType ds_type, + string& error_msg) + { + return cluster->add_datastore(id, ds_type, error_msg); }; virtual int del_object(Cluster* cluster, int id, string& error_msg) @@ -253,7 +283,11 @@ public: ~RequestManagerClusterVNet(){}; - virtual int add_object(Cluster* cluster, int id, string& error_msg) + virtual int add_object( + Cluster* cluster, + int id, + Datastore::DatastoreType ds_type, + string& error_msg) { return cluster->add_vnet(id, error_msg); }; diff --git a/src/cluster/Cluster.cc b/src/cluster/Cluster.cc index cc220f55e3..975d7413ec 100644 --- a/src/cluster/Cluster.cc +++ b/src/cluster/Cluster.cc @@ -117,7 +117,7 @@ string& Cluster::get_ds_location(string &ds_location) /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ -int Cluster::add_datastore(int id, string& error_msg) +int Cluster::add_datastore(int id, Datastore::DatastoreType ds_type, string& error_msg) { if ( id == DatastorePool::SYSTEM_DS_ID ) { @@ -130,19 +130,6 @@ int Cluster::add_datastore(int id, string& error_msg) return -1; } - // TODO: Do not lock DS here, take ds_type as an argument - - Datastore *ds = Nebula::instance().get_dspool()->get(id, true); - - if ( ds == 0 ) - { - return -1; - } - - Datastore::DatastoreType ds_type = ds->get_type(); - - ds->unlock(); - if ( ds_type == Datastore::SYSTEM_DS ) { if ( system_ds != DatastorePool::SYSTEM_DS_ID ) diff --git a/src/rm/RequestManagerAllocate.cc b/src/rm/RequestManagerAllocate.cc index 84dcd007c0..ef57836170 100644 --- a/src/rm/RequestManagerAllocate.cc +++ b/src/rm/RequestManagerAllocate.cc @@ -189,6 +189,8 @@ void RequestManagerAllocate::request_execute(xmlrpc_c::paramList const& params, if ( cluster_id != ClusterPool::NONE_CLUSTER_ID ) { + Datastore::DatastoreType ds_type = get_ds_type(id); + cluster = clpool->get(cluster_id, true); if ( cluster == 0 ) @@ -200,7 +202,7 @@ void RequestManagerAllocate::request_execute(xmlrpc_c::paramList const& params, return; } - rc = add_to_cluster(cluster, id, error_str); + rc = add_to_cluster(cluster, id, ds_type, error_str); if ( rc < 0 ) { diff --git a/src/rm/RequestManagerCluster.cc b/src/rm/RequestManagerCluster.cc index 6107511910..a2b98c0ad6 100644 --- a/src/rm/RequestManagerCluster.cc +++ b/src/rm/RequestManagerCluster.cc @@ -45,6 +45,8 @@ void RequestManagerCluster::add_generic( int old_cluster_id; string old_cluster_name; + Datastore::DatastoreType ds_type; + if ( cluster_id != ClusterPool::NONE_CLUSTER_ID ) { rc = get_info(clpool, cluster_id, PoolObjectSQL::CLUSTER, att, c_perms, cluster_name); @@ -102,6 +104,8 @@ void RequestManagerCluster::add_generic( old_cluster_id = cluster_obj->get_cluster_id(); old_cluster_name = cluster_obj->get_cluster_name(); + ds_type = get_ds_type(object); + if ( old_cluster_id == cluster_id ) { object->unlock(); @@ -141,7 +145,7 @@ void RequestManagerCluster::add_generic( return; } - if ( add_object(cluster, object_id, err_msg) < 0 ) + if ( add_object(cluster, object_id, ds_type, err_msg) < 0 ) { cluster->unlock(); From ca4504f984d65ed9500dbd08ac530d6b2ae7ed99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Mon, 17 Dec 2012 18:15:02 +0100 Subject: [PATCH 04/79] Bug #1694: If a DS updates its type to system_ds, update the cluster system_ds --- include/Cluster.h | 10 ++ include/Datastore.h | 9 +- include/RequestManagerUpdateTemplate.h | 5 +- src/cli/one_helper/onecluster_helper.rb | 3 +- src/datastore/Datastore.cc | 20 +++- src/rm/RequestManagerUpdateTemplate.cc | 123 ++++++++++++++++++++++++ 6 files changed, 165 insertions(+), 5 deletions(-) diff --git a/include/Cluster.h b/include/Cluster.h index 9f47652c07..eeada0ef3c 100644 --- a/include/Cluster.h +++ b/include/Cluster.h @@ -41,6 +41,16 @@ public: return system_ds; } + /** + * Sets the SYSTEM_DS attribute + * + * @param ds_id The new system datastore + */ + void set_ds_id(int ds_id) + { + system_ds = ds_id; + } + /** * Returns the DATASTORE_LOCATION for the hosts of the cluster. If not * defined that in oned.conf is returned. diff --git a/include/Datastore.h b/include/Datastore.h index a4b8d4243d..6db87fd919 100644 --- a/include/Datastore.h +++ b/include/Datastore.h @@ -57,11 +57,18 @@ public: /** * Return the string representation of a DatastoreType - * @param str_type string representing the DatastoreTypr + * @param str_type string representing the DatastoreType * @return the DatastoreType (defaults to IMAGE_DS) */ static DatastoreType str_to_type(string& str_type); + /** + * Returns the DS type found in the string template + * @param str_template string template + * @return the DatastoreType (defaults to IMAGE_DS) + */ + static DatastoreType type_in_template(string& str_template); + /** * Function to print the Datastore object into a string in XML format * @param xml the resulting XML string diff --git a/include/RequestManagerUpdateTemplate.h b/include/RequestManagerUpdateTemplate.h index 511f149ce7..07a19e93d3 100644 --- a/include/RequestManagerUpdateTemplate.h +++ b/include/RequestManagerUpdateTemplate.h @@ -40,7 +40,7 @@ protected: /* -------------------------------------------------------------------- */ - void request_execute(xmlrpc_c::paramList const& _paramList, + virtual void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); }; @@ -150,6 +150,9 @@ public: }; ~DatastoreUpdateTemplate(){}; + + virtual void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ diff --git a/src/cli/one_helper/onecluster_helper.rb b/src/cli/one_helper/onecluster_helper.rb index 2cd5716f2d..2edb601224 100644 --- a/src/cli/one_helper/onecluster_helper.rb +++ b/src/cli/one_helper/onecluster_helper.rb @@ -96,12 +96,13 @@ class OneClusterHelper < OpenNebulaHelper::OneHelper end def format_resource(cluster) - str="%-15s: %-20s" + str="%-18s: %-20s" str_h1="%-80s" CLIHelper.print_header(str_h1 % "CLUSTER #{cluster['ID']} INFORMATION") puts str % ["ID", cluster.id.to_s] puts str % ["NAME", cluster.name] + puts str % ["SYSTEM DATASTORE", cluster['SYSTEM_DS']] puts CLIHelper.print_header(str_h1 % "CLUSTER TEMPLATE", false) diff --git a/src/datastore/Datastore.cc b/src/datastore/Datastore.cc index 6e93122920..1fe0bf2ae6 100644 --- a/src/datastore/Datastore.cc +++ b/src/datastore/Datastore.cc @@ -122,6 +122,22 @@ Datastore::DatastoreType Datastore::str_to_type(string& str_type) /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ +Datastore::DatastoreType Datastore::type_in_template(string& str_template) +{ + string s_ds_type; + string error_str; + + Template tmp_template; + tmp_template.parse_str_or_xml(str_template, error_str); + + tmp_template.get("TYPE", s_ds_type); + + return Datastore::str_to_type(s_ds_type); +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + int Datastore::insert(SqlDB *db, string& error_str) { int rc; @@ -431,10 +447,10 @@ int Datastore::replace_template(const string& tmpl_str, string& error_str) else { type = str_to_type(s_ds_type); - - replace_template_attribute("TYPE", type_to_str(type)); } + replace_template_attribute("TYPE", type_to_str(type)); + if ( type == SYSTEM_DS ) { new_ds_mad = "-"; diff --git a/src/rm/RequestManagerUpdateTemplate.cc b/src/rm/RequestManagerUpdateTemplate.cc index 1c8988ccbb..6bcfde31a5 100644 --- a/src/rm/RequestManagerUpdateTemplate.cc +++ b/src/rm/RequestManagerUpdateTemplate.cc @@ -70,3 +70,126 @@ void RequestManagerUpdateTemplate::request_execute( return; } +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +void DatastoreUpdateTemplate::request_execute( + xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + int rc; + string error_str; + + int oid = xmlrpc_c::value_int(paramList.getInt(1)); + string tmpl = xmlrpc_c::value_string(paramList.getString(2)); + + Datastore * object; + + if ( basic_authorization(oid, att) == false ) + { + return; + } + + object = static_cast(pool)->get(oid,true); + + if ( object == 0 ) + { + failure_response(NO_EXISTS, + get_error(object_name(auth_object),oid), + att); + + return; + } + + Datastore::DatastoreType prev_type = object->get_type(); + Datastore::DatastoreType new_type = Datastore::type_in_template(tmpl); + + int cluster_id = object->get_cluster_id(); + + if ( (prev_type == Datastore::SYSTEM_DS || new_type == Datastore::SYSTEM_DS) && + prev_type != new_type && + cluster_id != ClusterPool::NONE_CLUSTER_ID ) + { + object->unlock(); + + Cluster *cluster = Nebula::instance().get_clpool()->get(cluster_id, true); + + if ( cluster == 0 ) + { + failure_response(NO_EXISTS, + get_error(object_name(PoolObjectSQL::CLUSTER),cluster_id), + att); + + return; + } + + if ( new_type == Datastore::SYSTEM_DS ) + { + if ( cluster->get_ds_id() == DatastorePool::SYSTEM_DS_ID ) + { + // Cluster has a new system ds + cluster->set_ds_id(oid); + } + else + { + ostringstream oss; + oss << "Cannot change datastore type to " + << Datastore::type_to_str(Datastore::SYSTEM_DS) + << ". Cluster " << cluster_id + << " already contains the System Datastore " + << cluster->get_ds_id() << "."; + + failure_response(INTERNAL, + request_error(oss.str(),error_str), + att); + + cluster->unlock(); + + return; + } + } + else if ( cluster->get_ds_id() == oid ) + { + // This was the cluster's system DS, now it must be set to '0' + cluster->set_ds_id( DatastorePool::SYSTEM_DS_ID ); + } + + Nebula::instance().get_clpool()->update(cluster); + cluster->unlock(); + + object = static_cast(pool)->get(oid,true); + + if ( object == 0 ) + { + failure_response(NO_EXISTS, + get_error(object_name(auth_object),oid), + att); + + return; + } + } + + rc = object->replace_template(tmpl, error_str); + + if ( rc != 0 ) + { + // TODO: rollback + + failure_response(INTERNAL, + request_error("Cannot update template",error_str), + att); + object->unlock(); + + return; + } + + pool->update(object); + + object->unlock(); + + success_response(oid, att); + + return; +} + + From 1cb2d27ffaccab95e3c4d5e3e67ce888a5c213c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Tue, 18 Dec 2012 13:46:54 +0100 Subject: [PATCH 05/79] Bug #1694: onedb migrator --- src/onedb/3.8.1_to_3.9.80.rb | 86 ++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/src/onedb/3.8.1_to_3.9.80.rb b/src/onedb/3.8.1_to_3.9.80.rb index 6c4f489615..d03487348a 100644 --- a/src/onedb/3.8.1_to_3.9.80.rb +++ b/src/onedb/3.8.1_to_3.9.80.rb @@ -259,6 +259,92 @@ module Migrator @db.run "DROP TABLE old_group_pool;" + ######################################################################## + # Bug #1694: SYSTEM_DS is now set with the method adddatastore + ######################################################################## + + @db.run "ALTER TABLE cluster_pool RENAME TO old_cluster_pool;" + @db.run "CREATE TABLE cluster_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));" + + @db.fetch("SELECT * FROM old_cluster_pool") do |row| + doc = Document.new(row[:body]) + + system_ds = 0 + + doc.root.each_element("TEMPLATE") do |e| + elem = e.delete_element("SYSTEM_DS") + + if !elem.nil? + system_ds = elem.text.to_i + end + end + + if system_ds != 0 + updated_body = nil + + @db.fetch("SELECT body FROM datastore_pool WHERE oid=#{system_ds}") do |ds_row| + ds_doc = Document.new(ds_row[:body]) + + type = "0" # IMAGE_DS + + ds_doc.root.each_element("TYPE") do |e| + type = e.text + end + + if type != "1" + puts " > Cluster #{row[:oid]} has the "<< + "System Datastore set to Datastore #{system_ds}, "<< + "but its type is not SYSTEM_DS. The System Datastore "<< + "for this Cluster will be set to 0" + + system_ds = 0 + else + cluster_id = "-1" + + ds_doc.root.each_element("CLUSTER_ID") do |e| + cluster_id = e.text + end + + if row[:oid] != cluster_id.to_i + puts " > Cluster #{row[:oid]} has the "<< + "System Datastore set to Datastore #{system_ds}, "<< + "but it is not part of the Cluster. It will be added now." + + ds_doc.root.each_element("CLUSTER_ID") do |e| + e.text = row[:oid] + end + + ds_doc.root.each_element("CLUSTER") do |e| + e.text = row[:name] + end + + updated_body = ds_doc.root.to_s + end + end + end + + if !updated_body.nil? + @db[:datastore_pool].where(:oid => system_ds).update( + :body => updated_body) + end + end + + doc.root.add_element("SYSTEM_DS").text = system_ds.to_s + + @db[:cluster_pool].insert( + :oid => row[:oid], + :name => row[:name], + :body => doc.root.to_s, + :uid => row[:uid], + :gid => row[:gid], + :owner_u => row[:owner_u], + :group_u => row[:group_u], + :other_u => row[:other_u]) + end + + @db.run "DROP TABLE old_cluster_pool;" + + ######################################################################## # # Banner for the new /var/lib/one/vms directory From a10e19fe05249d952228dcc8a454e9df5ed82cd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Tue, 18 Dec 2012 17:29:47 +0100 Subject: [PATCH 06/79] Bug #1694: FSCK checks the system_ds is part of the cluster, and that there are not more than one system ds per cluster --- src/onedb/fsck.rb | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/onedb/fsck.rb b/src/onedb/fsck.rb index 9a252c01fd..a63ba2a2c9 100644 --- a/src/onedb/fsck.rb +++ b/src/onedb/fsck.rb @@ -249,6 +249,7 @@ module OneDBFsck ######################################################################## # Clusters # + # CLUSTER/SYSTEM_DS # CLUSTER/HOSTS/ID # CLUSTER/DATASTORES/ID # CLUSTER/VNETS/ID @@ -277,6 +278,8 @@ module OneDBFsck cluster[row[:oid]][:hosts] = [] cluster[row[:oid]][:datastores] = [] cluster[row[:oid]][:vnets] = [] + + cluster[row[:oid]][:system_ds] = 0 end hosts_fix = {} @@ -331,7 +334,26 @@ module OneDBFsck datastores_fix[row[:oid]] = doc.to_s else - cluster[cluster_id][:datastores] << row[:oid] + if doc.root.get_text('TYPE').to_s != "1" + cluster[cluster_id][:datastores] << row[:oid] + else + if cluster[cluster_id][:system_ds] == 0 + cluster[cluster_id][:datastores] << row[:oid] + cluster[cluster_id][:system_ds] = row[:oid] + else + log_error("System Datastore #{row[:oid]} is in Cluster #{cluster_id}, but it already contains System Datastore #{cluster[cluster_id][:system_ds]}") + + doc.root.each_element('CLUSTER_ID') do |e| + e.text = "-1" + end + + doc.root.each_element('CLUSTER') do |e| + e.text = "" + end + + datastores_fix[row[:oid]] = doc.to_s + end + end end end end @@ -401,6 +423,16 @@ module OneDBFsck ds_new_elem = doc.root.add_element("DATASTORES") + doc.root.each_element("SYSTEM_DS") do |e| + system_ds = e.text.to_i + + if system_ds != cluster[cluster_id][:system_ds] + log_error("Cluster #{cluster_id} has System Datastore set to #{system_ds}, but it should be #{cluster[cluster_id][:system_ds]}") + + e.text = cluster[cluster_id][:system_ds].to_s + end + end + cluster[cluster_id][:datastores].each do |id| id_elem = ds_elem.elements.delete("ID[.=#{id}]") From 076ca44e751d595e91cdd8553edb1475445947e9 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Tue, 18 Dec 2012 15:52:11 +0100 Subject: [PATCH 07/79] feature #1700: Change oca files to be lowercase --- install.sh | 60 +++++++++---------- src/oca/ruby/{OpenNebula.rb => opennebula.rb} | 48 +++++++-------- .../{OpenNebula/Acl.rb => opennebula/acl.rb} | 0 .../AclPool.rb => opennebula/acl_pool.rb} | 2 +- .../Cluster.rb => opennebula/cluster.rb} | 2 +- .../cluster_pool.rb} | 2 +- .../Datastore.rb => opennebula/datastore.rb} | 2 +- .../datastore_pool.rb} | 2 +- .../Document.rb => opennebula/document.rb} | 2 +- .../document_json.rb} | 0 .../document_pool.rb} | 4 +- .../document_pool_json.rb} | 0 .../Group.rb => opennebula/group.rb} | 2 +- .../GroupPool.rb => opennebula/group_pool.rb} | 2 +- .../Host.rb => opennebula/host.rb} | 2 +- .../HostPool.rb => opennebula/host_pool.rb} | 2 +- .../Image.rb => opennebula/image.rb} | 2 +- .../ImagePool.rb => opennebula/image_pool.rb} | 2 +- .../Pool.rb => opennebula/pool.rb} | 0 .../System.rb => opennebula/system.rb} | 2 +- .../Template.rb => opennebula/template.rb} | 2 +- .../template_pool.rb} | 2 +- .../User.rb => opennebula/user.rb} | 2 +- .../UserPool.rb => opennebula/user_pool.rb} | 2 +- .../virtual_machine.rb} | 2 +- .../virtual_machine_pool.rb} | 2 +- .../virtual_network.rb} | 2 +- .../virtual_network_pool.rb} | 2 +- .../XMLUtils.rb => opennebula/xml_utils.rb} | 0 29 files changed, 77 insertions(+), 77 deletions(-) rename src/oca/ruby/{OpenNebula.rb => opennebula.rb} (86%) rename src/oca/ruby/{OpenNebula/Acl.rb => opennebula/acl.rb} (100%) rename src/oca/ruby/{OpenNebula/AclPool.rb => opennebula/acl_pool.rb} (98%) rename src/oca/ruby/{OpenNebula/Cluster.rb => opennebula/cluster.rb} (99%) rename src/oca/ruby/{OpenNebula/ClusterPool.rb => opennebula/cluster_pool.rb} (98%) rename src/oca/ruby/{OpenNebula/Datastore.rb => opennebula/datastore.rb} (99%) rename src/oca/ruby/{OpenNebula/DatastorePool.rb => opennebula/datastore_pool.rb} (98%) rename src/oca/ruby/{OpenNebula/Document.rb => opennebula/document.rb} (99%) rename src/oca/ruby/{OpenNebula/DocumentJSON.rb => opennebula/document_json.rb} (100%) rename src/oca/ruby/{OpenNebula/DocumentPool.rb => opennebula/document_pool.rb} (98%) rename src/oca/ruby/{OpenNebula/DocumentPoolJSON.rb => opennebula/document_pool_json.rb} (100%) rename src/oca/ruby/{OpenNebula/Group.rb => opennebula/group.rb} (99%) rename src/oca/ruby/{OpenNebula/GroupPool.rb => opennebula/group_pool.rb} (98%) rename src/oca/ruby/{OpenNebula/Host.rb => opennebula/host.rb} (99%) rename src/oca/ruby/{OpenNebula/HostPool.rb => opennebula/host_pool.rb} (99%) rename src/oca/ruby/{OpenNebula/Image.rb => opennebula/image.rb} (99%) rename src/oca/ruby/{OpenNebula/ImagePool.rb => opennebula/image_pool.rb} (99%) rename src/oca/ruby/{OpenNebula/Pool.rb => opennebula/pool.rb} (100%) rename src/oca/ruby/{OpenNebula/System.rb => opennebula/system.rb} (99%) rename src/oca/ruby/{OpenNebula/Template.rb => opennebula/template.rb} (99%) rename src/oca/ruby/{OpenNebula/TemplatePool.rb => opennebula/template_pool.rb} (99%) rename src/oca/ruby/{OpenNebula/User.rb => opennebula/user.rb} (99%) rename src/oca/ruby/{OpenNebula/UserPool.rb => opennebula/user_pool.rb} (98%) rename src/oca/ruby/{OpenNebula/VirtualMachine.rb => opennebula/virtual_machine.rb} (99%) rename src/oca/ruby/{OpenNebula/VirtualMachinePool.rb => opennebula/virtual_machine_pool.rb} (99%) rename src/oca/ruby/{OpenNebula/VirtualNetwork.rb => opennebula/virtual_network.rb} (99%) rename src/oca/ruby/{OpenNebula/VirtualNetworkPool.rb => opennebula/virtual_network_pool.rb} (99%) rename src/oca/ruby/{OpenNebula/XMLUtils.rb => opennebula/xml_utils.rb} (100%) diff --git a/install.sh b/install.sh index e316e55b94..88c9f877ee 100755 --- a/install.sh +++ b/install.sh @@ -376,7 +376,7 @@ LIB_MARKET_CLIENT_DIRS="$LIB_LOCATION/ruby \ $LIB_LOCATION/ruby/cloud/marketplace" LIB_OCA_CLIENT_DIRS="$LIB_LOCATION/ruby \ - $LIB_LOCATION/ruby/OpenNebula" + $LIB_LOCATION/ruby/opennebula" LIB_CLI_CLIENT_DIRS="$LIB_LOCATION/ruby/cli \ $LIB_LOCATION/ruby/cli/one_helper" @@ -406,7 +406,7 @@ INSTALL_FILES=( INCLUDE_FILES:$INCLUDE_LOCATION LIB_FILES:$LIB_LOCATION RUBY_LIB_FILES:$LIB_LOCATION/ruby - RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/OpenNebula + RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/opennebula MAD_RUBY_LIB_FILES:$LIB_LOCATION/ruby MAD_RUBY_LIB_FILES:$VAR_LOCATION/remotes MAD_SH_LIB_FILES:$LIB_LOCATION/sh @@ -1081,35 +1081,35 @@ INSTALL_GEMS_SHARE_FILE="share/install_gems/install_gems" #------------------------------------------------------------------------------- # OCA Files #------------------------------------------------------------------------------- -OCA_LIB_FILES="src/oca/ruby/OpenNebula.rb" +OCA_LIB_FILES="src/oca/ruby/opennebula.rb" -RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/OpenNebula/Host.rb \ - src/oca/ruby/OpenNebula/HostPool.rb \ - src/oca/ruby/OpenNebula/Pool.rb \ - src/oca/ruby/OpenNebula/User.rb \ - src/oca/ruby/OpenNebula/UserPool.rb \ - src/oca/ruby/OpenNebula/VirtualMachine.rb \ - src/oca/ruby/OpenNebula/VirtualMachinePool.rb \ - src/oca/ruby/OpenNebula/VirtualNetwork.rb \ - src/oca/ruby/OpenNebula/VirtualNetworkPool.rb \ - src/oca/ruby/OpenNebula/Image.rb \ - src/oca/ruby/OpenNebula/ImagePool.rb \ - src/oca/ruby/OpenNebula/Template.rb \ - src/oca/ruby/OpenNebula/TemplatePool.rb \ - src/oca/ruby/OpenNebula/Document.rb \ - src/oca/ruby/OpenNebula/DocumentPool.rb \ - src/oca/ruby/OpenNebula/DocumentJSON.rb \ - src/oca/ruby/OpenNebula/DocumentPoolJSON.rb \ - src/oca/ruby/OpenNebula/Group.rb \ - src/oca/ruby/OpenNebula/GroupPool.rb \ - src/oca/ruby/OpenNebula/Acl.rb \ - src/oca/ruby/OpenNebula/AclPool.rb \ - src/oca/ruby/OpenNebula/Datastore.rb \ - src/oca/ruby/OpenNebula/DatastorePool.rb \ - src/oca/ruby/OpenNebula/Cluster.rb \ - src/oca/ruby/OpenNebula/ClusterPool.rb \ - src/oca/ruby/OpenNebula/XMLUtils.rb \ - src/oca/ruby/OpenNebula/System.rb" +RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/opennebula/host.rb \ + src/oca/ruby/opennebula/host_pool.rb \ + src/oca/ruby/opennebula/pool.rb \ + src/oca/ruby/opennebula/user.rb \ + src/oca/ruby/opennebula/user_pool.rb \ + src/oca/ruby/opennebula/virtual_machine.rb \ + src/oca/ruby/opennebula/virtual_machine_pool.rb \ + src/oca/ruby/opennebula/virtual_network.rb \ + src/oca/ruby/opennebula/virtual_network_pool.rb \ + src/oca/ruby/opennebula/image.rb \ + src/oca/ruby/opennebula/image_pool.rb \ + src/oca/ruby/opennebula/template.rb \ + src/oca/ruby/opennebula/template_pool.rb \ + src/oca/ruby/opennebula/document.rb \ + src/oca/ruby/opennebula/document_pool.rb \ + src/oca/ruby/opennebula/document_json.rb \ + src/oca/ruby/opennebula/document_pool_json.rb \ + src/oca/ruby/opennebula/group.rb \ + src/oca/ruby/opennebula/group_pool.rb \ + src/oca/ruby/opennebula/acl.rb \ + src/oca/ruby/opennebula/acl_pool.rb \ + src/oca/ruby/opennebula/datastore.rb \ + src/oca/ruby/opennebula/datastore_pool.rb \ + src/oca/ruby/opennebula/cluster.rb \ + src/oca/ruby/opennebula/cluster_pool.rb \ + src/oca/ruby/opennebula/xml_utils.rb \ + src/oca/ruby/opennebula/system.rb" #------------------------------------------------------------------------------- # Common Cloud Files diff --git a/src/oca/ruby/OpenNebula.rb b/src/oca/ruby/opennebula.rb similarity index 86% rename from src/oca/ruby/OpenNebula.rb rename to src/oca/ruby/opennebula.rb index 9e60d0be8f..0c720589fe 100644 --- a/src/oca/ruby/OpenNebula.rb +++ b/src/oca/ruby/opennebula.rb @@ -25,30 +25,30 @@ require 'digest/sha1' require 'rexml/document' require 'pp' -require 'OpenNebula/XMLUtils' -require 'OpenNebula/VirtualMachine' -require 'OpenNebula/VirtualMachinePool' -require 'OpenNebula/VirtualNetwork' -require 'OpenNebula/VirtualNetworkPool' -require 'OpenNebula/Image' -require 'OpenNebula/ImagePool' -require 'OpenNebula/User' -require 'OpenNebula/UserPool' -require 'OpenNebula/Host' -require 'OpenNebula/HostPool' -require 'OpenNebula/Template' -require 'OpenNebula/TemplatePool' -require 'OpenNebula/Group' -require 'OpenNebula/GroupPool' -require 'OpenNebula/Acl' -require 'OpenNebula/AclPool' -require 'OpenNebula/Datastore' -require 'OpenNebula/DatastorePool' -require 'OpenNebula/Cluster' -require 'OpenNebula/ClusterPool' -require 'OpenNebula/Document' -require 'OpenNebula/DocumentPool' -require 'OpenNebula/System' +require 'opennebula/xml_utils' +require 'opennebula/virtual_machine' +require 'opennebula/virtual_machine_pool' +require 'opennebula/virtual_network' +require 'opennebula/virtual_network_pool' +require 'opennebula/image' +require 'opennebula/image_pool' +require 'opennebula/user' +require 'opennebula/user_pool' +require 'opennebula/host' +require 'opennebula/host_pool' +require 'opennebula/template' +require 'opennebula/template_pool' +require 'opennebula/group' +require 'opennebula/group_pool' +require 'opennebula/acl' +require 'opennebula/acl_pool' +require 'opennebula/datastore' +require 'opennebula/datastore_pool' +require 'opennebula/cluster' +require 'opennebula/cluster_pool' +require 'opennebula/document' +require 'opennebula/document_pool' +require 'opennebula/system' module OpenNebula diff --git a/src/oca/ruby/OpenNebula/Acl.rb b/src/oca/ruby/opennebula/acl.rb similarity index 100% rename from src/oca/ruby/OpenNebula/Acl.rb rename to src/oca/ruby/opennebula/acl.rb diff --git a/src/oca/ruby/OpenNebula/AclPool.rb b/src/oca/ruby/opennebula/acl_pool.rb similarity index 98% rename from src/oca/ruby/OpenNebula/AclPool.rb rename to src/oca/ruby/opennebula/acl_pool.rb index 4c7a1deef1..4118111145 100644 --- a/src/oca/ruby/OpenNebula/AclPool.rb +++ b/src/oca/ruby/opennebula/acl_pool.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class AclPool < Pool diff --git a/src/oca/ruby/OpenNebula/Cluster.rb b/src/oca/ruby/opennebula/cluster.rb similarity index 99% rename from src/oca/ruby/OpenNebula/Cluster.rb rename to src/oca/ruby/opennebula/cluster.rb index e6abb4c7a3..1319753c88 100644 --- a/src/oca/ruby/OpenNebula/Cluster.rb +++ b/src/oca/ruby/opennebula/cluster.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class Cluster < PoolElement diff --git a/src/oca/ruby/OpenNebula/ClusterPool.rb b/src/oca/ruby/opennebula/cluster_pool.rb similarity index 98% rename from src/oca/ruby/OpenNebula/ClusterPool.rb rename to src/oca/ruby/opennebula/cluster_pool.rb index 780b72a347..7ab1ca0aa6 100644 --- a/src/oca/ruby/OpenNebula/ClusterPool.rb +++ b/src/oca/ruby/opennebula/cluster_pool.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class ClusterPool < Pool diff --git a/src/oca/ruby/OpenNebula/Datastore.rb b/src/oca/ruby/opennebula/datastore.rb similarity index 99% rename from src/oca/ruby/OpenNebula/Datastore.rb rename to src/oca/ruby/opennebula/datastore.rb index fa1410203a..dfe41800b6 100644 --- a/src/oca/ruby/OpenNebula/Datastore.rb +++ b/src/oca/ruby/opennebula/datastore.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class Datastore < PoolElement diff --git a/src/oca/ruby/OpenNebula/DatastorePool.rb b/src/oca/ruby/opennebula/datastore_pool.rb similarity index 98% rename from src/oca/ruby/OpenNebula/DatastorePool.rb rename to src/oca/ruby/opennebula/datastore_pool.rb index b491d394fe..5a41ba2389 100644 --- a/src/oca/ruby/OpenNebula/DatastorePool.rb +++ b/src/oca/ruby/opennebula/datastore_pool.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class DatastorePool < Pool diff --git a/src/oca/ruby/OpenNebula/Document.rb b/src/oca/ruby/opennebula/document.rb similarity index 99% rename from src/oca/ruby/OpenNebula/Document.rb rename to src/oca/ruby/opennebula/document.rb index bcb186c8e5..5b3be75da7 100644 --- a/src/oca/ruby/OpenNebula/Document.rb +++ b/src/oca/ruby/opennebula/document.rb @@ -14,7 +14,7 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula diff --git a/src/oca/ruby/OpenNebula/DocumentJSON.rb b/src/oca/ruby/opennebula/document_json.rb similarity index 100% rename from src/oca/ruby/OpenNebula/DocumentJSON.rb rename to src/oca/ruby/opennebula/document_json.rb diff --git a/src/oca/ruby/OpenNebula/DocumentPool.rb b/src/oca/ruby/opennebula/document_pool.rb similarity index 98% rename from src/oca/ruby/OpenNebula/DocumentPool.rb rename to src/oca/ruby/opennebula/document_pool.rb index 3b428aa698..167820e278 100644 --- a/src/oca/ruby/OpenNebula/DocumentPool.rb +++ b/src/oca/ruby/opennebula/document_pool.rb @@ -14,7 +14,7 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula @@ -22,7 +22,7 @@ module OpenNebula # and the factory method. # # @example - # require 'OpenNebula/DocumentPool' + # require 'opennebuña/document_pool' # # module OpenNebula # class CustomObjectPool < DocumentPool diff --git a/src/oca/ruby/OpenNebula/DocumentPoolJSON.rb b/src/oca/ruby/opennebula/document_pool_json.rb similarity index 100% rename from src/oca/ruby/OpenNebula/DocumentPoolJSON.rb rename to src/oca/ruby/opennebula/document_pool_json.rb diff --git a/src/oca/ruby/OpenNebula/Group.rb b/src/oca/ruby/opennebula/group.rb similarity index 99% rename from src/oca/ruby/OpenNebula/Group.rb rename to src/oca/ruby/opennebula/group.rb index fcfefe8e38..ec6bb05e7a 100644 --- a/src/oca/ruby/OpenNebula/Group.rb +++ b/src/oca/ruby/opennebula/group.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class Group < PoolElement diff --git a/src/oca/ruby/OpenNebula/GroupPool.rb b/src/oca/ruby/opennebula/group_pool.rb similarity index 98% rename from src/oca/ruby/OpenNebula/GroupPool.rb rename to src/oca/ruby/opennebula/group_pool.rb index 20ebdeed08..8a6a83fc85 100644 --- a/src/oca/ruby/OpenNebula/GroupPool.rb +++ b/src/oca/ruby/opennebula/group_pool.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class GroupPool < Pool diff --git a/src/oca/ruby/OpenNebula/Host.rb b/src/oca/ruby/opennebula/host.rb similarity index 99% rename from src/oca/ruby/OpenNebula/Host.rb rename to src/oca/ruby/opennebula/host.rb index 1519351f80..8eb3cf8d29 100644 --- a/src/oca/ruby/OpenNebula/Host.rb +++ b/src/oca/ruby/opennebula/host.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class Host < PoolElement diff --git a/src/oca/ruby/OpenNebula/HostPool.rb b/src/oca/ruby/opennebula/host_pool.rb similarity index 99% rename from src/oca/ruby/OpenNebula/HostPool.rb rename to src/oca/ruby/opennebula/host_pool.rb index 8d71712d5a..7ac3e25400 100644 --- a/src/oca/ruby/OpenNebula/HostPool.rb +++ b/src/oca/ruby/opennebula/host_pool.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class HostPool < Pool diff --git a/src/oca/ruby/OpenNebula/Image.rb b/src/oca/ruby/opennebula/image.rb similarity index 99% rename from src/oca/ruby/OpenNebula/Image.rb rename to src/oca/ruby/opennebula/image.rb index 53a2f8aea7..de21fe8848 100644 --- a/src/oca/ruby/OpenNebula/Image.rb +++ b/src/oca/ruby/opennebula/image.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' require 'fileutils' module OpenNebula diff --git a/src/oca/ruby/OpenNebula/ImagePool.rb b/src/oca/ruby/opennebula/image_pool.rb similarity index 99% rename from src/oca/ruby/OpenNebula/ImagePool.rb rename to src/oca/ruby/opennebula/image_pool.rb index 97cab2eb67..08fe1f7d6d 100644 --- a/src/oca/ruby/OpenNebula/ImagePool.rb +++ b/src/oca/ruby/opennebula/image_pool.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class ImagePool < Pool diff --git a/src/oca/ruby/OpenNebula/Pool.rb b/src/oca/ruby/opennebula/pool.rb similarity index 100% rename from src/oca/ruby/OpenNebula/Pool.rb rename to src/oca/ruby/opennebula/pool.rb diff --git a/src/oca/ruby/OpenNebula/System.rb b/src/oca/ruby/opennebula/system.rb similarity index 99% rename from src/oca/ruby/OpenNebula/System.rb rename to src/oca/ruby/opennebula/system.rb index 9092e0be85..12d5ab81f7 100644 --- a/src/oca/ruby/OpenNebula/System.rb +++ b/src/oca/ruby/opennebula/system.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class System diff --git a/src/oca/ruby/OpenNebula/Template.rb b/src/oca/ruby/opennebula/template.rb similarity index 99% rename from src/oca/ruby/OpenNebula/Template.rb rename to src/oca/ruby/opennebula/template.rb index 73a6d48aac..69cef3d027 100644 --- a/src/oca/ruby/OpenNebula/Template.rb +++ b/src/oca/ruby/opennebula/template.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class Template < PoolElement diff --git a/src/oca/ruby/OpenNebula/TemplatePool.rb b/src/oca/ruby/opennebula/template_pool.rb similarity index 99% rename from src/oca/ruby/OpenNebula/TemplatePool.rb rename to src/oca/ruby/opennebula/template_pool.rb index 820d7c8d7b..ed8f724d6f 100644 --- a/src/oca/ruby/OpenNebula/TemplatePool.rb +++ b/src/oca/ruby/opennebula/template_pool.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class TemplatePool < Pool diff --git a/src/oca/ruby/OpenNebula/User.rb b/src/oca/ruby/opennebula/user.rb similarity index 99% rename from src/oca/ruby/OpenNebula/User.rb rename to src/oca/ruby/opennebula/user.rb index a4c381ccb6..fbcc9b2c80 100644 --- a/src/oca/ruby/OpenNebula/User.rb +++ b/src/oca/ruby/opennebula/user.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class User < PoolElement diff --git a/src/oca/ruby/OpenNebula/UserPool.rb b/src/oca/ruby/opennebula/user_pool.rb similarity index 98% rename from src/oca/ruby/OpenNebula/UserPool.rb rename to src/oca/ruby/opennebula/user_pool.rb index b4d9b733a6..964f1bb49e 100644 --- a/src/oca/ruby/OpenNebula/UserPool.rb +++ b/src/oca/ruby/opennebula/user_pool.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class UserPool < Pool diff --git a/src/oca/ruby/OpenNebula/VirtualMachine.rb b/src/oca/ruby/opennebula/virtual_machine.rb similarity index 99% rename from src/oca/ruby/OpenNebula/VirtualMachine.rb rename to src/oca/ruby/opennebula/virtual_machine.rb index 31cd2952e8..e4805271e1 100644 --- a/src/oca/ruby/OpenNebula/VirtualMachine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class VirtualMachine < PoolElement diff --git a/src/oca/ruby/OpenNebula/VirtualMachinePool.rb b/src/oca/ruby/opennebula/virtual_machine_pool.rb similarity index 99% rename from src/oca/ruby/OpenNebula/VirtualMachinePool.rb rename to src/oca/ruby/opennebula/virtual_machine_pool.rb index b0a06af35a..0afe393374 100644 --- a/src/oca/ruby/OpenNebula/VirtualMachinePool.rb +++ b/src/oca/ruby/opennebula/virtual_machine_pool.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class VirtualMachinePool < Pool diff --git a/src/oca/ruby/OpenNebula/VirtualNetwork.rb b/src/oca/ruby/opennebula/virtual_network.rb similarity index 99% rename from src/oca/ruby/OpenNebula/VirtualNetwork.rb rename to src/oca/ruby/opennebula/virtual_network.rb index b6964b4d0e..1d85bc0ffc 100644 --- a/src/oca/ruby/OpenNebula/VirtualNetwork.rb +++ b/src/oca/ruby/opennebula/virtual_network.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class VirtualNetwork < PoolElement diff --git a/src/oca/ruby/OpenNebula/VirtualNetworkPool.rb b/src/oca/ruby/opennebula/virtual_network_pool.rb similarity index 99% rename from src/oca/ruby/OpenNebula/VirtualNetworkPool.rb rename to src/oca/ruby/opennebula/virtual_network_pool.rb index 135da47e72..31b4c95d60 100644 --- a/src/oca/ruby/OpenNebula/VirtualNetworkPool.rb +++ b/src/oca/ruby/opennebula/virtual_network_pool.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # -require 'OpenNebula/Pool' +require 'opennebula/pool' module OpenNebula class VirtualNetworkPool < Pool diff --git a/src/oca/ruby/OpenNebula/XMLUtils.rb b/src/oca/ruby/opennebula/xml_utils.rb similarity index 100% rename from src/oca/ruby/OpenNebula/XMLUtils.rb rename to src/oca/ruby/opennebula/xml_utils.rb From 18657919d2c751aff97ad9511c6bc3f802c72150 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Tue, 18 Dec 2012 09:14:47 -0600 Subject: [PATCH 08/79] feature #1700: Change oca libs dir in install.sh --- install.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/install.sh b/install.sh index 88c9f877ee..e277d77fdb 100755 --- a/install.sh +++ b/install.sh @@ -196,7 +196,7 @@ ETC_DIRS="$ETC_LOCATION/im_ec2 \ $ETC_LOCATION/cli" LIB_DIRS="$LIB_LOCATION/ruby \ - $LIB_LOCATION/ruby/OpenNebula \ + $LIB_LOCATION/ruby/opennebula \ $LIB_LOCATION/ruby/zona \ $LIB_LOCATION/ruby/cloud/ \ $LIB_LOCATION/ruby/cloud/econe \ @@ -357,22 +357,22 @@ SELF_SERVICE_DIRS="\ $LIB_LOCATION/ruby/cloud/occi/ui/public/vendor/FontAwesome/font" OZONES_CLIENT_DIRS="$LIB_LOCATION/ruby \ - $LIB_LOCATION/ruby/OpenNebula \ + $LIB_LOCATION/ruby/opennebula \ $LIB_LOCATION/ruby/cli \ $LIB_LOCATION/ruby/cli/ozones_helper \ $LIB_LOCATION/ruby/zona" LIB_ECO_CLIENT_DIRS="$LIB_LOCATION/ruby \ - $LIB_LOCATION/ruby/OpenNebula \ + $LIB_LOCATION/ruby/opennebula \ $LIB_LOCATION/ruby/cloud/ \ $LIB_LOCATION/ruby/cloud/econe" LIB_OCCI_CLIENT_DIRS="$LIB_LOCATION/ruby \ - $LIB_LOCATION/ruby/OpenNebula \ + $LIB_LOCATION/ruby/opennebula \ $LIB_LOCATION/ruby/cloud/occi" LIB_MARKET_CLIENT_DIRS="$LIB_LOCATION/ruby \ - $LIB_LOCATION/ruby/OpenNebula \ + $LIB_LOCATION/ruby/opennebula \ $LIB_LOCATION/ruby/cloud/marketplace" LIB_OCA_CLIENT_DIRS="$LIB_LOCATION/ruby \ @@ -488,11 +488,11 @@ INSTALL_CLIENT_FILES=( OZONES_LIB_API_ZONA_FILES:$LIB_LOCATION/ruby/zona CLI_CONF_FILES:$ETC_LOCATION/cli OCA_LIB_FILES:$LIB_LOCATION/ruby - RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/OpenNebula + RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/opennebula ) INSTALL_SUNSTONE_RUBY_FILES=( - RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/OpenNebula + RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/opennebula OCA_LIB_FILES:$LIB_LOCATION/ruby ) @@ -541,7 +541,7 @@ INSTALL_SUNSTONE_ETC_FILES=( INSTALL_OZONES_RUBY_FILES=( OZONES_RUBY_LIB_FILES:$LIB_LOCATION/ruby - RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/OpenNebula + RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/opennebula ) INSTALL_OZONES_FILES=( @@ -673,7 +673,7 @@ RUBY_LIB_FILES="src/mad/ruby/ActionManager.rb \ src/mad/ruby/ssh_stream.rb \ src/vnm_mad/one_vnm.rb \ src/mad/ruby/Ganglia.rb \ - src/oca/ruby/OpenNebula.rb \ + src/oca/ruby/opennebula.rb \ src/authm_mad/remotes/ssh/ssh_auth.rb \ src/authm_mad/remotes/server_x509/server_x509_auth.rb \ src/authm_mad/remotes/server_cipher/server_cipher_auth.rb \ From b4f467553437aa620887db0fac18247cafa47f51 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Tue, 18 Dec 2012 11:30:09 -0600 Subject: [PATCH 09/79] feature #1700: Take out OCA classes to different files and change requires --- install.sh | 5 + src/cli/one_helper.rb | 2 +- src/cloud/common/CloudServer.rb | 2 +- src/cloud/ec2/lib/ImageEC2.rb | 2 +- src/cloud/occi/lib/ImageOCCI.rb | 2 +- src/cloud/occi/lib/UserOCCI.rb | 2 +- src/cloud/occi/lib/VirtualMachineOCCI.rb | 2 +- src/cloud/occi/lib/VirtualNetworkOCCI.rb | 2 +- src/im_mad/remotes/vmware.d/vmware.rb | 2 +- src/oca/ruby/opennebula.rb | 122 +---- src/oca/ruby/opennebula/client.rb | 102 +++++ src/oca/ruby/opennebula/document.rb | 2 +- src/oca/ruby/opennebula/error.rb | 52 +++ src/oca/ruby/opennebula/pool.rb | 250 ---------- src/oca/ruby/opennebula/pool_element.rb | 268 +++++++++++ src/oca/ruby/opennebula/xml_element.rb | 427 ++++++++++++++++++ src/oca/ruby/opennebula/xml_pool.rb | 45 ++ src/oca/ruby/opennebula/xml_utils.rb | 410 +---------------- src/oca/ruby/test/HostPool_spec.rb | 2 +- src/oca/ruby/test/Host_spec.rb | 2 +- src/oca/ruby/test/UserPool_spec.rb | 2 +- src/oca/ruby/test/User_spec.rb | 2 +- src/oca/ruby/test/VirtualMachinePool_spec.rb | 2 +- src/oca/ruby/test/VirtualMachine_spec.rb | 2 +- src/oca/ruby/test/VirtualNetworkPool_spec.rb | 2 +- src/oca/ruby/test/VirtualNetwork_spec.rb | 2 +- src/oca/ruby/test/XMLUtils_spec.rb | 4 +- src/ozones/Server/lib/OZones.rb | 2 +- .../Server/lib/test/helpers/OpenNebula.rb | 30 +- src/sunstone/OpenNebulaVNC.rb | 2 +- src/sunstone/models/OpenNebulaJSON.rb | 2 +- 31 files changed, 939 insertions(+), 816 deletions(-) create mode 100644 src/oca/ruby/opennebula/client.rb create mode 100644 src/oca/ruby/opennebula/error.rb create mode 100644 src/oca/ruby/opennebula/pool_element.rb create mode 100644 src/oca/ruby/opennebula/xml_element.rb create mode 100644 src/oca/ruby/opennebula/xml_pool.rb diff --git a/install.sh b/install.sh index e277d77fdb..e419fe066f 100755 --- a/install.sh +++ b/install.sh @@ -1109,6 +1109,11 @@ RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/opennebula/host.rb \ src/oca/ruby/opennebula/cluster.rb \ src/oca/ruby/opennebula/cluster_pool.rb \ src/oca/ruby/opennebula/xml_utils.rb \ + src/oca/ruby/opennebula/client.rb \ + src/oca/ruby/opennebula/error.rb \ + src/oca/ruby/opennebula/pool_element.rb \ + src/oca/ruby/opennebula/xml_element.rb \ + src/oca/ruby/opennebula/xml_pool.rb \ src/oca/ruby/opennebula/system.rb" #------------------------------------------------------------------------------- diff --git a/src/cli/one_helper.rb b/src/cli/one_helper.rb index 8330a43446..4d82d79d92 100644 --- a/src/cli/one_helper.rb +++ b/src/cli/one_helper.rb @@ -16,7 +16,7 @@ require 'cli_helper' -require 'OpenNebula' +require 'opennebula' include OpenNebula module OpenNebulaHelper diff --git a/src/cloud/common/CloudServer.rb b/src/cloud/common/CloudServer.rb index 904e072ec0..f6524255f1 100644 --- a/src/cloud/common/CloudServer.rb +++ b/src/cloud/common/CloudServer.rb @@ -14,7 +14,7 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -require 'OpenNebula' +require 'opennebula' ############################################################################## # This class represents a generic Cloud Server using the OpenNebula Cloud diff --git a/src/cloud/ec2/lib/ImageEC2.rb b/src/cloud/ec2/lib/ImageEC2.rb index 585fedd81f..bfce8fd97f 100644 --- a/src/cloud/ec2/lib/ImageEC2.rb +++ b/src/cloud/ec2/lib/ImageEC2.rb @@ -15,7 +15,7 @@ #--------------------------------------------------------------------------- # require 'uuidtools' -require 'OpenNebula' +require 'opennebula' include OpenNebula diff --git a/src/cloud/occi/lib/ImageOCCI.rb b/src/cloud/occi/lib/ImageOCCI.rb index f95f4f65bc..4a09bab2a8 100644 --- a/src/cloud/occi/lib/ImageOCCI.rb +++ b/src/cloud/occi/lib/ImageOCCI.rb @@ -14,7 +14,7 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -require 'OpenNebula' +require 'opennebula' include OpenNebula diff --git a/src/cloud/occi/lib/UserOCCI.rb b/src/cloud/occi/lib/UserOCCI.rb index 0038bdaa3a..aa82255d81 100644 --- a/src/cloud/occi/lib/UserOCCI.rb +++ b/src/cloud/occi/lib/UserOCCI.rb @@ -14,7 +14,7 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -require 'OpenNebula' +require 'opennebula' include OpenNebula diff --git a/src/cloud/occi/lib/VirtualMachineOCCI.rb b/src/cloud/occi/lib/VirtualMachineOCCI.rb index 0af7e05e2c..90f67b9e3f 100644 --- a/src/cloud/occi/lib/VirtualMachineOCCI.rb +++ b/src/cloud/occi/lib/VirtualMachineOCCI.rb @@ -15,7 +15,7 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -require 'OpenNebula' +require 'opennebula' include OpenNebula diff --git a/src/cloud/occi/lib/VirtualNetworkOCCI.rb b/src/cloud/occi/lib/VirtualNetworkOCCI.rb index 6efe071bba..b145a9bfed 100644 --- a/src/cloud/occi/lib/VirtualNetworkOCCI.rb +++ b/src/cloud/occi/lib/VirtualNetworkOCCI.rb @@ -14,7 +14,7 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -require 'OpenNebula' +require 'opennebula' require 'ipaddr' include OpenNebula diff --git a/src/im_mad/remotes/vmware.d/vmware.rb b/src/im_mad/remotes/vmware.d/vmware.rb index cd02f42fbe..5bccd3f900 100755 --- a/src/im_mad/remotes/vmware.d/vmware.rb +++ b/src/im_mad/remotes/vmware.d/vmware.rb @@ -41,7 +41,7 @@ ENV['LANG'] = 'C' require "scripts_common" require 'yaml' require "CommandManager" -require 'OpenNebula' +require 'opennebula' include OpenNebula begin diff --git a/src/oca/ruby/opennebula.rb b/src/oca/ruby/opennebula.rb index 0c720589fe..f3d9d0ff39 100644 --- a/src/oca/ruby/opennebula.rb +++ b/src/oca/ruby/opennebula.rb @@ -20,12 +20,13 @@ begin # require 'rubygems' rescue Exception end -require 'xmlrpc/client' require 'digest/sha1' require 'rexml/document' require 'pp' require 'opennebula/xml_utils' +require 'opennebula/client' +require 'opennebula/error' require 'opennebula/virtual_machine' require 'opennebula/virtual_machine_pool' require 'opennebula/virtual_network' @@ -54,123 +55,4 @@ module OpenNebula # OpenNebula version VERSION = '3.9.0' - - # The Error Class represents a generic error in the OpenNebula - # library. It contains a readable representation of the error. - # Any function in the OpenNebula module will return an Error - # object in case of error. - class Error - ESUCCESS = 0x0000 - EAUTHENTICATION = 0x0100 - EAUTHORIZATION = 0x0200 - ENO_EXISTS = 0x0400 - EACTION = 0x0800 - EXML_RPC_API = 0x1000 - EINTERNAL = 0x2000 - ENOTDEFINED = 0x1111 - - attr_reader :message, :errno - - # +message+ Description of the error - # +errno+ OpenNebula code error - def initialize(message=nil, errno=0x1111) - @message = message - @errno = errno - end - - def to_str() - @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==OpenNebula::Error - end - - - if OpenNebula::NOKOGIRI - class NokogiriStreamParser < XMLRPC::XMLParser::AbstractStreamParser - def initialize - @parser_class = NokogiriParser - end - - class NokogiriParser < Nokogiri::XML::SAX::Document - include XMLRPC::XMLParser::StreamParserMixin - - alias :cdata_block :character - alias :characters :character - alias :end_element :endElement - alias :start_element :startElement - - def parse(str) - parser = Nokogiri::XML::SAX::Parser.new(self) - parser.parse(str) - end - end - end - end - - - # The client class, represents the connection with the core and handles the - # xml-rpc calls. - class Client - attr_accessor :one_auth - - begin - require 'xmlparser' - XMLPARSER=true - rescue LoadError - XMLPARSER=false - end - - def initialize(secret=nil, endpoint=nil) - if secret - @one_auth = secret - elsif ENV["ONE_AUTH"] and !ENV["ONE_AUTH"].empty? and File.file?(ENV["ONE_AUTH"]) - @one_auth = File.read(ENV["ONE_AUTH"]) - elsif File.file?(ENV["HOME"]+"/.one/one_auth") - @one_auth = File.read(ENV["HOME"]+"/.one/one_auth") - else - raise "ONE_AUTH file not present" - end - - @one_auth.rstrip! - - if endpoint - @one_endpoint = endpoint - elsif ENV["ONE_XMLRPC"] - @one_endpoint = ENV["ONE_XMLRPC"] - else - @one_endpoint = "http://localhost:2633/RPC2" - end - - @server = XMLRPC::Client.new2(@one_endpoint) - - if OpenNebula::NOKOGIRI - @server.set_parser(NokogiriStreamParser.new) - elsif XMLPARSER - @server.set_parser(XMLRPC::XMLParser::XMLStreamParser.new) - end - end - - def call(action, *args) - begin - response = @server.call_async("one."+action, @one_auth, *args) - - if response[0] == false - Error.new(response[1], response[2]) - else - response[1] #response[1..-1] - end - rescue Exception => e - Error.new(e.message) - end - end - - def get_version() - call("system.version") - end - end end diff --git a/src/oca/ruby/opennebula/client.rb b/src/oca/ruby/opennebula/client.rb new file mode 100644 index 0000000000..b7e7ad78f1 --- /dev/null +++ b/src/oca/ruby/opennebula/client.rb @@ -0,0 +1,102 @@ +# -------------------------------------------------------------------------- # +# 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 'xmlrpc/client' + +module OpenNebula + if OpenNebula::NOKOGIRI + class NokogiriStreamParser < XMLRPC::XMLParser::AbstractStreamParser + def initialize + @parser_class = NokogiriParser + end + + class NokogiriParser < Nokogiri::XML::SAX::Document + include XMLRPC::XMLParser::StreamParserMixin + + alias :cdata_block :character + alias :characters :character + alias :end_element :endElement + alias :start_element :startElement + + def parse(str) + parser = Nokogiri::XML::SAX::Parser.new(self) + parser.parse(str) + end + end + end + end + + # The client class, represents the connection with the core and handles the + # xml-rpc calls. + class Client + attr_accessor :one_auth + + begin + require 'xmlparser' + XMLPARSER=true + rescue LoadError + XMLPARSER=false + end + + def initialize(secret=nil, endpoint=nil) + if secret + @one_auth = secret + elsif ENV["ONE_AUTH"] and !ENV["ONE_AUTH"].empty? and File.file?(ENV["ONE_AUTH"]) + @one_auth = File.read(ENV["ONE_AUTH"]) + elsif File.file?(ENV["HOME"]+"/.one/one_auth") + @one_auth = File.read(ENV["HOME"]+"/.one/one_auth") + else + raise "ONE_AUTH file not present" + end + + @one_auth.rstrip! + + if endpoint + @one_endpoint = endpoint + elsif ENV["ONE_XMLRPC"] + @one_endpoint = ENV["ONE_XMLRPC"] + else + @one_endpoint = "http://localhost:2633/RPC2" + end + + @server = XMLRPC::Client.new2(@one_endpoint) + + if OpenNebula::NOKOGIRI + @server.set_parser(NokogiriStreamParser.new) + elsif XMLPARSER + @server.set_parser(XMLRPC::XMLParser::XMLStreamParser.new) + end + end + + def call(action, *args) + begin + response = @server.call_async("one."+action, @one_auth, *args) + + if response[0] == false + Error.new(response[1], response[2]) + else + response[1] #response[1..-1] + end + rescue Exception => e + Error.new(e.message) + end + end + + def get_version() + call("system.version") + end + end +end diff --git a/src/oca/ruby/opennebula/document.rb b/src/oca/ruby/opennebula/document.rb index 5b3be75da7..6c735bcd6e 100644 --- a/src/oca/ruby/opennebula/document.rb +++ b/src/oca/ruby/opennebula/document.rb @@ -21,7 +21,7 @@ module OpenNebula # All subclasses must define the DOCUMENT_TYPE constant. # # @example - # require 'OpenNebula/Document' + # require 'opennebula/document' # # module OpenNebula # class CustomObject < Document diff --git a/src/oca/ruby/opennebula/error.rb b/src/oca/ruby/opennebula/error.rb new file mode 100644 index 0000000000..a0981de571 --- /dev/null +++ b/src/oca/ruby/opennebula/error.rb @@ -0,0 +1,52 @@ +# -------------------------------------------------------------------------- # +# 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 + # The Error Class represents a generic error in the OpenNebula + # library. It contains a readable representation of the error. + # Any function in the OpenNebula module will return an Error + # object in case of error. + class Error + ESUCCESS = 0x0000 + EAUTHENTICATION = 0x0100 + EAUTHORIZATION = 0x0200 + ENO_EXISTS = 0x0400 + EACTION = 0x0800 + EXML_RPC_API = 0x1000 + EINTERNAL = 0x2000 + ENOTDEFINED = 0x1111 + + attr_reader :message, :errno + + # +message+ Description of the error + # +errno+ OpenNebula code error + def initialize(message=nil, errno=0x1111) + @message = message + @errno = errno + end + + def to_str() + @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==OpenNebula::Error + end +end diff --git a/src/oca/ruby/opennebula/pool.rb b/src/oca/ruby/opennebula/pool.rb index e917f7bb32..7308a30cfe 100644 --- a/src/oca/ruby/opennebula/pool.rb +++ b/src/oca/ruby/opennebula/pool.rb @@ -153,254 +153,4 @@ module OpenNebula return str end end - - # The PoolElement Class represents a generic element of a Pool in - # XML format - class PoolElement < XMLElement - - protected - # node:: _XML_is a XML element that represents the Pool element - # client:: _Client_ represents a XML-RPC connection - def initialize(node, client) - @xml = node - @client = client - - if self['ID'] - @pe_id = self['ID'].to_i - else - @pe_id = nil - end - @name = self['NAME'] if self['NAME'] - end - - ####################################################################### - # Common XML-RPC Methods for all the Pool Element Types - ####################################################################### - - # Common client call wrapper. Checks that @pe_id is defined, and - # returns nil instead of the response if it is successful - # - # @param [String] xml_method xml-rpc method - # @param [Array] args any arguments for the xml-rpc method - # - # @return [nil, OpenNebula::Error] nil in case of success, Error - # otherwise - def call(xml_method, *args) - return Error.new('ID not defined') if !@pe_id - - rc = @client.call(xml_method, *args) - rc = nil if !OpenNebula.is_error?(rc) - - return rc - end - - # Calls to the corresponding info method to retreive the element - # detailed information in XML format - # - # @param [String] xml_method the name of the XML-RPC method - # @param [String] root_element Base XML element name - # @param [Array] args additional arguments - # - # @return [nil, OpenNebula::Error] nil in case of success, Error - # otherwise - def info(xml_method, root_element) - return Error.new('ID not defined') if !@pe_id - - rc = @client.call(xml_method, @pe_id) - - if !OpenNebula.is_error?(rc) - initialize_xml(rc, root_element) - rc = nil - - @pe_id = self['ID'].to_i if self['ID'] - @name = self['NAME'] if self['NAME'] - end - - return rc - end - - # Calls to the corresponding allocate method to create a new element - # in the OpenNebula core - # - # @param [String] xml_method the name of the XML-RPC method - # @param [Array] args any extra arguments for the xml-rpc method - # - # @return [nil, OpenNebula::Error] nil in case of success, Error - # otherwise - def allocate(xml_method, *args) - rc = @client.call(xml_method, *args) - - if !OpenNebula.is_error?(rc) - @pe_id = rc - rc = nil - end - - return rc - end - - # Calls to the corresponding update method to modify - # the object's template - # - # @param [String] xml_method the name of the XML-RPC method - # @param [String] new_template the new template contents - # @param [Array] args any extra arguments for the xml-rpc method - # - # @return [nil, OpenNebula::Error] nil in case of success, Error - # otherwise - def update(xml_method, new_template, *args) - new_template ||= template_xml - - return call(xml_method, @pe_id, new_template, *args) - end - - # Calls to the corresponding delete method to remove this element - # from the OpenNebula core - # - # @param [String] xml_method the name of the XML-RPC method - # - # @return [nil, OpenNebula::Error] nil in case of success, Error - # otherwise - def delete(xml_method) - return call(xml_method,@pe_id) - end - - # Calls to the corresponding chown method to modify - # the object's owner and group - # - # @param [String] xml_method the name of the XML-RPC method - # @param [Integer] uid the new owner id. Set to -1 to leave the current one - # @param [Integer] gid the new goup id. Set to -1 to leave the current one - # - # @return [nil, OpenNebula::Error] nil in case of success, Error - # otherwise - def chown(xml_method, uid, gid) - return call(xml_method, @pe_id, uid, gid) - end - - # Calls to the corresponding chmod method to modify - # the object's permission bits - # - # @param xml_method [String] the name of the XML-RPC method - # @param octet [String] Permissions octed , e.g. 640 - # - # @return [nil, OpenNebula::Error] nil in case of success, Error - # otherwise - def chmod_octet(xml_method, octet) - owner_u = octet[0..0].to_i & 4 != 0 ? 1 : 0 - owner_m = octet[0..0].to_i & 2 != 0 ? 1 : 0 - owner_a = octet[0..0].to_i & 1 != 0 ? 1 : 0 - group_u = octet[1..1].to_i & 4 != 0 ? 1 : 0 - group_m = octet[1..1].to_i & 2 != 0 ? 1 : 0 - group_a = octet[1..1].to_i & 1 != 0 ? 1 : 0 - other_u = octet[2..2].to_i & 4 != 0 ? 1 : 0 - other_m = octet[2..2].to_i & 2 != 0 ? 1 : 0 - other_a = octet[2..2].to_i & 1 != 0 ? 1 : 0 - - chmod(owner_u, owner_m, owner_a, group_u, group_m, group_a, other_u, - other_m, other_a) - end - - # Calls to the corresponding chmod method to modify - # the object's permission bits - # Each [Integer] parameter must be 1 to allow, 0 deny, -1 do not change - # - # @param xml_method [String] the name of the XML-RPC method - # - # @return [nil, OpenNebula::Error] nil in case of success, Error - # otherwise - def chmod(xml_method, owner_u, owner_m, owner_a, group_u, group_m, group_a, other_u, - other_m, other_a) - return call(xml_method, @pe_id, owner_u, owner_m, - owner_a, group_u, group_m, group_a, other_u, - other_m, other_a) - end - - - # Retrieves this Element's monitoring data from OpenNebula - # - # @param [String] xml_method the name of the XML-RPC method - # @param [String] root_elem Root for each individual PoolElement - # @param [String] timestamp_elem Name of the XML element with the last - # monitorization timestamp - # @param xpath_expressions [Array] Xpath expressions for the - # elements to retrieve. - # - # @return [Hash>, OpenNebula::Error] Hash with - # the requested xpath expressions, and an Array of [timestamp, value]. - def monitoring(xml_method, root_elem, timestamp_elem, xpath_expressions) - return Error.new('ID not defined') if !@pe_id - - rc = @client.call(xml_method, @pe_id) - - if ( OpenNebula.is_error?(rc) ) - return rc - end - - xmldoc = XMLElement.new - xmldoc.initialize_xml(rc, 'MONITORING_DATA') - - - return OpenNebula.process_monitoring( - xmldoc, root_elem, timestamp_elem, @pe_id, xpath_expressions) - end - - public - - # Creates new element specifying its id - # id:: identifyier of the element - # client:: initialized OpenNebula::Client object - def self.new_with_id(id, client=nil) - self.new(self.build_xml(id), client) - end - - # Returns element identifier - # [return] _Integer_ the PoolElement ID - def id - @pe_id - end - - # Gets element name - # [return] _String_ the PoolElement name - def name - @name - end - - # DO NOT USE - ONLY REXML BACKEND - def to_str - str = "" - REXML::Formatters::Pretty.new(1).write(@xml,str) - - return str - end - end - - # Processes the monitoring data in XML returned by OpenNebula - # - # @param [XMLElement] xmldoc monitoring data returned by OpenNebula - # @param [String] root_elem Root for each individual PoolElement - # @param [String] timestamp_elem Name of the XML element with the last - # monitorization timestamp - # @param [Integer] Id of the object to process - # @param [Array] xpath_expressions Elements to retrieve. - # @param args arguemnts for the xml_method call - # - # @return [Hash>, OpenNebula::Error] Hash with - # the requested xpath expressions, and an Array of [timestamp, value]. - def self.process_monitoring(xmldoc, root_elem, timestamp_elem, oid, xpath_expressions) - hash = {} - timestamps = xmldoc.retrieve_elements( - "#{root_elem}[ID=#{oid}]/#{timestamp_elem}") - - xpath_expressions.each { |xpath| - xpath_values = xmldoc.retrieve_elements("#{root_elem}[ID=#{oid}]/#{xpath}") - - if ( xpath_values.nil? ) - hash[xpath] = [] - else - hash[xpath] = timestamps.zip(xpath_values) - end - } - - return hash - end end diff --git a/src/oca/ruby/opennebula/pool_element.rb b/src/oca/ruby/opennebula/pool_element.rb new file mode 100644 index 0000000000..d7dd3670b2 --- /dev/null +++ b/src/oca/ruby/opennebula/pool_element.rb @@ -0,0 +1,268 @@ +# -------------------------------------------------------------------------- # +# 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 + # The PoolElement Class represents a generic element of a Pool in + # XML format + class PoolElement < XMLElement + + protected + # node:: _XML_is a XML element that represents the Pool element + # client:: _Client_ represents a XML-RPC connection + def initialize(node, client) + @xml = node + @client = client + + if self['ID'] + @pe_id = self['ID'].to_i + else + @pe_id = nil + end + @name = self['NAME'] if self['NAME'] + end + + ####################################################################### + # Common XML-RPC Methods for all the Pool Element Types + ####################################################################### + + # Common client call wrapper. Checks that @pe_id is defined, and + # returns nil instead of the response if it is successful + # + # @param [String] xml_method xml-rpc method + # @param [Array] args any arguments for the xml-rpc method + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def call(xml_method, *args) + return Error.new('ID not defined') if !@pe_id + + rc = @client.call(xml_method, *args) + rc = nil if !OpenNebula.is_error?(rc) + + return rc + end + + # Calls to the corresponding info method to retreive the element + # detailed information in XML format + # + # @param [String] xml_method the name of the XML-RPC method + # @param [String] root_element Base XML element name + # @param [Array] args additional arguments + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def info(xml_method, root_element) + return Error.new('ID not defined') if !@pe_id + + rc = @client.call(xml_method, @pe_id) + + if !OpenNebula.is_error?(rc) + initialize_xml(rc, root_element) + rc = nil + + @pe_id = self['ID'].to_i if self['ID'] + @name = self['NAME'] if self['NAME'] + end + + return rc + end + + # Calls to the corresponding allocate method to create a new element + # in the OpenNebula core + # + # @param [String] xml_method the name of the XML-RPC method + # @param [Array] args any extra arguments for the xml-rpc method + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def allocate(xml_method, *args) + rc = @client.call(xml_method, *args) + + if !OpenNebula.is_error?(rc) + @pe_id = rc + rc = nil + end + + return rc + end + + # Calls to the corresponding update method to modify + # the object's template + # + # @param [String] xml_method the name of the XML-RPC method + # @param [String] new_template the new template contents + # @param [Array] args any extra arguments for the xml-rpc method + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def update(xml_method, new_template, *args) + new_template ||= template_xml + + return call(xml_method, @pe_id, new_template, *args) + end + + # Calls to the corresponding delete method to remove this element + # from the OpenNebula core + # + # @param [String] xml_method the name of the XML-RPC method + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def delete(xml_method) + return call(xml_method,@pe_id) + end + + # Calls to the corresponding chown method to modify + # the object's owner and group + # + # @param [String] xml_method the name of the XML-RPC method + # @param [Integer] uid the new owner id. Set to -1 to leave the current one + # @param [Integer] gid the new goup id. Set to -1 to leave the current one + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def chown(xml_method, uid, gid) + return call(xml_method, @pe_id, uid, gid) + end + + # Calls to the corresponding chmod method to modify + # the object's permission bits + # + # @param xml_method [String] the name of the XML-RPC method + # @param octet [String] Permissions octed , e.g. 640 + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def chmod_octet(xml_method, octet) + owner_u = octet[0..0].to_i & 4 != 0 ? 1 : 0 + owner_m = octet[0..0].to_i & 2 != 0 ? 1 : 0 + owner_a = octet[0..0].to_i & 1 != 0 ? 1 : 0 + group_u = octet[1..1].to_i & 4 != 0 ? 1 : 0 + group_m = octet[1..1].to_i & 2 != 0 ? 1 : 0 + group_a = octet[1..1].to_i & 1 != 0 ? 1 : 0 + other_u = octet[2..2].to_i & 4 != 0 ? 1 : 0 + other_m = octet[2..2].to_i & 2 != 0 ? 1 : 0 + other_a = octet[2..2].to_i & 1 != 0 ? 1 : 0 + + chmod(owner_u, owner_m, owner_a, group_u, group_m, group_a, other_u, + other_m, other_a) + end + + # Calls to the corresponding chmod method to modify + # the object's permission bits + # Each [Integer] parameter must be 1 to allow, 0 deny, -1 do not change + # + # @param xml_method [String] the name of the XML-RPC method + # + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def chmod(xml_method, owner_u, owner_m, owner_a, group_u, group_m, group_a, other_u, + other_m, other_a) + return call(xml_method, @pe_id, owner_u, owner_m, + owner_a, group_u, group_m, group_a, other_u, + other_m, other_a) + end + + + # Retrieves this Element's monitoring data from OpenNebula + # + # @param [String] xml_method the name of the XML-RPC method + # @param [String] root_elem Root for each individual PoolElement + # @param [String] timestamp_elem Name of the XML element with the last + # monitorization timestamp + # @param xpath_expressions [Array] Xpath expressions for the + # elements to retrieve. + # + # @return [Hash>, OpenNebula::Error] Hash with + # the requested xpath expressions, and an Array of [timestamp, value]. + def monitoring(xml_method, root_elem, timestamp_elem, xpath_expressions) + return Error.new('ID not defined') if !@pe_id + + rc = @client.call(xml_method, @pe_id) + + if ( OpenNebula.is_error?(rc) ) + return rc + end + + xmldoc = XMLElement.new + xmldoc.initialize_xml(rc, 'MONITORING_DATA') + + + return OpenNebula.process_monitoring( + xmldoc, root_elem, timestamp_elem, @pe_id, xpath_expressions) + end + + public + + # Creates new element specifying its id + # id:: identifyier of the element + # client:: initialized OpenNebula::Client object + def self.new_with_id(id, client=nil) + self.new(self.build_xml(id), client) + end + + # Returns element identifier + # [return] _Integer_ the PoolElement ID + def id + @pe_id + end + + # Gets element name + # [return] _String_ the PoolElement name + def name + @name + end + + # DO NOT USE - ONLY REXML BACKEND + def to_str + str = "" + REXML::Formatters::Pretty.new(1).write(@xml,str) + + return str + end + end + + # Processes the monitoring data in XML returned by OpenNebula + # + # @param [XMLElement] xmldoc monitoring data returned by OpenNebula + # @param [String] root_elem Root for each individual PoolElement + # @param [String] timestamp_elem Name of the XML element with the last + # monitorization timestamp + # @param [Integer] Id of the object to process + # @param [Array] xpath_expressions Elements to retrieve. + # @param args arguemnts for the xml_method call + # + # @return [Hash>, OpenNebula::Error] Hash with + # the requested xpath expressions, and an Array of [timestamp, value]. + def self.process_monitoring(xmldoc, root_elem, timestamp_elem, oid, xpath_expressions) + hash = {} + timestamps = xmldoc.retrieve_elements( + "#{root_elem}[ID=#{oid}]/#{timestamp_elem}") + + xpath_expressions.each { |xpath| + xpath_values = xmldoc.retrieve_elements("#{root_elem}[ID=#{oid}]/#{xpath}") + + if ( xpath_values.nil? ) + hash[xpath] = [] + else + hash[xpath] = timestamps.zip(xpath_values) + end + } + + return hash + end +end diff --git a/src/oca/ruby/opennebula/xml_element.rb b/src/oca/ruby/opennebula/xml_element.rb new file mode 100644 index 0000000000..0d4f966e84 --- /dev/null +++ b/src/oca/ruby/opennebula/xml_element.rb @@ -0,0 +1,427 @@ +# -------------------------------------------------------------------------- # +# 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 + # 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 a text element from the XML description of the PoolElement. + # + # @param [String] key Xpath expression + # + # @return [String, nil] If a text element is found, the element's + # text value. Otherwise, an empty string or nil, depending + # on the backend + # + # @example + # vm['VID'] # gets VM id + # vm['HISTORY/HOSTNAME'] # get the hostname from the history + def [](key) + if NOKOGIRI + element=@xml.xpath(key.to_s) + + return nil if element.size == 0 + else + element=@xml.elements[key.to_s] + + return "" if element && !element.has_text? + end + + element.text if element + end + + # Delete an element from the xml + # xpath::_String_ xpath expression that selects the elemnts to be deleted + def delete_element(xpath) + if NOKOGIRI + @xml.xpath(xpath.to_s).remove + else + @xml.delete_element(xpath.to_s) + end + end + + # Add a new element to the xml + # xpath::_String_ xpath xpression where the elemente will be added + # elems::_Hash_ Hash containing the pairs key-value to be included + # Examples: + # add_element('VM', 'NEW_ITEM' => 'NEW_VALUE') + # NEW_VALUE... + # + # add_element('VM/TEMPLATE', 'V1' => {'X1' => 'A1', 'Y2' => 'A2'}) + # + 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