1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-08 21:17:43 +03:00

Feature #1112: Clusters are coming back into fashion this season

This commit is contained in:
Carlos Martín 2012-02-24 15:53:53 +01:00
parent f4743b6077
commit 4e2b33fa23
26 changed files with 1312 additions and 8 deletions

View File

@ -57,6 +57,7 @@ main_env.Append(LIBPATH=[
cwd+'/src/log',
cwd+'/src/sql',
cwd+'/src/host',
cwd+'/src/cluster',
cwd+'/src/datastore',
cwd+'/src/group',
cwd+'/src/mad',
@ -188,6 +189,7 @@ build_scripts=[
'src/common/SConstruct',
'src/template/SConstruct',
'src/host/SConstruct',
'src/cluster/SConstruct',
'src/datastore/SConstruct',
'src/group/SConstruct',
'src/mad/SConstruct',
@ -238,6 +240,7 @@ if testing=='yes':
'src/authm/test/SConstruct',
'src/common/test/SConstruct',
'src/host/test/SConstruct',
'src/cluster/test/SConstruct',
'src/datastore/test/SConstruct',
'src/group/test/SConstruct',
'src/image/test/SConstruct',

137
include/Cluster.h Normal file
View File

@ -0,0 +1,137 @@
/* ------------------------------------------------------------------------ */
/* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------*/
#ifndef CLUSTER_H_
#define CLUSTER_H_
#include "PoolSQL.h"
#include "ObjectCollection.h"
using namespace std;
/**
* The Cluster class.
*/
class Cluster : public PoolObjectSQL, ObjectCollection
{
public:
/**
* Function to print the Cluster object into a string in XML format
* @param xml the resulting XML string
* @return a reference to the generated string
*/
string& to_xml(string& xml) const;
/**
* Rebuilds the object from an xml formatted string
* @param xml_str The xml-formatted string
*
* @return 0 on success, -1 otherwise
*/
int from_xml(const string &xml_str);
/**
* Adds this user's ID to the set.
* @param id of the user to be added to the cluster
* @return 0 on success
*/
int add_host(int id)
{
return add_collection_id(id);
}
/**
* Deletes this users's ID from the set.
* @param id of the user to be deleted from the cluster
* @return 0 on success
*/
int del_host(int id)
{
return del_collection_id(id);
}
private:
// -------------------------------------------------------------------------
// Friends
// -------------------------------------------------------------------------
friend class ClusterPool;
// *************************************************************************
// Constructor
// *************************************************************************
Cluster(int id, const string& name):
PoolObjectSQL(id,CLUSTER,name,-1,-1,"","",table),
ObjectCollection("HOSTS"){};
virtual ~Cluster(){};
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************
static const char * db_names;
static const char * db_bootstrap;
static const char * table;
/**
* Execute an INSERT or REPLACE Sql query.
* @param db The SQL DB
* @param replace Execute an INSERT or a REPLACE
* @param error_str Returns the error reason, if any
* @return 0 one success
*/
int insert_replace(SqlDB *db, bool replace, string& error_str);
/**
* Bootstraps the database table(s) associated to the Cluster
* @return 0 on success
*/
static int bootstrap(SqlDB * db)
{
ostringstream oss(Cluster::db_bootstrap);
return db->exec(oss);
};
/**
* Writes the Cluster in the database.
* @param db pointer to the db
* @return 0 on success
*/
int insert(SqlDB *db, string& error_str)
{
return insert_replace(db, false, error_str);
}
/**
* Writes/updates the Cluster's data fields in the database.
* @param db pointer to the db
* @return 0 on success
*/
int update(SqlDB *db)
{
string error_str;
return insert_replace(db, true, error_str);
}
};
#endif /*CLUSTER_H_*/

158
include/ClusterPool.h Normal file
View File

@ -0,0 +1,158 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef CLUSTER_POOL_H_
#define CLUSTER_POOL_H_
#include "Cluster.h"
#include "SqlDB.h"
using namespace std;
class ClusterPool : public PoolSQL
{
public:
ClusterPool(SqlDB * db);
~ClusterPool(){};
/* ---------------------------------------------------------------------- */
/* Constants for DB management */
/* ---------------------------------------------------------------------- */
/**
* Name for the default cluster
*/
static const string DEFAULT_CLUSTER_NAME;
/**
* Identifier for the default cluster
*/
static const int DEFAULT_CLUSTER_ID;
/* ---------------------------------------------------------------------- */
/* Methods for DB management */
/* ---------------------------------------------------------------------- */
/**
* Allocates a new cluster, writting it in the pool database. No memory is
* allocated for the object.
* @param name Cluster name
* @param oid the id assigned to the Cluster
* @param error_str Returns the error reason, if any
*
* @return the oid assigned to the object, -1 in case of failure
*/
int allocate(string name,
int * oid,
string& error_str);
/**
* Function to get a cluster from the pool, if the object is not in memory
* it is loaded from the DB
* @param oid cluster unique id
* @param lock locks the cluster mutex
* @return a pointer to the cluster, 0 if the cluster could not be loaded
*/
Cluster * get(int oid, bool lock)
{
return static_cast<Cluster *>(PoolSQL::get(oid,lock));
};
/**
* Gets an object from the pool (if needed the object is loaded from the
* database).
* @param name of the object
* @param lock locks the object if true
*
* @return a pointer to the object, 0 in case of failure
*/
Cluster * get(const string& name, bool lock)
{
// The owner is set to -1, because it is not used in the key() method
return static_cast<Cluster *>(PoolSQL::get(name,-1,lock));
};
/**
* Generate an index key for the object
* @param name of the object
* @param uid owner of the object, only used if needed
*
* @return the key, a string
*/
string key(const string& name, int uid)
{
// Name is enough key because Clusters can't repeat names.
return name;
};
/** Update a particular Cluster
* @param user pointer to Cluster
* @return 0 on success
*/
int update(Cluster * cluster)
{
return cluster->update(db);
};
/**
* Drops the Cluster from the data base. The object mutex SHOULD be
* locked.
* @param objsql a pointer to a Cluster object
* @param error_msg Error reason, if any
* @return 0 on success,
* -1 DB error,
* -2 object is a system cluster (ID < 100)
* -3 Cluster's User IDs set is not empty
*/
int drop(PoolObjectSQL * objsql, string& error_msg);
/**
* Bootstraps the database table(s) associated to the Cluster pool
* @return 0 on success
*/
static int bootstrap(SqlDB * _db)
{
return Cluster::bootstrap(_db);
};
/**
* Dumps the Cluster pool in XML format. A filter can be also added to the
* query
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where)
{
return PoolSQL::dump(oss, "CLUSTER_POOL", Cluster::table, where);
};
private:
/**
* Factory method to produce objects
* @return a pointer to the new object
*/
PoolObjectSQL * create()
{
return new Cluster(-1,"");
};
};
#endif /*CLUSTER_POOL_H_*/

140
include/ClusterPoolOld.h Normal file
View File

@ -0,0 +1,140 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef CLUSTER_POOL_H_
#define CLUSTER_POOL_H_
#include <string>
#include <sstream>
#include <map>
#include "SqlDB.h"
using namespace std;
/**
* A cluster helper class. It is not a normal PoolSQL,
* but a series of static methods related to clusters.
*/
class ClusterPool
{
public:
/**
* Cluster name for the default cluster
*/
static const string DEFAULT_CLUSTER_NAME;
private:
// -------------------------------------------------------------------------
// Friends
// -------------------------------------------------------------------------
friend class HostPool;
/* ---------------------------------------------------------------------- */
/* Attributes */
/* ---------------------------------------------------------------------- */
/**
* This map stores the clusters
*/
map<int, string> cluster_names;
/* ---------------------------------------------------------------------- */
/* Methods for cluster management */
/* ---------------------------------------------------------------------- */
/**
* Returns true if the clid is an id for an existing cluster
* @param clid ID of the cluster
*
* @return true if the clid is an id for an existing cluster
*/
bool exists(int clid)
{
return cluster_names.count(clid) > 0;
};
/**
* Allocates a new cluster in the pool
* @param clid the id assigned to the cluster
* @return the id assigned to the cluster or -1 in case of failure
*/
int allocate(int * clid, string name, SqlDB *db, string& error_str);
/**
* Returns the xml representation of the given cluster
* @param clid ID of the cluster
*
* @return the xml representation of the given cluster
*/
string info(int clid);
/**
* Removes the given cluster from the pool and the DB
* @param clid ID of the cluster
*
* @return 0 on success
*/
int drop(int clid, SqlDB *db);
/**
* Dumps the cluster pool in XML format.
* @param oss the output stream to dump the pool contents
*
* @return 0 on success
*/
int dump(ostringstream& oss);
/**
* Bootstraps the database table(s) associated to the Cluster
*/
static void bootstrap(SqlDB * db)
{
ostringstream oss(ClusterPool::db_bootstrap);
db->exec(oss);
};
/**
* Function to insert new Cluster in the pool
* @param oid the id assigned to the Cluster
* @param name the Cluster's name
* @return 0 on success, -1 in case of failure
*/
int insert (int oid, string name, SqlDB *db);
/**
* Formats as XML the given id and name.
* @param oss the output stream to dump the pool contents
*
* @return 0 on success
*/
void dump_cluster(ostringstream& oss, int id, string name);
/* ---------------------------------------------------------------------- */
/* DB manipulation */
/* ---------------------------------------------------------------------- */
static const char * db_names;
static const char * db_bootstrap;
static const char * table;
};
#endif /*CLUSTER_POOL_H_*/

View File

@ -28,6 +28,7 @@
#include "VMTemplatePool.h"
#include "GroupPool.h"
#include "DatastorePool.h"
#include "ClusterPool.h"
#include "VirtualMachineManager.h"
#include "LifeCycleManager.h"
@ -97,6 +98,11 @@ public:
return dspool;
};
ClusterPool * get_clpool()
{
return clpool;
};
// --------------------------------------------------------------
// Manager Accessors
// --------------------------------------------------------------
@ -260,8 +266,8 @@ private:
// -----------------------------------------------------------------------
Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0),
upool(0),ipool(0),gpool(0),tpool(0),dspool(0),lcm(0),vmm(0),im(0),tm(0),
dm(0),rm(0),hm(0),authm(0),aclm(0),imagem(0)
upool(0),ipool(0),gpool(0),tpool(0),dspool(0),clpool(0),
lcm(0),vmm(0),im(0),tm(0),dm(0),rm(0),hm(0),authm(0),aclm(0),imagem(0)
{
const char * nl = getenv("ONE_LOCATION");
@ -333,6 +339,11 @@ private:
{
delete dspool;
}
if ( clpool != 0)
{
delete clpool;
}
if ( vmm != 0)
{
@ -433,6 +444,7 @@ private:
GroupPool * gpool;
VMTemplatePool * tpool;
DatastorePool * dspool;
ClusterPool * clpool;
// ---------------------------------------------------------------
// Nebula Managers

View File

@ -57,7 +57,8 @@ public:
TEMPLATE = 0x0000020000000000LL,
GROUP = 0x0000040000000000LL,
ACL = 0x0000080000000000LL,
DATASTORE = 0x0000100000000000LL
DATASTORE = 0x0000100000000000LL,
CLUSTER = 0x0000200000000000LL
};
static string type_to_str(ObjectType ob)
@ -73,6 +74,7 @@ public:
case GROUP: return "GROUP" ; break;
case ACL: return "ACL" ; break;
case DATASTORE: return "DATASTORE" ; break;
case CLUSTER: return "CLUSTER" ; break;
default: return "";
}
};

