1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-02-18 17:57:24 +03:00

Merge branch 'master' into bug-4349

This commit is contained in:
Javi Fontan 2016-03-31 17:08:21 +02:00
commit 51aff13b6e
474 changed files with 15430 additions and 11409 deletions

View File

@ -261,17 +261,16 @@ private:
* @return true if any rule grants permission
*/
bool match_rules(
long long user_req,
long long resource_oid_req,
long long resource_gid_req,
long long resource_cid_req,
long long resource_all_req,
long long rights_req,
long long individual_obj_type,
long long group_obj_type,
long long cluster_obj_type,
multimap<long long, AclRule*> &rules);
long long user_req,
long long resource_oid_req,
long long resource_gid_req,
const set<long long>& resource_cid_req,
long long resource_all_req,
long long rights_req,
long long resource_oid_mask,
long long resource_gid_mask,
long long resource_cid_mask,
const multimap<long long, AclRule*>& rules);
/**
* Wrapper for match_rules. It will check if any rules in the temporary
* multimap or in the internal one grants permission.
@ -290,17 +289,16 @@ private:
* @return true if any rule grants permission
*/
bool match_rules_wrapper(
long long user_req,
long long resource_oid_req,
long long resource_gid_req,
long long resource_cid_req,
long long resource_all_req,
long long rights_req,
long long individual_obj_type,
long long group_obj_type,
long long cluster_obj_type,
multimap<long long, AclRule*> &tmp_rules);
long long user_req,
long long resource_oid_req,
long long resource_gid_req,
const set<long long>& resource_cid_req,
long long resource_all_req,
long long rights_req,
long long individual_obj_type,
long long group_obj_type,
long long cluster_obj_type,
const multimap<long long, AclRule*> &tmp_rules);
/**
* Deletes all rules that match the user mask
*

View File

@ -42,7 +42,12 @@ public:
/* Set the action in the set */
void set(T action)
{
action_set += 1 << static_cast<int>(action);
action_set |= 1 << static_cast<int>(action);
};
void clear(T action)
{
action_set &= (~ (1 << static_cast<int>(action)));
};
/**

View File

@ -22,6 +22,8 @@
#include <sstream>
#include <algorithm>
#include "NebulaUtil.h"
using namespace std;
/**
@ -163,8 +165,8 @@ public:
{
string * xml = new string;
*xml = "<" + name() + "><![CDATA[" + attribute_value
+ "]]></"+ name() + ">";
*xml = "<" + name() + ">" + one_util::escape_xml(attribute_value) +
"</"+ name() + ">";
return xml;
}

View File

@ -19,6 +19,7 @@
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/client_simple.hpp>
#include <xmlrpc-c/girerr.hpp>
#include <iostream>
#include <string>
@ -34,19 +35,67 @@ using namespace std;
// http://xmlrpc-c.sourceforge.net/doc/libxmlrpc_client++.html#simple_client
// =============================================================================
//TODO add documentation to the Client methods...
/**
* This class represents the connection with the core and handles the
* xml-rpc calls.
*/
class Client : public xmlrpc_c::clientSimple
class Client
{
public:
//--------------------------------------------------------------------------
// PUBLIC INTERFACE
//--------------------------------------------------------------------------
/**
* Singleton accessor
*/
static Client * client()
{
return _client;
};
/**
* Singleton initializer
*/
static Client * initialize(const std::string& secret,
const std::string& endpoint, size_t message_size, unsigned int tout)
{
if ( _client == 0 )
{
_client = new Client(secret, endpoint, message_size, tout);
}
return _client;
};
size_t get_message_size() const
{
return xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID);
};
/**
* Reads ONE_AUTH from environment or its default location at
* $HOME/.one/one_auth
*/
static int read_oneauth(std::string &secret, std::string& error);
/**
* Performs an xmlrpc call to the initialized server and credentials.
* This method automatically adds the credential argument.
* @param method name
* @param format of the arguments, supported arguments are i:int, s:string
* and b:bool
* @param result to store the xmlrpc call result
* @param ... xmlrpc arguments
*/
void call(const std::string &method, const std::string format,
xmlrpc_c::value * const result, ...);
/**
* Performs a xmlrpc call to the initialized server
* @param method name
* @param plist initialized param list
* @param result of the xmlrpc call
*/
void call(const std::string& method, const xmlrpc_c::paramList& plist,
xmlrpc_c::value * const result);
private:
/**
* Creates a new xml-rpc client with specified options.
*
@ -58,42 +107,15 @@ public:
* @param message_size for XML elements in the client library (in bytes)
* @throws Exception if the authorization options are invalid
*/
Client(const string& secret, const string& endpoint, size_t message_size)
{
set_one_auth(secret);
set_one_endpoint(endpoint);
Client(const string& secret, const string& endpoint, size_t message_size,
unsigned int tout);
xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, message_size);
}
const string& get_oneauth()
{
return one_auth;
}
const string& get_endpoint()
{
return one_endpoint;
}
size_t get_message_size()
{
return xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID);
}
//--------------------------------------------------------------------------
// PRIVATE ATTRIBUTES AND METHODS
//--------------------------------------------------------------------------
private:
string one_auth;
string one_endpoint;
void set_one_auth(string secret);
unsigned int timeout;
void set_one_endpoint(string endpoint);
void read_oneauth(string &secret);
static Client * _client;
};
#endif /*ONECLIENT_H_*/

View File

@ -30,15 +30,6 @@ using namespace std;
class Cluster : public PoolObjectSQL
{
public:
/**
* Returns the DATASTORE_LOCATION for the hosts of the cluster. If not
* defined that in oned.conf is returned.
*
* @param ds_location string to copy the DATASTORE_LOCATION to
* @return DATASTORE_LOCATION
*/
string& get_ds_location(string &ds_location);
// *************************************************************************
// Object Collections (Public)
// *************************************************************************
@ -82,11 +73,10 @@ 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, Datastore::DatastoreType ds_type, string& error_msg);
int add_datastore(int id, string& error_msg);
/**
* Deletes this datastore ID from the set.
@ -213,7 +203,6 @@ private:
// *************************************************************************
// Constructor
// *************************************************************************
Cluster(int id,
const string& name,
ClusterTemplate* cl_template);
@ -223,7 +212,6 @@ private:
// *************************************************************************
// Attributes (Private)
// *************************************************************************
ObjectCollection hosts;
ObjectCollection datastores;
ObjectCollection vnets;
@ -231,13 +219,18 @@ private:
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************
static const char * db_names;
static const char * db_bootstrap;
static const char * table;
static const char * datastore_table;
static const char * datastore_db_names;
static const char * datastore_db_bootstrap;
static const char * network_table;
static const char * network_db_names;
static const char * network_db_bootstrap;
/**
* Execute an INSERT or REPLACE Sql query.
* @param db The SQL DB
@ -253,9 +246,19 @@ private:
*/
static int bootstrap(SqlDB * db)
{
ostringstream oss(Cluster::db_bootstrap);
int rc;
ostringstream oss;
return db->exec(oss);
oss.str(Cluster::db_bootstrap);
rc = db->exec(oss);
oss.str(Cluster::datastore_db_bootstrap);
rc += db->exec(oss);
oss.str(Cluster::network_db_bootstrap);
rc += db->exec(oss);
return rc;
};
/**

View File

@ -44,6 +44,16 @@ public:
*/
static const int NONE_CLUSTER_ID;
/**
* 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 */
/* ---------------------------------------------------------------------- */
@ -136,8 +146,16 @@ public:
limit);
};
/**
* Generates the cluster part of the ACL filter to look for objects. This
* filter is generated for objects that can be part of a cluster
* @param acl_filter stream to write the filter
* @param auth_object to generate the filter for
* @param cids vector of cluster ids
*/
static void cluster_acl_filter(ostringstream& filter,
PoolObjectSQL::ObjectType auth_object, const vector<int>& cids);
private:
/**
* Factory method to produce objects
* @return a pointer to the new object

View File

@ -17,62 +17,66 @@
#ifndef CLUSTERABLE_H_
#define CLUSTERABLE_H_
using namespace std;
#include "ObjectCollection.h"
class Clusterable
{
public:
/**
* Changes the cluster this object belongs to
*
* @param _cluster_id Id of the new cluster
* @param _cluster Name of the new cluster
*/
void set_cluster(int _cluster_id, const string& _cluster)
int add_cluster(int cluster_id)
{
cluster_id = _cluster_id;
cluster = _cluster;
return cluster_ids.add(cluster_id);
};
int del_cluster(int cluster_id)
{
return cluster_ids.del(cluster_id);
};
/**
* Returns the cluster ID
* Returns the cluster IDs
*
* @return The cluster ID
* @return The cluster IDs set
*/
int get_cluster_id() const
std::set<int> get_cluster_ids() const
{
return cluster_id;
return cluster_ids.clone();
};
/**
* Returns the cluster name
* Rebuilds the cluster collection from an xml object
* @param xml xml object
* @param xpath_prefix Parent nodes, e.g. "/DATASTORE/"
*
* @return The cluster name
* @return 0 on success, -1 otherwise
*/
const string& get_cluster_name() const
int from_xml(const ObjectXML* xml, const std::string& xpath_prefix)
{
return cluster;
return cluster_ids.from_xml(xml, xpath_prefix);
};
/**
* Function to print the cluster IDs into a string in
* XML format
* @param xml the resulting XML string
* @return a reference to the generated string
*/
std::string& to_xml(std::string& xml) const
{
return cluster_ids.to_xml(xml);
};
protected:
Clusterable(int _cluster_id, const string& _cluster):
cluster_id(_cluster_id),
cluster(_cluster){};
Clusterable(const std::set<int> &_cluster_ids):
cluster_ids("CLUSTERS", _cluster_ids){};
~Clusterable(){};
/**
* ID of the cluster this object belongs to.
* IDs of the clusters this object belongs to.
*/
int cluster_id;
/**
* Name of the cluster this object belongs to.
*/
string cluster;
ObjectCollection cluster_ids;
};
#endif /*CLUSTERABLE_H_*/

View File

@ -0,0 +1,76 @@
/* ------------------------------------------------------------------------ */
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------*/
#ifndef CLUSTERABLE_SINGLE_H_
#define CLUSTERABLE_SINGLE_H_
class ClusterableSingle
{
public:
/**
* Changes the cluster this object belongs to
*
* @param _cluster_id Id of the new cluster
* @param _cluster Name of the new cluster
*/
void set_cluster(int _cluster_id, const std::string& _cluster)
{
cluster_id = _cluster_id;
cluster = _cluster;
};
/**
* Returns the cluster ID
*
* @return The cluster ID
*/
int get_cluster_id() const
{
return cluster_id;
};
/**
* Returns the cluster name
*
* @return The cluster name
*/
const std::string& get_cluster_name() const
{
return cluster;
};
protected:
ClusterableSingle(int _cluster_id, const std::string& _cluster):
cluster_id(_cluster_id),
cluster(_cluster){};
~ClusterableSingle(){};
/**
* ID of the cluster this object belongs to.
*/
int cluster_id;
/**
* Name of the cluster this object belongs to.
*/
std::string cluster;
};
#endif /*CLUSTERABLE_SINGLE_H_*/

View File

@ -319,8 +319,7 @@ private:
const string& gname,
int umask,
DatastoreTemplate* ds_template,
int cluster_id,
const string& cluster_name);
const set<int> &cluster_ids);
virtual ~Datastore();

View File

@ -78,8 +78,7 @@ public:
* @param umask permissions umask
* @param ds_template Datastore definition template
* @param oid the id assigned to the Datastore
* @param cluster_id the id of the cluster this Datastore will belong to
* @param cluster_name the name of the cluster this Datastore will belong to
* @param cluster_ids the ids of the clusters this Datastore will belong to
* @param error_str Returns the error reason, if any
*
* @return the oid assigned to the object, -1 in case of failure
@ -92,8 +91,7 @@ public:
int umask,
DatastoreTemplate * ds_template,
int * oid,
int cluster_id,
const string& cluster_name,
const set<int> &cluster_ids,
string& error_str);
/**
@ -201,7 +199,9 @@ private:
*/
PoolObjectSQL * create()
{
return new Datastore(-1,-1,"","", 0, 0, -1, "");
set<int> empty;
return new Datastore(-1,-1,"","", 0, 0, empty);
};
};

View File

@ -20,7 +20,7 @@
#include "PoolSQL.h"
#include "HostTemplate.h"
#include "HostShare.h"
#include "Clusterable.h"
#include "ClusterableSingle.h"
#include "ObjectCollection.h"
#include "NebulaLog.h"
#include "NebulaUtil.h"
@ -30,7 +30,7 @@ using namespace std;
/**
* The Host class.
*/
class Host : public PoolObjectSQL, public Clusterable
class Host : public PoolObjectSQL, public ClusterableSingle
{
public:

View File

@ -322,9 +322,20 @@ public:
return cloning_ops;
}
int dec_cloning(int img_id)
int dec_cloning(PoolObjectSQL::ObjectType ot, int oid)
{
if ( img_clone_collection.del(img_id) == 0 )
int rc = -1;
if (ot == PoolObjectSQL::IMAGE)
{
rc = img_clone_collection.del(oid);
}
else //if (ot == PoolObjectSQL::MARKETPLACEAPP)
{
rc = app_clone_collection.del(oid);
}
if ( rc == 0 )
{
cloning_ops--;
}
@ -332,9 +343,20 @@ public:
return cloning_ops;
}
int inc_cloning(int img_id)
int inc_cloning(PoolObjectSQL::ObjectType ot, int oid)
{
if ( img_clone_collection.add(img_id) == 0 )
int rc = -1;
if (ot == PoolObjectSQL::IMAGE)
{
rc = img_clone_collection.add(oid);
}
else //if (ot == PoolObjectSQL::MARKETPLACEAPP)
{
rc = app_clone_collection.add(oid);
}
if ( rc == 0 )
{
cloning_ops++;
}
@ -581,7 +603,7 @@ private:
int running_vms;
/**
* Number of pending cloning operations
* Number of pending cloning operations, for both images and apps
*/
int cloning_ops;
@ -611,6 +633,11 @@ private:
*/
ObjectCollection img_clone_collection;
/**
* Stores a collection with the Marketplace apps cloning this image
*/
ObjectCollection app_clone_collection;
/**
* Snapshot list for this image
*/

View File

@ -116,9 +116,30 @@ public:
/**
* Closes any cloning operation on the image, updating the state if needed
* @param iid image id of the image to that was being cloned
* @param clone_img_id the cloned image (id > 0) or market app (id =< 0)
* @param ot Object type, image or market app
* @param clone_oid the cloned resource id
*/
void release_cloning_image(int iid, int clone_img_id);
void release_cloning_resource(int iid, PoolObjectSQL::ObjectType ot, int clone_oid);
/**
* Closes any cloning operation on the image, updating the state if needed
* @param iid image id of the image to that was being cloned
* @param clone_img_id the cloned image id
*/
void release_cloning_image(int iid, int clone_img_id)
{
release_cloning_resource(iid, PoolObjectSQL::IMAGE, clone_img_id);
};
/**
* Closes any cloning operation on the image, updating the state if needed
* @param iid image id of the image to that was being cloned
* @param clone_oid the cloned marketplace app id
*/
void release_cloning_app(int iid, int clone_oid)
{
release_cloning_resource(iid, PoolObjectSQL::MARKETPLACEAPP, clone_oid);
};
/**
* Enables the image
@ -155,12 +176,38 @@ public:
/**
* Sets the state to CLONE for the given image
* @param new_id for the target image (new_id>0) or market app (new_id =<0)
* @param ot Object type, image or market app
* @param new_id for the target image or market app
* @param clonning_id the ID of the image to be cloned
* @param error if any
* @return 0 if siccess
* @return 0 on success
*/
int set_clone_state(int new_id, int cloning_id, std::string& error);
int set_clone_state(PoolObjectSQL::ObjectType ot, int new_id,
int cloning_id, std::string& error);
/**
* Sets the state to CLONE for the given image
* @param new_id for the target image
* @param clonning_id the ID of the image to be cloned
* @param error if any
* @return 0 on success
*/
int set_img_clone_state(int new_id, int cloning_id, std::string& error)
{
return set_clone_state(PoolObjectSQL::IMAGE, new_id, cloning_id, error);
};
/**
* Sets the state to CLONE for the given image
* @param new_id for the target market app
* @param clonning_id the ID of the image to be cloned
* @param error if any
* @return 0 on success
*/
int set_app_clone_state(int new_id, int cloning_id, std::string& error)
{
return set_clone_state(PoolObjectSQL::MARKETPLACEAPP, new_id, cloning_id, error);
};
/**
* Clone an existing image to the repository

View File

@ -147,7 +147,11 @@ private:
class StdLog : public Log
{
public:
StdLog(const MessageType level = WARNING):Log(level){};
StdLog(const MessageType level):Log(level){};
StdLog(const MessageType level,
int oid,
const PoolObjectSQL::ObjectType obj_type);
~StdLog(){};
@ -155,6 +159,9 @@ public:
const char * module,
const MessageType type,
const char * message);
private:
string resource_label;
};
/* -------------------------------------------------------------------------- */

View File

@ -82,6 +82,14 @@ public:
return market_mad;
};
/**
* Get zone for this market
* @return zone id
*/
int get_zone_id() const
{
return zone_id;
};
/**
* Set monitor information for the MarketPlace
* @param data template with monitor information
@ -98,8 +106,31 @@ public:
return supported_actions.is_set(action);
}
/**
* @return true if this is a public (external) marketplace
*/
bool is_public() const;
/**
* Disbale de monitor action for this marketplace
* @return true if the monitor was enabled
*/
bool disable_monitor()
{
bool enabled = supported_actions.is_set(MarketPlaceApp::MONITOR);
supported_actions.clear(MarketPlaceApp::MONITOR);
return enabled;
}
/**
* Enable the monitor action
*/
void enable_monitor()
{
supported_actions.set(MarketPlaceApp::MONITOR);
}
private:
friend class MarketPlacePool;
@ -127,6 +158,11 @@ private:
*/
long long used_mb;
/**
* Zone where this market lives
*/
int zone_id;
/**
* Supported actions on MarketPlaceApps
*/
@ -160,6 +196,14 @@ private:
static const char * table;
/**
* Builds the marketplace from the template. This function MUST be called
* with the template initialized
* @param error_str describing the error
* @return 0 on success;
*/
int parse_template(string& error_str);
/**
* Execute an INSERT or REPLACE Sql query.
* @param db The SQL DB

View File

@ -235,6 +235,11 @@ public:
return state;
}
int get_zone_id() const
{
return zone_id;
}
//--------------------------------------------------------------------------
// Set Marketplace app attributes
//--------------------------------------------------------------------------
@ -335,6 +340,11 @@ private:
*/
int origin_id;
/**
* ID of the zone where this app lives
*/
int zone_id;
// *************************************************************************
// Constructor
// *************************************************************************
@ -358,6 +368,14 @@ private:
static const char * table;
/**
* Builds the market app from the template. This function MUST be called
* with apptemplate initialized
* @param error_str describing the error
* @return 0 on success;
*/
int parse_template(string& error_str);
/**
* Execute an INSERT or REPLACE Sql query.
* @param db The SQL DB

View File

@ -45,7 +45,6 @@ public:
* @param apptemplate MarketPlaceApp definition template
* @param mp_id of the MarketPlace to store de App
* @param mp_name of the MarketPlace
* @param mp_data XML representation of the target MarketPlace
* @param oid the id assigned to the MarketPlace
* @param error_str Returns the error reason, if any
*
@ -60,7 +59,6 @@ public:
MarketPlaceAppTemplate * apptemplate,
int mp_id,
const std::string& mp_name,
const std::string& mp_data,
int * oid,
std::string& error_str);
@ -142,8 +140,6 @@ public:
*/
int update(PoolObjectSQL * objsql);
private:
/**
* Factory method to produce objects
* @return a pointer to the new object

View File

@ -148,8 +148,6 @@ public:
return PoolSQL::list(oids, MarketPlace::table);
}
private:
/**
* Factory method to produce objects
* @return a pointer to the new object

View File

@ -281,7 +281,7 @@ public:
*
*
*/
int get_ds_location(int cluster_id, string& dsloc);
void get_ds_location(string& dsloc);
/**
* Returns the default vms location. When ONE_LOCATION is defined this path
@ -338,7 +338,7 @@ public:
*/
static string shared_db_version()
{
return "4.11.80";
return "4.90.0";
}
/**
@ -347,7 +347,7 @@ public:
*/
static string local_db_version()
{
return "4.13.85";
return "4.90.0";
}
/**

View File

@ -21,6 +21,7 @@
#include <sstream>
#include <vector>
#include <set>
#include <algorithm>
namespace one_util
{
@ -150,6 +151,19 @@ namespace one_util
return oss.str();
}
/**
* Joins the given element with the delimiter
*
* @param values set of values
* @param delim delimiter character
* @return the joined strings
*/
template <class T>
std::string join(const std::set<T> values, char delim)
{
return join(values.begin(), values.end(), delim);
}
/**
* Creates a string from the given float, using fixed notation. If the
* number has any decimals, they will be truncated to 2.
@ -212,6 +226,18 @@ namespace one_util
*/
std::string gsub(const std::string& st, const std::string& sfind,
const std::string& replacement);
template <class T>
std::set<T> set_intersection(const std::set<T> &first, const std::set<T> &second)
{
std::set<T> output;
std::set_intersection(
first.begin(), first.end(), second.begin(), second.end(),
std::inserter(output, output.begin()));
return output;
}
};
#endif /* _NEBULA_UTIL_H_ */

View File

