From f6615f66d241f931550174efe2d319c395b8296b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Fri, 24 Feb 2012 18:55:21 +0100 Subject: [PATCH] Feature #1112: New method & command onecluster addhost --- include/RequestManagerCluster.h | 86 ++++++++++++++ src/cli/onecluster | 11 ++ src/oca/ruby/OpenNebula/Cluster.rb | 14 ++- src/rm/RequestManager.cc | 5 + src/rm/RequestManagerCluster.cc | 175 +++++++++++++++++++++++++++++ src/rm/SConstruct | 1 + 6 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 include/RequestManagerCluster.h create mode 100644 src/rm/RequestManagerCluster.cc diff --git a/include/RequestManagerCluster.h b/include/RequestManagerCluster.h new file mode 100644 index 0000000000..10c2f38977 --- /dev/null +++ b/include/RequestManagerCluster.h @@ -0,0 +1,86 @@ +/* -------------------------------------------------------------------------- */ +/* 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_CLUSTER_H +#define REQUEST_MANAGER_CLUSTER_H + +#include "Request.h" +#include "Nebula.h" + +using namespace std; + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +class RequestManagerCluster: public Request +{ +protected: + RequestManagerCluster(const string& method_name, + const string& help, + const string& params) + :Request(method_name,params,help) + { + Nebula& nd = Nebula::instance(); + clpool = nd.get_clpool(); + hpool = nd.get_hpool(); + + auth_object = PoolObjectSQL::CLUSTER; + auth_op = AuthRequest::MANAGE; + }; + + ~RequestManagerCluster(){}; + + /* --------------------------------------------------------------------- */ + + ClusterPool * clpool; + HostPool * hpool; + + /* --------------------------------------------------------------------- */ + + virtual void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att) = 0; + + int get_info (PoolSQL * pool, + int id, + PoolObjectSQL::ObjectType type, + RequestAttributes& att, + PoolObjectAuth& perms, + string& name); +}; + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +class ClusterAddHost : public RequestManagerCluster +{ +public: + ClusterAddHost(): + RequestManagerCluster("ClusterAddHost", + "Adds a host to the cluster", + "A:sii"){}; + + ~ClusterAddHost(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +#endif diff --git a/src/cli/onecluster b/src/cli/onecluster index 3af1a1aa8e..7c04cc566d 100755 --- a/src/cli/onecluster +++ b/src/cli/onecluster @@ -96,4 +96,15 @@ cmd=CommandParser::CmdParser.new(ARGV) do helper.show_resource(args[0],options) end + addhost_desc = <<-EOT.unindent + Adds a Host to the given Cluster + EOT + + # TODO: allow the second param to be [:range, :hostid_list] + command :addhost, addhost_desc,:clusterid, :hostid do + helper.perform_actions(args[0],options,"updated") do |cluster| + cluster.addhost(args[1].to_i) + end + end + end diff --git a/src/oca/ruby/OpenNebula/Cluster.rb b/src/oca/ruby/OpenNebula/Cluster.rb index 699445e117..8cb0d1793f 100644 --- a/src/oca/ruby/OpenNebula/Cluster.rb +++ b/src/oca/ruby/OpenNebula/Cluster.rb @@ -26,7 +26,8 @@ module OpenNebula CLUSTER_METHODS = { :info => "cluster.info", :allocate => "cluster.allocate", - :delete => "cluster.delete" + :delete => "cluster.delete", + :addhost => "cluster.addhost" } # Creates a Cluster description with just its identifier @@ -72,6 +73,17 @@ module OpenNebula super(CLUSTER_METHODS[:delete]) end + # Adds a Host to this Cluster + # @param hid [Integer] Host ID + def addhost(hid) + return Error.new('ID not defined') if !@pe_id + + rc = @client.call(CLUSTER_METHODS[:addhost], @pe_id, hid) + rc = nil if !OpenNebula.is_error?(rc) + + return rc + end + # --------------------------------------------------------------------- # Helpers to get information # --------------------------------------------------------------------- diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index b73c8723fb..c1085d2263 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -33,6 +33,7 @@ #include "RequestManagerImage.h" #include "RequestManagerUser.h" #include "RequestManagerAcl.h" +#include "RequestManagerCluster.h" #include #include @@ -324,6 +325,9 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr acl_delrule(new AclDelRule()); xmlrpc_c::methodPtr acl_info(new AclInfo()); + // Cluster Methods + xmlrpc_c::methodPtr cluster_addhost(new ClusterAddHost()); + /* VM related methods */ RequestManagerRegistry.addMethod("one.vm.deploy", vm_deploy); RequestManagerRegistry.addMethod("one.vm.action", vm_action); @@ -417,6 +421,7 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.cluster.allocate",cluster_allocate); RequestManagerRegistry.addMethod("one.cluster.delete", cluster_delete); RequestManagerRegistry.addMethod("one.cluster.info", cluster_info); + RequestManagerRegistry.addMethod("one.cluster.addhost", cluster_addhost); RequestManagerRegistry.addMethod("one.clusterpool.info",clusterpool_info); }; diff --git a/src/rm/RequestManagerCluster.cc b/src/rm/RequestManagerCluster.cc new file mode 100644 index 0000000000..315162d72d --- /dev/null +++ b/src/rm/RequestManagerCluster.cc @@ -0,0 +1,175 @@ +/* -------------------------------------------------------------------------- */ +/* 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 "RequestManagerCluster.h" + +using namespace std; + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +// TODO: same method in RequestManagerChown, should be moved to Request + +int RequestManagerCluster::get_info (PoolSQL * pool, + int id, + PoolObjectSQL::ObjectType type, + RequestAttributes& att, + PoolObjectAuth& perms, + string& name) +{ + PoolObjectSQL * ob; + + if ((ob = pool->get(id,true)) == 0 ) + { + failure_response(NO_EXISTS, get_error(object_name(type), id), att); + return -1; + } + + ob->get_permissions(perms); + + name = ob->get_name(); + + ob->unlock(); + + return 0; +} + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +void ClusterAddHost::request_execute( + xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + int cluster_id = xmlrpc_c::value_int(paramList.getInt(1)); + int host_id = xmlrpc_c::value_int(paramList.getInt(2)); + int old_cluster_id; + + int rc; + + string cluster_name; + string host_name; + + Cluster * cluster; + Host * host; + + PoolObjectAuth c_perms; + PoolObjectAuth h_perms; + + rc = get_info(clpool, cluster_id, PoolObjectSQL::CLUSTER, att, c_perms, cluster_name); + + if ( rc == -1 ) + { + return; + } + + rc = get_info(hpool, host_id, PoolObjectSQL::HOST, att, h_perms, host_name); + + if ( rc == -1 ) + { + return; + } + + if ( att.uid != 0 ) + { + AuthRequest ar(att.uid, att.gid); + + ar.add_auth(auth_op, c_perms); // MANAGE CLUSTER + ar.add_auth(AuthRequest::ADMIN, h_perms); // ADMIN HOST + + if (UserPool::authorize(ar) == -1) + { + failure_response(AUTHORIZATION, + authorization_error(ar.message, att), + att); + + return; + } + } + + // ------------- Add host to new cluster --------------------- + + cluster = clpool->get(cluster_id, true); + + if ( cluster == 0 ) + { + failure_response(NO_EXISTS, + get_error(object_name(PoolObjectSQL::CLUSTER),cluster_id), + att); + return; + } + + cluster->add_host(host_id); + + clpool->update(cluster); + + cluster->unlock(); + + // ------------- Set new cluster id in host --------------------- + + host = hpool->get(host_id, true); + + if ( host == 0 ) + { + failure_response(NO_EXISTS, + get_error(object_name(PoolObjectSQL::HOST), host_id), + att); + + // TODO: rollback + // clpool->get (cluster_id) + // cluster->del_host(host_id); + + return; + } + + old_cluster_id = host->get_cluster_id(); + + if ( old_cluster_id == cluster_id ) + { + host->unlock(); + success_response(cluster_id, att); + return; + } + + host->set_cluster(cluster_id, cluster_name); + + hpool->update(host); + + host->unlock(); + + // ------------- Remove host from old cluster --------------------- + + cluster = clpool->get(old_cluster_id, true); + + if ( cluster == 0 ) + { + // This point should be unreachable. + // The old cluster is not empty (at least has the host_id), + // so it cannot be deleted + success_response(cluster_id, att); + return; + } + + cluster->del_host(host_id); + + clpool->update(cluster); + + cluster->unlock(); + + success_response(cluster_id, att); + + return; +} diff --git a/src/rm/SConstruct b/src/rm/SConstruct index cc692552f9..5c565c5b73 100644 --- a/src/rm/SConstruct +++ b/src/rm/SConstruct @@ -38,6 +38,7 @@ source_files=[ 'RequestManagerChown.cc', 'RequestManagerAcl.cc', 'RequestManagerChmod.cc', + 'RequestManagerCluster.cc' ] # Build library