View File

@ -309,6 +309,32 @@ public:
RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class ClusterAllocate: public RequestManagerAllocate
{
public:
ClusterAllocate():
RequestManagerAllocate("ClusterAllocate",
"Allocates a new cluster",
"A:ss",
false)
{
Nebula& nd = Nebula::instance();
pool = nd.get_clpool();
auth_object = PoolObjectSQL::CLUSTER;
};
~ClusterAllocate(){};
int pool_allocate(xmlrpc_c::paramList const& _paramList,
Template * tmpl,
int& id,
string& error_str,
RequestAttributes& att);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -140,7 +140,6 @@ public:
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class GroupDelete: public RequestManagerDelete
{
public:
@ -196,6 +195,24 @@ public:
~DatastoreDelete(){};
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class ClusterDelete: public RequestManagerDelete
{
public:
ClusterDelete():
RequestManagerDelete("ClusterDelete", "Deletes a cluster")
{
Nebula& nd = Nebula::instance();
pool = nd.get_clpool();
auth_object = PoolObjectSQL::CLUSTER;
auth_op = AuthRequest::ADMIN;
};
~ClusterDelete(){};
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -162,7 +162,6 @@ public:
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class GroupInfo: public RequestManagerInfo
{
public:
@ -214,6 +213,24 @@ public:
~DatastoreInfo(){};
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class ClusterInfo: public RequestManagerInfo
{
public:
ClusterInfo():
RequestManagerInfo("ClusterInfo",
"Returns cluster information")
{
Nebula& nd = Nebula::instance();
pool = nd.get_clpool();
auth_object = PoolObjectSQL::CLUSTER;
};
~ClusterInfo(){};
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -248,6 +248,30 @@ public:
xmlrpc_c::paramList const& paramList, RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class ClusterPoolInfo: public RequestManagerPoolInfoFilter
{
public:
ClusterPoolInfo():
RequestManagerPoolInfoFilter("ClusterPoolInfo",
"Returns the cluster pool",
"A:s")
{
Nebula& nd = Nebula::instance();
pool = nd.get_clpool();
auth_object = PoolObjectSQL::CLUSTER;
};
~ClusterPoolInfo(){};
/* -------------------------------------------------------------------- */
void request_execute(
xmlrpc_c::paramList const& paramList, RequestAttributes& att);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -563,6 +563,7 @@ BIN_FILES="src/nebula/oned \
src/cli/onetemplate \
src/cli/oneacl \
src/cli/onedatastore \
src/cli/onecluster \
src/onedb/onedb \
src/authm_mad/remotes/quota/onequota \
src/mad/utils/tty_expect \
@ -963,6 +964,8 @@ RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/OpenNebula/Host.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"
#-------------------------------------------------------------------------------
@ -1068,7 +1071,8 @@ ONE_CLI_LIB_FILES="src/cli/one_helper/onegroup_helper.rb \
src/cli/one_helper/onevm_helper.rb \
src/cli/one_helper/onevnet_helper.rb \
src/cli/one_helper/oneacl_helper.rb \
src/cli/one_helper/onedatastore_helper.rb"
src/cli/one_helper/onedatastore_helper.rb \
src/cli/one_helper/onecluster_helper.rb"
CLI_BIN_FILES="src/cli/onevm \
src/cli/onehost \
@ -1078,7 +1082,8 @@ CLI_BIN_FILES="src/cli/onevm \
src/cli/onetemplate \
src/cli/onegroup \
src/cli/oneacl \
src/cli/onedatastore"
src/cli/onedatastore \
src/cli/onecluster"
CLI_CONF_FILES="src/cli/etc/onegroup.yaml \
src/cli/etc/onehost.yaml \
@ -1088,7 +1093,8 @@ CLI_CONF_FILES="src/cli/etc/onegroup.yaml \
src/cli/etc/onevm.yaml \
src/cli/etc/onevnet.yaml \
src/cli/etc/oneacl.yaml \
src/cli/etc/onedatastore.yaml"
src/cli/etc/onedatastore.yaml \
src/cli/etc/onecluster.yaml"
ETC_CLIENT_FILES="src/cli/etc/group.default"
@ -1423,6 +1429,7 @@ MAN_FILES="share/man/oneauth.1.gz \
share/man/onegroup.1.gz \
share/man/onedb.1.gz \
share/man/onedatastore.1.gz \
share/man/onecluster.1.gz \
share/man/econe-describe-images.1.gz \
share/man/econe-describe-instances.1.gz \
share/man/econe-register.1.gz \

View File

@ -0,0 +1,14 @@
---
:ID:
:desc: ONE identifier for the Cluster
:size: 4
:NAME:
:desc: Name of the Cluster
:size: 15
:left: true
:default:
- :ID
- :NAME

View File

@ -0,0 +1,76 @@
# -------------------------------------------------------------------------- #
# 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 'one_helper'
class OneClusterHelper < OpenNebulaHelper::OneHelper
def self.rname
"CLUSTER"
end
def self.conf_file
"onecluster.yaml"
end
def format_pool(options)
config_file = self.class.table_conf
table = CLIHelper::ShowTable.new(config_file, self) do
column :ID, "ONE identifier for the Cluster", :size=>4 do |d|
d["ID"]
end
column :NAME, "Name of the Cluster", :left, :size=>15 do |d|
d["NAME"]
end
default :ID, :NAME
end
table
end
private
def factory(id=nil)
if id
OpenNebula::Cluster.new_with_id(id, @client)
else
xml=OpenNebula::Cluster.build_xml
OpenNebula::Cluster.new(xml, @client)
end
end
def factory_pool(user_flag=-2)
OpenNebula::ClusterPool.new(@client)
end
def format_resource(cluster)
str="%-15s: %-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
CLIHelper.print_header(str_h1 % "HOSTS", false)
CLIHelper.print_header("%-15s" % ["ID"])
cluster.host_ids.each do |id|
puts "%-15s" % [id]
end
end
end

100
src/cli/onecluster Executable file
View File

@ -0,0 +1,100 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << RUBY_LIB_LOCATION+"/cli"
require 'command_parser'
require 'one_helper/onecluster_helper'
cmd=CommandParser::CmdParser.new(ARGV) do
usage "`onecluster` <command> [<args>] [<options>]"
version OpenNebulaHelper::ONE_VERSION
helper = OneClusterHelper.new
########################################################################
# Global Options
########################################################################
set :option, CommandParser::OPTIONS
list_options = CLIHelper::OPTIONS
list_options << OpenNebulaHelper::XML
list_options << OpenNebulaHelper::NUMERIC
########################################################################
# Formatters for arguments
########################################################################
set :format, :clusterid, OneClusterHelper.to_id_desc do |arg|
helper.to_id(arg)
end
set :format, :clusterid_list, OneClusterHelper.list_to_id_desc do |arg|
helper.list_to_id(arg)
end
########################################################################
# Commands
########################################################################
create_desc = <<-EOT.unindent
Creates a new Cluster
EOT
command :create, create_desc, :name do
helper.create_resource(options) do |cluster|
cluster.allocate(args[0])
end
end
delete_desc = <<-EOT.unindent
Deletes the given Cluster
EOT
command :delete, delete_desc, [:range, :clusterid_list] do
helper.perform_actions(args[0],options,"deleted") do |obj|
obj.delete
end
end
list_desc = <<-EOT.unindent
Lists Clusters in the pool
EOT
command :list, list_desc, :options=>list_options do
helper.list_pool(options)
end
show_desc = <<-EOT.unindent
Shows information for the given Cluster
EOT
command :show, show_desc,[:clusterid, nil], :options=>OpenNebulaHelper::XML do
cluster = args[0] || OpenNebula::Cluster::SELF
helper.show_resource(cluster,options)
end
end

191
src/cluster/Cluster.cc Normal file
View File

@ -0,0 +1,191 @@
/* ------------------------------------------------------------------------ */
/* 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 <limits.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include "Cluster.h"
#include "GroupPool.h"
const char * Cluster::table = "cluster_pool";
const char * Cluster::db_names =
"oid, name, body, uid, gid, owner_u, group_u, other_u";
const char * Cluster::db_bootstrap = "CREATE TABLE IF NOT EXISTS 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))";
/* ************************************************************************ */
/* Cluster :: Database Access Functions */
/* ************************************************************************ */
int Cluster::insert_replace(SqlDB *db, bool replace, string& error_str)
{
ostringstream oss;
int rc;
string xml_body;
char * sql_name;
char * sql_xml;
// Set the owner and group to oneadmin
set_user(0, "");
set_group(GroupPool::ONEADMIN_ID, GroupPool::ONEADMIN_NAME);
// Update the Cluster
sql_name = db->escape_str(name.c_str());
if ( sql_name == 0 )
{
goto error_name;
}
sql_xml = db->escape_str(to_xml(xml_body).c_str());
if ( sql_xml == 0 )
{
goto error_body;
}
if ( validate_xml(sql_xml) != 0 )
{
goto error_xml;
}
if ( replace )
{
oss << "REPLACE";
}
else
{
oss << "INSERT";
}
// Construct the SQL statement to Insert or Replace
oss <<" INTO "<<table <<" ("<< db_names <<") VALUES ("
<< oid << ","
<< "'" << sql_name << "',"
<< "'" << sql_xml << "',"
<< uid << ","
<< gid << ","
<< owner_u << ","
<< group_u << ","
<< other_u << ")";
rc = db->exec(oss);
db->free_str(sql_name);
db->free_str(sql_xml);
return rc;
error_xml:
db->free_str(sql_name);
db->free_str(sql_xml);
error_str = "Error transforming the Cluster to XML.";
goto error_common;
error_body:
db->free_str(sql_name);
goto error_generic;
error_name:
goto error_generic;
error_generic:
error_str = "Error inserting Cluster in DB.";
error_common:
return -1;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
string& Cluster::to_xml(string& xml) const
{
ostringstream oss;
string collection_xml;
ObjectCollection::to_xml(collection_xml);
oss <<
"<CLUSTER>" <<
"<ID>" << oid << "</ID>" <<
"<NAME>" << name << "</NAME>" <<
collection_xml <<
"</CLUSTER>";
xml = oss.str();
return xml;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Cluster::from_xml(const string& xml)
{
int rc = 0;
vector<xmlNodePtr> content;
// Initialize the internal XML object
update_from_str(xml);
// Get class base attributes
rc += xpath(oid, "/CLUSTER/ID", -1);
rc += xpath(name,"/CLUSTER/NAME", "not_found");
// Set oneadmin as the owner
set_user(0,"");
// Set the Cluster ID as the cluster it belongs to
set_group(oid, name);
// Get associated classes
ObjectXML::get_nodes("/CLUSTER/HOSTS", content);
if (content.empty())
{
return -1;
}
// Set of IDs
rc += ObjectCollection::from_xml_node(content[0]);
ObjectXML::free_nodes(content);
if (rc != 0)
{
return -1;
}
return 0;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

154
src/cluster/ClusterPool.cc Normal file
View File

@ -0,0 +1,154 @@
/* -------------------------------------------------------------------------- */
/* 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 "ClusterPool.h"
#include "Nebula.h"
#include "NebulaLog.h"
#include <stdexcept>
/* -------------------------------------------------------------------------- */
/* There is a default cluster boostrapped by the core: */
/* The first 100 cluster IDs are reserved for system clusters. */
/* Regular ones start from ID 100 */
/* -------------------------------------------------------------------------- */
const string ClusterPool::DEFAULT_CLUSTER_NAME = "default";
const int ClusterPool::DEFAULT_CLUSTER_ID = 0;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
ClusterPool::ClusterPool(SqlDB * db):PoolSQL(db, Cluster::table)
{
ostringstream oss;
string error_str;
if (get_lastOID() == -1) //lastOID is set in PoolSQL::init_cb
{
int rc;
Cluster * cluster;
cluster = new Cluster(DEFAULT_CLUSTER_ID, DEFAULT_CLUSTER_NAME);
rc = PoolSQL::allocate(cluster, error_str);
if( rc < 0 )
{
goto error_bootstrap;
}
set_update_lastOID(99);
}
return;
error_bootstrap:
oss << "Error trying to create default cluster: " << error_str;
NebulaLog::log("CLUSTER",Log::ERROR,oss);
throw runtime_error(oss.str());
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ClusterPool::allocate(string name, int * oid, string& error_str)
{
Cluster * cluster;
ostringstream oss;
if ( name.empty() )
{
goto error_name;
}
if ( name.length() > 128 )
{
goto error_name_length;
}
// Check for duplicates
cluster = get(name, false);
if( cluster != 0 )
{
goto error_duplicated;
}
// Build a new Cluster object
cluster = new Cluster(-1, name);
// Insert the Object in the pool
*oid = PoolSQL::allocate(cluster, error_str);
return *oid;
error_name:
oss << "NAME cannot be empty.";
goto error_common;
error_name_length:
oss << "NAME is too long; max length is 128 chars.";
goto error_common;
error_duplicated:
oss << "NAME is already taken by CLUSTER " << cluster->get_oid() << ".";
error_common:
*oid = -1;
error_str = oss.str();
return *oid;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ClusterPool::drop(PoolObjectSQL * objsql, string& error_msg)
{
Cluster * cluster = static_cast<Cluster*>(objsql);
int rc;
// Return error if the cluster is a default one.
if( cluster->get_oid() < 100 )
{
error_msg = "System Clusters (ID < 100) cannot be deleted.";
NebulaLog::log("CLUSTER", Log::ERROR, error_msg);
return -2;
}
if( cluster->get_collection_size() > 0 )
{
ostringstream oss;
oss << "Cluster " << cluster->get_oid() << " is not empty.";
error_msg = oss.str();
NebulaLog::log("CLUSTER", Log::ERROR, error_msg);
return -3;
}
rc = cluster->drop(db);
if( rc != 0 )
{
error_msg = "SQL DB error";
rc = -1;
}
return rc;
}

30
src/cluster/SConstruct Normal file
View File

@ -0,0 +1,30 @@
# SConstruct for src/group
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
Import('env')
lib_name='nebula_cluster'
# Sources to generate the library
source_files=[
'ClusterPool.cc',
'Cluster.cc'
]
# Build library
env.StaticLibrary(lib_name, source_files)

View File

@ -249,6 +249,7 @@ void Nebula::start()
rc += VMTemplatePool::bootstrap(db);
rc += AclManager::bootstrap(db);
rc += DatastorePool::bootstrap(db);
rc += ClusterPool::bootstrap(db);
// Create the versioning table only if bootstrap went well
if ( rc == 0 )
@ -314,6 +315,8 @@ void Nebula::start()
tpool = new VMTemplatePool(db);
dspool = new DatastorePool(db);
clpool = new ClusterPool(db);
}
catch (exception&)
{

View File

@ -50,6 +50,7 @@ env.Prepend(LIBS=[
'nebula_image',
'nebula_pool',
'nebula_host',
'nebula_cluster',
'nebula_vnm',
'nebula_vm',
'nebula_vmtemplate',

View File

@ -44,6 +44,8 @@ require 'OpenNebula/Acl'
require 'OpenNebula/AclPool'
require 'OpenNebula/Datastore'
require 'OpenNebula/DatastorePool'
require 'OpenNebula/Cluster'
require 'OpenNebula/ClusterPool'
module OpenNebula

View File

@ -0,0 +1,99 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'OpenNebula/Pool'
module OpenNebula
class Cluster < PoolElement
#######################################################################
# Constants and Class Methods
#######################################################################
CLUSTER_METHODS = {
:info => "cluster.info",
:allocate => "cluster.allocate",
:delete => "cluster.delete"
}
# Creates a Cluster description with just its identifier
# this method should be used to create plain Cluster objects.
# +id+ the id of the host
#
# Example:
# cluster = Cluster.new(Cluster.build_xml(3),rpc_client)
#
def Cluster.build_xml(pe_id=nil)
if pe_id
cluster_xml = "<CLUSTER><ID>#{pe_id}</ID></CLUSTER>"
else
cluster_xml = "<CLUSTER></CLUSTER>"
end
XMLElement.build_xml(cluster_xml,'CLUSTER')
end
# Class constructor
def initialize(xml, client)
super(xml,client)
end
#######################################################################
# XML-RPC Methods for the Cluster Object
#######################################################################
# Retrieves the information of the given Cluster.
def info()
super(CLUSTER_METHODS[:info], 'CLUSTER')
end
# Allocates a new Cluster in OpenNebula
#
# +clustername+ A string containing the name of the Cluster.
def allocate(clustername)
super(CLUSTER_METHODS[:allocate], clustername)
end
# Deletes the Cluster
def delete()
super(CLUSTER_METHODS[:delete])
end
# ---------------------------------------------------------------------
# Helpers to get information
# ---------------------------------------------------------------------
# Returns whether or not the host with id 'uid' is part of this group
def contains(uid)
#This doesn't work in ruby 1.8.5
#return self["HOSTS/ID[.=#{uid}]"] != nil
id_array = retrieve_elements('HOSTS/ID')
return id_array != nil && id_array.include?(uid.to_s)
end
# Returns an array with the numeric host ids
def host_ids
array = Array.new
self.each("HOSTS/ID") do |id|
array << id.text.to_i
end
return array
end
end
end

View File

@ -0,0 +1,53 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'OpenNebula/Pool'
module OpenNebula
class ClusterPool < Pool
#######################################################################
# Constants and Class attribute accessors
#######################################################################
CLUSTER_POOL_METHODS = {
:info => "clusterpool.info"
}
#######################################################################
# Class constructor & Pool Methods
#######################################################################
# +client+ a Client object that represents a XML-RPC connection
def initialize(client)
super('CLUSTER_POOL','CLUSTER',client)
end
# Factory method to create Cluster objects
def factory(element_xml)
OpenNebula::Cluster.new(element_xml,@client)
end
#######################################################################
# XML-RPC Methods for the Cluster Object
#######################################################################
# Retrieves all the Clusters in the pool.
def info()
super(CLUSTER_POOL_METHODS[:info])
end
end
end

View File

@ -179,6 +179,8 @@ string Request::object_name(PoolObjectSQL::ObjectType ob)
return "ACL";
case PoolObjectSQL::DATASTORE:
return "datastore";
case PoolObjectSQL::CLUSTER:
return "cluster";
default:
return "-";
}

View File

@ -264,6 +264,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr host_allocate(new HostAllocate());
xmlrpc_c::methodPtr user_allocate(new UserAllocate());
xmlrpc_c::methodPtr datastore_allocate(new DatastoreAllocate());
xmlrpc_c::methodPtr cluster_allocate(new ClusterAllocate());
// Delete Methods
xmlrpc_c::methodPtr host_delete(new HostDelete());
@ -273,6 +274,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr user_delete(new UserDelete());
xmlrpc_c::methodPtr image_delete(new ImageDelete());
xmlrpc_c::methodPtr datastore_delete(new DatastoreDelete());
xmlrpc_c::methodPtr cluster_delete(new ClusterDelete());
// Info Methods
xmlrpc_c::methodPtr vm_info(new VirtualMachineInfo());
@ -283,6 +285,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr user_info(new UserInfo());
xmlrpc_c::methodPtr image_info(new ImageInfo());
xmlrpc_c::methodPtr datastore_info(new DatastoreInfo());
xmlrpc_c::methodPtr cluster_info(new ClusterInfo());
// PoolInfo Methods
xmlrpc_c::methodPtr hostpool_info(new HostPoolInfo());
@ -293,6 +296,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr template_pool_info(new TemplatePoolInfo());
xmlrpc_c::methodPtr vnpool_info(new VirtualNetworkPoolInfo());
xmlrpc_c::methodPtr imagepool_info(new ImagePoolInfo());
xmlrpc_c::methodPtr clusterpool_info(new ClusterPoolInfo());
// Host Methods
xmlrpc_c::methodPtr host_enable(new HostEnable());
@ -409,6 +413,12 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.datastorepool.info",datastorepool_info);
/* Cluster related 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.clusterpool.info",clusterpool_info);
};
/* -------------------------------------------------------------------------- */

View File

@ -386,3 +386,19 @@ int DatastoreAllocate::pool_allocate(
return dspool->allocate(ds_tmpl, &id, error_str);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ClusterAllocate::pool_allocate(xmlrpc_c::paramList const& paramList,
Template * tmpl,
int& id,
string& error_str,
RequestAttributes& att)
{
string name = xmlrpc_c::value_string(paramList.getString(1));
ClusterPool * clpool = static_cast<ClusterPool *>(pool);
return clpool->allocate(name, &id, error_str);
}

View File

@ -131,6 +131,16 @@ void DatastorePoolInfo::request_execute(
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void ClusterPoolInfo::request_execute(
xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
dump(att, ALL, -1, -1, "", "");
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void RequestManagerPoolInfoFilter::dump(
RequestAttributes& att,
int filter_flag,