@ -33,6 +33,9 @@ public:
ObjectCollection(const string& _collection_name)
:collection_name(_collection_name){};
ObjectCollection(const string& cname, const set<int>& cset)
:collection_name(cname), collection_set(cset){};
~ObjectCollection(){};
/**
@ -69,12 +72,13 @@ public:
};
/**
* Rebuilds the object from an xml node
* @param node The xml node pointer
* Rebuilds the object from an xml object
* @param xml xml object
* @param xpath_prefix Parent nodes, e.g. "/DATASTORE/"
*
* @return 0 on success, -1 otherwise
* @return 0 on success, -1 otherwise
*/
int from_xml_node(const xmlNodePtr node);
int from_xml(const ObjectXML* xml, const string& xpath_prefix);
/**
* Function to print the Collection object into a string in
@ -135,6 +139,13 @@ private:
*/
set<int> collection_set;
/**
* Rebuilds the object from an xml node
* @param node The xml node pointer
*
* @return 0 on success, -1 otherwise
*/
int from_xml_node(const xmlNodePtr node);
};
#endif /*OBJECT_COLLECTION_H_*/

View File

@ -172,19 +172,20 @@ public:
*
* @return -1 if the element was not found
*/
virtual int search(const char *name, std::string& value);
virtual int search(const char *name, std::string& value)
{
return __search(name, value);
}
/**
* Search the Object for a given attribute in a set of object specific
* routes. integer version
*/
virtual int search(const char *name, int& value);
virtual int search(const char *name, int& value)
{
return __search(name, value);
}
/**
* Search the Object for a given attribute in a set of object specific
* routes. float version
*/
virtual int search(const char *name, float& value);
virtual int search(const char *name, float& value)
{
return __search(name, value);
}
/**
* Get xml nodes by Xpath
@ -193,7 +194,8 @@ public:
* returned as pointers to the object nodes.
* @return the number of nodes found
*/
int get_nodes(const char * xpath_expr, std::vector<xmlNodePtr>& content);
int get_nodes(const std::string& xpath_expr,
std::vector<xmlNodePtr>& content) const;
/**
* Adds a copy of the node as a child of the node in the xpath expression.
@ -211,7 +213,7 @@ public:
* Frees a vector of XMLNodes, as returned by the get_nodes function
* @param content the vector of xmlNodePtr
*/
void free_nodes(std::vector<xmlNodePtr>& content)
void free_nodes(std::vector<xmlNodePtr>& content) const
{
std::vector<xmlNodePtr>::iterator it;
@ -327,9 +329,57 @@ private:
* @param name of the attribute
* @results vector of attributes that matches the query
*/
void search(const char* name, std::vector<std::string>& results);
template<typename T>
void __search(const char* name, std::vector<T>& results)
{
if (name[0] == '/')
{
xpaths(results, name);
}
else if (num_paths == 0)
{
results.clear();
}
else
{
std::ostringstream xpath;
xpath << paths[0] << name;
for (int i = 1; i < num_paths ; i++)
{
xpath << '|' << paths[i] << name;
}
xpaths(results, xpath.str().c_str());
}
}
/**
* Search the Object for a given attribute in a set of object specific
* routes.
* @param name of the attribute
* @param value of the attribute
*
* @return -1 if the element was not found
*/
template<typename T>
int __search(const char *name, T& value)
{
std::vector<T> results;
__search(name, results);
if (results.size() != 0)
{
value = results[0];
return 0;
}
return -1;
};
};
#endif /*OBJECT_XML_H_*/

View File

@ -1,322 +0,0 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems */
/* */
/* 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 ONECLIENT_H_
#define ONECLIENT_H_
#ifdef __cplusplus
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/client_simple.hpp>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
/**
* OneClient class. Provides a simple interface to invoke the ONE methods. This
* class can be used as base to build complex clients or VM applications
*/
class OneClient : public xmlrpc_c::clientSimple
{
public:
/* ---------------------------------------------------------------------- */
/* ONE Session Constructors */
/* ---------------------------------------------------------------------- */
/**
* Set the connection values to communicate with ONE
* @param oneurl the ONE front-end to interact with, defaults to "localhost".
* @param socket the socket where ONE listen to, defaults to 2633.
*/
OneClient(string oneurl="localhost",unsigned int socket=2633)
{
ostringstream oss;
oss << "http://" << oneurl << ":" << socket << "/RPC2";
url=oss.str();
session = "oneclient";
};
~OneClient(){};
/* ---------------------------------------------------------------------- */
/* ONE Virtual Machine Methods */
/* ---------------------------------------------------------------------- */
/**
* Add a new VM to the VM pool and starts it.
* @param template_file path, description of the Virtual Machine template
* @param vmid, the id of the new VM
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int allocate(string template_file, int& vmid, string& error);
/**
* Add a new VM to the VM pool and starts it.
* @param template description of the Virtual Machine template
* @param vmid, the id of the new VM
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int allocate_template(const string& template_file,
int& vmid,
string& error);
/**
* Deploys the virtual machine "vmid" into the host "hid".
* @param vmid the virtual machine to deploy.
* @param hid the host id to deploy the VM.
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int deploy(int vmid, int hid, string& error);
/**
* Migrate the virtual machine "vmid" to the host "hid".
* @param vmid the virtual machine to migrate.
* @param hid the destination host.
* @param live try a "live migration".
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int migrate(int vmid, int hid, bool live, string& error);
/**
* Shutdown a virtual machine.
* @param vmid the vm identifier to shutdown.
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int shutdown(int vmid, string& error)
{
return action(vmid,"shutdown",error);
};
/**
* Sets a VM to hold, scheduler will not deploy it.
* @param vmid the vm identifier to hold.
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int hold(int vmid, string& error)
{
return action(vmid,"hold",error);
};
/**
* Release a VM from hold state.
* @param vmid the vm identifier to release.
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int release(int vmid, string& error)
{
return action(vmid,"release",error);
};
/**
* Stop a running VM
* @param vmid the vm identifier to stop.
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int stop(int vmid, string& error)
{
return action(vmid,"stop",error);
};
/**
* Saves a running VM
* @param vmid the vm identifier to suspend.
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int suspend(int vmid, string& error)
{
return action(vmid,"suspend",error);
};
/**
* Resumes the execution of a saved VM
* @param vmid the vm identifier to resume.
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int resume(int vmid, string& error)
{
return action(vmid,"resume",error);
};
/**
* Cancel the execution of a VM,
* @param vmid the vm identifier to resume.
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int cancel(int vmid, string& error)
{
return action(vmid,"cancel",error);
};
/**
* Remove the VM from the DB
* @param vmid the vm identifier to resume.
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int finalize(int vmid, string& error)
{
return action(vmid,"finalize",error);
};
/**
* Gets information on a virtual machine
* @param vmid the vm identifier.
* @param info the VM information
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int info(int vmid, string& info, string& error);
/* ---------------------------------------------------------------------- */
/* ONE Host Methods */
/* ---------------------------------------------------------------------- */
/**
* Gets system info from a single host ( "hid" ).
* @param hid the host id to get for information
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int host_info(int hid, string& info, string& error);
/**
* Removes a host from the pool
* @param hid the host id to remove
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int host_delete(int hid, string& error);
/**
* Enables a given host.
* @param hid the host id to enable.
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int host_enable(int hid, string& error)
{
return host_available(hid,true,error);
};
/**
* Disables a given host.
* @param hid the host id to disable.
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int host_disable(int hid, string& error)
{
return host_available(hid,false,error);
};
/**
* Adds a new Host to the Pool
* @param name hostname of the host to add
* @param im_mad the name of the information driver, from oned.conf
* @param vmm_mad the name of the virtual machine manager driver, from oned.conf
* @param error if an error occurs this is the error message
* @return -1 if an error occurs, 0 on success.
*/
int host_allocate(string& name,
string& im_mad,
string& vmm_mad,
int& hid,
string& error);
private:
/**
* URl - url to connect to ONE.
*/
string url;
/**
* Session - Client session id
*/
string session;
/**
* Submits an action to be performed on a VM.
* @param vmid the VM id.
* @param action the "transition" to execute.
* @param error if an error occurs this is error message.
* @return -1 if an error occurs, otherwise 0.
*/
int action(int vmid, const char * action, string& error);
/**
* Enables or disables a given host.
* @param hid the host id to enable/disable.
* @param enable true to enavle the target host.
* @param error if an error occurs this is error message.
* @return -1 if an error occurs, otherwise "0".
*/
int host_available(int hid, bool enable, string& error);
};
extern "C"
{
#endif
void c_oneStart(void);
int c_oneDeploy(int vmid, int hid);
int c_oneMigrate(int vmid, int hid, int flag);
int c_oneAllocate(char* vm_template);
int c_oneAllocateTemplate(char* vm_template);
int c_oneAction(int vmid,char* action);
int c_oneShutdown(int vmid);
int c_oneSuspend(int vmid);
int c_oneStop(int vmid);
int c_oneResume(int vmid);
int c_oneCancel(int vmid);
int c_oneFinalize(int vmid);
int c_oneVmInfo(int vmid, char* ret_info,int leng);
void c_oneFree(void);
#ifdef __cplusplus
}
#endif
#endif /*ONECLIENT_H_*/

View File

@ -34,7 +34,6 @@ public:
oid(-1),
uid(-1),
gid(-1),
cid(-1),
owner_u(1),
owner_m(1),
owner_a(0),
@ -65,7 +64,7 @@ public:
int oid;
int uid;
int gid;
int cid;
set<int> cids;
int owner_u;
int owner_m;

View File

@ -79,7 +79,7 @@ protected:
return pool_allocate(_paramList, tmpl, id, att);
};
virtual int get_cluster_id(xmlrpc_c::paramList const& paramList)
virtual int get_cluster_id(xmlrpc_c::paramList const& paramList)
{
return ClusterPool::NONE_CLUSTER_ID;
};
@ -87,7 +87,6 @@ protected:
virtual int add_to_cluster(
Cluster* cluster,
int id,
Datastore::DatastoreType ds_type,
string& error_msg)
{
return -1;
@ -101,6 +100,17 @@ protected:
protected:
ClusterPool * clpool;
int get_cluster_id(xmlrpc_c::paramList const& paramList, int cluster_pos)
{
int cid = xmlrpc_c::value_int(paramList.getInt(cluster_pos));
if (cid == -1)
{
cid = ClusterPool::DEFAULT_CLUSTER_ID;
}
return cid;
};
private:
bool do_template;
@ -176,15 +186,14 @@ public:
int cluster_id,
const string& cluster_name);
int get_cluster_id(xmlrpc_c::paramList const& paramList)
int get_cluster_id(xmlrpc_c::paramList const& paramList)
{
return xmlrpc_c::value_int(paramList.getInt(2));
return RequestManagerAllocate::get_cluster_id(paramList, 2);
};
int add_to_cluster(
Cluster* cluster,
int id,
Datastore::DatastoreType ds_type,
string& error_msg)
{
return cluster->add_vnet(id, error_msg);
@ -280,15 +289,14 @@ public:
int cluster_id,
const string& cluster_name);
int get_cluster_id(xmlrpc_c::paramList const& paramList)
int get_cluster_id(xmlrpc_c::paramList const& paramList)
{
return xmlrpc_c::value_int(paramList.getInt(5));
return RequestManagerAllocate::get_cluster_id(paramList, 5);
};
int add_to_cluster(
Cluster* cluster,
int id,
Datastore::DatastoreType ds_type,
string& error_msg)
{
return cluster->add_host(id, error_msg);
@ -385,32 +393,17 @@ public:
int cluster_id,
const string& cluster_name);
int get_cluster_id(xmlrpc_c::paramList const& paramList)
int get_cluster_id(xmlrpc_c::paramList const& paramList)
{
return xmlrpc_c::value_int(paramList.getInt(2));
};
virtual Datastore::DatastoreType get_ds_type(int oid)
{
Datastore::DatastoreType ds_type = Datastore::FILE_DS;
Datastore *ds = static_cast<DatastorePool*>(pool)->get(oid, true);
if ( ds != 0 )
{
ds_type = ds->get_type();
ds->unlock();
}
return ds_type;
return RequestManagerAllocate::get_cluster_id(paramList, 2);
};
int add_to_cluster(
Cluster* cluster,
int id,
Datastore::DatastoreType ds_type,
string& error_msg)
{
return cluster->add_datastore(id, ds_type, error_msg);
return cluster->add_datastore(id, error_msg);
};
};

View File

@ -0,0 +1,118 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems */
/* */
/* 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_ALLOCATE_DB_H
#define REQUEST_MANAGER_ALLOCATE_DB_H
#include "Request.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class RequestManagerAllocateDB: public Request
{
protected:
RequestManagerAllocateDB(): Request("AllocateDB", "A:ss",
"Allocates a new object from its template representation")
{
auth_op = AuthRequest::MANAGE;
};
virtual ~RequestManagerAllocateDB(){};
virtual PoolObjectSQL * create(const std::string& xml) = 0;
/* -------------------------------------------------------------------- */
void request_execute(xmlrpc_c::paramList const& pl, RequestAttributes& att)
{
std::string xml = xmlrpc_c::value_string(pl.getString(1));
if ( att.uid != UserPool::ONEADMIN_ID )
{
failure_response(AUTHORIZATION, att);
return;
}
PoolObjectSQL * obj = create(xml);
int rc = pool->allocate(obj, att.resp_msg);
if ( rc == -1 )
{
failure_response(INTERNAL, att);
return;
}
success_response(rc, att);
return;
}
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class MarketPlaceAppAllocateDB: public RequestManagerAllocateDB
{
public:
MarketPlaceAppAllocateDB(): RequestManagerAllocateDB()
{
auth_object = PoolObjectSQL::MARKETPLACEAPP;
pool = Nebula::instance().get_apppool();
};
virtual ~MarketPlaceAppAllocateDB(){};
/* -------------------------------------------------------------------- */
PoolObjectSQL * create(const std::string& xml)
{
PoolObjectSQL * app = static_cast<MarketPlaceAppPool *>(pool)->create();
app->from_xml(xml);
return app;
}
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class MarketPlaceAllocateDB: public RequestManagerAllocateDB
{
public:
MarketPlaceAllocateDB(): RequestManagerAllocateDB()
{
auth_object = PoolObjectSQL::MARKETPLACE;
pool = Nebula::instance().get_marketpool();
};
virtual ~MarketPlaceAllocateDB(){};
/* -------------------------------------------------------------------- */
PoolObjectSQL * create(const std::string& xml)
{
PoolObjectSQL * mp = static_cast<MarketPlacePool *>(pool)->create();
mp->from_xml(xml);
return mp;
}
};
#endif /* REQUEST_MANAGER_ALLOCATE_DB_H */

View File

@ -36,7 +36,6 @@ protected:
{
Nebula& nd = Nebula::instance();
clpool = nd.get_clpool();
hpool = nd.get_hpool();
dspool = nd.get_dspool();
vnpool = nd.get_vnpool();
@ -49,7 +48,6 @@ protected:
/* --------------------------------------------------------------------- */
ClusterPool * clpool;
HostPool * hpool;
DatastorePool * dspool;
VirtualNetworkPool * vnpool;
@ -63,12 +61,28 @@ protected:
int object_id,
RequestAttributes& att,
PoolSQL * pool,
PoolObjectSQL::ObjectType type);
virtual Datastore::DatastoreType get_ds_type(PoolObjectSQL *obj)
PoolObjectSQL::ObjectType type)
{
return Datastore::FILE_DS;
};
action_generic(cluster_id, object_id, att, pool, type, true);
}
void del_generic(
int cluster_id,
int object_id,
RequestAttributes& att,
PoolSQL * pool,
PoolObjectSQL::ObjectType type)
{
action_generic(cluster_id, object_id, att, pool, type, false);
}
void action_generic(
int cluster_id,
int object_id,
RequestAttributes& att,
PoolSQL * pool,
PoolObjectSQL::ObjectType type,
bool add);
/**
* Add object to cluster id collection
@ -81,7 +95,6 @@ protected:
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;
@ -92,38 +105,36 @@ protected:
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class RequestManagerClusterHost : public RequestManagerCluster
class RequestManagerClusterHost: public Request
{
public:
protected:
RequestManagerClusterHost(
const string& method_name,
const string& help,
const string& params):
RequestManagerCluster(method_name, help, params){};
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::ADMIN;
};
~RequestManagerClusterHost(){};
virtual int add_object(
Cluster* cluster,
int id,
Datastore::DatastoreType ds_type,
string& error_msg)
{
return cluster->add_host(id, error_msg);
};
/* --------------------------------------------------------------------- */
virtual int del_object(Cluster* cluster, int id, string& error_msg)
{
return cluster->del_host(id, error_msg);
};
ClusterPool * clpool;
HostPool * hpool;
virtual void get(int oid, bool lock, PoolObjectSQL ** object, Clusterable ** cluster_obj)
{
Host * host = hpool->get(oid, lock);
/* --------------------------------------------------------------------- */
*object = static_cast<PoolObjectSQL *>(host);
*cluster_obj = static_cast<Clusterable *>(host);
};
void add_generic(
int cluster_id,
int host_id,
RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */
@ -145,8 +156,7 @@ public:
int cluster_id = xmlrpc_c::value_int(paramList.getInt(1));
int object_id = xmlrpc_c::value_int(paramList.getInt(2));
return add_generic(cluster_id, object_id, att,
hpool, PoolObjectSQL::HOST);
return add_generic(cluster_id, object_id, att);
}
};
@ -168,11 +178,10 @@ public:
{
// First param is ignored, as objects can be assigned to only
// one cluster
int cluster_id = ClusterPool::NONE_CLUSTER_ID;
int cluster_id = ClusterPool::DEFAULT_CLUSTER_ID;
int object_id = xmlrpc_c::value_int(paramList.getInt(2));
return add_generic(cluster_id, object_id, att,
hpool, PoolObjectSQL::HOST);
return add_generic(cluster_id, object_id, att);
}
};
@ -190,18 +199,12 @@ public:
~RequestManagerClusterDatastore(){};
virtual Datastore::DatastoreType get_ds_type(PoolObjectSQL *obj)
{
return static_cast<Datastore*>(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);
return cluster->add_datastore(id, error_msg);
};
virtual int del_object(Cluster* cluster, int id, string& error_msg)
@ -258,12 +261,10 @@ public:
void request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
// First param is ignored, as objects can be assigned to only
// one cluster
int cluster_id = ClusterPool::NONE_CLUSTER_ID;
int cluster_id = xmlrpc_c::value_int(paramList.getInt(1));
int object_id = xmlrpc_c::value_int(paramList.getInt(2));
return add_generic(cluster_id, object_id, att,
return del_generic(cluster_id, object_id, att,
dspool, PoolObjectSQL::DATASTORE);
}
};
@ -286,7 +287,6 @@ public:
virtual int add_object(
Cluster* cluster,
int id,
Datastore::DatastoreType ds_type,
string& error_msg)
{
return cluster->add_vnet(id, error_msg);
@ -346,12 +346,10 @@ public:
void request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
// First param is ignored, as objects can be assigned to only
// one cluster
int cluster_id = ClusterPool::NONE_CLUSTER_ID;
int cluster_id = xmlrpc_c::value_int(paramList.getInt(1));
int object_id = xmlrpc_c::value_int(paramList.getInt(2));
return add_generic(cluster_id, object_id, att,
return del_generic(cluster_id, object_id, att,
vnpool, PoolObjectSQL::NET);
}
};

View File

@ -70,9 +70,10 @@ protected:
virtual int drop(int oid, PoolObjectSQL * object, string& error_msg);
virtual int get_cluster_id(PoolObjectSQL * object)
virtual set<int> get_cluster_ids(PoolObjectSQL * object)
{
return ClusterPool::NONE_CLUSTER_ID;
set<int> empty;
return empty;
};
virtual int del_from_cluster(Cluster* cluster, int id, string& error_msg)
@ -127,9 +128,9 @@ public:
/* -------------------------------------------------------------------- */
int get_cluster_id(PoolObjectSQL * object)
set<int> get_cluster_ids(PoolObjectSQL * object)
{
return static_cast<VirtualNetwork*>(object)->get_cluster_id();
return static_cast<VirtualNetwork*>(object)->get_cluster_ids();
};
int del_from_cluster(Cluster* cluster, int id, string& error_msg)
@ -181,9 +182,13 @@ public:
/* -------------------------------------------------------------------- */
int get_cluster_id(PoolObjectSQL * object)
set<int> get_cluster_ids(PoolObjectSQL * object)
{
return static_cast<Host*>(object)->get_cluster_id();
set<int> ids;
ids.insert( static_cast<Host*>(object)->get_cluster_id() );
return ids;
};
int del_from_cluster(Cluster* cluster, int id, string& error_msg)
@ -266,9 +271,9 @@ public:
/* -------------------------------------------------------------------- */
int get_cluster_id(PoolObjectSQL * object)
set<int> get_cluster_ids(PoolObjectSQL * object)
{
return static_cast<Datastore*>(object)->get_cluster_id();
return static_cast<Datastore*>(object)->get_cluster_ids();
};
int del_from_cluster(Cluster* cluster, int id, string& error_msg)

View File

@ -0,0 +1,87 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems */
/* */
/* 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_DROP_DB_H
#define REQUEST_MANAGER_DROP_DB_H
#include "Request.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class RequestManagerDropDB: public Request
{
protected:
RequestManagerDropDB(): Request("DropDB", "A:si",
"Drops an object from DB")
{
auth_op = AuthRequest::MANAGE;
};
virtual ~RequestManagerDropDB(){};
/* -------------------------------------------------------------------- */
void request_execute(xmlrpc_c::paramList const& pl, RequestAttributes& att)
{
std::string error;
int oid = xmlrpc_c::value_int(pl.getInt(1));
if ( att.uid != UserPool::ONEADMIN_ID )
{
failure_response(AUTHORIZATION, att);
return;
}
PoolObjectSQL * object = pool->get(oid,true);
if ( object == 0 )
{
att.resp_id = oid;
failure_response(NO_EXISTS, att);
return;
}
if ( pool->drop(object, error) != 0 )
{
att.resp_msg = error;
failure_response(ACTION, att);
}
else
{
success_response(oid, att);
}
object->unlock();
return;
}
};
class MarketPlaceAppDropDB : public RequestManagerDropDB
{
public:
MarketPlaceAppDropDB():RequestManagerDropDB()
{
auth_object = PoolObjectSQL::MARKETPLACEAPP;
pool = Nebula::instance().get_apppool();
}
~MarketPlaceAppDropDB(){};
};
#endif /* REQUEST_MANAGER_DROP_DB_H */

View File

@ -28,18 +28,23 @@ using namespace std;
class RequestManagerProxy: public Request
{
public:
RequestManagerProxy(string _method);
RequestManagerProxy(string _method): Request("RequestManagerProxy", "?",
"Forwards the request to another OpenNebula"), method(_method)
{
method_name = ("RequestManagerProxy." + method);
};
~RequestManagerProxy();
~RequestManagerProxy(){};
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
void hide_argument(int arg);
void hide_argument(int arg)
{
hidden_params.insert(arg);
};
private:
Client * client;
string method;
};

View File

@ -0,0 +1,118 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef REQUEST_MANAGER_UPDATE_DB_H
#define REQUEST_MANAGER_UPDATE_DB_H
#include "Request.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class RequestManagerUpdateDB: public Request
{
protected:
RequestManagerUpdateDB(): Request("UpdateDB", "A:sis",
"Updates the DB object from a XML document")
{
auth_op = AuthRequest::MANAGE;
};
virtual ~RequestManagerUpdateDB(){};
/* -------------------------------------------------------------------- */
void request_execute(xmlrpc_c::paramList const& pl, RequestAttributes& att)
{
int oid = xmlrpc_c::value_int(pl.getInt(1));
std::string xml = xmlrpc_c::value_string(pl.getString(2));
if ( att.uid != UserPool::ONEADMIN_ID )
{
failure_response(AUTHORIZATION, att);
return;
}
PoolObjectSQL * object = pool->get(oid,true);
if ( object == 0 )
{
att.resp_id = oid;
failure_response(NO_EXISTS, att);
return;
}
string old_xml;
object->to_xml(old_xml);
if ( object->from_xml(xml) != 0 )
{
object->from_xml(old_xml);
att.resp_msg = "Cannot update object from XML";
failure_response(INTERNAL, att);
object->unlock();
return;
}
if ( object->get_oid() != oid )
{
object->from_xml(old_xml);
att.resp_msg = "Consistency check failed";
failure_response(INTERNAL, att);
object->unlock();
return;
}
pool->update(object);
object->unlock();
success_response(oid, att);
return;
}
};
class MarketPlaceAppUpdateDB : public RequestManagerUpdateDB
{
public:
MarketPlaceAppUpdateDB():RequestManagerUpdateDB()
{
auth_object = PoolObjectSQL::MARKETPLACEAPP;
pool = Nebula::instance().get_apppool();
}
~MarketPlaceAppUpdateDB(){};
};
class MarketPlaceUpdateDB : public RequestManagerUpdateDB
{
public:
MarketPlaceUpdateDB():RequestManagerUpdateDB()
{
auth_object = PoolObjectSQL::MARKETPLACE;
pool = Nebula::instance().get_marketpool();
}
~MarketPlaceUpdateDB(){};
};
#endif /* REQUEST_MANAGER_UPDATE_DB_H */

View File

@ -80,7 +80,7 @@ protected:
int get_ds_information(
int ds_id,
int& ds_cluster_id,
set<int>& ds_cluster_ids,
string& tm_mad,
RequestAttributes& att,
bool& ds_migr);

View File

@ -129,14 +129,16 @@ public:
* @param vm The VM
* @param token_password Owner user's token password
* @param system_tm_mad The Transfer Manager for the system datastore
* @param disk_id of the context disk
* @param xfr Stream where the transfer command will be written
*
* @return 0 on success
* @return -1 in case of error, 0 if the VM has no context, 1 on success
*/
int prolog_context_command(
VirtualMachine * vm,
const string& token_password,
string& system_tm_mad,
int& disk_id,
ostream& xfr);
/**

View File

@ -165,8 +165,10 @@ public:
DISK_SNAPSHOT_REVERT_SUSPENDED = 55,
DISK_SNAPSHOT_DELETE_SUSPENDED = 56,
DISK_SNAPSHOT = 57,
DISK_SNAPSHOT_REVERT = 58,
DISK_SNAPSHOT_DELETE = 59
//DISK_SNAPSHOT_REVERT = 58,
DISK_SNAPSHOT_DELETE = 59,
PROLOG_MIGRATE_UNKNOWN = 60,
PROLOG_MIGRATE_UNKNOWN_FAILURE = 61
};
static int lcm_state_from_str(string& st, LcmState& state)
@ -229,8 +231,9 @@ public:
else if ( st == "DISK_SNAPSHOT_REVERT_SUSPENDED") { state = DISK_SNAPSHOT_REVERT_SUSPENDED; }
else if ( st == "DISK_SNAPSHOT_DELETE_SUSPENDED") { state = DISK_SNAPSHOT_DELETE_SUSPENDED; }
else if ( st == "DISK_SNAPSHOT") { state = DISK_SNAPSHOT; }
else if ( st == "DISK_SNAPSHOT_REVERT") { state = DISK_SNAPSHOT_REVERT; }
else if ( st == "DISK_SNAPSHOT_DELETE") { state = DISK_SNAPSHOT_DELETE; }
else if ( st == "PROLOG_MIGRATE_UNKNOWN") { state = PROLOG_MIGRATE_UNKNOWN; }
else if ( st == "PROLOG_MIGRATE_UNKNOWN_FAILURE") { state = PROLOG_MIGRATE_UNKNOWN_FAILURE; }
else {return -1;}
return 0;
@ -296,8 +299,9 @@ public:
case DISK_SNAPSHOT_REVERT_SUSPENDED: st = "DISK_SNAPSHOT_REVERT_SUSPENDED"; break;
case DISK_SNAPSHOT_DELETE_SUSPENDED: st = "DISK_SNAPSHOT_DELETE_SUSPENDED"; break;
case DISK_SNAPSHOT: st = "DISK_SNAPSHOT"; break;
case DISK_SNAPSHOT_REVERT: st = "DISK_SNAPSHOT_REVERT"; break;
case DISK_SNAPSHOT_DELETE: st = "DISK_SNAPSHOT_DELETE"; break;
case PROLOG_MIGRATE_UNKNOWN: st = "PROLOG_MIGRATE_UNKNOWN"; break;
case PROLOG_MIGRATE_UNKNOWN_FAILURE: st = "PROLOG_MIGRATE_UNKNOWN_FAILURE"; break;
}
return st;
@ -1289,6 +1293,11 @@ public:
*/
bool is_imported() const;
/**
* Return state of the VM right before import
*/
string get_import_state();
/**
* Checks if the current VM MAD supports the given action for imported VMs
* @param action VM action to check
@ -1342,15 +1351,10 @@ public:
* in the context block device (CBD)
* @param files space separated list of paths to be included in the CBD
* @param disk_id CONTEXT/DISK_ID attribute value
* @param token_password Password to encrypt the token, if it is set
* @param password Password to encrypt the token, if it is set
* @return -1 in case of error, 0 if the VM has no context, 1 on success
*/
int generate_context(string &files, int &disk_id, const string& token_password);
const VectorAttribute* get_context() const
{
return obj_template->get("CONTEXT");
}
int generate_context(string &files, int &disk_id, const string& password);
/**
* Returns the CREATED_BY template attribute, or the uid if it does not exist
@ -1987,6 +1991,24 @@ private:
static const int NUM_NO_NIC_DEFAULTS;
/**
* Parse and generate the ETH_ network attributed of a NIC
* @param context attribute
* @param nic attribute
*
* @return 0 on success
*/
void parse_nic_context(VectorAttribute * context, VectorAttribute * nic);
/**
* Generate the NETWORK related CONTEXT setions, i.e. ETH_*. This function
* is invoked when ever the context is prepared for the VM to capture
* netowrking updates.
* @param context attribute of the VM
* @return true if the net context was generated.
*/
bool generate_network_context(VectorAttribute * context);
/**
* Parse the "NIC_DEFAULT" attribute
* @param error_str Returns the error reason, if any

View File

@ -67,8 +67,7 @@ public:
SNAPSHOT_CREATE,
SNAPSHOT_REVERT,
SNAPSHOT_DELETE,
DISK_SNAPSHOT_CREATE,
DISK_SNAPSHOT_REVERT
DISK_SNAPSHOT_CREATE
};
/**
@ -432,13 +431,6 @@ private:
*/
void disk_snapshot_create_action(int vid);
/**
* Reverts to a disk snapshot.
*
* @param vid the id of the VM.
*/
void disk_snapshot_revert_action(int vid);
/**
* This function cancels the current driver operation
*/

View File

@ -384,19 +384,6 @@ private:
write_drv("DISKSNAPSHOTCREATE", oid, drv_msg);
}
/**
* Sends a disk snapshot revert request to the MAD:
* "DISKSNAPSHOTREVERT ID XML_DRV_MSG"
* @param oid the virtual machine id.
* @param drv_msg xml data for the mad operation
*/
void disk_snapshot_revert (
const int oid,
const string& drv_msg) const
{
write_drv("DISKSNAPSHOTREVERT", oid, drv_msg);
}
/**
* Sends a request to update the VM security groups:
* "UPDATESG ID XML_DRV_MSG"

View File

@ -457,6 +457,11 @@ private:
// Binded physical attributes
// -------------------------------------------------------------------------
/**
* Name of the vn mad
*/
string vn_mad;
/**
* Name of the bridge this VNW binds to
*/
@ -472,11 +477,6 @@ private:
*/
string vlan_id;
/**
* Whether or not to isolate this network with the vnm driver
*/
int vlan;
/**
* Parent VNET ID if any
*/
@ -541,7 +541,7 @@ private:
int from_xml(const string &xml_str);
/**
* Updates the BRIDGE, PHY_DEV, VLAN_ID and VLAN attributes.
* Updates the BRIDGE, PHY_DEV, and VLAN_ID attributes.
* @param error string describing the error if any
* @return 0 on success
*/
@ -557,8 +557,7 @@ private:
const string& _gname,
int _umask,
int _parent_vid,
int _cluster_id,
const string& _cluster_name,
const set<int> &_cluster_ids,
VirtualNetworkTemplate * _vn_template = 0);
~VirtualNetwork();

View File

@ -49,8 +49,7 @@ public:
* @param umask permissions umask
* @param vn_template a VirtualNetworkTemplate describing the VNET
* @param oid the id assigned to the VM (output)
* @param cluster_id the id of the cluster this VNET will belong to
* @param cluster_name the name of the cluster this VNET will belong to
* @param cluster_ids the ids of the clusters this VNET will belong to
* @param error_str Returns the error reason, if any
* @return oid on success, -1 error
*/
@ -63,8 +62,7 @@ public:
int parent_vid,
VirtualNetworkTemplate * vn_template,
int * oid,
int cluster_id,
const string& cluster_name,
const set<int> &cluster_ids,
string& error_str);
/**
@ -203,7 +201,8 @@ private:
*/
PoolObjectSQL * create()
{
return new VirtualNetwork(-1,-1,"","",0,-1,-1,"",0);
set <int> empty;
return new VirtualNetwork(-1,-1,"","",0,-1,empty,0);
};
/**

View File

@ -233,11 +233,6 @@ LIB_DIRS="$LIB_LOCATION/ruby \
$LIB_LOCATION/ruby/onedb/local \
$LIB_LOCATION/ruby/onedb/patches \
$LIB_LOCATION/ruby/vendors \
$LIB_LOCATION/ruby/vendors/rbvmomi \
$LIB_LOCATION/ruby/vendors/rbvmomi/lib \
$LIB_LOCATION/ruby/vendors/rbvmomi/lib/rbvmomi \
$LIB_LOCATION/ruby/vendors/rbvmomi/lib/rbvmomi/utils \
$LIB_LOCATION/ruby/vendors/rbvmomi/lib/rbvmomi/vim \
$LIB_LOCATION/mads \
$LIB_LOCATION/sh \
$LIB_LOCATION/ruby/cli \
@ -284,6 +279,7 @@ VAR_DIRS="$VAR_LOCATION/remotes \
$VAR_LOCATION/remotes/tm/lvm \
$VAR_LOCATION/remotes/tm/ceph \
$VAR_LOCATION/remotes/tm/dev \
$VAR_LOCATION/remotes/tm/vcenter \
$VAR_LOCATION/remotes/tm/iscsi \
$VAR_LOCATION/remotes/hooks \
$VAR_LOCATION/remotes/hooks/ft \
@ -294,6 +290,7 @@ VAR_DIRS="$VAR_LOCATION/remotes \
$VAR_LOCATION/remotes/datastore/lvm \
$VAR_LOCATION/remotes/datastore/ceph \
$VAR_LOCATION/remotes/datastore/dev \
$VAR_LOCATION/remotes/datastore/vcenter \
$VAR_LOCATION/remotes/market \
$VAR_LOCATION/remotes/market/http \
$VAR_LOCATION/remotes/market/one \
@ -422,6 +419,7 @@ INSTALL_FILES=(
TM_DEV_FILES:$VAR_LOCATION/remotes/tm/dev
TM_ISCSI_FILES:$VAR_LOCATION/remotes/tm/iscsi
TM_DUMMY_FILES:$VAR_LOCATION/remotes/tm/dummy
TM_VCENTER_FILES:$VAR_LOCATION/remotes/tm/vcenter
DATASTORE_DRIVER_COMMON_SCRIPTS:$VAR_LOCATION/remotes/datastore/
DATASTORE_DRIVER_DUMMY_SCRIPTS:$VAR_LOCATION/remotes/datastore/dummy
DATASTORE_DRIVER_FS_SCRIPTS:$VAR_LOCATION/remotes/datastore/fs
@ -429,6 +427,7 @@ INSTALL_FILES=(
DATASTORE_DRIVER_LVM_SCRIPTS:$VAR_LOCATION/remotes/datastore/lvm
DATASTORE_DRIVER_CEPH_SCRIPTS:$VAR_LOCATION/remotes/datastore/ceph
DATASTORE_DRIVER_DEV_SCRIPTS:$VAR_LOCATION/remotes/datastore/dev
DATASTORE_DRIVER_VCENTER_SCRIPTS:$VAR_LOCATION/remotes/datastore/vcenter
DATASTORE_DRIVER_ISCSI_SCRIPTS:$VAR_LOCATION/remotes/datastore/iscsi
MARKETPLACE_DRIVER_HTTP_SCRIPTS:$VAR_LOCATION/remotes/market/http
MARKETPLACE_DRIVER_ONE_SCRIPTS:$VAR_LOCATION/remotes/market/one
@ -455,11 +454,7 @@ INSTALL_FILES=(
DOCS_FILES:$DOCS_LOCATION
CLI_LIB_FILES:$LIB_LOCATION/ruby/cli
ONE_CLI_LIB_FILES:$LIB_LOCATION/ruby/cli/one_helper
RBVMOMI_VENDOR_RUBY_FILES:$LIB_LOCATION/ruby/vendors/rbvmomi
RBVMOMI_VENDOR_RUBY_LIB_FILES:$LIB_LOCATION/ruby/vendors/rbvmomi/lib
RBVMOMI_VENDOR_RUBY_LIB_RBVMOMI_FILES:$LIB_LOCATION/ruby/vendors/rbvmomi/lib/rbvmomi
RBVMOMI_VENDOR_RUBY_LIB_RBVMOMI_VIM_FILES:$LIB_LOCATION/ruby/vendors/rbvmomi/lib/rbvmomi/vim
RBVMOMI_VENDOR_RUBY_LIB_RBVMOMI_UTILS_FILES:$LIB_LOCATION/ruby/vendors/rbvmomi/lib/rbvmomi/utils
VENDOR_DIRS:$LIB_LOCATION/ruby/vendors
)
INSTALL_CLIENT_FILES=(
@ -936,7 +931,6 @@ AUTH_PLAIN_FILES="src/authm_mad/remotes/plain/authenticate"
NETWORK_FILES="src/vnm_mad/remotes/lib/vnm_driver.rb \
src/vnm_mad/remotes/lib/vnmmad.rb \
src/vnm_mad/remotes/OpenNebulaNetwork.conf \
src/vnm_mad/remotes/lib/fw_driver.rb \
src/vnm_mad/remotes/lib/sg_driver.rb \
src/vnm_mad/remotes/lib/address.rb \
src/vnm_mad/remotes/lib/command.rb \
@ -1156,6 +1150,20 @@ TM_DEV_FILES="src/tm_mad/dev/clone \
src/tm_mad/dev/failmigrate \
src/tm_mad/dev/delete"
TM_VCENTER_FILES="src/tm_mad/vcenter/clone \
src/tm_mad/vcenter/ln \
src/tm_mad/vcenter/mv \
src/tm_mad/vcenter/mvds \
src/tm_mad/vcenter/cpds \
src/tm_mad/vcenter/premigrate \
src/tm_mad/vcenter/postmigrate \
src/tm_mad/vcenter/snap_create \
src/tm_mad/vcenter/snap_create_live \
src/tm_mad/vcenter/snap_delete \
src/tm_mad/vcenter/snap_revert \
src/tm_mad/vcenter/failmigrate \
src/tm_mad/vcenter/delete"
TM_ISCSI_FILES="src/tm_mad/iscsi/clone \
src/tm_mad/iscsi/ln \
src/tm_mad/iscsi/mv \
@ -1180,6 +1188,8 @@ TM_ISCSI_FILES="src/tm_mad/iscsi/clone \
DATASTORE_DRIVER_COMMON_SCRIPTS="src/datastore_mad/remotes/xpath.rb \
src/datastore_mad/remotes/downloader.sh \
src/datastore_mad/remotes/vcenter_uploader.rb \
src/datastore_mad/remotes/vcenter_downloader.rb \
src/datastore_mad/remotes/url.rb \
src/datastore_mad/remotes/libfs.sh"
@ -1250,6 +1260,17 @@ DATASTORE_DRIVER_DEV_SCRIPTS="src/datastore_mad/remotes/dev/cp \
src/datastore_mad/remotes/dev/snap_flatten \
src/datastore_mad/remotes/dev/clone"
DATASTORE_DRIVER_VCENTER_SCRIPTS="src/datastore_mad/remotes/vcenter/cp \
src/datastore_mad/remotes/vcenter/mkfs \
src/datastore_mad/remotes/vcenter/stat \
src/datastore_mad/remotes/vcenter/rm \
src/datastore_mad/remotes/vcenter/monitor \
src/datastore_mad/remotes/vcenter/snap_delete \
src/datastore_mad/remotes/vcenter/snap_revert \
src/datastore_mad/remotes/vcenter/snap_flatten \
src/datastore_mad/remotes/vcenter/clone \
src/datastore_mad/remotes/vcenter/export"
DATASTORE_DRIVER_ISCSI_SCRIPTS="src/datastore_mad/remotes/iscsi/cp \
src/datastore_mad/remotes/iscsi/mkfs \
src/datastore_mad/remotes/iscsi/stat \
@ -1951,49 +1972,7 @@ DOCS_FILES="LICENSE NOTICE README.md"
# Ruby VENDOR files
#-----------------------------------------------------------------------------
RBVMOMI_VENDOR_RUBY_FILES="share/vendor/ruby/gems/rbvmomi/LICENSE \
share/vendor/ruby/gems/rbvmomi/README.rdoc \
share/vendor/ruby/gems/rbvmomi/VERSION \
share/vendor/ruby/gems/rbvmomi/vmodl.db"
RBVMOMI_VENDOR_RUBY_LIB_FILES="share/vendor/ruby/gems/rbvmomi/lib/rbvmomi.rb"
RBVMOMI_VENDOR_RUBY_LIB_RBVMOMI_FILES="share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/basic_types.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/connection.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/deserialization.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/fault.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/pbm.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/trivial_soap.rb
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/trollop.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/type_loader.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim.rb"
RBVMOMI_VENDOR_RUBY_LIB_RBVMOMI_UTILS_FILES="share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/utils/admission_control.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/utils/deploy.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/utils/leases.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/utils/perfdump.rb"
RBVMOMI_VENDOR_RUBY_LIB_RBVMOMI_VIM_FILES="share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/ComputeResource.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/Datacenter.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/Datastore.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/DynamicTypeMgrAllTypeInfo.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/DynamicTypeMgrDataTypeInfo.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/DynamicTypeMgrManagedTypeInfo.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/Folder.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/HostSystem.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/ManagedEntity.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/ManagedObject.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/ObjectContent.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/ObjectUpdate.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/OvfManager.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/PerfCounterInfo.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/PerformanceManager.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/PropertyCollector.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/ReflectManagedMethodExecuter.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/ResourcePool.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/ServiceInstance.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/Task.rb \
share/vendor/ruby/gems/rbvmomi/lib/rbvmomi/vim/VirtualMachine.rb"
VENDOR_DIRS="share/vendor/ruby/gems/rbvmomi"
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------

View File

@ -71,6 +71,8 @@ digraph OpenNebula {
prolog_migrate_suspend;
prolog_migrate_suspend_failure;
prolog_undeploy;
prolog_migrate_unknown;
prolog_migrate_unknown_failure;
color="white"
}
subgraph {
@ -154,7 +156,8 @@ digraph OpenNebula {
prolog_migrate -> boot_migrate [style="dashed", color="blue"];
boot_migrate -> running [style="dashed", color="blue"];
unknown -> boot [label="migrate"];
unknown -> prolog_migrate_unknown [label="migrate"];
prolog_migrate_unknown -> boot [style="dashed", color="blue"];
poweroff -> prolog_migrate_poweroff [label="migrate"];
prolog_migrate_poweroff -> poweroff [style="dashed", color="blue"];
@ -304,6 +307,9 @@ digraph OpenNebula {
prolog_resume -> stopped [style="dotted", color="red"];
prolog_undeploy -> undeployed [style="dotted", color="red"];
prolog_migrate_unknown -> prolog_migrate_unknown_failure [label=" ", style="dotted", color="red"];
prolog_migrate_unknown_failure -> prolog_migrate_unknown [label="migrate"];
boot -> boot_failure [label=" ", style="dotted", color="red"];
boot_migrate -> boot_migrate_failure [label=" ", style="dotted", color="red"];
boot_poweroff -> poweroff [style="dotted", color="red"];

View File

@ -174,7 +174,9 @@
DISK_SNAPSHOT_DELETE_SUSPENDED = 56,
DISK_SNAPSHOT = 57,
DISK_SNAPSHOT_REVERT = 58,
DISK_SNAPSHOT_DELETE = 59
DISK_SNAPSHOT_DELETE = 59,
PROLOG_MIGRATE_UNKNOWN = 60,
PROLOG_MIGRATE_UNKNOWN_FAILURE = 61
-->
<xs:element name="LCM_STATE" type="xs:integer"/>
<xs:element name="PREV_STATE" type="xs:integer"/>

View File

@ -24,15 +24,19 @@
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="DS_MAD" type="xs:string"/>
<xs:element name="TM_MAD" type="xs:string"/>
<xs:element name="BASE_PATH" type="xs:string"/>
<xs:element name="TYPE" type="xs:integer"/>
<xs:element name="DISK_TYPE" type="xs:integer"/>
<xs:element name="STATE" type="xs:integer"/>
<xs:element name="CLUSTER_ID" type="xs:integer"/>
<xs:element name="CLUSTER" type="xs:string"/>
<xs:element name="CLUSTERS">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="TOTAL_MB" type="xs:integer"/>
<xs:element name="FREE_MB" type="xs:integer"/>
<xs:element name="USED_MB" type="xs:integer"/>

View File

@ -65,6 +65,13 @@
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="APP_CLONES">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="TEMPLATE" type="xs:anyType"/>
<xs:element name="SNAPSHOTS">
<xs:complexType>

View File

@ -105,7 +105,9 @@
DISK_SNAPSHOT_DELETE_SUSPENDED = 56,
DISK_SNAPSHOT = 57,
DISK_SNAPSHOT_REVERT = 58,
DISK_SNAPSHOT_DELETE = 59
DISK_SNAPSHOT_DELETE = 59,
PROLOG_MIGRATE_UNKNOWN = 60,
PROLOG_MIGRATE_UNKNOWN_FAILURE = 61
-->
<xs:element name="LCM_STATE" type="xs:integer"/>
<xs:element name="PREV_STATE" type="xs:integer"/>

View File

@ -25,10 +25,15 @@
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="CLUSTER_ID" type="xs:integer"/>
<xs:element name="CLUSTER" type="xs:string"/>
<xs:element name="CLUSTERS">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="BRIDGE" type="xs:string"/>
<xs:element name="VLAN" type="xs:integer"/>
<xs:element name="VN_MAD" type="xs:integer"/>
<xs:element name="PARENT_NETWORK_ID" type="xs:string"/>
<xs:element name="PHYDEV" type="xs:string"/>
<xs:element name="VLAN_ID" type="xs:string"/>
@ -48,7 +53,7 @@
<xs:element name="SIZE" type="xs:integer"/>
<xs:element name="TYPE" type="xs:string"/>
<xs:element name="ULA_PREFIX" type="xs:string" minOccurs="0"/>
<xs:element name="VLAN" type="xs:string" minOccurs="0"/>
<xs:element name="VN_MAD" type="xs:string" minOccurs="0"/>
<xs:element name="MAC_END" type="xs:string" minOccurs="0"/>
<xs:element name="IP_END" type="xs:string" minOccurs="0"/>
<xs:element name="IP6_ULA" type="xs:string" minOccurs="0"/>

View File

@ -32,7 +32,7 @@
<xs:element name="CLUSTER_ID" type="xs:integer"/>
<xs:element name="CLUSTER" type="xs:string"/>
<xs:element name="BRIDGE" type="xs:string"/>
<xs:element name="VLAN" type="xs:integer"/>
<xs:element name="VN_MAD" type="xs:integer"/>
<xs:element name="PARENT_NETWORK_ID" type="xs:string"/>
<xs:element name="PHYDEV" type="xs:string"/>
<xs:element name="VLAN_ID" type="xs:string"/>
@ -53,7 +53,7 @@
<xs:element name="SIZE" type="xs:integer"/>
<xs:element name="TYPE" type="xs:string"/>
<xs:element name="ULA_PREFIX" type="xs:string" minOccurs="0"/>
<xs:element name="VLAN" type="xs:string" minOccurs="0"/>
<xs:element name="VN_MAD" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>

View File

@ -145,7 +145,8 @@ DEFAULT_COST = [
# a single connection
#
# TIMEOUT: Maximum time in seconds the server will wait for the client to
# do anything while processing an RPC
# do anything while processing an RPC. This timeout will be also used when
# proxy calls to the master in a federation.
#
# RPC_LOG: Create a separated log file for xml-rpc requests, in
# "/var/log/one/one_xmlrpc.log".
@ -196,9 +197,6 @@ MAC_PREFIX = "02:00"
# HOSTS AND *NOT* THE FRONT-END. It defaults to /var/lib/one/datastores (or
# $ONE_LOCATION/var/datastores in self-contained mode)
#
# You can define a different DATASTORE_LOCATION in each cluster by updating
# its properties with onecluster update.
#
# DATASTORE_BASE_PATH: This is the base path for the SOURCE attribute of
# the images registered in a Datastore. This is a default value, that can be
# changed when the datastore is created.
@ -449,11 +447,6 @@ IM_MAD = [
# An example: "-l migrate=migrate_local,save"
# -p more than one action per host in parallel, needs support from hypervisor
# -s <shell> to execute remote commands, bash by default
# -d default snapshot strategy. It can be either 'detach' or 'suspend'. It
# defaults to 'suspend'.
# -i try to do live-snapshot if available. Currently supported only for kvm
# with qcow2 as the datastore TM_MAD. If not available, it will fallback
# on the default (-d)
#
# Note: You can use type = "qemu" to use qemu emulated guests, e.g. if your
# CPU does not have virtualization extensions or use nested Qemu-KVM hosts
@ -461,7 +454,7 @@ IM_MAD = [
VM_MAD = [
name = "kvm",
executable = "one_vmm_exec",
arguments = "-t 15 -r 0 -i kvm",
arguments = "-t 15 -r 0 kvm",
default = "vmm_exec/vmm_exec_kvm.conf",
type = "kvm",
imported_vms_actions = "shutdown, shutdown-hard, hold, release, suspend,
@ -629,7 +622,7 @@ VM_MAD = [
TM_MAD = [
executable = "one_tm",
arguments = "-t 15 -d dummy,lvm,shared,fs_lvm,qcow2,ssh,vmfs,ceph,dev,iscsi"
arguments = "-t 15 -d dummy,lvm,shared,fs_lvm,qcow2,ssh,vmfs,ceph,dev,vcenter,iscsi"
]
#*******************************************************************************
@ -648,7 +641,7 @@ TM_MAD = [
DATASTORE_MAD = [
executable = "one_datastore",
arguments = "-t 15 -d dummy,fs,vmfs,lvm,ceph,dev,iscsi -s shared,ssh,ceph"
arguments = "-t 15 -d dummy,fs,vmfs,lvm,ceph,dev,iscsi,vcenter -s shared,ssh,ceph"
]
#*******************************************************************************
@ -893,14 +886,14 @@ IMAGE_RESTRICTED_ATTR = "SOURCE"
# Normal VNets do not have restricted attributes.
#*******************************************************************************
VNET_RESTRICTED_ATTR = "VN_MAD"
VNET_RESTRICTED_ATTR = "PHYDEV"
VNET_RESTRICTED_ATTR = "VLAN_ID"
VNET_RESTRICTED_ATTR = "VLAN"
VNET_RESTRICTED_ATTR = "BRIDGE"
VNET_RESTRICTED_ATTR = "AR/VN_MAD"
VNET_RESTRICTED_ATTR = "AR/PHYDEV"
VNET_RESTRICTED_ATTR = "AR/VLAN_ID"
VNET_RESTRICTED_ATTR = "AR/VLAN"
VNET_RESTRICTED_ATTR = "AR/BRIDGE"
#*******************************************************************************
@ -942,6 +935,12 @@ INHERIT_IMAGE_ATTR = "ISCSI_IQN"
INHERIT_DATASTORE_ATTR = "GLUSTER_HOST"
INHERIT_DATASTORE_ATTR = "GLUSTER_VOLUME"
INHERIT_DATASTORE_ATTR = "DISK_TYPE"
INHERIT_DATASTORE_ATTR = "ADAPTER_TYPE"
INHERIT_IMAGE_ATTR = "DISK_TYPE"
INHERIT_IMAGE_ATTR = "ADAPTER_TYPE"
INHERIT_VNET_ATTR = "VLAN_TAGGED_ID"
INHERIT_VNET_ATTR = "BRIDGE_OVS"
INHERIT_VNET_ATTR = "FILTER_IP_SPOOFING"
@ -1017,6 +1016,10 @@ TM_MAD_CONF = [
NAME = "dev", LN_TARGET = "NONE", CLONE_TARGET = "NONE", SHARED = "YES"
]
TM_MAD_CONF = [
NAME = "vcenter", LN_TARGET = "NONE", CLONE_TARGET = "NONE", SHARED = "YES"
]
#*******************************************************************************
# Datastore Manager Driver Behavior Configuration
#*******************************************************************************
@ -1071,6 +1074,10 @@ DS_MAD_CONF = [
NAME = "vmfs", REQUIRED_ATTRS = "BRIDGE_LIST", PERSISTENT_ONLY = "NO"
]
DS_MAD_CONF = [
NAME = "vcenter", REQUIRED_ATTRS = "VCENTER_CLUSTER", PERSISTENT_ONLY = "YES"
]
#*******************************************************************************
# MarketPlace Driver Behavior Configuration
#*******************************************************************************

View File

@ -1,5 +1,5 @@
require 'rake/testtask'
require 'rake/rdoctask'
require 'rdoc/task'
require 'yard'
begin

View File

@ -1 +1 @@
1.6.0
1.8.2

View File

@ -185,7 +185,9 @@ class ManagedObject < ObjectWithMethods
:objectSet => [{ :obj => self }],
}])[0]
if ret.propSet.empty?
if !ret
return nil
elsif ret.propSet.empty?
return nil if ret.missingSet.empty?
raise ret.missingSet[0].fault
else
@ -217,7 +219,7 @@ class ManagedObject < ObjectWithMethods
def == x
out = (x.class == self.class && x._ref == @ref)
out = (out && x._connection.instanceUuid == self._connection.instanceUuid)
out = (x._connection.instanceUuid == self._connection.instanceUuid) if out && x._connection.host
out
end

View File

@ -115,27 +115,29 @@ class Connection < TrivialSoap
# hic sunt dracones
def obj2xml xml, name, type, is_array, o, attrs={}
expected = type(type)
fail "expected array, got #{o.class.wsdl_name}" if is_array and not (o.is_a? Array or (o.is_a? Hash and expected == BasicTypes::KeyValue))
fail "expected array for '#{name}', got #{o.class.wsdl_name}" if is_array and not (o.is_a? Array or (o.is_a? Hash and expected == BasicTypes::KeyValue))
case o
when Array, BasicTypes::KeyValue
if o.is_a? BasicTypes::KeyValue and expected != BasicTypes::KeyValue
fail "expected #{expected.wsdl_name}, got KeyValue"
fail "expected #{expected.wsdl_name} for '#{name}', got KeyValue"
elsif expected == BasicTypes::KeyValue and not is_array
xml.tag! name, attrs do
xml.tag! 'key', o[0].to_s
xml.tag! 'value', o[1].to_s
end
else
fail "expected #{expected.wsdl_name}, got array" unless is_array
fail "expected #{expected.wsdl_name} for '#{name}', got array" unless is_array
o.each do |e|
obj2xml xml, name, expected.wsdl_name, false, e, attrs
end
end
when BasicTypes::ManagedObject
fail "expected #{expected.wsdl_name}, got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class and not expected == BasicTypes::AnyType
fail "expected #{expected.wsdl_name} for '#{name}', got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class and not expected == BasicTypes::AnyType
xml.tag! name, o._ref, :type => o.class.wsdl_name
when BasicTypes::DataObject
fail "expected #{expected.wsdl_name}, got #{o.class.wsdl_name} for field #{name.inspect}" if expected and not expected >= o.class and not expected == BasicTypes::AnyType
if expected and not expected >= o.class and not expected == BasicTypes::AnyType
fail "expected #{expected.wsdl_name} for '#{name}', got #{o.class.wsdl_name} for field #{name.inspect}"
end
xml.tag! name, attrs.merge("xsi:type" => o.class.wsdl_name) do
o.class.full_props_desc.each do |desc|
if o.props.member? desc['name'].to_sym
@ -151,11 +153,11 @@ class Connection < TrivialSoap
if expected == BasicTypes::KeyValue and is_array
obj2xml xml, name, type, is_array, o.to_a, attrs
else
fail "expected #{expected.wsdl_name}, got a hash" unless expected <= BasicTypes::DataObject
fail "expected #{expected.wsdl_name} for '#{name}', got a hash" unless expected <= BasicTypes::DataObject
obj2xml xml, name, type, false, expected.new(o), attrs
end
when true, false
fail "expected #{expected.wsdl_name}, got a boolean" unless [BasicTypes::Boolean, BasicTypes::AnyType].member? expected
fail "expected #{expected.wsdl_name} for '#{name}', got a boolean" unless [BasicTypes::Boolean, BasicTypes::AnyType].member? expected
attrs['xsi:type'] = 'xsd:boolean' if expected == BasicTypes::AnyType
xml.tag! name, (o ? '1' : '0'), attrs
when Symbol, String
@ -181,7 +183,7 @@ class Connection < TrivialSoap
when BasicTypes::Int
attrs['xsi:type'] = 'xsd:int'
xml.tag! name, o.to_s, attrs
else fail "unexpected object class #{o.class}"
else fail "unexpected object class #{o.class} for '#{name}'"
end
xml
rescue

View File

@ -43,6 +43,13 @@ class NewDeserializer
def deserialize node, type=nil
type_attr = node['type']
# Work around for 1.5.x which doesn't populate node['type']
# XXX what changed
if node.attributes['type'] and not type_attr
type_attr = node.attributes['type'].value
end
type = type_attr if type_attr
if action = BUILTIN_TYPE_ACTIONS[type]
@ -64,15 +71,18 @@ class NewDeserializer
else fail
end
else
if type =~ /:/
type = type.split(":", 2)[1]
end
if type =~ /^ArrayOf/
type = DEMANGLED_ARRAY_TYPES[$'] || $'
return node.children.select(&:element?).map { |c| deserialize c, type }
end
if type =~ /:/
type = type.split(":", 2)[1]
end
klass = @loader.get(type) or fail "no such type #{type}"
klass = @loader.get(type) or fail "no such type '#{type}'"
case klass.kind
when :data
traverse_data node, klass
@ -229,7 +239,7 @@ class OldDeserializer
end
end
if ENV['RBVMOMI_NEW_DESERIALIZER'] == '1'
if ENV['RBVMOMI_NEW_DESERIALIZER'] == '1' || true # Always use new one now
Deserializer = NewDeserializer
else
Deserializer = OldDeserializer

View File

@ -49,9 +49,9 @@ class PBM < Connection
@serviceInstance ||= VIM::PbmServiceInstance self, 'ServiceInstance'
end
# Alias to serviceInstance.RetrieveServiceContent
# Alias to serviceInstance.PbmRetrieveServiceContent
def serviceContent
@serviceContent ||= serviceInstance.RetrieveServiceContent
@serviceContent ||= serviceInstance.PbmRetrieveServiceContent
end
# @private

View File

@ -0,0 +1,61 @@
# Copyright (c) 2013 VMware, Inc. All Rights Reserved.
require 'rbvmomi'
module RbVmomi
# A connection to one vSphere SMS endpoint.
# @see #serviceInstance
class SMS < Connection
# Connect to a vSphere SMS endpoint
#
# @param [VIM] Connection to main vSphere API endpoint
# @param [Hash] opts The options hash.
# @option opts [String] :host Host to connect to.
# @option opts [Numeric] :port (443) Port to connect to.
# @option opts [Boolean] :ssl (true) Whether to use SSL.
# @option opts [Boolean] :insecure (false) If true, ignore SSL certificate errors.
# @option opts [String] :path (/sms/sdk) SDK endpoint path.
# @option opts [Boolean] :debug (false) If true, print SOAP traffic to stderr.
def self.connect vim, opts = {}
fail unless opts.is_a? Hash
opts[:host] = vim.host
opts[:ssl] = true unless opts.member? :ssl or opts[:"no-ssl"]
opts[:insecure] ||= true
opts[:port] ||= (opts[:ssl] ? 443 : 80)
opts[:path] ||= '/sms/sdk'
opts[:ns] ||= 'urn:sms'
rev_given = opts[:rev] != nil
opts[:rev] = '4.0' unless rev_given
opts[:debug] = (!ENV['RBVMOMI_DEBUG'].empty? rescue false) unless opts.member? :debug
new(opts).tap do |sms|
sms.vcSessionCookie = vim.cookie.split('"')[1]
end
end
def vcSessionCookie= cookie
@vcSessionCookie = cookie
end
def rev= x
super
@serviceContent = nil
end
# Return the ServiceInstance
#
# The ServiceInstance is the root of the vSphere inventory.
def serviceInstance
@serviceInstance ||= VIM::SmsServiceInstance self, 'ServiceInstance'
end
# @private
def pretty_print pp
pp.text "SMS(#{@opts[:host]})"
end
add_extension_dir File.join(File.dirname(__FILE__), "sms")
load_vmodl(ENV['VMODL'] || File.join(File.dirname(__FILE__), "../../vmodl.db"))
end
end

View File

@ -0,0 +1,7 @@
class RbVmomi::SMS::SmsStorageManager
def RegisterProvider_Task2 providerSpec
self.RegisterProvider_Task providerSpec
end
end

View File

@ -14,7 +14,7 @@ class RbVmomi::TrivialSoap
@opts = opts
return unless @opts[:host] # for testcases
@debug = @opts[:debug]
@cookie = nil
@cookie = @opts[:cookie]
@lock = Mutex.new
@http = nil
restart_http

View File

@ -52,7 +52,7 @@ class TypeLoader
end
def get name
fail unless name.is_a? String
fail "name '#{name}' is #{name.class} expecting String" unless name.is_a? String
first_char = name[0].chr
if first_char.downcase == first_char

View File

@ -41,6 +41,8 @@
# computer (cluster), resource pool, vm_folder and datastore. Currently once
# computed, a new updated placement can't be generated.
class AdmissionControlledResourceScheduler
attr_reader :rp
def initialize vim, opts = {}
@vim = vim
@ -330,6 +332,10 @@ class AdmissionControlledResourceScheduler
# datastore without much intelligence, as long as it passes admission control.
# @return [VIM::Datastore] Chosen datastore
def datastore placementHint = nil
if @datastore
return @datastore
end
pod_datastores = pick_computer.datastore & datastores
eligible = pod_datastores.select do |ds|

View File

@ -102,6 +102,13 @@ class CachedOvfDeployer
# simplicity this function assumes we need to read the OVF file
# ourselves to know the names, and we map all of them to the same
# VIM::Network.
# If we're handling a file:// URI we need to strip the scheme as open-uri
# can't handle them.
if URI(ovf_url).scheme == "file" && URI(ovf_url).host.nil?
ovf_url = URI(ovf_url).path
end
ovf = open(ovf_url, 'r'){|io| Nokogiri::XML(io.read)}
ovf.remove_namespaces!
networks = ovf.xpath('//NetworkSection/Network').map{|x| x['name']}
@ -178,11 +185,10 @@ class CachedOvfDeployer
# prepare it for (linked) cloning and mark it as a template to signal
# we are done.
if !wait_for_template
vm.add_delta_disk_layer_on_all_disks
if opts[:config]
# XXX: Should we add a version that does retries?
vm.ReconfigVM_Task(:spec => opts[:config]).wait_for_completion
end
config = opts[:config] || {}
config = vm.update_spec_add_delta_disk_layer_on_all_disks(config)
# XXX: Should we add a version that does retries?
vm.ReconfigVM_Task(:spec => config).wait_for_completion
vm.MarkAsTemplate
end
end
@ -207,7 +213,7 @@ class CachedOvfDeployer
# or nil
def lookup_template template_name
template_path = "#{template_name}-#{@computer.name}"
template = @template_folder.traverse(template_path, VIM::VirtualMachine)
template = @template_folder.traverse(template_path, RbVmomi::VIM::VirtualMachine)
if template
config = template.config
is_template = config && config.template

View File

@ -93,7 +93,8 @@ class PerfAggregator
RbVmomi::VIM.SelectionSpec(:name => 'tsFolder'),
RbVmomi::VIM.SelectionSpec(:name => 'tsDatacenterVmFolder'),
RbVmomi::VIM.SelectionSpec(:name => 'tsDatacenterHostFolder'),
RbVmomi::VIM.SelectionSpec(:name => 'tsCluster'),
RbVmomi::VIM.SelectionSpec(:name => 'tsClusterRP'),
RbVmomi::VIM.SelectionSpec(:name => 'tsClusterHost'),
]
),
RbVmomi::VIM.TraversalSpec(
@ -115,7 +116,7 @@ class PerfAggregator
]
),
RbVmomi::VIM.TraversalSpec(
:name => 'tsCluster',
:name => 'tsClusterRP',
:type => 'ClusterComputeResource',
:path => 'resourcePool',
:skip => false,
@ -123,6 +124,13 @@ class PerfAggregator
RbVmomi::VIM.SelectionSpec(:name => 'tsRP'),
]
),
RbVmomi::VIM.TraversalSpec(
:name => 'tsClusterHost',
:type => 'ClusterComputeResource',
:path => 'host',
:skip => false,
:selectSet => []
),
RbVmomi::VIM.TraversalSpec(
:name => 'tsRP',
:type => 'ResourcePool',
@ -141,6 +149,7 @@ class PerfAggregator
:pathSet => ['name', 'parent', 'summary.effectiveCpu', 'summary.effectiveMemory']
},
{ :type => 'ResourcePool', :pathSet => ['name', 'parent'] },
{ :type => 'HostSystem', :pathSet => ['name', 'parent', 'runtime.connectionState'] },
{ :type => 'VirtualMachine', :pathSet => vm_prop_names },
]
)
@ -316,9 +325,18 @@ class PerfAggregator
'virtualDisk.totalWriteLatency' => :avg_ignore_zero,
}
end
host_perf_metrics = opts[:host_perf_metrics]
if !host_perf_metrics
host_perf_metrics = {
'cpu.usage' => :avg,
'mem.usage' => :avg,
}
end
vms_props, inventory = all_inventory_flat root_folder, prop_names
vms = vms_props.keys
hosts_props = inventory.select{|k, v| k.is_a?(VIM::HostSystem)}
conn = root_folder._connection
sc = conn.serviceContent
@ -349,8 +367,31 @@ class PerfAggregator
end
raise
end
connected_hosts = hosts_props.select do |k,v|
v['runtime.connectionState'] != "disconnected"
end
if connected_hosts.length > 0
hosts_stats = pm.retrieve_stats(
connected_hosts.keys, host_perf_metrics.keys,
:max_samples => 3
)
end
hosts_props.each do |host, props|
if !connected_hosts[host]
next
end
stats = hosts_stats[host] || {}
stats = stats[:metrics] || {}
stats = _aggregate_metrics [stats], host_perf_metrics
props.merge!(stats)
end
vms_props.each do |vm, props|
if !connected_vms.member?(vm)
next
end
props['num.vm'] = 1
powered_on = (props['runtime.powerState'] == 'poweredOn')
props['num.poweredonvm'] = powered_on ? 1 : 0
@ -392,25 +433,35 @@ class PerfAggregator
props['vc_uuid'] = vc_uuid
end
[vms_props, inventory]
[vms_props, inventory, hosts_props]
end
def collect_info_on_all_vms root_folders, opts = {}
log "Fetching information from all VCs ..."
vms_props = {}
hosts_props = {}
inventory = {}
lock = Mutex.new
root_folders.map do |root_folder|
Thread.new do
single_vms_props, single_inventory =
_collect_info_on_all_vms_single(root_folder, opts)
lock.synchronize do
vms_props.merge!(single_vms_props)
if inventory['root']
single_inventory['root']['children'] += inventory['root']['children']
begin
single_vms_props, single_inventory, single_hosts_props =
_collect_info_on_all_vms_single(root_folder, opts)
lock.synchronize do
vms_props.merge!(single_vms_props)
if inventory['root']
single_inventory['root']['children'] += inventory['root']['children']
end
inventory.merge!(single_inventory)
hosts_props.merge!(single_hosts_props)
end
inventory.merge!(single_inventory)
rescue Exception => ex
log "#{ex.class}: #{ex.message}"
ex.backtrace.each do |line|
log line
end
raise
end
end
end.each{|t| t.join}
@ -418,6 +469,7 @@ class PerfAggregator
log "Make data marshal friendly ..."
inventory = _make_marshal_friendly(inventory)
vms_props = _make_marshal_friendly(vms_props)
hosts_props = _make_marshal_friendly(hosts_props)
log "Perform external post processing ..."
if @vm_processing_callback
@ -442,7 +494,11 @@ class PerfAggregator
@inventory = inventory
@vms_props = vms_props
nil
{
'inventory' => inventory,
'vms_props' => vms_props,
'hosts_props' => hosts_props,
}
end
def _make_marshal_friendly hash

View File

@ -13,6 +13,7 @@ class VIM < Connection
# @option opts [Numeric] :port (443) Port to connect to.
# @option opts [Boolean] :ssl (true) Whether to use SSL.
# @option opts [Boolean] :insecure (false) If true, ignore SSL certificate errors.
# @option opts [String] :cookie If set, use cookie to connect instead of user/password
# @option opts [String] :user (root) Username.
# @option opts [String] :password Password.
# @option opts [String] :path (/sdk) SDK endpoint path.
@ -20,6 +21,7 @@ class VIM < Connection
def self.connect opts
fail unless opts.is_a? Hash
fail "host option required" unless opts[:host]
opts[:cookie] ||= nil
opts[:user] ||= 'root'
opts[:password] ||= ''
opts[:ssl] = true unless opts.member? :ssl or opts[:"no-ssl"]
@ -32,10 +34,12 @@ class VIM < Connection
opts[:debug] = (!ENV['RBVMOMI_DEBUG'].empty? rescue false) unless opts.member? :debug
new(opts).tap do |vim|
vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
unless opts[:cookie]
vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
end
unless rev_given
rev = vim.serviceContent.about.apiVersion
vim.rev = [rev, '5.0'].min
vim.rev = [rev, '5.5'].min
end
end
end
@ -45,7 +49,7 @@ class VIM < Connection
self.cookie = nil
super
end
def rev= x
super
@serviceContent = nil
@ -85,11 +89,36 @@ class VIM < Connection
def pretty_print pp
pp.text "VIM(#{@opts[:host]})"
end
def instanceUuid
serviceContent.about.instanceUuid
end
def get_log_lines logKey, lines=5, start=nil, host=nil
diagMgr = self.serviceContent.diagnosticManager
if !start
log = diagMgr.BrowseDiagnosticLog(:host => host, :key => logKey, :start => 999999999)
lineEnd = log.lineEnd
start = lineEnd - lines
end
start = start < 0 ? 0 : start
log = diagMgr.BrowseDiagnosticLog(:host => host, :key => logKey, :start => start)
if log.lineText.size > 0
[log.lineText.slice(-lines, log.lineText.size), log.lineEnd]
else
[log.lineText, log.lineEnd]
end
end
def get_log_keys host=nil
diagMgr = self.serviceContent.diagnosticManager
keys = []
diagMgr.QueryDescriptions(:host => host).each do |desc|
keys << "#{desc.key}"
end
keys
end
add_extension_dir File.join(File.dirname(__FILE__), "vim")
(ENV['RBVMOMI_VIM_EXTENSION_PATH']||'').split(':').each { |dir| add_extension_dir dir }

View File

@ -53,6 +53,16 @@ class RbVmomi::VIM::Folder
x if x.is_a? type
end
# Retrieve a managed entity by inventory path.
# @param path [String] A path of the form "My Folder/My Datacenter/vm/Discovered VM/VM1"
# @return [VIM::ManagedEntity]
def findByInventoryPath path
propSpecs = {
:entity => self, :inventoryPath => path
}
x = _connection.searchIndex.FindByInventoryPath(propSpecs)
end
# Alias to <tt>traverse path, type, true</tt>
# @see #traverse
def traverse! path, type=Object

View File

@ -35,7 +35,12 @@ class RbVmomi::VIM::ManagedObject
:type => self.class.wsdl_name
}]
}
_connection.propertyCollector.RetrieveProperties(:specSet => [spec])[0].to_hash
ret = _connection.propertyCollector.RetrieveProperties(:specSet => [spec])
if ret && ret.length > 0
ret[0].to_hash
else
{}
end
end
# Efficiently retrieve multiple properties from an object.

View File

@ -48,7 +48,16 @@ class RbVmomi::VIM::OvfManager
result.warning.each{|x| puts "OVF Warning: #{x.localizedMessage.chomp}" }
end
nfcLease = opts[:resourcePool].ImportVApp(:spec => result.importSpec,
importSpec = result.importSpec
if importSpec && importSpec.instantiationOst && importSpec.instantiationOst.child
importSpec.instantiationOst.child.each do |child|
child.section.map do |section|
section.xml = _handle_ost(section.xml, opts)
end
end
end
nfcLease = opts[:resourcePool].ImportVApp(:spec => importSpec,
:folder => opts[:vmFolder],
:host => opts[:host])
@ -56,30 +65,70 @@ class RbVmomi::VIM::OvfManager
raise nfcLease.error if nfcLease.state == "error"
begin
nfcLease.HttpNfcLeaseProgress(:percent => 5)
timeout, = nfcLease.collect 'info.leaseTimeout'
puts "DEBUG: Timeout: #{timeout}"
if timeout < 4 * 60
puts "WARNING: OVF upload NFC lease timeout less than 4 minutes"
end
progress = 5.0
result.fileItem.each do |fileItem|
deviceUrl = nfcLease.info.deviceUrl.find{|x| x.importKey == fileItem.deviceId}
leaseInfo, leaseState, leaseError = nfcLease.collect 'info', 'state', 'error'
# Retry nfcLease.collect because of PR 969599:
# If retrying property collector works, this means there is a network
# or VC overloading problem.
retrynum = 5
i = 1
while i <= retrynum && !leaseState
puts "Retrying at iteration #{i}"
sleep 1
leaseInfo, leaseState, leaseError = nfcLease.collect 'info', 'state', 'error'
i += 1
end
if leaseState != "ready"
raise "NFC lease is no longer ready: #{leaseState}: #{leaseError}"
end
if leaseInfo == nil
raise "NFC lease disappeared?"
end
deviceUrl = leaseInfo.deviceUrl.find{|x| x.importKey == fileItem.deviceId}
if !deviceUrl
raise "Couldn't find deviceURL for device '#{fileItem.deviceId}'"
end
# XXX handle file:// URIs
ovfFilename = opts[:uri].to_s
tmp = ovfFilename.split(/\//)
tmp.pop
tmp << fileItem.path
filename = tmp.join("/")
# If filename doesn't have a URI scheme, we're considering it a local file
if URI(filename).scheme.nil?
filename = "file://" + filename
end
method = fileItem.create ? "PUT" : "POST"
keepAliveThread = Thread.new do
while true
sleep 2 * 60
nfcLease.HttpNfcLeaseProgress(:percent => progress.to_i)
sleep 1 * 60
end
end
href = deviceUrl.url.gsub("*", opts[:host].config.network.vnic[0].spec.ip.ipAddress)
i = 1
ip = nil
begin
begin
puts "Iteration #{i}: Trying to get host's IP address ..."
ip = opts[:host].config.network.vnic[0].spec.ip.ipAddress
rescue Exception=>e
puts "Iteration #{i}: Couldn't get host's IP address: #{e}"
end
sleep 1
i += 1
end while i <= 5 && !ip
raise "Couldn't get host's IP address" unless ip
href = deviceUrl.url.gsub("*", ip)
downloadCmd = "#{CURLBIN} -L '#{URI::escape(filename)}'"
uploadCmd = "#{CURLBIN} -Ss -X #{method} --insecure -T - -H 'Content-Type: application/x-vnd.vmware-streamVmdk' '#{URI::escape(href)}'"
# Previously we used to append "-H 'Content-Length: #{fileItem.size}'"
@ -96,12 +145,56 @@ class RbVmomi::VIM::OvfManager
end
nfcLease.HttpNfcLeaseProgress(:percent => 100)
vm = nfcLease.info.entity
nfcLease.HttpNfcLeaseComplete
raise nfcLease.error if nfcLease.state == "error"
i = 1
vm = nil
begin
begin
puts "Iteration #{i}: Trying to access nfcLease.info.entity ..."
vm = nfcLease.info.entity
rescue Exception=>e
puts "Iteration #{i}: Couldn't access nfcLease.info.entity: #{e}"
end
sleep 1
i += 1
end while i <= 5 && !vm
raise "Couldn't access nfcLease.info.entity" unless vm
# Ignore sporadic connection errors caused by PR 1019166..
# Three attempts are made to execute HttpNfcLeaseComplete.
# Not critical if none goes through, as long as vm is obtained
#
# TODO: find the reason why HttpNfcLeaseComplete gets a wrong
# response (RetrievePropertiesResponse)
i = 0
begin
nfcLease.HttpNfcLeaseComplete
puts "HttpNfcLeaseComplete succeeded"
rescue RbVmomi::VIM::InvalidState
puts "HttpNfcLeaseComplete already finished.."
rescue Exception => e
puts "HttpNfcLeaseComplete failed at iteration #{i} with exception: #{e}"
i += 1
retry if i < 3
puts "Giving up HttpNfcLeaseComplete.."
end
vm
end
rescue Exception
(nfcLease.HttpNfcLeaseAbort rescue nil) if nfcLease
raise
end
def _handle_ost ost, opts = {}
ost = Nokogiri::XML(ost)
if opts[:vservice] == ['com.vmware.vim.vsm:extension_vservice']
ost.xpath('//vmw:Annotations/vmw:Providers/vmw:Provider').each do |x|
x['vmw:selected'] = 'selected'
end
ost.xpath('//vmw:Annotations/vmw:Providers').each do |x|
x['vmw:selected'] = 'com.vmware.vim.vsm:extension_vservice'
end
end
ost.to_s
end
end

View File

@ -46,13 +46,21 @@ class RbVmomi::VIM::PerformanceManager
end
end
metric_ids = metrics.map do |x|
instances = opts[:instance] || '*'
if !instances.is_a?(Array)
instances = [instances]
end
metric_ids = []
metrics.each do |x|
counter = perfcounter_hash[x]
if !counter
pp perfcounter_hash.keys
fail "Counter for #{x} couldn't be found"
end
RbVmomi::VIM::PerfMetricId(:counterId => counter.key, :instance => '*')
instances.each do |instance|
metric_ids << RbVmomi::VIM::PerfMetricId(:counterId => counter.key,
:instance => instance)
end
end
query_specs = objects.map do |obj|
RbVmomi::VIM::PerfQuerySpec({
@ -65,19 +73,36 @@ class RbVmomi::VIM::PerformanceManager
end
stats = QueryPerf(:querySpec => query_specs)
Hash[stats.map do |res|
[
res.entity,
{
:sampleInfo => res.sampleInfo,
:metrics => Hash[res.value.map do |metric|
[perfcounter_idhash[metric.id.counterId].name, metric.value]
end]
}
]
end]
if !opts[:multi_instance]
Hash[stats.map do |res|
[
res.entity,
{
:sampleInfo => res.sampleInfo,
:metrics => Hash[res.value.map do |metric|
metric_name = perfcounter_idhash[metric.id.counterId].name
[metric_name, metric.value]
end]
}
]
end]
else
Hash[stats.map do |res|
[
res.entity,
{
:sampleInfo => res.sampleInfo,
:metrics => Hash[res.value.map do |metric|
metric_name = perfcounter_idhash[metric.id.counterId].name
[[metric_name, metric.id.instance], metric.value]
end]
}
]
end]
end
end
def active_intervals
intervals = historicalInterval
Hash[(1..4).map { |level| [level, intervals.select { |x| x.enabled && x.level >= level }] }]

View File

@ -34,26 +34,41 @@ class RbVmomi::VIM::VirtualMachine
def add_delta_disk_layer_on_all_disks
devices, = self.collect 'config.hardware.device'
disks = devices.grep(RbVmomi::VIM::VirtualDisk)
# XXX: Should create a single reconfig spec instead of one per disk
spec = update_spec_add_delta_disk_layer_on_all_disks
self.ReconfigVM_Task(:spec => spec).wait_for_completion
end
# Updates a passed in spec to perform the task of adding a delta disk layer
# on top of all disks. Does the same as add_delta_disk_layer_on_all_disks
# but instead of issuing the ReconfigVM_Task, it just constructs the
# spec, so that the caller can batch a couple of updates into one
# ReconfigVM_Task.
def update_spec_add_delta_disk_layer_on_all_disks spec = {}
devices, = self.collect 'config.hardware.device'
disks = devices.grep(RbVmomi::VIM::VirtualDisk)
device_change = []
disks.each do |disk|
spec = {
:deviceChange => [
{
:operation => :remove,
:device => disk
},
{
:operation => :add,
:fileOperation => :create,
:device => disk.dup.tap { |x|
x.backing = x.backing.dup
x.backing.fileName = "[#{disk.backing.datastore.name}]"
x.backing.parent = disk.backing
},
}
]
device_change << {
:operation => :remove,
:device => disk
}
device_change << {
:operation => :add,
:fileOperation => :create,
:device => disk.dup.tap { |x|
x.backing = x.backing.dup
x.backing.fileName = "[#{disk.backing.datastore.name}]"
x.backing.parent = disk.backing
},
}
self.ReconfigVM_Task(:spec => spec).wait_for_completion
end
if spec.is_a?(RbVmomi::VIM::VirtualMachineConfigSpec)
spec.deviceChange ||= []
spec.deviceChange += device_change
else
spec[:deviceChange] ||= []
spec[:deviceChange] += device_change
end
spec
end
end

Binary file not shown.

View File

@ -209,8 +209,6 @@ const bool AclManager::authorize(
const PoolObjectAuth& obj_perms,
AuthRequest::Operation op)
{
ostringstream oss;
bool auth = false;
// Build masks for request
@ -241,17 +239,19 @@ const bool AclManager::authorize(
resource_gid_req = AclRule::NONE_ID;
}
long long resource_cid_req;
set<long long> resource_cid_req;
if ((obj_perms.cid >= 0) && (!obj_perms.disable_cluster_acl))
if (!obj_perms.disable_cluster_acl)
{
resource_cid_req = obj_perms.obj_type |
AclRule::CLUSTER_ID |
obj_perms.cid;
}
else
{
resource_cid_req = AclRule::NONE_ID;
set<int>::iterator i;
for(i = obj_perms.cids.begin(); i != obj_perms.cids.end(); i++)
{
resource_cid_req.insert( obj_perms.obj_type |
AclRule::CLUSTER_ID |
*i
);
}
}
long long resource_all_req ;
@ -279,34 +279,35 @@ const bool AclManager::authorize(
AclRule::CLUSTER_ID |
0x00000000FFFFFFFFLL;
// Create a temporal rule, to log the request
long long log_resource;
if (NebulaLog::log_level() >= Log::DDEBUG)
{
ostringstream oss;
if ( obj_perms.oid >= 0 )
{
log_resource = resource_oid_req;
}
else if ( obj_perms.gid >= 0 )
{
log_resource = resource_gid_req;
}
else if ( obj_perms.cid >= 0 )
{
log_resource = resource_cid_req;
}
else
{
log_resource = resource_all_req;
}
// Create a temporal rule, to log the request
long long log_resource;
AclRule log_rule(-1,
AclRule::INDIVIDUAL_ID | uid,
log_resource,
rights_req,
AclRule::INDIVIDUAL_ID | zone_id);
if ( obj_perms.oid >= 0 )
{
log_resource = resource_oid_req;
}
else if ( obj_perms.gid >= 0 )
{
log_resource = resource_gid_req;
}
else
{
log_resource = resource_all_req;
}
oss << "Request " << log_rule.to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
AclRule log_rule(-1,
AclRule::INDIVIDUAL_ID | uid,
log_resource,
rights_req,
AclRule::INDIVIDUAL_ID | zone_id);
oss << "Request " << log_rule.to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
}
// -------------------------------------------------------------------------
// Create temporary rules from the object permissions
@ -388,8 +389,7 @@ const bool AclManager::authorize(
}
}
oss.str("No more rules, permission not granted ");
NebulaLog::log("ACL",Log::DDEBUG,oss);
NebulaLog::log("ACL",Log::DDEBUG,"No more rules, permission not granted ");
return false;
}
@ -398,16 +398,16 @@ const bool AclManager::authorize(
/* -------------------------------------------------------------------------- */
bool AclManager::match_rules_wrapper(
long long user_req,
long long resource_oid_req,
long long resource_gid_req,
long long resource_cid_req,
long long resource_all_req,
long long rights_req,
long long individual_obj_type,
long long group_obj_type,
long long cluster_obj_type,
multimap<long long, AclRule*> &tmp_rules)
long long user_req,
long long resource_oid_req,
long long resource_gid_req,
const set<long long>& resource_cid_req,
long long resource_all_req,
long long rights_req,
long long individual_obj_type,
long long group_obj_type,
long long cluster_obj_type,
const multimap<long long, AclRule*> &tmp_rules)
{
bool auth = false;
@ -452,26 +452,47 @@ bool AclManager::match_rules_wrapper(
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool AclManager::match_rules(
long long user_req,
long long resource_oid_req,
long long resource_gid_req,
long long resource_cid_req,
long long resource_all_req,
long long rights_req,
long long resource_oid_mask,
long long resource_gid_mask,
static bool match_cluster_req(
const set<long long> &resource_cid_req,
long long resource_cid_mask,
multimap<long long, AclRule*> &rules)
long long rule_resource)
{
set<long long>::iterator i;
for(i = resource_cid_req.begin(); i != resource_cid_req.end(); i++)
{
// rule's object type and cluster object ID match
if ( ( rule_resource & resource_cid_mask ) == *i )
{
return true;
}
}
return false;
}
/* -------------------------------------------------------------------------- */
bool AclManager::match_rules(
long long user_req,
long long resource_oid_req,
long long resource_gid_req,
const set<long long>& resource_cid_req,
long long resource_all_req,
long long rights_req,
long long resource_oid_mask,
long long resource_gid_mask,
long long resource_cid_mask,
const multimap<long long, AclRule*> &rules)
{
bool auth = false;
ostringstream oss;
multimap<long long, AclRule *>::iterator it;
multimap<long long, AclRule *>::const_iterator it;
pair<multimap<long long, AclRule *>::iterator,
multimap<long long, AclRule *>::iterator> index;
pair<multimap<long long, AclRule *>::const_iterator,
multimap<long long, AclRule *>::const_iterator> index;
long long zone_oid_mask = AclRule::INDIVIDUAL_ID | 0x00000000FFFFFFFFLL;
long long zone_req = AclRule::INDIVIDUAL_ID | zone_id;
@ -481,9 +502,12 @@ bool AclManager::match_rules(
for ( it = index.first; it != index.second; it++)
{
oss.str("");
oss << "> Rule " << it->second->to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
if (NebulaLog::log_level() >= Log::DDEBUG)
{
oss.str("");
oss << "> Rule " << it->second->to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
}
auth =
(
@ -507,14 +531,14 @@ bool AclManager::match_rules(
// Or rule's object type and individual object ID match
( ( it->second->resource & resource_oid_mask ) == resource_oid_req )
||
// Or rule's object type and cluster object ID match
( ( it->second->resource & resource_cid_mask ) == resource_cid_req )
// Or rule's object type and one of the cluster object ID match
match_cluster_req(resource_cid_req, resource_cid_mask,
it->second->resource)
);
if ( auth == true )
{
oss.str("Permission granted");
NebulaLog::log("ACL",Log::DDEBUG,oss);
NebulaLog::log("ACL",Log::DDEBUG,"Permission granted");
break;
}
@ -960,19 +984,22 @@ void AclManager::reverse_search(int uid,
long long zone_all_req = AclRule::ALL_ID;
// Create a temporal rule, to log the request
long long log_resource;
if (NebulaLog::log_level() >= Log::DDEBUG)
{
// Create a temporal rule, to log the request
long long log_resource;
log_resource = resource_all_req;
log_resource = resource_all_req;
AclRule log_rule(-1,
AclRule::INDIVIDUAL_ID | uid,
log_resource,
rights_req,
zone_oid_req);
AclRule log_rule(-1,
AclRule::INDIVIDUAL_ID | uid,
log_resource,
rights_req,
zone_oid_req);
oss << "Reverse search request " << log_rule.to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
oss << "Reverse search request " << log_rule.to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
}
// ---------------------------------------------------
// Look for the rules that match
@ -1015,9 +1042,12 @@ void AclManager::reverse_search(int uid,
)
)
{
oss.str("");
oss << "> Rule " << it->second->to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
if (NebulaLog::log_level() >= Log::DDEBUG)
{
oss.str("");
oss << "> Rule " << it->second->to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
}
// Rule grants permission for all objects of this type
if ((!disable_all_acl) &&
@ -1099,7 +1129,6 @@ int AclManager::select_cb(void *nil, int num, char **values, char **names)
return -1;
}
ostringstream oss;
istringstream iss;
int oid = atoi(values[0]);
@ -1126,8 +1155,13 @@ int AclManager::select_cb(void *nil, int num, char **values, char **names)
rule_values[2],
rule_values[3]);
oss << "Loading ACL Rule " << rule->to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
if (NebulaLog::log_level() >= Log::DDEBUG)
{
ostringstream oss;
oss << "Loading ACL Rule " << rule->to_str();
NebulaLog::log("ACL",Log::DDEBUG,oss);
}
acl_rules.insert( make_pair(rule->user, rule) );
acl_rules_oids.insert( make_pair(rule->oid, rule) );

View File

@ -27,8 +27,8 @@
:size: 5
:left: true
:CLUSTER:
:desc: Name of the Cluster
:CLUSTERS:
:desc: Cluster IDs
:size: 12
:left: true
@ -61,7 +61,7 @@
- :NAME
- :SIZE
- :AVAIL
- :CLUSTER
- :CLUSTERS
- :IMAGES
- :TYPE
- :DS

View File

@ -18,8 +18,8 @@
:size: 19
:left: true
:CLUSTER:
:desc: Name of the Cluster
:CLUSTERS:
:desc: Cluster IDs
:size: 10
:left: true
@ -37,6 +37,6 @@
- :USER
- :GROUP
- :NAME
- :CLUSTER
- :CLUSTERS
- :BRIDGE
- :LEASES

View File

@ -289,8 +289,8 @@ EOT
:name => 'ssh',
:large => '--ssh [file]',
:description => "Add an ssh public key to the context. If the \n"<<
(' '*31)<<"file is omited then the user variable \n"<<
(' '*31)<<"SSH_PUBLIC_KEY will be used.",
(' '*31) << "file is omited then the user variable \n"<<
(' '*31) << "SSH_PUBLIC_KEY will be used.",
:format => String,
:proc => lambda do |o, options|
if !o
@ -332,6 +332,12 @@ EOT
}
]
FORCE={
:name => 'force',
:large => '--force',
:description => 'Overwrite the file'
}
TEMPLATE_OPTIONS_VM=[TEMPLATE_NAME_VM]+TEMPLATE_OPTIONS+[DRY]
CAPACITY_OPTIONS_VM=[TEMPLATE_OPTIONS[0],TEMPLATE_OPTIONS[1],TEMPLATE_OPTIONS[3]]
@ -820,6 +826,15 @@ EOT
end
end
def OpenNebulaHelper.clusters_str(clusters)
if clusters.nil?
"-"
else
[clusters].flatten.join(',')
end
end
def OpenNebulaHelper.update_template(id, resource, path=nil, xpath='TEMPLATE')
return update_template_helper(false, id, resource, path, xpath)
end
@ -955,7 +970,7 @@ EOT
end
if !lines.empty?
"CONTEXT=[\n"<<lines.map{|l| " "<<l }.join(",\n")<<"\n]\n"
"CONTEXT=[\n" << lines.map{|l| " " << l }.join(",\n") << "\n]\n"
else
nil
end
@ -1006,7 +1021,7 @@ EOT
if options[:vnc_password]
template << ", PASSWD=\"#{options[:vnc_password]}\""
end
template<<' ]'<<"\n"
template<<' ]' << "\n"
end
if options[:spice]
@ -1015,7 +1030,7 @@ EOT
if options[:spice_password]
template << ", PASSWD=\"#{options[:spice_password]}\""
end
template<<' ]'<<"\n"
template<<' ]' << "\n"
end
context=create_context(options)
@ -1046,4 +1061,105 @@ EOT
# in options hash
(template_options-options.keys)!=template_options
end
def self.sunstone_url
if (one_sunstone = ENV['ONE_SUNSTONE'])
one_sunstone
elsif (one_xmlrpc = ENV['ONE_XMLRPC'])
uri = URI(one_xmlrpc)
"#{uri.scheme}://#{uri.host}:9869"
else
"http://localhost:9869"
end
end
def self.download_resource_sunstone(kind, id, path, force)
client = OneHelper.client
user, password = client.one_auth.split(":", 2)
# Step 1: Build Session to get Cookie
uri = URI(File.join(sunstone_url,"login"))
req = Net::HTTP::Post.new(uri)
req.basic_auth user, password
begin
res = Net::HTTP.start(uri.hostname, uri.port) do |http|
http.request(req)
end
rescue
return OpenNebula::Error.new("Error connecting to '#{uri}'.")
end
cookie = res.response['set-cookie'].split('; ')[0]
if cookie.nil?
return OpenNebula::Error.new("Unable to get Cookie. Is OpenNebula running?")
end
# Step 2: Open '/' to get the csrftoken
uri = URI(sunstone_url)
req = Net::HTTP::Get.new(uri)
req['Cookie'] = cookie
begin
res = Net::HTTP.start(uri.hostname, uri.port) do |http|
http.request(req)
end
rescue
return OpenNebula::Error.new("Error connecting to '#{uri}'.")
end
m = res.body.match(/var csrftoken = '(.*)';/)
csrftoken = m[1] rescue nil
if csrftoken.nil?
return OpenNebula::Error.new("Unable to get csrftoken.")
end
# Step 3: Download resource
uri = URI(File.join(sunstone_url,
kind.to_s,
id.to_s,
"download?csrftoken=#{csrftoken}"))
req = Net::HTTP::Get.new(uri)
req['Cookie'] = cookie
req['User-Agent'] = "OpenNebula CLI"
begin
File.open(path, 'wb') do |f|
Net::HTTP.start(uri.hostname, uri.port) do |http|
http.request(req) do |res|
res.read_body do |chunk|
f.write(chunk)
end
end
end
end
rescue Errno::EACCES
return OpenNebula::Error.new("Target file not writable.")
end
error_message = nil
File.open(path, 'rb') do |f|
begin
f.seek(-1024, IO::SEEK_END)
rescue Errno::EINVAL
end
tail = f.read
m = tail.match(/@\^_\^@ (.*) @\^_\^@/m)
error_message = m[1] if m
end
if error_message
File.unlink(path)
return OpenNebula::Error.new("Remote server error: #{error_message}")
end
end
end

View File

@ -75,8 +75,8 @@ class OneDatastoreHelper < OpenNebulaHelper::OneHelper
end
end
column :CLUSTER, "Name of the Cluster", :left, :size=>12 do |d|
OpenNebulaHelper.cluster_str(d["CLUSTER"])
column :CLUSTERS, "Cluster IDs", :left, :size=>12 do |d|
OpenNebulaHelper.clusters_str(d["CLUSTERS"]["ID"])
end
column :IMAGES, "Number of Images", :size=>6 do |d|
@ -105,7 +105,7 @@ class OneDatastoreHelper < OpenNebulaHelper::OneHelper
Datastore::SHORT_DATASTORE_STATES[state]
end
default :ID, :USER, :GROUP, :NAME, :SIZE, :AVAIL, :CLUSTER, :IMAGES,
default :ID, :USER, :GROUP, :NAME, :SIZE, :AVAIL, :CLUSTERS, :IMAGES,
:TYPE, :DS, :TM, :STAT
end
@ -136,7 +136,8 @@ class OneDatastoreHelper < OpenNebulaHelper::OneHelper
puts str % ["NAME", datastore.name]
puts str % ["USER", datastore['UNAME']]
puts str % ["GROUP", datastore['GNAME']]
puts str % ["CLUSTER", OpenNebulaHelper.cluster_str(datastore['CLUSTER'])]
puts str % ["CLUSTERS",
OpenNebulaHelper.clusters_str(datastore.retrieve_elements("CLUSTERS/ID"))]
puts str % ["TYPE", datastore.type_str]
puts str % ["DS_MAD", datastore['DS_MAD']]

View File

@ -17,6 +17,32 @@
require 'one_helper'
class OneMarketPlaceAppHelper < OpenNebulaHelper::OneHelper
TEMPLATE_OPTIONS=[
{
:name => "name",
:large => "--name name",
:format => String,
:description => "Name of the new MarketPlaceApp"
},
{
:name => "description",
:large => "--description description",
:format => String,
:description => "Description for the new MarketPlaceApp"
},
{
:name => "image",
:large => "--image id|name" ,
:description => "Selects the image",
:format => String,
:template_key => "origin_id",
:proc => lambda { |o, options|
OpenNebulaHelper.rname_to_id(o, "IMAGE")
}
},
OpenNebulaHelper::DRY
]
def self.rname
"MARKETPLACEAPP"
end
@ -74,6 +100,18 @@ class OneMarketPlaceAppHelper < OpenNebulaHelper::OneHelper
table
end
def self.create_template_options_used?(options)
# Get the template options names as symbols. options hash
# uses symbols
template_options=self::TEMPLATE_OPTIONS.map do |o|
o[:name].to_sym
end
# Check if one at least one of the template options is
# in options hash
(template_options-options.keys)!=template_options
end
private
def factory(id=nil)
@ -141,4 +179,34 @@ class OneMarketPlaceAppHelper < OpenNebulaHelper::OneHelper
puts
end
def self.create_variables(options, name)
if Array===name
names=name
else
names=[name]
end
t=''
names.each do |n|
if options[n]
t<<"#{n.to_s.upcase}=\"#{options[n]}\"\n"
end
end
t
end
def self.create_datastore_template(options)
template_options=TEMPLATE_OPTIONS.map do |o|
o[:name].to_sym
end
template=create_variables(options, template_options-[:dry,:image])
template<<"ORIGIN_ID=#{options[:image]}\n" if options[:image]
template << "TYPE=image\n"
[0, template]
end
end

View File

@ -131,7 +131,7 @@ EOT
puts "There are some parameters that require user input. Use the string <<EDITOR>> to launch an editor (e.g. for multi-line inputs)"
user_inputs.each do |key, val|
input_cfg = val.split('|')
input_cfg = val.split('|', -1)
if input_cfg.length < 3
STDERR.puts "Malformed user input. It should have at least 3 parts separated by '|':"
@ -139,8 +139,8 @@ EOT
exit(-1)
end
optional, type, description, params, initial = input_cfg
optional.strip!
mandatory, type, description, params, initial = input_cfg
optional = mandatory.strip == "O"
type.strip!
description.strip!
@ -195,7 +195,13 @@ EOT
answer = STDIN.readline.chop
answer = initial if (answer == "")
end while (answer =~ exp) == nil
noanswer = ((answer == "") && optional)
end while !noanswer && (answer =~ exp) == nil
if noanswer
next
end
when 'range', 'range-float'
min,max = params.split('..')
@ -225,7 +231,13 @@ EOT
answer = STDIN.readline.chop
answer = initial if (answer == "")
end while ((answer =~ exp) == nil || answer.to_f < min || answer.to_f > max)
noanswer = ((answer == "") && optional)
end while !noanswer && ((answer =~ exp) == nil || answer.to_f < min || answer.to_f > max)
if noanswer
next
end
when 'list'
options = params.split(",")
@ -248,7 +260,17 @@ EOT
answer = options[answer.to_i]
end
end while (!options.include?(answer))
noanswer = ((answer == "") && optional)
end while !noanswer && (!options.include?(answer))
if noanswer
next
end
when 'fixed'
puts " Fixed value of (#{initial}). Cannot be changed"
answer = initial
else
STDERR.puts "Wrong type for user input:"
@ -256,8 +278,12 @@ EOT
exit(-1)
end
answers << "#{key} = \""
answers << answer.gsub('"', "\\\"") << "\"\n"
# Do not replace values that are equal to the ones already in the
# template. Useful for cpu, mem, vcpu
if answer != template['VMTEMPLATE']['TEMPLATE'][key]
answers << "#{key} = \""
answers << answer.gsub('"', "\\\"") << "\"\n"
end
end
answers

View File

@ -336,6 +336,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
:PROLOG_MIGRATE_FAILURE => :migrate,
:PROLOG_MIGRATE_POWEROFF_FAILURE => :migrate,
:PROLOG_MIGRATE_SUSPEND_FAILURE => :migrate,
:PROLOG_MIGRATE_UNKNOWN_FAILURE => :migrate,
:PROLOG_FAILURE => :prolog,
:PROLOG_RESUME_FAILURE => :resume,
:PROLOG_UNDEPLOY_FAILURE => :resume,
@ -729,7 +730,6 @@ in the frontend machine.
nic_default = {"NETWORK" => "-",
"IP" => "-",
"MAC"=> "-",
"VLAN"=>"no",
"BRIDGE"=>"-"}
shown_ips = []
@ -781,8 +781,7 @@ in the frontend machine.
"NIC_ID" => "-",
"IP" => ip,
"NETWORK" => "Additional IP",
"BRIDGE" => "-",
"VLAN" => "-"
"BRIDGE" => "-"
}
end
@ -803,14 +802,6 @@ in the frontend machine.
end
end
column :VLAN, "", :size=>4 do |d|
if d["DOUBLE_ENTRY"]
""
else
d["VLAN"].downcase
end
end
column :BRIDGE, "", :left, :size=>12 do |d|
if d["DOUBLE_ENTRY"]
""

View File

@ -102,10 +102,11 @@ class OneVNetHelper < OpenNebulaHelper::OneHelper
:description=> "Netmask in dot notation"
]
VLAN = [
:name => "vlan",
:large => "--vlan",
:description=> "Use network isolation"
VN_MAD = [
:name => "vn_mad",
:large => "--vn_mad mad",
:format => String,
:description=> "Use this driver for the network"
]
VLAN_ID = [
@ -116,7 +117,7 @@ class OneVNetHelper < OpenNebulaHelper::OneHelper
]
ADDAR_OPTIONS = [
SIZE, MAC, IP, IP6_GLOBAL, IP6_ULA, GATEWAY, NETMASK, VLAN, VLAN_ID ]
SIZE, MAC, IP, IP6_GLOBAL, IP6_ULA, GATEWAY, NETMASK, VN_MAD, VLAN_ID ]
def self.rname
"VNET"
@ -149,8 +150,8 @@ class OneVNetHelper < OpenNebulaHelper::OneHelper
d["NAME"]
end
column :CLUSTER, "Name of the Cluster", :left, :size=>10 do |d|
OpenNebulaHelper.cluster_str(d["CLUSTER"])
column :CLUSTERS, "Cluster IDs", :left, :size=>10 do |d|
OpenNebulaHelper.clusters_str(d["CLUSTERS"]["ID"])
end
column :BRIDGE, "Bridge associated to the Virtual Network", :left,
@ -163,7 +164,7 @@ class OneVNetHelper < OpenNebulaHelper::OneHelper
d["USED_LEASES"]
end
default :ID, :USER, :GROUP, :NAME, :CLUSTER, :BRIDGE, :LEASES
default :ID, :USER, :GROUP, :NAME, :CLUSTERS, :BRIDGE, :LEASES
end
table
@ -209,9 +210,10 @@ class OneVNetHelper < OpenNebulaHelper::OneHelper
puts str % ["NAME", vn['NAME']]
puts str % ["USER", vn['UNAME']]
puts str % ["GROUP", vn['GNAME']]
puts str % ["CLUSTER", OpenNebulaHelper.cluster_str(vn['CLUSTER'])]
puts str % ["CLUSTERS",
OpenNebulaHelper.clusters_str(vn.retrieve_elements("CLUSTERS/ID"))]
puts str % ["BRIDGE", vn["BRIDGE"]]
puts str % ["VLAN", OpenNebulaHelper.boolean_to_str(vn['VLAN'])]
puts str % ["VN_MAD", vn['VN_MAD']] if !vn['VN_MAD'].empty?
puts str % ["PHYSICAL DEVICE", vn["PHYDEV"]] if !vn["PHYDEV"].empty?
puts str % ["VLAN ID", vn["VLAN_ID"]] if !vn["VLAN_ID"].empty?
puts str % ["USED LEASES", vn['USED_LEASES']]
@ -251,6 +253,7 @@ class OneVNetHelper < OpenNebulaHelper::OneHelper
str="%-15s: %-20s"
puts str % ["SIZE", ar["SIZE"]]
puts str % ["LEASES", ar["USED_LEASES"]]
puts str % ["VN_MAD", ar["VN_MAD"]] if ar["VN_MAD"]
puts
format = "%-10s %34s %34s"

View File

@ -176,16 +176,6 @@ cmd=CommandParser::CmdParser.new(ARGV) do
end
end
download_desc = <<-EOT.unindent
Downloads an image to a file
EOT
command :download, download_desc, :imageid, :path do
helper.perform_action(args[0],options,"downloaded") do |image|
image.download(args[1], helper.client)
end
end
delete_desc = <<-EOT.unindent
Deletes the given Image
EOT

View File

@ -88,7 +88,8 @@ CommandParser::CmdParser.new(ARGV) do
Creates a new marketplace app in the given marketplace
EOT
command :create, create_desc, :file, :options=>CREATE_OPTIONS do
command :create, create_desc, [:file, nil], :options=>CREATE_OPTIONS +
OneMarketPlaceAppHelper::TEMPLATE_OPTIONS do
if options[:marketplace].nil?
STDERR.puts "Marketplace to save the app is mandatory: "
@ -96,12 +97,35 @@ CommandParser::CmdParser.new(ARGV) do
exit(-1)
end
if args[0] && OneMarketPlaceAppHelper.create_template_options_used?(options)
STDERR.puts "You can not use both template file and template"<<
" creation options."
next -1
end
helper.create_resource(options) do |app|
begin
template=File.read(args[0])
if args[0]
template=File.read(args[0])
else
res = OneMarketPlaceAppHelper.create_datastore_template(options)
if res.first != 0
STDERR.puts res.last
next -1
end
template = res.last
end
if options[:dry]
puts template
exit 0
end
app.allocate(template, options[:marketplace])
rescue => e
STDERR.puts e.messsage
STDERR.puts e.message
exit(-1)
end
end
@ -131,9 +155,11 @@ CommandParser::CmdParser.new(ARGV) do
Downloads a MarketApp to a file
EOT
command :download, download_desc, :appid, :path do
command :download, download_desc, :appid, :path,
:options => [OpenNebulaHelper::FORCE] do
helper.perform_action(args[0],options,"downloaded") do |app|
app.download(args[1], helper.client)
download_args = [:marketplaceapp, args[0], args[1], options[:force]]
OpenNebulaHelper.download_resource_sunstone(*download_args)
end
end

View File

@ -195,6 +195,115 @@ cmd=CommandParser::CmdParser.new(ARGV) do
next if STDIN.gets.strip.downcase != 'y'
ds_input = ""
rp_input = ""
# Datastores
STDOUT.print "\n This template is currently set to be "\
"deployed in datastore #{t[:default_ds]}."\
"\n Do you want to keep the default [y/n]? "
if STDIN.gets.strip.downcase == 'n'
ds_split = t[:ds].split("|")
list_of_ds = ds_split[-2]
default_ds = ds_split[-1]
ds_input = ds_split[0] + "|" + ds_split[1] + "|" +
ds_split[2] + "|"
# Available list of datastores
input_str = " The list of available datastores to be"\
" presented to the user are \"#{list_of_ds}\""
input_str+= "\n Press y to agree, or input a comma"\
" separated list of datastores to edit "\
"[y/comma separated list] "
STDOUT.print input_str
answer = STDIN.gets.strip
if answer.downcase == 'y'
ds_input += ds_split[3] + "|"
else
ds_input += answer + "|"
end
# Default
input_str = " The default datastore presented to "\
"the end user is set to \"#{default_ds}\"."
input_str+= "\n Press y to agree, or input a new "\
"datastore [y/datastore name] "
STDOUT.print input_str
answer = STDIN.gets.strip
if answer.downcase == 'y'
ds_input += ds_split[4]
else
ds_input += answer
end
end
# Resource Pools
rp_split = t[:rp].split("|")
if rp_split.size > 3
STDOUT.print "\n Do you want VMs cloned from this"\
" template to run in the default"\
" resource pool [y/n]? "
if STDIN.gets.strip.downcase == 'n'
list_of_rp = rp_split[-2]
default_rp = rp_split[-1]
rp_input = rp_split[0] + "|" + rp_split[1] + "|" +
rp_split[2] + "|"
# Available list of resource pools
input_str = " The list of available resource pools "\
"to be presented to the user are "\
"\"#{list_of_rp}\""
input_str+= "\n Press y to agree, or input a comma"\
" separated list of resource pools to edit "\
"[y/comma separated list] "
STDOUT.print input_str
answer = STDIN.gets.strip
if answer.downcase == 'y'
rp_input += rp_split[3] + "|"
else
rp_input += answer + "|"
end
# Default
input_str = " The default resource pool presented "\
"to the end user is set to"\
" \"#{default_rp}\"."
input_str+= "\n Press y to agree, or input a new "\
"resource pool [y/resource pool name] "
STDOUT.print input_str
answer = STDIN.gets.strip
if answer.downcase == 'y'
rp_input += rp_split[4]
else
rp_input += answer
end
end
end
if ds_input != "" ||
rp_input != ""
t[:one] += "USER_INPUTS=["
t[:one] += "VCENTER_DATASTORE=\"#{ds_input}\"," if ds_input != ""
t[:one] += "RESOURCE_POOL=\"#{rp_input}\"," if rp_input != ""
t[:one] = t[:one][0..-2]
t[:one] += "]"
end
one_t = ::OpenNebula::Template.new(
::OpenNebula::Template.build_xml, vc.one)
@ -368,4 +477,148 @@ cmd=CommandParser::CmdParser.new(ARGV) do
exit 0
end
datastores_desc = <<-EOT.unindent
Import vCenter Datastores into OpenNebula
EOT
command :datastores, datastores_desc, :options=>[ VCENTER, USER, PASS ] do
if options[:vuser].nil? ||
options[:vpass].nil? ||
options[:vcenter].nil?
STDERR.puts "vCenter connection parameters are mandatory to import"\
" Datastores:\n"\
"\t --vcenter vCenter hostname\n"\
"\t --vuser username to login in vcenter\n"\
"\t --vpass password for the user"
exit -1
end
begin
STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
vc = VCenterDriver::VIClient.new_connection(
:user => options[:vuser],
:password => options[:vpass],
:host => options[:vcenter])
STDOUT.print "done!\n\n"
STDOUT.print "Looking for Datastores..."
rs = vc.vcenter_datastores
STDOUT.print "done!\n"
rs.each {|dc, tmps|
STDOUT.print "\nDo you want to process datacenter #{dc} [y/n]? "
next if STDIN.gets.strip.downcase != 'y'
if tmps.empty?
STDOUT.print " No new Datastores found in #{dc}...\n\n"
next
end
tmps.each{ |d|
STDOUT.print "\n * Datastore found:\n"\
" - Name : #{d[:name]}\n"\
" - Total MB : #{d[:total_mb]}\n"\
" - Free MB : #{d[:free_mb]}\n"\
" - Cluster : #{d[:cluster]}\n"\
" Import this Datastore [y/n]? "
next if STDIN.gets.strip.downcase != 'y'
one_d = ::OpenNebula::Datastore.new(
::OpenNebula::Datastore.build_xml, vc.one)
rc = one_d.allocate(d[:one])
if ::OpenNebula.is_error?(rc)
STDOUT.puts " Error creating datastore: #{rc.message}\n"\
" One datastore can exist only once, and "\
"can be used in any vCenter Cluster that "\
"has access to it. Also, no spaces allowed "\
"in datastore name (rename it in vCenter "\
"and try again)"
else
STDOUT.puts " OpenNebula datastore #{one_d.id} created!\n"
end
}
}
rescue Exception => e
STDOUT.puts "error: #{e.message}"
exit -1
end
exit 0
end
images_desc = <<-EOT.unindent
Import vCenter Images into OpenNebula
EOT
command :images, images_desc, :ds_name, :options=>[ VCENTER, USER, PASS ] do
ds_name = args[0]
if !ds_name
STDERR.puts "Datastore name needed to import images from"
exit -1
end
if options[:vuser].nil? ||
options[:vpass].nil? ||
options[:vcenter].nil?
STDERR.puts "vCenter connection parameters are mandatory to import"\
" Datastores:\n"\
"\t --vcenter vCenter hostname\n"\
"\t --vuser username to login in vcenter\n"\
"\t --vpass password for the user"
exit -1
end
begin
STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
vc = VCenterDriver::VIClient.new_connection(
:user => options[:vuser],
:password => options[:vpass],
:host => options[:vcenter])
STDOUT.print "done!\n\n"
STDOUT.print "Looking for Images..."
images = vc.vcenter_images(ds_name)
STDOUT.print "done!\n"
images.each{ |i|
STDOUT.print "\n * Image found:\n"\
" - Name : #{i[:name]}\n"\
" - Path : #{i[:path]}\n"\
" - Type : #{i[:type]}\n"\
" Import this Image [y/n]? "
next if STDIN.gets.strip.downcase != 'y'
one_i = ::OpenNebula::Image.new(
::OpenNebula::Image.build_xml, vc.one)
rc = one_i.allocate(i[:one], i[:dsid].to_i)
if ::OpenNebula.is_error?(rc)
STDOUT.puts " Error creating image: #{rc.message}\n"
else
STDOUT.puts " OpenNebula image #{one_i.id} created!\n"
end
}
rescue Exception => e
STDOUT.puts "error: #{e.message}"
exit -1
end
exit 0
end
end

View File

@ -826,7 +826,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
disk_snapshot_revert_desc = <<-EOT.unindent
Reverts disk state to a previously taken snapshot.
States: RUNNING, POWEROFF, SUSPENDED
States: POWEROFF, SUSPENDED
EOT
command :"disk-snapshot-revert", disk_snapshot_revert_desc,

View File

@ -148,9 +148,9 @@ cmd=CommandParser::CmdParser.new(ARGV) do
ar << ", ULA_PREFIX = " <<
options[:ip6_ula] if options[:ip6_ula]
ar << ", GATEWAY = " << options[:gateway] if options[:gateway]
ar << ", MASK = " << options[:netmask] if options[:netmask]
ar << ", VLAN = YES" if options[:vlan]
ar << ", VLAN_ID = " << options[:vlanid] if options[:vlanid]
ar << ", MASK = " << options[:netmask] if options[:netmask]
ar << ", VN_MAD = " << options[:vn_mad] if options[:vn_mad]
ar << ", VLAN_ID = " << options[:vlanid] if options[:vlanid]
ar << "]"
end

View File

@ -30,108 +30,180 @@
#include <unistd.h>
#include <sys/types.h>
Client * Client::_client = 0;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Client::set_one_auth(string secret)
Client::Client(const string& secret, const string& endpoint,
size_t message_size, unsigned int tout)
{
if (secret.empty())
string error;
char * xmlrpc_env;
if (!secret.empty())
{
read_oneauth(secret);
one_auth = secret;
}
else if (read_oneauth(one_auth, error) != 0 )
{
NebulaLog::log("XMLRPC", Log::ERROR, error);
throw runtime_error(error);
}
one_auth = secret;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Client::read_oneauth(string &secret)
{
ostringstream oss;
string one_auth_file;
const char * one_auth_env;
ifstream file;
int rc = -1;
// Read $ONE_AUTH file and copy its contents into secret.
one_auth_env = getenv("ONE_AUTH");
if (!one_auth_env)
if(!endpoint.empty())
{
one_endpoint = endpoint;
}
else if ( (xmlrpc_env = getenv("ONE_XMLRPC"))!= 0 )
{
one_endpoint = xmlrpc_env;
}
else
{
one_endpoint = "http://localhost:2633/RPC2";
}
xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, message_size);
timeout = tout * 1000;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Client::read_oneauth(string &secret, string& error_msg)
{
string one_auth_file;
ifstream file;
const char * one_auth_env = getenv("ONE_AUTH");
if (!one_auth_env) //No $ONE_AUTH, read $HOME/.one/one_auth
{
// If $ONE_AUTH doesn't exist, read $HOME/.one/one_auth
struct passwd * pw_ent;
pw_ent = getpwuid(getuid());
if ((pw_ent != NULL) && (pw_ent->pw_dir != NULL))
if ((pw_ent == NULL) || (pw_ent->pw_dir == NULL))
{
one_auth_file = pw_ent->pw_dir;
one_auth_file += "/.one/one_auth";
error_msg = "Could not get one_auth file location";
return -1;
}
one_auth_env = one_auth_file.c_str();
}
else
{
oss << "Could not get one_auth file location";
}
one_auth_file = pw_ent->pw_dir;
one_auth_file += "/.one/one_auth";
one_auth_env = one_auth_file.c_str();
}
file.open(one_auth_env);
if (file.good())
if (!file.good())
{
getline(file, secret);
if (file.fail())
{
oss << "Error reading file: " << one_auth_env;
}
else
{
rc = 0;
}
error_msg = "Could not open file " + one_auth_file;
return -1;
}
else
getline(file, secret);
if (file.fail())
{
oss << "Could not open file: " << one_auth_env;
error_msg = "Error reading file " + one_auth_file;
file.close();
return -1;
}
file.close();
if (rc != 0)
{
NebulaLog::log("XMLRPC",Log::ERROR,oss);
throw runtime_error( oss.str() );
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Client::set_one_endpoint(string endpoint)
void Client::call(const std::string &method, const std::string format,
xmlrpc_c::value * const result, ...)
{
one_endpoint = "http://localhost:2633/RPC2";
va_list args;
va_start(args, result);
if(endpoint != "")
std::string::const_iterator i;
std::string sval;
int ival;
bool bval;
const char* pval;
xmlrpc_c::paramList plist;
plist.add(xmlrpc_c::value_string(one_auth));
for (i = format.begin(); i != format.end(); ++i)
{
one_endpoint = endpoint;
switch(*i)
{
case 's':
pval = static_cast<const char*>(va_arg(args, char *));
sval = pval;
plist.add(xmlrpc_c::value_string(sval));
break;
case 'i':
ival = va_arg(args, int);
plist.add(xmlrpc_c::value_int(ival));
break;
case 'b':
bval = va_arg(args, int);
plist.add(xmlrpc_c::value_boolean(bval));
break;
default:
break;
}
}
va_end(args);
call(method, plist, result);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Client::call(const std::string& method, const xmlrpc_c::paramList& plist,
xmlrpc_c::value * const result)
{
xmlrpc_c::clientXmlTransport_curl ctrans;
xmlrpc_c::client_xml client(&ctrans);
xmlrpc_c::rpcPtr rpc(method, plist);
xmlrpc_c::carriageParm_curl0 cparam(one_endpoint);
rpc->start(&client, &cparam);
client.finishAsync(xmlrpc_c::timeout(timeout));
if (!rpc->isFinished())
{
rpc->finishErr(girerr::error("XMLRPC method " + method +
" timeout, resetting call"));
}
if (rpc->isSuccessful())
{
*result = rpc->getResult();
}
else
{
char * xmlrpc_env;
xmlrpc_env = getenv("ONE_XMLRPC");
xmlrpc_c::fault failure = rpc->getFault();
if ( xmlrpc_env != 0 )
{
one_endpoint = xmlrpc_env;
}
girerr::error(failure.getDescription());
}
// TODO Check url format, and log error (if any)
}
};

View File

@ -34,6 +34,18 @@ const char * Cluster::db_bootstrap = "CREATE TABLE IF NOT EXISTS cluster_pool ("
"gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, "
"UNIQUE(name))";
const char * Cluster::datastore_table = "cluster_datastore_relation";
const char * Cluster::datastore_db_names = "cid, oid";
const char * Cluster::datastore_db_bootstrap =
"CREATE TABLE IF NOT EXISTS cluster_datastore_relation ("
"cid INTEGER, oid INTEGER, PRIMARY KEY(cid, oid))";
const char * Cluster::network_table = "cluster_network_relation";
const char * Cluster::network_db_names = "cid, oid";
const char * Cluster::network_db_bootstrap =
"CREATE TABLE IF NOT EXISTS cluster_network_relation ("
"cid INTEGER, oid INTEGER, PRIMARY KEY(cid, oid))";
/* ************************************************************************** */
/* Cluster :: Constructor/Destructor */
/* ************************************************************************** */
@ -105,24 +117,7 @@ error_common:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& Cluster::get_ds_location(string &ds_location)
{
obj_template->get("DATASTORE_LOCATION", ds_location);
if ( ds_location.empty() == true )
{
Nebula& nd = Nebula::instance();
nd.get_configuration_attribute("DATASTORE_LOCATION", ds_location);
}
return ds_location;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Cluster::add_datastore(int id, Datastore::DatastoreType ds_type, string& error_msg)
int Cluster::add_datastore(int id, string& error_msg)
{
int rc = datastores.add(id);
@ -247,6 +242,98 @@ int Cluster::insert_replace(SqlDB *db, bool replace, string& error_str)
db->free_str(sql_name);
db->free_str(sql_xml);
if (rc == 0)
{
if (db->multiple_values_support())
{
set<int>::iterator i;
rc = 0;
oss.str("");
oss << "DELETE FROM " << network_table << " WHERE cid = " << oid;
rc += db->exec(oss);
oss.str("");
oss << "DELETE FROM " << datastore_table<< " WHERE cid = " << oid;
rc += db->exec(oss);
set<int> datastore_set = datastores.get_collection();
if (!datastore_set.empty())
{
oss.str("");
oss << "INSERT INTO " << datastore_table
<< " (" << datastore_db_names << ") VALUES ";
i = datastore_set.begin();
oss << "(" << oid << "," << *i << ")";
for(++i; i != datastore_set.end(); i++)
{
oss << ", (" << oid << "," << *i << ")";
}
rc += db->exec(oss);
}
set<int> vnet_set = vnets.get_collection();
if (!vnet_set.empty())
{
oss.str("");
oss << "INSERT INTO " << network_table
<< " (" << network_db_names << ") VALUES ";
i = vnet_set.begin();
oss << "(" << oid << "," << *i << ")";
for(++i; i != vnet_set.end(); i++)
{
oss << ", (" << oid << "," << *i << ")";
}
rc += db->exec(oss);
}
}
else
{
oss.str("");
oss << "BEGIN; "
<< "DELETE FROM " << network_table << " WHERE cid = " << oid << "; "
<< "DELETE FROM " << datastore_table<< " WHERE cid = " << oid << "; ";
set<int>::iterator i;
set<int> datastore_set = datastores.get_collection();
for(i = datastore_set.begin(); i != datastore_set.end(); i++)
{
oss << "INSERT INTO " << datastore_table
<< " (" << datastore_db_names << ") VALUES ("
<< oid << ","
<< *i << "); ";
}
set<int> vnet_set = vnets.get_collection();
for(i = vnet_set.begin(); i != vnet_set.end(); i++)
{
oss << "INSERT INTO " << network_table
<< " (" << network_db_names << ") VALUES ("
<< oid << ","
<< *i << "); ";
}
oss << "COMMIT";
rc = db->exec(oss);
}
}
return rc;
error_xml:
@ -317,55 +404,11 @@ int Cluster::from_xml(const string& xml)
// Set the Cluster ID as the cluster it belongs to
set_group(oid, name);
// -------------------------------------------------------------------------
// Get associated hosts
// -------------------------------------------------------------------------
ObjectXML::get_nodes("/CLUSTER/HOSTS", content);
if (content.empty())
{
return -1;
}
// Set of IDs
rc += hosts.from_xml_node(content[0]);
ObjectXML::free_nodes(content);
content.clear();
// -------------------------------------------------------------------------
// Get associated datastores
// -------------------------------------------------------------------------
ObjectXML::get_nodes("/CLUSTER/DATASTORES", content);
if (content.empty())
{
return -1;
}
// Set of IDs
rc += datastores.from_xml_node(content[0]);
ObjectXML::free_nodes(content);
content.clear();
// -------------------------------------------------------------------------
// Get associated vnets
// -------------------------------------------------------------------------
ObjectXML::get_nodes("/CLUSTER/VNETS", content);
if (content.empty())
{
return -1;
}
// Set of IDs
rc += vnets.from_xml_node(content[0]);
ObjectXML::free_nodes(content);
content.clear();
// Get associated classes
rc += hosts.from_xml(this, "/CLUSTER/");
rc += datastores.from_xml(this, "/CLUSTER/");
rc += vnets.from_xml(this, "/CLUSTER/");
ObjectXML::get_nodes("/CLUSTER/TEMPLATE", content);
if (content.empty())

View File

@ -21,7 +21,7 @@
#include <stdexcept>
/* -------------------------------------------------------------------------- */
/* There is a default cluster boostrapped by the core: */
/* There is a default cluster boostrapped by the core: 0, default */
/* The first 100 cluster IDs are reserved for system clusters. */
/* Regular ones start from ID 100 */
/* -------------------------------------------------------------------------- */
@ -29,6 +29,9 @@
const string ClusterPool::NONE_CLUSTER_NAME = "";
const int ClusterPool::NONE_CLUSTER_ID = -1;
const string ClusterPool::DEFAULT_CLUSTER_NAME = "default";
const int ClusterPool::DEFAULT_CLUSTER_ID = 0;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -37,12 +40,48 @@ ClusterPool::ClusterPool(SqlDB * db):PoolSQL(db, Cluster::table, true, true)
ostringstream oss;
string error_str;
// ---------------------------------------------------------------------
// Create the default cluster
// ---------------------------------------------------------------------
if (get_lastOID() == -1) //lastOID is set in PoolSQL::init_cb
{
int rc;
allocate(DEFAULT_CLUSTER_NAME, &rc, error_str);
if( rc != DEFAULT_CLUSTER_ID )
{
goto error_bootstrap;
}
Cluster* cluster = get(DEFAULT_CLUSTER_ID, true);
if (cluster == 0)
{
goto error_bootstrap;
}
cluster->add_datastore(DatastorePool::SYSTEM_DS_ID, error_str);
cluster->add_datastore(DatastorePool::DEFAULT_DS_ID, error_str);
cluster->add_datastore(DatastorePool::FILE_DS_ID, error_str);
update(cluster);
cluster->unlock();
// User created clusters will start from ID 100
set_update_lastOID(99);
}
return;
error_bootstrap:
oss.str("");
oss << "Error trying to create default cluster: " << error_str;
NebulaLog::log("CLUSTER",Log::ERROR,oss);
throw runtime_error(oss.str());
}
/* -------------------------------------------------------------------------- */
@ -122,3 +161,51 @@ int ClusterPool::drop(PoolObjectSQL * objsql, string& error_msg)
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void ClusterPool::cluster_acl_filter(ostringstream& filter,
PoolObjectSQL::ObjectType auth_object, const vector<int>& cids)
{
if ( cids.empty() )
{
return;
}
string fc = "";
switch (auth_object)
{
case PoolObjectSQL::HOST:
filter << " OR ";
break;
case PoolObjectSQL::DATASTORE:
filter << " OR oid IN ( SELECT oid from " << Cluster::datastore_table
<< " WHERE ";
fc = ")";
break;
case PoolObjectSQL::NET:
filter << " OR oid IN ( SELECT oid from " << Cluster::network_table
<< " WHERE ";
fc = ")";
break;
default:
return;
}
for ( vector<int>::const_iterator it = cids.begin(); it < cids.end(); it++ )
{
if ( it != cids.begin() )
{
filter << " OR ";
}
filter << "cid = " << *it;
}
filter << fc;
}

View File

@ -19,8 +19,7 @@
#include <cstring>
#include "Attribute.h"
#define TO_UPPER(S) transform(S.begin(),S.end(),S.begin(),(int(*)(int))toupper)
#include "NebulaUtil.h"
const char * VectorAttribute::magic_sep = "@^_^@";
const int VectorAttribute::magic_sep_size = 5;
@ -101,8 +100,9 @@ void VectorAttribute::to_xml(ostringstream &oss) const
}
else
{
oss << "<" << it->first << "><![CDATA[" << it->second
<< "]]></"<< it->first << ">";
oss << "<" << it->first << ">"
<< one_util::escape_xml(it->second)
<< "</" << it->first << ">";
}
}
@ -294,7 +294,7 @@ int VectorAttribute::vector_value(const char *name, bool& value) const
string tmp = it->second;
TO_UPPER(tmp);
one_util::toupper(tmp);
if (tmp == "YES")
{

View File

@ -22,13 +22,12 @@
const char * Datastore::table = "datastore_pool";
const char * Datastore::db_names =
"oid, name, body, uid, gid, owner_u, group_u, other_u, cid";
"oid, name, body, uid, gid, owner_u, group_u, other_u";
const char * Datastore::db_bootstrap =
"CREATE TABLE IF NOT EXISTS datastore_pool ("
"oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, "
"gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, "
"cid INTEGER)";
"gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER)";
/* ************************************************************************ */
/* Datastore :: Constructor/Destructor */
@ -41,10 +40,9 @@ Datastore::Datastore(
const string& gname,
int umask,
DatastoreTemplate* ds_template,
int cluster_id,
const string& cluster_name):
const set<int> &cluster_ids):
PoolObjectSQL(-1,DATASTORE,"",uid,gid,uname,gname,table),
Clusterable(cluster_id, cluster_name),
Clusterable(cluster_ids),
ds_mad(""),
tm_mad(""),
base_path(""),
@ -119,12 +117,11 @@ void Datastore::disk_attribute(
disk->replace("DATASTORE_ID", oss.str());
disk->replace("TM_MAD", get_tm_mad());
if ( get_cluster_id() != ClusterPool::NONE_CLUSTER_ID )
{
oss.str("");
oss << get_cluster_id();
set<int> cluster_ids = get_cluster_ids();
disk->replace("CLUSTER_ID", oss.str());
if (!cluster_ids.empty())
{
disk->replace("CLUSTER_ID", one_util::join(cluster_ids, ','));
}
get_template_attribute("CLONE_TARGET", st);
@ -607,9 +604,7 @@ int Datastore::insert_replace(SqlDB *db, bool replace, string& error_str)
<< gid << ","
<< owner_u << ","
<< group_u << ","
<< other_u << ","
<< cluster_id << ")";
<< other_u << ")";
rc = db->exec(oss);
@ -645,32 +640,32 @@ error_common:
string& Datastore::to_xml(string& xml) const
{
ostringstream oss;
string collection_xml;
string clusters_xml;
string images_xml;
string template_xml;
string perms_xml;
oss <<
"<DATASTORE>" <<
"<ID>" << oid << "</ID>" <<
"<UID>" << uid << "</UID>" <<
"<GID>" << gid << "</GID>" <<
"<UNAME>" << uname << "</UNAME>" <<
"<GNAME>" << gname << "</GNAME>" <<
"<NAME>" << name << "</NAME>" <<
"<ID>" << oid << "</ID>" <<
"<UID>" << uid << "</UID>" <<
"<GID>" << gid << "</GID>" <<
"<UNAME>" << uname << "</UNAME>" <<
"<GNAME>" << gname << "</GNAME>" <<
"<NAME>" << name << "</NAME>" <<
perms_to_xml(perms_xml) <<
"<DS_MAD><![CDATA[" << ds_mad << "]]></DS_MAD>" <<
"<TM_MAD><![CDATA[" << tm_mad << "]]></TM_MAD>" <<
"<BASE_PATH><![CDATA[" << base_path << "]]></BASE_PATH>"<<
"<TYPE>" << type << "</TYPE>" <<
"<DISK_TYPE>" << disk_type << "</DISK_TYPE>" <<
"<STATE>" << state << "</STATE>" <<
"<CLUSTER_ID>" << cluster_id << "</CLUSTER_ID>" <<
"<CLUSTER>" << cluster << "</CLUSTER>" <<
"<TOTAL_MB>" << total_mb << "</TOTAL_MB>" <<
"<FREE_MB>" << free_mb << "</FREE_MB>" <<
"<USED_MB>" << used_mb << "</USED_MB>" <<
images.to_xml(collection_xml) <<
obj_template->to_xml(template_xml) <<
"<DS_MAD>" << one_util::escape_xml(ds_mad) << "</DS_MAD>" <<
"<TM_MAD>" << one_util::escape_xml(tm_mad) << "</TM_MAD>" <<
"<BASE_PATH>" << one_util::escape_xml(base_path)<< "</BASE_PATH>"<<
"<TYPE>" << type << "</TYPE>" <<
"<DISK_TYPE>" << disk_type << "</DISK_TYPE>" <<
"<STATE>" << state << "</STATE>" <<
Clusterable::to_xml(clusters_xml) <<
"<TOTAL_MB>" << total_mb << "</TOTAL_MB>" <<
"<FREE_MB>" << free_mb << "</FREE_MB>" <<
"<USED_MB>" << used_mb << "</USED_MB>" <<
images.to_xml(images_xml) <<
obj_template->to_xml(template_xml) <<
"</DATASTORE>";
xml = oss.str();
@ -706,9 +701,6 @@ int Datastore::from_xml(const string& xml)
rc += xpath(int_disk_type,"/DATASTORE/DISK_TYPE", -1);
rc += xpath(int_state, "/DATASTORE/STATE", 0);
rc += xpath(cluster_id, "/DATASTORE/CLUSTER_ID", -1);
rc += xpath(cluster, "/DATASTORE/CLUSTER", "not_found");
rc += xpath<long long>(total_mb,"/DATASTORE/TOTAL_MB",0);
rc += xpath<long long>(free_mb, "/DATASTORE/FREE_MB", 0);
rc += xpath<long long>(used_mb, "/DATASTORE/USED_MB", 0);
@ -720,19 +712,11 @@ int Datastore::from_xml(const string& xml)
type = static_cast<Datastore::DatastoreType>(int_ds_type);
state = static_cast<DatastoreState>(int_state);
// Get associated classes
ObjectXML::get_nodes("/DATASTORE/IMAGES", content);
// Set of Image IDs
rc += images.from_xml(this, "/DATASTORE/");
if (content.empty())
{
return -1;
}
// Set of IDs
rc += images.from_xml_node(content[0]);
ObjectXML::free_nodes(content);
content.clear();
// Set of cluster IDs
rc += Clusterable::from_xml(this, "/DATASTORE/");
// Get associated classes
ObjectXML::get_nodes("/DATASTORE/TEMPLATE", content);

View File

@ -57,7 +57,10 @@ DatastorePool::DatastorePool(
if (get_lastOID() == -1) //lastOID is set in PoolSQL::init_cb
{
DatastoreTemplate * ds_tmpl;
int rc;
int rc;
set<int> cluster_ids;
cluster_ids.insert(ClusterPool::DEFAULT_CLUSTER_ID);
// ---------------------------------------------------------------------
// Create the system datastore
@ -82,8 +85,7 @@ DatastorePool::DatastorePool(
0137,
ds_tmpl,
&rc,
ClusterPool::NONE_CLUSTER_ID,
ClusterPool::NONE_CLUSTER_NAME,
cluster_ids,
error_str);
if( rc < 0 )
@ -116,8 +118,7 @@ DatastorePool::DatastorePool(
0137,
ds_tmpl,
&rc,
ClusterPool::NONE_CLUSTER_ID,
ClusterPool::NONE_CLUSTER_NAME,
cluster_ids,
error_str);
if( rc < 0 )
@ -150,8 +151,7 @@ DatastorePool::DatastorePool(
0137,
ds_tmpl,
&rc,
ClusterPool::NONE_CLUSTER_ID,
ClusterPool::NONE_CLUSTER_NAME,
cluster_ids,
error_str);
if( rc < 0 )
@ -184,8 +184,7 @@ int DatastorePool::allocate(
int umask,
DatastoreTemplate * ds_template,
int * oid,
int cluster_id,
const string& cluster_name,
const set<int> &cluster_ids,
string& error_str)
{
Datastore * ds;
@ -196,7 +195,7 @@ int DatastorePool::allocate(
ostringstream oss;
ds = new Datastore(uid, gid, uname, gname, umask,
ds_template, cluster_id, cluster_name);
ds_template, cluster_ids);
// -------------------------------------------------------------------------
// Check name & duplicates

View File

@ -115,10 +115,14 @@ else
CHECKSUM="$MD5"
fi
if [ -z "\$CHECKSUM" ]; then
exit 1
fi
cat <<EOT
<MD5>\$CHECKSUM</MD5>
<SIZE>$SIZE</SIZE>
<FORMAT>${FORMAT}</FORMAT>
<MD5><![CDATA[\$CHECKSUM]]></MD5>
<SIZE><![CDATA[$SIZE]]></SIZE>
<FORMAT><![CDATA[${FORMAT}]]></FORMAT>
EOT
EOF
)
@ -133,7 +137,7 @@ fi
cat <<EOF
<IMPORT_INFO>
<IMPORT_SOURCE>$IMPORT_SOURCE</IMPORT_SOURCE>
<IMPORT_SOURCE><![CDATA[$IMPORT_SOURCE]]></IMPORT_SOURCE>
$INFO
<DISPOSE>NO</DISPOSE>
</IMPORT_INFO>"

View File

@ -18,8 +18,10 @@
if [ -z "${ONE_LOCATION}" ]; then
LIB_LOCATION=/usr/lib/one
VAR_LOCATION=/var/lib/one
else
LIB_LOCATION=$ONE_LOCATION/lib
VAR_LOCATION=$ONE_LOCATION/var
fi
. $LIB_LOCATION/sh/scripts_common.sh
@ -295,6 +297,9 @@ s3://*)
rbd://*)
command="$(get_rbd_cmd $FROM)"
;;
vcenter://*)
command="$VAR_LOCATION/remotes/datastore/vcenter_downloader.rb \"$FROM\""
;;
*)
if [ ! -r $FROM ]; then
echo "Cannot read from $FROM" >&2

View File

@ -56,15 +56,17 @@ BRIDGE_LIST="${XPATH_ELEMENTS[i++]}"
#-------------------------------------------------------------------------------
INFO_SCRIPT=$(cat <<EOF
CHECKSUM=\$(${MD5SUM} ${SRC} | cut -f1 -d' ')
SIZE=\$(${DU} -Lm ${SRC} | cut -f1)
FORMAT=\$(${QEMU_IMG} info ${SRC} 2>/dev/null | grep -Po '(?<=file format: )\w+')
echo "<MD5>\$CHECKSUM</MD5>"
echo "<SIZE>\$SIZE</SIZE>"
echo "<FORMAT>\${FORMAT-"unknown"}</FORMAT>"
if [ -z "\$CHECKSUM" -o -z "\$SIZE" ]; then
exit 1
fi
echo "<MD5><![CDATA[\$CHECKSUM]]></MD5>"
echo "<SIZE><![CDATA[\$SIZE]]></SIZE>"
echo "<FORMAT><![CDATA[\${FORMAT:-unknown}]]></FORMAT>"
EOF
)
@ -83,7 +85,7 @@ if [ "$INFO_STATUS" != "0" ]; then
exit $INFO_STATUS
fi
echo "<IMPORT_INFO><IMPORT_SOURCE>$SRC</IMPORT_SOURCE> \
echo "<IMPORT_INFO><IMPORT_SOURCE><![CDATA[$SRC]]></IMPORT_SOURCE> \
$INFO \
<DISPOSE>NO</DISPOSE></IMPORT_INFO>"

View File

@ -170,12 +170,12 @@ function fs_size {
http://*|https://*)
HEADERS=`curl -LIk --max-time 60 $1 2>&1`
if echo "$HEADERS" | grep -q "OpenNebula-AppMarket-Size"; then
if echo "$HEADERS" | grep -i -q "OpenNebula-AppMarket-Size"; then
# An AppMarket/Marketplace URL
SIZE=$(echo "$HEADERS" | grep "^OpenNebula-AppMarket-Size:" | tail -n1 | cut -d: -f2)
SIZE=$(echo "$HEADERS" | grep -i "^OpenNebula-AppMarket-Size:" | tail -n1 | cut -d: -f2)
else
# Not an AppMarket/Marketplace URL
SIZE=$(echo "$HEADERS" | grep "^Content-Length:" | tail -n1 | cut -d: -f2)
SIZE=$(echo "$HEADERS" | grep -i "^Content-Length:" | tail -n1 | cut -d: -f2)
fi
error=$?
;;

View File

@ -0,0 +1,65 @@
#!/usr/bin/env ruby
# ---------------------------------------------------------------------------- #
# Copyright 2002-2015, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
###############################################################################
# This script is used retrieve the file size of a disk
###############################################################################
ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
end
$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)
require 'vcenter_driver'
require 'digest'
drv_action_enc = ARGV[0]
id = ARGV[1]
drv_action = OpenNebula::XMLElement.new
drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA')
ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"]
hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"]
img_path = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/PATH"]
if ds_name.nil? || hostname.nil? || img_path.nil?
STDERR.puts "Not enough information to clone the image, missing datastore"\
" name or vcenter cluster name or image path."
exit -1
end
# Generate target path
str_for_target_path = Time.now.to_s + id.to_s
target_path = Digest::MD5.hexdigest(str_for_target_path) + ".vmdk"
begin
host_id = VCenterDriver::VIClient.translate_hostname(hostname)
vi_client = VCenterDriver::VIClient.new host_id
puts vi_client.copy_virtual_disk(img_path, ds_name, target_path)
rescue Exception => e
STDERR.puts "Error cloning img #{img_path} size. Reason: #{e.message}"
exit -1
end

View File

@ -0,0 +1,234 @@
#!/usr/bin/env ruby
# ---------------------------------------------------------------------------- #
# Copyright 2002-2015, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
###############################################################################
# This script is used retrieve the file size of a disk
###############################################################################
ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
VAR_LOCATION="/var/lib/one" if !defined?(VAR_LOCATION)
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
VAR_LOCATION=ONE_LOCATION+"/var" if !defined?(VAR_LOCATION)
end
$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)
require 'opennebula'
require 'fileutils'
require 'tempfile'
def is_remote?(file)
file.match(%r{^https?://})
end
def get_type(file)
type = %x{file -b --mime-type #{file}}
if $?.exitstatus != 0
STDERR.puts "Can not read file #{file}"
exit(-1)
end
type.strip
end
def needs_unpack?(file)
temp = Tempfile.new('one-')
temp.close
file_path = file
if is_remote?(file)
rc = system("curl --fail -sS -k -L #{file_path} | head -c 1024 > #{temp.path}")
if !rc
STDERR.puts "Can not download file #{file_path}"
exit(-1)
end
file_path = temp.path
end
type = get_type(file_path)
type.gsub!(%r{^application/x-}, '')
unpack = %w{bzip2 gzip tar}.include?(type)
temp.unlink
unpack
end
def vmdk_info(file)
file_path = file
if File.directory?(file_path)
files = Dir["#{file_path}/*.vmdk"]
found = false
count = 0
last = nil
files.each do |f|
if get_type(f).strip == "text/plain"
file_path = f
found = true
break
else
count += 1
last = f
end
end
if !found
if count == 1
file_path = last
found = true
else
STDERR.puts "Could not find vmdk"
exit(-1)
end
end
end
if get_type(file_path).strip == "application/octet-stream"
return {
:type => :standalone,
:file => file_path,
:dir => File.dirname(file_path)
}
elsif get_type(file_path).strip == "text/plain"
info = {
:type => :flat,
:file => file_path,
:dir => File.dirname(file_path)
}
files_list = []
descriptor = File.read(file_path).split("\n")
flat_files = descriptor.select {|l| l.start_with?("RW")}
flat_files.each do |f|
files_list << info[:dir] + "/" +
f.split(" ")[3].chomp.chomp('"').reverse.chomp('"').reverse
end
info[:flat_files] = files_list
return info
else
STDERR.puts "Unrecognized file type"
exit(-1)
end
end
drv_action_enc = ARGV[0]
id = ARGV[1]
drv_action = OpenNebula::XMLElement.new
drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA')
img_path = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/PATH"]
md5 = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/MD5"]
sha1 = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/SHA1"]
nodecomp = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/NO_DECOMPRESS"]
limit_bw = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/LIMIT_TRANSFER_BW"]
hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"]
ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"]
if img_path.nil?
STDERR.puts "Not enough information to register the image,"\
" missing image path."
exit(-1)
end
if img_path.start_with? "vcenter://"
# File already in the vCenter datastore
puts img_path.sub("vcenter://","")
exit(0)
end
downsh_args = " "
downsh_args += "--md5 #{md5} " if md5 and !md5.empty? and !md5.eql? "-"
downsh_args += "--sha1 #{sha1} " if sha1 and !sha1.empty?
downsh_args += "--nodecomp " if nodecomp and !nodecomp.empty?
downsh_args += "--limit #{limit_bw} " if limit_bw and !limit_bw.empty?
downloader = "#{File.dirname(__FILE__)}/../downloader.sh #{downsh_args}"
# Generate target path
str_for_target_path = Time.now.to_s + id.to_s
target_path = Digest::MD5.hexdigest(str_for_target_path)
files_to_upload = Array.new
file_path = img_path
skip_download = false
delete_file = false
files_to_upload = []
if is_remote?(file_path) || needs_unpack?(file_path)
temp_folder = File.join(VAR_LOCATION, "vcenter")
temp_file = File.join(temp_folder, File.basename(target_path))
FileUtils.mkdir_p(temp_folder) if !File.directory?(temp_folder)
rc = system("#{downloader} #{file_path} #{temp_file}")
if !rc
STDERR.puts "Error downloading #{file_path}"
FileUtils.rm_rf(temp_file)
exit(-1)
end
delete_file = true
file_path = temp_file
end
info = vmdk_info(file_path)
case info[:type]
when :standalone
files_to_upload << info[:file]
when :flat
files_to_upload = info[:flat_files]
files_to_upload << info[:file]
end
files_to_upload.each_with_index do |f, index|
path = "#{target_path}/#{File.basename(f)}"
if index == files_to_upload.size - 1
uploader_args = hostname + " " + ds_name + " " + path + " " + f
else
uploader_args = hostname + " " + ds_name + " " +
path + " " + f + " &> /dev/null"
end
cmd = "#{File.dirname(__FILE__)}/../vcenter_uploader.rb #{uploader_args}"
rc = system(cmd)
if !rc
STDERR.puts "Can not upload file #{f}"
FileUtils.rm_rf(temp_file) if delete_file
exit(-1)
end
end
FileUtils.rm_rf(temp_file) if delete_file

View File

@ -0,0 +1,75 @@
#!/usr/bin/env ruby
# ---------------------------------------------------------------------------- #
# Copyright 2002-2015, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
###############################################################################
# This script is used retrieve the file size of a disk
###############################################################################
ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
end
$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)
require 'opennebula'
drv_action_enc = ARGV[0]
id = ARGV[1]
drv_action = OpenNebula::XMLElement.new
drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA')
img_source = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/SOURCE"]
img_size = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/SIZE"]
md5 = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/MD5"]
md5 = md5.nil? ? "-" : md5
hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"]
ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"]
if img_source.nil?
STDERR.puts "Not enough information to export the image,"\
" missing image source."
exit -1
end
# Create vcenter url with all needed information to extract the file from
# the vCenter datastore
vcenter_url_img = "vcenter://#{img_source}?"\
"param_dsname=#{ds_name}&"\
"param_host=#{hostname}"
# Create import info document for marketplace import script
puts "<IMPORT_INFO>
<IMPORT_SOURCE><![CDATA[#{vcenter_url_img}]]></IMPORT_SOURCE>
<MD5><![CDATA[#{md5}]]></MD5>
<SIZE><![CDATA[#{img_size}]]></SIZE>
<FORMAT>VMDK</FORMAT>
<DISPOSE>NO</DISPOSE>
</IMPORT_INFO>"

View File

@ -0,0 +1,72 @@
#!/usr/bin/env ruby
# ---------------------------------------------------------------------------- #
# Copyright 2002-2015, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
###############################################################################
# This script is used retrieve the file size of a disk
###############################################################################
ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
end
$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)
require 'vcenter_driver'
drv_action_enc = ARGV[0]
id = ARGV[1]
drv_action =OpenNebula::XMLElement.new
drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA')
ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"]
hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"]
adapter_type = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/ADAPTER_TYPE"]
disk_type = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/TEMPLATE/DISK_TYPE"]
size = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/SIZE"]
img_name = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/NAME"]
if ds_name.nil? ||
hostname.nil? ||
adapter_type.nil? ||
disk_type.nil? ||
size.nil? ||
img_name.nil?
STDERR.puts "Not enough information to create the image."
exit -1
end
begin
host_id = VCenterDriver::VIClient.translate_hostname(hostname)
vi_client = VCenterDriver::VIClient.new host_id
puts vi_client.create_virtual_disk(img_name,
ds_name,
size,
adapter_type,
disk_type)
rescue Exception => e
STDERR.puts "Error creating virtual disk in #{ds_name}."\
" Reason: #{e.message}"
exit -1
end

View File

@ -0,0 +1,59 @@
#!/usr/bin/env ruby
# ---------------------------------------------------------------------------- #
# Copyright 2002-2015, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
###############################################################################
# This script is used to monitor the free and used space of a datastore
###############################################################################
ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
end
$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)
require 'vcenter_driver'
drv_action_enc = ARGV[0]
id = ARGV[1]
drv_action = OpenNebula::XMLElement.new
drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA')
ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"]
hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"]
if ds_name.nil? ||
hostname.nil?
STDERR.puts "Not enough information to monitor the image."
exit -1
end
begin
host_id = VCenterDriver::VIClient.translate_hostname(hostname)
vi_client = VCenterDriver::VIClient.new host_id
puts vi_client.monitor_ds(ds_name)
rescue Exception => e
STDERR.puts "Error monitoring #{ds_name}. Reason: #{e.message}"
exit -1
end

View File

@ -0,0 +1,63 @@
#!/usr/bin/env ruby
# ---------------------------------------------------------------------------- #
# Copyright 2002-2015, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
###############################################################################
# This script is used retrieve the file size of a disk
###############################################################################
ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
end
$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)
require 'vcenter_driver'
drv_action_enc = ARGV[0]
id = ARGV[1]
drv_action =OpenNebula::XMLElement.new
drv_action.initialize_xml(Base64.decode64(drv_action_enc), 'DS_DRIVER_ACTION_DATA')
ds_name = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/NAME"]
hostname = drv_action["/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/VCENTER_CLUSTER"]
img_src = drv_action["/DS_DRIVER_ACTION_DATA/IMAGE/SOURCE"]
if ds_name.nil? ||
hostname.nil? ||
img_src.nil?
STDERR.puts "Not enough information to delete the image."
exit -1
end
begin
host_id = VCenterDriver::VIClient.translate_hostname(hostname)
vi_client = VCenterDriver::VIClient.new host_id
vi_client.delete_virtual_disk(img_src,
ds_name)
rescue Exception => e
STDERR.puts "Error delete virtual disk #{img_src} in #{ds_name}."\
" Reason: #{e.message}"
exit -1
end

View File

@ -0,0 +1 @@
../common/not_supported.sh

View File

@ -0,0 +1 @@
../common/not_supported.sh

View File

@ -0,0 +1 @@
../common/not_supported.sh

Some files were not shown because too many files have changed in this diff Show More