1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-31 17:17:40 +03:00

Merged TransferManager and VirtualNetworkManager branches.

git-svn-id: http://svn.opennebula.org/one/trunk@230 3034c82b-c49b-4eb3-8279-a7acafdc01c0
This commit is contained in:
Constantino Vázquez Blanco 2008-11-13 16:21:17 +00:00
parent d820054ec5
commit ee411e7963
95 changed files with 5768 additions and 473 deletions

View File

@ -35,6 +35,7 @@ main_env.Append(LIBPATH=[
cwd+'/src/dm',
cwd+'/src/im',
cwd+'/src/rm',
cwd+'/src/vnm',
])
# Compile flags
@ -103,7 +104,8 @@ build_scripts=[
'src/tm/SConstruct',
'src/im/SConstruct',
'src/dm/SConstruct',
'src/scheduler/SConstruct',
'src/scheduler/SConstruct',
'src/vnm/SConstruct',
]
for script in build_scripts:

View File

@ -33,7 +33,7 @@ class Attribute
{
public:
Attribute(string& aname):attribute_name(aname)
Attribute(const string& aname):attribute_name(aname)
{
transform (
attribute_name.begin(),
@ -77,7 +77,7 @@ public:
/**
* Builds a new attribute from a string.
*/
virtual void unmarshall(string& sattr) = 0;
virtual void unmarshall(const string& sattr) = 0;
/**
* Returns the attribute type
@ -104,12 +104,12 @@ class SingleAttribute : public Attribute
{
public:
SingleAttribute(string& name):Attribute(name){};
SingleAttribute(const string& name):Attribute(name){};
SingleAttribute(string& name, string& value):
SingleAttribute(const string& name, const string& value):
Attribute(name),attribute_value(value){};
SingleAttribute(const char * name, string& value):
SingleAttribute(const char * name, const string& value):
Attribute(name),attribute_value(value){};
~SingleAttribute(){};
@ -139,11 +139,19 @@ public:
/**
* Builds a new attribute from a string.
*/
void unmarshall(string& sattr)
void unmarshall(const string& sattr)
{
attribute_value = sattr;
};
/**
* Replaces the attribute value from a string.
*/
void replace(const string& sattr)
{
attribute_value = sattr;
};
/**
* Returns the attribute type
*/
@ -169,9 +177,9 @@ class VectorAttribute : public Attribute
{
public:
VectorAttribute(string& name):Attribute(name){};
VectorAttribute(const string& name):Attribute(name){};
VectorAttribute(string& name, map<string,string>& value):
VectorAttribute(const string& name,const map<string,string>& value):
Attribute(name),attribute_value(value){};
~VectorAttribute(){};
@ -201,7 +209,13 @@ public:
* Builds a new attribute from a string of the form:
* "VAL_NAME_1=VAL_VALUE_1,...,VAL_NAME_N=VAL_VALUE_N".
*/
void unmarshall(string& sattr);
void unmarshall(const string& sattr);
/**
* Replace the value of the given attribute with the provided map
*/
void replace(const map<string,string>& attr);
/**
* Returns the attribute type

View File

@ -214,7 +214,7 @@ private:
HostPool * hpool;
/**
* Pointer to the Host Pool, to access hosts
* Pointer to the Virtual Machine Pool, to access hosts
*/
VirtualMachinePool * vmpool;

115
include/FixedLeases.h Normal file
View File

@ -0,0 +1,115 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef FIXED_LEASES_H_
#define FIXED_LEASES_H_
#include "Leases.h"
using namespace std;
/**
* The FixedLeases class represents a pool of fixed IP-MAC leases. A lease can
* be either a IP (the MAC is then PREFIX:IP) or the IP and MAC addresses. The
* pool is read from a template file, each lease is in the form:
* LEASE = [ IP = "<the ip>", MAC = "<the mac>"]
*/
class FixedLeases : public Leases
{
public:
/**
* Create a FixedLeases from template
*/
FixedLeases(SqliteDB * db,
int _oid,
unsigned int _mac_prefix,
vector<const Attribute*>& vector_leases);
/**
* Create a plain FixedLeases, you can populate the lease pool using
* select()
*/
FixedLeases(SqliteDB * db,
int _oid,
unsigned int _mac_prefix):
Leases(db,_oid,0),
mac_prefix(_mac_prefix),
current(leases.begin()){};
~FixedLeases(){};
/**
* Returns an unused lease, which becomes used
* @param vid identifier of the VM getting this lease
* @param ip ip of the returned lease
* @param mac mac of the returned lease
* @return 0 if success
*/
int get(int vid, string& ip, string& mac);
/**
* Release an used lease, which becomes unused
* @param ip of the lease in use
*/
void release(const string& ip)
{
del(ip);
}
/**
* Loads the leases from the DB.
*/
int select(SqliteDB * db)
{
//Read the leases from the DB
int rc = Leases::select(db);
//Update the size
size = leases.size();
return rc;
}
private:
/**
* The default MAC prefix for the OpenNebula cluster
*/
unsigned int mac_prefix;
/**
* Current lease pointer
*/
map<unsigned int, Lease *>::iterator current;
/**
* Add a lease, from the Lease interface
* @param ip ip of the lease
* @param mac mac of the lease
* @param vid identifier of the VM getting this lease
* @return 0 if success
*/
int add(const string& ip, const string& mac, int vid, bool used=true);
/**
* Remove a lease, from the Lease interface
* @param db pointer to DB
* @param ip ip of the lease to be deleted
* @return 0 if success
*/
int del(const string& ip);
};
#endif /*FIXED_LEASES_H_*/

View File

@ -66,7 +66,7 @@ private:
// ----------------------------------------
enum ColNames
{
OID = 0,
VID = 0,
SEQ = 1,
HOSTNAME = 2,
VM_DIR = 3,
@ -115,7 +115,7 @@ private:
int seq;
string hostname;
string vm_rdir;
string vm_dir;
int hid;
@ -138,13 +138,13 @@ private:
//Non-persistent history fields
string vm_lhome;
string transfer_file;
string deployment_file;
string vm_rhome;
string deployment_lfile;
string deployment_rfile;
string checkpoint_file;
string rdeployment_file;
friend int history_select_cb (
void * _history,
int num,

View File

@ -425,7 +425,7 @@ protected:
enum ColNames
{
HID = 0,
OID = 0,
HOST_NAME = 1,
STATE = 2,
IM_MAD = 3,

View File

@ -171,7 +171,7 @@ private:
enum ColNames
{
HSID = 0,
HID = 0,
ENDPOINT = 1,
DISK_USAGE = 2,
MEM_USAGE = 3,

315
include/Leases.h Normal file
View File

@ -0,0 +1,315 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef LEASES_H_
#define LEASES_H_
#include <sqlite3.h>
#include "ObjectSQL.h"
#include "Attribute.h"
#include <map>
#include <vector>
#include <sstream>
using namespace std;
extern "C" int leases_select_cb (
void * _lease,
int num,
char ** values,
char ** names);
/**
* The Leases class represents all the IP and MAC addresses (lease) that can
* be asigned (or are asigned) in a Virtual Network
*/
class Leases : public ObjectSQL
{
public:
/**
* Creates a new Lease set for a given Virtual Network (oid)
* @param _db pinter to the DB object used to store the leases
* @param _oid the virtual network unique identifier
* @param _size the max number of leases
*/
Leases(SqliteDB * _db, int _oid, unsigned long _size):
oid(_oid), size(_size), db(_db){};
virtual ~Leases()
{
map<unsigned int, Lease *>::iterator it;
for(it=leases.begin();it!=leases.end();it++)
{
delete it->second;
}
};
friend ostream& operator<<(ostream& os, Leases& _leases);
/**
* Returns an unused lease, which becomes used
* @param vid identifier of the VM getting this lease
* @param ip ip of the returned lease
* @param mac mac of the returned lease
* @return 0 if success
*/
virtual int get(int vid,
string& ip,
string& mac) = 0;
/**
* Release an used lease, which becomes unused
* @param ip of the lease in use
*/
virtual void release(const string& ip) = 0;
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
protected:
/**
* The Lease class, it represents a pair of IP and MAC assigned to
* a Virtual Machine
*/
class Lease
{
public:
/**
* Creates a new lease, string form. This constructor throws a runtime
* exception if the IP or MAC format is wrong.
* @param _ip, the Lease IP in string format
* @param _mac, the Lease MAC in string format
* @param _vid, the ID of the VM owning the lease
* @param _used, the lease is in use
*/
//Lease(const string& _ip, const string& _mac,int _vid, bool _used=true);
/**
* Creates a new lease, numeric form.
* @param _ip, the Lease IP in numeric format
* @param _mac, the Lease MAC in numeric format
* @param _vid, the ID of the VM owning the lease
* @param _used, the lease is in use
*/
Lease(unsigned int _ip, unsigned int _mac[], int _vid, bool _used=true)
:ip(_ip), vid(_vid), used(_used)
{
// TODO check size
mac[PREFIX]=_mac[PREFIX];
mac[SUFFIX]=_mac[SUFFIX];
};
~Lease(){};
/**
* Converts this lease's IP and MAC to string
* @param ip ip of the lease in string
* @param mac mac of the lease in string
*/
void to_string(string& _ip, string& _mac);
/**
* Conversion from string IP to unsigned int IP
* @return 0 if success
*/
static int ip_to_number(const string& ip, unsigned int& i_ip);
/**
* Conversion from unsigned int IP to string IP
*/
static void ip_to_string(const unsigned int i_ip, string& ip);
/**
* Conversion from string MAC to unsigned int[] MAC
* @return 0 if success
*/
static int mac_to_number(const string& mac, unsigned int i_mac[]);
/**
* Conversion from string IP to unsigned int IP
*/
static void mac_to_string(const unsigned int i_mac[], string& mac);
/**
* Prints a Lease in a single line
*/
friend ostream& operator<<(ostream& os, Lease& _lease);
/**
* Constants to access the array storing the MAC address
*/
enum MACIndex
{
SUFFIX = 0,/**< Lower significant 4 bytes */
PREFIX = 1 /**< Higher significant 2 bytes */
};
unsigned int ip;
unsigned int mac [2];
int vid;
bool used;
};
friend ostream& operator<<(ostream& os, Lease& _lease);
friend class VirtualNetwork;
// -------------------------------------------------------------------------
// Leases fields
// -------------------------------------------------------------------------
/**
* Leases indentifier. Connects it to a Virtual Network
*/
int oid;
/**
* Number of possible leases (free + asigned)
*/
unsigned int size;
/**
* Hash of leases, indexed by lease.ip
*/
map<unsigned int, Lease *> leases;
// -------------------------------------------------------------------------
// DataBase implementation variables
// -------------------------------------------------------------------------
/**
* Pointer to the DataBase
*/
SqliteDB * db;
enum ColNames
{
OID = 0,
IP = 1,
MAC_PREFIX = 2,
MAC_SUFFIX = 3,
VID = 4,
USED = 5,
LIMIT = 6
};
static const char * table;
static const char * db_names;
static const char * db_bootstrap;
// -------------------------------------------------------------------------
// Leases methods
// -------------------------------------------------------------------------
/**
* Check if the passed ip corresponds with a given lease
* @param ip of the lease to be checked
* @return true if the ip was already assigned
*/
bool check(const string& ip);
bool check(unsigned int ip);
/**
* Reads the leases from the DB, and updates the lease hash table
* @param db pointer to the database.
* @return 0 on success.
*/
virtual int select(SqliteDB * db);
private:
friend int leases_select_cb (
void * _leases,
int num,
char ** values,
char ** names);
/**
* Function to unmarshall a leases object
* @param num the number of columns read from the DB
* @para names the column names
* @para vaues the column values
* @return 0 on success
*/
int unmarshall(int num, char **names, char ** values);
/**
* This method should not be called, leases are added/removed/updated
* through add/del interface
* @param db pointer to the database.
* @return 0 on success.
*/
int insert(SqliteDB * db);
/**
* Leases are added/removed/updated through add/del interface
* This method is for pool management.
* @param db pointer to the database.
* @return 0 on success.
*/
int drop(SqliteDB * db);
/**
* This method should not be called, leases are added/removed/updated
* through add/del interface
* @param db pointer to the database.
* @return 0 on success.
*/
int update(SqliteDB * db);
/**
* Sets the value of a column in the pool for a given object
* @param db pointer to Database
* @param column to be selected
* @param where condition to select the column
* @param value of the column
* @return 0 on success
*/
int update_column(
SqliteDB * db,
const string& column,
const string& where,
const string& value)
{
return ObjectSQL::update_column(db,table,column,where,value);
}
/**
* Gets the value of a column in the pool for a given object
* @param db pointer to Database
* @param column to be selected
* @param where condition to select the column
* @param value of the column
* @return 0 on success
*/
int select_column(
SqliteDB * db,
const string& column,
const string& where,
string * value)
{
return ObjectSQL::select_column(db,table,column,where,value);
}
};
#endif /*LEASES_H_*/

View File

@ -24,6 +24,7 @@
#include "NebulaTemplate.h"
#include "VirtualMachinePool.h"
#include "VirtualNetworkPool.h"
#include "HostPool.h"
#include "VirtualMachineManager.h"
@ -87,6 +88,11 @@ public:
{
return hpool;
};
VirtualNetworkPool * get_vnpool()
{
return vnpool;
};
// --------------------------------------------------------------
// Manager Accessors
@ -121,14 +127,20 @@ public:
// Environment & Configuration
// --------------------------------------------------------------
string& get_nebula_location()
const string& get_nebula_location()
{
return nebula_location;
};
const string& get_nebula_hostname()
{
return hostname;
};
static string version()
{
return "ONE0.1";
return "ONE1.1";
};
void start();
@ -148,7 +160,7 @@ private:
//Constructors and = are private to only access the class through instance
// -----------------------------------------------------------------------
Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),lcm(0),
Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0),lcm(0),
vmm(0),im(0),tm(0),dm(0),rm(0){};
~Nebula()
@ -213,6 +225,7 @@ private:
// ---------------------------------------------------------------
string nebula_location;
string hostname;
// ---------------------------------------------------------------
// Configuration
@ -224,9 +237,10 @@ private:
// Nebula Pools
// ---------------------------------------------------------------
SqliteDB * db;
SqliteDB * db;
VirtualMachinePool * vmpool;
HostPool * hpool;
HostPool * hpool;
VirtualNetworkPool * vnpool;
// ---------------------------------------------------------------
// Nebula Managers

View File

@ -156,7 +156,7 @@ private:
int lastOID;
/**
* The pool is implemented with a Map, of SQL object pointers, using the
* The pool is implemented with a Map of SQL object pointers, using the
* OID as key.
*/
map<int,PoolObjectSQL *> pool;
@ -175,7 +175,7 @@ private:
/**
* FIFO-like replacement policy function. Before removing an object (pop)
* from the cache it's lock is checked. The object is removed only if
* from the cache its lock is checked. The object is removed only if
* the associated mutex IS NOT blocked. Otherwise the oid is sent to the
* back of the queue.
*/

101
include/RangedLeases.h Normal file
View File

@ -0,0 +1,101 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef RANGED_LEASES_H_
#define RANGED_LEASES_H_
#include "Leases.h"
using namespace std;
class RangedLeases : public Leases
{
public:
// *************************************************************************
// Constructor
// *************************************************************************
RangedLeases(SqliteDB * db,
int _oid,
unsigned long _size,
unsigned int _mac_prefix,
const string& _network_address);
~RangedLeases(){};
/**
* Returns an unused lease, which becomes used
* @param vid identifier of the VM getting this lease
* @param ip ip of the returned lease
* @param mac mac of the returned lease
* @return 0 if success
*/
int get(int vid, string& ip, string& mac);
/**
* Release an used lease, which becomes unused
* @param ip of the lease in use
*/
void release(const string& ip)
{
del(ip);
}
/**
* Loads the leases from the DB.
*/
int select(SqliteDB * db)
{
//Read the leases from the DB
int rc = Leases::select(db);
return rc;
}
private:
/**
* The default MAC prefix for the OpenNebula cluster
*/
unsigned int mac_prefix;
/**
* The Network address to generate leases
*/
unsigned int network_address;
unsigned int current;
/**
* Add a lease, from the Lease interface
* @param ip ip of the lease
* @param mac mac of the lease
* @param vid identifier of the VM getting this lease
* @return 0 if success
*/
int add(unsigned int ip, unsigned int mac[], int vid, bool used=true);
/**
* Remove a lease, from the Lease interface
* @param db pointer to DB
* @param ip ip of the lease to be deleted
* @return 0 if success
*/
int del(const string& ip);
};
#endif /*RANGED_LEASES_H_*/

View File

@ -21,7 +21,7 @@
#include "ActionManager.h"
#include "VirtualMachinePool.h"
#include "HostPool.h"
#include "VirtualNetworkPool.h"
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
@ -40,9 +40,10 @@ public:
RequestManager(
VirtualMachinePool * _vmpool,
HostPool * _hpool,
VirtualNetworkPool * _vnpool,
int _port,
string _xml_log_file)
:vmpool(_vmpool),hpool(_hpool),port(_port),socket_fd(-1),
:vmpool(_vmpool),hpool(_hpool),vnpool(_vnpool),port(_port),socket_fd(-1),
xml_log_file(_xml_log_file)
{
am.addListener(this);
@ -98,7 +99,7 @@ private:
pthread_t rm_xml_server_thread;
/**
* Pointer to the Host Pool, to access hosts
* Pointer to the VM Pool, to access Virtual Machines
*/
VirtualMachinePool * vmpool;
@ -106,6 +107,11 @@ private:
* Pointer to the Host Pool, to access hosts
*/
HostPool * hpool;
/**
* Pointer to the VN Pool, to access Virtual Netowrks
*/
VirtualNetworkPool * vnpool;
/**
* Port number where the connection will be open
@ -352,7 +358,75 @@ private:
private:
HostPool * hpool;
};
};
/* ---------------------------------------------------------------------- */
/* Virtual Network Interface */
/* ---------------------------------------------------------------------- */
class VirtualNetworkAllocate: public xmlrpc_c::method
{
public:
VirtualNetworkAllocate(VirtualNetworkPool * _vnpool):vnpool(_vnpool)
{
_signature="A:ss";
_help="Creates a virtual network";
};
~VirtualNetworkAllocate(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
VirtualNetworkPool * vnpool;
};
/* ---------------------------------------------------------------------- */
class VirtualNetworkInfo: public xmlrpc_c::method
{
public:
VirtualNetworkInfo(VirtualNetworkPool * _vnpool):vnpool(_vnpool)
{
_signature="A:si";
_help="Returns virtual network information";
};
~VirtualNetworkInfo(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
VirtualNetworkPool * vnpool;
};
/* ---------------------------------------------------------------------- */
class VirtualNetworkDelete: public xmlrpc_c::method
{
public:
VirtualNetworkDelete(VirtualNetworkPool * _vnpool):vnpool(_vnpool)
{
_signature="A:si";
_help="Deletes a virtual network";
};
~VirtualNetworkDelete(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
VirtualNetworkPool * vnpool;
};
};
/* -------------------------------------------------------------------------- */

View File

@ -96,8 +96,17 @@ public:
* @returns the number of elements in the vector
*/
virtual int get(
string& name,
const string& name,
vector<const Attribute*>& values) const;
/**
* Gets all the attributes with the given name, non-const version
* @param name the attribute name.
* @returns the number of elements in the vector
*/
virtual int get(
const string& name,
vector<Attribute*>& values);
/**
* Gets the value of a Single attributes (string) with the given name.

View File

@ -92,7 +92,8 @@ protected:
* @param name of the attribute.
* @param value of the new attribute.
*/
int replace_attribute(SqliteDB * db, string& name, string& value);
int replace_attribute(SqliteDB * db, const string& name, const string& value);
};
/* -------------------------------------------------------------------------- */

View File

@ -22,6 +22,7 @@
#include "ActionManager.h"
#include "VirtualMachinePool.h"
#include "LifeCycleManager.h"
#include "TransferManagerDriver.h"
using namespace std;
@ -32,10 +33,12 @@ class TransferManager : public MadManager, public ActionListener
public:
TransferManager(
VirtualMachinePool * pool,
VirtualMachinePool * _vmpool,
HostPool * _hpool,
vector<const Attribute*>& _mads):
MadManager(_mads),
hpool(pool)
vmpool(_vmpool),
hpool(_hpool)
{
am.addListener(this);
};
@ -45,7 +48,10 @@ public:
enum Actions
{
PROLOG,
PROLOG_MIGR,
PROLOG_RESUME,
EPILOG,
EPILOG_STOP,
CHECKPOINT,
FINALIZE
};
@ -75,7 +81,7 @@ public:
* identity will be used. Otherwise the Mad will be loaded through the
* sudo application.
*/
void load_mads(int uid){};
void load_mads(int uid);
/**
* Gets the thread identification.
@ -93,15 +99,54 @@ private:
pthread_t tm_thread;
/**
* Pointer to the VM Pool, to access virtual machines
* Pointer to the Virtual Machine Pool, to access VMs
*/
VirtualMachinePool * hpool;
VirtualMachinePool * vmpool;
/**
* Pointer to the Host Pool, to access hosts
*/
HostPool * hpool;
/**
* Action engine for the Manager
*/
ActionManager am;
ActionManager am;
/**
* Returns a pointer to a Transfer Manager driver.
* @param uid of the owner of the driver
* @param name of an attribute of the driver (e.g. its type)
* @param value of the attribute
* @return the TM driver owned by uid with attribute name equal to value
* or 0 in not found
*/
const TransferManagerDriver * get(
int uid,
const string& name,
const string& value)
{
return static_cast<const TransferManagerDriver *>
(MadManager::get(uid,name,value));
};
/**
* Returns a pointer to a Transfer Manager driver. The driver is
* searched by its name.
* @param uid of the owner of the driver
* @param name the name of the driver
* @return the TM driver owned by uid with attribute name equal to value
* or 0 in not found
*/
const TransferManagerDriver * get(
int uid,
const string& name)
{
string _name("NAME");
return static_cast<const TransferManagerDriver *>
(MadManager::get(uid,_name,name));
};
/**
* Function to execute the Manager action loop method within a new pthread
* (requires C linkage)
@ -122,11 +167,26 @@ private:
*/
void prolog_action(int vid);
/**
* This function starts the prolog migration sequence
*/
void prolog_migr_action(int vid);
/**
* This function starts the prolog resume sequence
*/
void prolog_resume_action(int vid);
/**
* This function starts the epilog sequence
*/
void epilog_action(int vid);
/**
* This function starts the epilog_stop sequence
*/
void epilog_stop_action(int vid);
/**
* This function starts the epilog sequence
*/

View File

@ -0,0 +1,84 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef TRANSFER_MANAGER_DRIVER_H_
#define TRANSFER_MANAGER_DRIVER_H_
#include <map>
#include <string>
#include <sstream>
#include "Mad.h"
#include "VirtualMachinePool.h"
using namespace std;
/**
* TransferManagerDriver provides a base class to implement TM
* Drivers. This class implements the protocol and recover functions
* from the Mad interface.
*/
class TransferManagerDriver : public Mad
{
public:
TransferManagerDriver(
int userid,
const map<string,string>& attrs,
bool sudo,
VirtualMachinePool * pool);
virtual ~TransferManagerDriver(){};
/**
* Implements the VM Manager driver protocol.
* @param message the string read from the driver
*/
void protocol(
string& message);
/**
* TODO: What do we need here? Check on-going xfr?
*/
void recover();
private:
friend class TransferManager;
/**
* Configuration file for the driver
*/
Template driver_conf;
/**
* Pointer to the Virtual Machine Pool, to access VMs
*/
VirtualMachinePool * vmpool;
/**
* Sends a transfer request to the MAD: "TRANSFER ID XFR_FILE"
* @param oid the virtual machine id.
* @param xfr_file is the path to the transfer script
*/
void transfer (const int oid, const string& xfr_file) const;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#endif /*TRANSFER_MANAGER_DRIVER_H_*/

View File

@ -72,10 +72,11 @@ public:
SAVE_SUSPEND = 6,
SAVE_MIGRATE = 7,
PROLOG_MIGRATE = 8,
EPILOG_STOP = 9,
EPILOG = 10,
SHUTDOWN = 11,
CANCEL = 12
PROLOG_RESUME = 9,
EPILOG_STOP = 10,
EPILOG = 11,
SHUTDOWN = 12,
CANCEL = 13
};
// -------------------------------------------------------------------------
@ -250,34 +251,71 @@ public:
};
/**
* Returns the deployment filename (local path). The hasHistory()
* function MUST be called before this one.
* @return the deployment filename
* Returns the transfer filename. The transfer file is in the form:
* $ONE_LOCATION/var/$VM_ID/transfer.$SEQ
* The hasHistory() function MUST be called before this one.
* @return the transfer filename
*/
const string & get_deployment_lfile() const
const string & get_transfer_file() const
{
return history->deployment_lfile;
return history->transfer_file;
};
/**
* Returns the deployment filename for the current host (remote). The
* hasHistory() function MUST be called before this one.
* Returns the deployment filename. The deployment file is in the form:
* $ONE_LOCATION/var/$VM_ID/deployment.$SEQ
* The hasHistory() function MUST be called before this one.
* @return the deployment filename
*/
const string & get_deployment_rfile() const
const string & get_deployment_file() const
{
return history->deployment_rfile;
return history->deployment_file;
};
/**
* Returns the remote deployment filename. The file is in the form:
* $VM_DIR/$VM_ID/images/deployment.$SEQ
* The hasHistory() function MUST be called before this one.
* @return the deployment filename
*/
const string & get_remote_deployment_file() const
{
return history->rdeployment_file;
};
/**
* Returns the checkpoint filename for the current host (remote). The
* hasHistory() function MUST be called before this one.
* Returns the checkpoint filename for the current host. The checkpoint file
* is in the form:
* $VM_DIR/$VM_ID/images/checkpoint
* The hasHistory() function MUST be called before this one.
* @return the checkpoint filename
*/
const string & get_checkpoint_file() const
{
return history->checkpoint_file;
};
/**
* Returns the remote VM directory. The VM remote dir is in the form:
* $VM_DIR/$VM_ID/
* The hasHistory() function MUST be called before this one.
* @return the remote directory
*/
const string & get_remote_dir() const
{
return history->vm_rhome;
};
/**
* Returns the local VM directory. The VM local dir is in the form:
* $ONE_LOCATION/var/$VM_ID/
* The hasHistory() function MUST be called before this one.
* @return the remote directory
*/
const string & get_local_dir() const
{
return history->vm_lhome;
};
/**
* Returns the hostname for the current host. The hasHistory()
@ -299,6 +337,15 @@ public:
return previous_history->hostname;
};
/**
* Returns the reason that originated the VM migration in the previous host
* @return the migration reason to leave this host
*/
const History::MigrationReason get_previous_reason() const
{
return previous_history->reason;
};
/**
* Get host id where the VM is or is going to execute. The hasHistory()
* function MUST be called before this one.
@ -532,6 +579,7 @@ public:
{
return uid;
};
// ------------------------------------------------------------------------
// Timers
@ -561,6 +609,15 @@ public:
* @param disk
*/
void get_requirements (int& cpu, int& memory, int& disk);
// ------------------------------------------------------------------------
// Leases
// ------------------------------------------------------------------------
/**
* Releases all network leases taken by this Virtual Machine
*/
void release_leases();
private:
@ -578,20 +635,11 @@ private:
// *************************************************************************
// Virtual Machine Attributes
// *************************************************************************
// -------------------------------------------------------------------------
// Identification variables
// -------------------------------------------------------------------------
/**
* Array id
*/
int aid;
/**
* Task id
*/
int tid;
/**
* User (owner) id
*/
@ -599,22 +647,7 @@ private:
// -------------------------------------------------------------------------
// VM Scheduling & Managing Information
// -------------------------------------------------------------------------
/**
* Static scheduling priority
*/
int priority;
/**
* The VM reschedule flag
*/
bool reschedule;
/**
* Last time (in epoch) that the VM was rescheduled
*/
time_t last_reschedule;
// -------------------------------------------------------------------------
/**
* Last time (in epoch) that the VM was polled to get its status
*/
@ -783,24 +816,19 @@ protected:
enum ColNames
{
OID = 0,
AID = 1,
TID = 2,
UID = 3,
PRIORITY = 4,
RESCHEDULE = 5,
LAST_RESCHEDULE = 6,
LAST_POLL = 7,
TEMPLATE_ID = 8,
STATE = 9,
LCM_STATE = 10,
STIME = 11,
ETIME = 12,
DEPLOY_ID = 13,
MEMORY = 14,
CPU = 15,
NET_TX = 16,
NET_RX = 17,
LIMIT = 18
UID = 1,
LAST_POLL = 2,
TEMPLATE_ID = 3,
STATE = 4,
LCM_STATE = 5,
STIME = 6,
ETIME = 7,
DEPLOY_ID = 8,
MEMORY = 9,
CPU = 10,
NET_TX = 11,
NET_RX = 12,
LIMIT = 13
};
static const char * table;

349
include/VirtualNetwork.h Normal file
View File

@ -0,0 +1,349 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef VIRTUAL_NETWORK_H_
#define VIRTUAL_NETWORK_H_
#include "PoolSQL.h"
#include "VirtualNetworkTemplate.h"
#include "Leases.h"
#include <vector>
#include <string>
#include <map>
#include <time.h>
#include <sstream>
using namespace std;
extern "C" int vn_select_cb (void * _vn, int num,char ** values, char ** names);
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/**
* The Virtual Network class. It represents a Virtual Network at manages its leases.
* One lease is formed by one IP and one MAC address.
* MAC address are derived from IP addresses.
*/
class VirtualNetwork : public PoolObjectSQL
{
public:
/**
* Possible types of networks
*/
enum NetworkType
{
UNINITIALIZED = -1,
RANGED = 0,
FIXED = 1,
};
// *************************************************************************
// Virtual Network Public Methods
// *************************************************************************
/**
* Gets a new lease for a specific VM
* @param vid VM identifier
* @param _ip pointer to string for IP to be stored into
* @param _mac pointer to string for MAC to be stored into
* @param _bridge name of the physical bridge this VN binds to
* @return 0 if success
*/
int get_lease(int vid, string& _ip, string& _mac, string& _bridge)
{
_bridge = bridge;
return leases->get(vid,_ip,_mac);
};
/**
* Release previously given lease
* @param _ip IP identifying the lease
* @return 0 if success
*/
void release_lease(const string& ip)
{
return leases->release(ip);
};
/**
* Gets size of the network (used + free)
* @return number of hosts that can be fitted in this network
*/
unsigned int get_size()
{
return leases->size;
};
/**
* Function to write a Virtual Network in an output stream
*/
friend ostream& operator<<(ostream& os, VirtualNetwork& vn);
private:
// -------------------------------------------------------------------------
// Friends
// -------------------------------------------------------------------------
friend class VirtualNetworkPool;
friend int vn_select_cb (
void * _vm,
int num,
char ** values,
char ** names);
// *************************************************************************
// Virtual Network Private Attributes
// *************************************************************************
// -------------------------------------------------------------------------
// Identification variables
// -------------------------------------------------------------------------
/**
* Name of the Virtual Network
*/
string name;
/**
* Owner of the Virtual Network
*/
int uid;
// -------------------------------------------------------------------------
// Binded physical attributes
// -------------------------------------------------------------------------
/**
* Name of the bridge this VNW binds to
*/
string bridge;
// -------------------------------------------------------------------------
// Virtual Network Description
// -------------------------------------------------------------------------
/**
* Holds the type of this network
*/
NetworkType type;
/**
* Pointer to leases class, can be fixed or ranged.
* Holds information on given (and, optionally, possible) leases
*/
Leases * leases;
/**
* The Virtual Network template, holds the VNW attributes.
*/
VirtualNetworkTemplate vn_template;
// *************************************************************************
// Non persistent data members from Nebula.conf
// *************************************************************************
/**
* MAC prefix for this OpenNebula site
*/
unsigned int mac_prefix;
/**
* Default size for virtual networks
*/
int default_size;
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************
/**
* Bootstraps the database table(s) associated to the Virtual Network
*/
static void bootstrap(SqliteDB * db)
{
db->exec(VirtualNetwork::db_bootstrap);
db->exec(VirtualNetworkTemplate::db_bootstrap);
db->exec(Leases::db_bootstrap);
};
/**
* Function to unmarshall a VNW object, and associated classes.
* @param num the number of columns read from the DB
* @para names the column names
* @para vaues the column values
* @return 0 on success
*/
int unmarshall(int num, char **names, char ** values);
/**
* Function to drop VN entry in vn_pool
* @return 0 on success
*/
int vn_drop(SqliteDB * db);
// ------------------------------------------------------------------------
// Template
// ------------------------------------------------------------------------
/**
* Gets the values of a template attribute
* @param name of the attribute
* @param values of the attribute
* @return the number of values
*/
int get_template_attribute(
string& name,
vector<const Attribute*>& values) const
{
return vn_template.get(name,values);
};
/**
* Gets the values of a template attribute
* @param name of the attribute
* @param values of the attribute
* @return the number of values
*/
int get_template_attribute(
const char *name,
vector<const Attribute*>& values) const
{
string str=name;
return vn_template.get(str,values);
};
/**
* Gets a string based VN attribute
* @param name of the attribute
* @param value of the attribute (a string), will be "" if not defined
*/
void get_template_attribute(
const char * name,
string& value) const
{
string str=name;
vn_template.get(str,value);
}
/**
* Gets a string based VN attribute
* @param name of the attribute
* @param value of the attribute (an int), will be 0 if not defined
*/
void get_template_attribute(
const char * name,
int& value) const
{
string str=name;
vn_template.get(str,value);
}
/**
* Updates the template of a VNW, adding a new attribute (replacing it if
* already defined), the VN's mutex SHOULD be locked
* @param vm pointer to the virtual network object
* @param name of the new attribute
* @param value of the new attribute
* @return 0 on success
*/
int update_template_attribute(
SqliteDB * db,
string& name,
string& value)
{
return vn_template.replace_attribute(db,name,value);
}
protected:
//**************************************************************************
// Constructor
//**************************************************************************
VirtualNetwork(unsigned int _mac_prefix, int _default_size);
~VirtualNetwork();
// *************************************************************************
// DataBase implementation
// *************************************************************************
enum ColNames
{
OID = 0,
UID = 1,
NAME = 2,
TYPE = 3,
BRIDGE = 4,
LIMIT = 5
};
static const char * table;
static const char * db_names;
static const char * db_bootstrap;
/**
* Reads the Virtual Network (identified with its OID) from the database.
* @param db pointer to the db
* @return 0 on success
*/
int select(SqliteDB * db);
/**
* Writes the Virtual Network and its associated template and leases in the database.
* @param db pointer to the db
* @return 0 on success
*/
int insert(SqliteDB * db);
/**
* Writes/updates the Virtual Network data fields in the database.
* @param db pointer to the db
* @return 0 on success
*/
int update(SqliteDB * db);
/**
* Deletes a VNW from the database and all its associated information:
* - VNW template
* - given leases
* @param db pointer to the db
* @return 0 on success
*/
int drop(SqliteDB * db)
{
int rc;
rc = vn_template.drop(db);
rc += leases->drop(db);
rc += vn_drop(db);
return rc;
}
};
#endif /*VIRTUAL_NETWORK_H_*/

View File

@ -0,0 +1,144 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef VIRTUAL_NETWORK_POOL_H_
#define VIRTUAL_NETWORK_POOL_H_
#include "PoolSQL.h"
#include "VirtualNetwork.h"
#include <time.h>
using namespace std;
/**
* The Virtual Network Pool class. ...
*/
class VirtualNetworkPool : public PoolSQL
{
public:
VirtualNetworkPool(SqliteDB * db,
const string& str_mac_prefix,
int default_size);
~VirtualNetworkPool(){};
/**
* Function to allocate a new VN object
* @param uid user identifier
* @param stemplate a string describing the VN
* @param oid the id assigned to the VM (output)
* @return 0 on success, -1 error inserting in DB,-2 error parsing
* the template, -3 wrong attributes in template
*/
int allocate (
int uid,
const string& stemplate,
int * oid);
/**
* Function to get a VN from the pool, if the object is not in memory
* it is loaded from the DB
* @param oid VN unique id
* @param lock locks the VN mutex
* @return a pointer to the VN, 0 if the VN could not be loaded
*/
VirtualNetwork * get(
int oid,
bool lock)
{
return static_cast<VirtualNetwork *>(PoolSQL::get(oid,lock));
};
/**
* Function to get a VN from the pool using the network name
* If the object is not in memory it is loaded from the DB
* @param name VN unique name
* @param lock locks the VN mutex
* @return a pointer to the VN, 0 if the VN could not be loaded
*/
VirtualNetwork * get(
const string& name,
bool lock);
//--------------------------------------------------------------------------
// Virtual Network DB access functions
//--------------------------------------------------------------------------
/**
* Updates the template of a VN, adding a new attribute (replacing it if
* already defined), the VN's mutex SHOULD be locked
* @param vn pointer to the virtual network object
* @param name of the new attribute
* @param value of the new attribute
* @return 0 on success
*/
int update_template_attribute(
VirtualNetwork * vn,
string& name,
string& value)
{
return vn->update_template_attribute(db,name,value);
};
/**
* Bootstraps the database table(s) associated to the VirtualNetwork pool
*/
void bootstrap()
{
VirtualNetwork::bootstrap(db);
};
/** Drops a VN from the cache & DB, the VN mutex MUST BE locked
* @param vn pointer to VN
*/
int drop(VirtualNetwork * vn)
{
int rc = vn->drop(db);
if ( rc == 0)
{
remove(static_cast<PoolObjectSQL *>(vn));
}
return rc;
};
private:
/**
* Factory method to produce VN objects
* @return a pointer to the new VN
*/
PoolObjectSQL * create()
{
return new VirtualNetwork(mac_prefix, default_size);
};
/**
* Holds the system-wide MAC prefix
*/
unsigned int mac_prefix;
/**
* Default size for Virtual Networks
*/
unsigned int default_size;
};
#endif /*VIRTUAL_NETWORK_POOL_H_*/

View File

@ -0,0 +1,47 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef VIRTUAL_NETWORK_TEMPLATE_H_
#define VIRTUAL_NETWORK_TEMPLATE_H_
#include "TemplateSQL.h"
using namespace std;
/**
* Virtual Network Template class, it represents a VN configuration file.
*/
class VirtualNetworkTemplate : public TemplateSQL
{
public:
VirtualNetworkTemplate(int tid = -1):
TemplateSQL(table,tid){};
~VirtualNetworkTemplate(){};
private:
friend class VirtualNetwork;
static const char * table;
static const char * db_bootstrap;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#endif /*VIRTUAL_NETWORK_TEMPLATE_H_*/

View File

@ -30,7 +30,7 @@ if [ -z "$SRC_DIR" -o -z "$DST_DIR" ]; then
exit -1
fi
DIRS="/bin /include /etc /etc/im_kvm /etc/im_xen /etc/vmm_kvm /etc/vmm_xen /libexec /lib/ruby /var /share/examples /lib/im_probes /etc/vmm_ec2 /etc/im_ec2"
DIRS="/bin /include /etc /etc/im_kvm /etc/im_xen /etc/vmm_kvm /etc/vmm_xen /libexec /lib/ruby /var /share/examples /lib/im_probes /lib/tm_commands/nfs /lib/tm_commands/ssh /etc/vmm_ec2 /etc/im_ec2 /etc/tm_nfs /etc/tm_ssh"
for d in $DIRS; do
mkdir -p $DST_DIR$d
@ -43,6 +43,7 @@ inst_ln src/scheduler/mm_sched bin
inst_ln src/client/ruby/onevm bin
inst_ln src/client/ruby/onehost bin
inst_ln src/client/ruby/onenetwork bin
inst_ln share/scripts/madcommon.sh libexec
inst_ln share/scripts/one bin
@ -56,6 +57,7 @@ inst_ln include/OneClient.h include/
inst_ln src/mad/ruby/one_mad.rb lib/ruby
inst_ln src/mad/ruby/one_ssh.rb lib/ruby
inst_ln src/mad/ruby/ThreadScheduler.rb lib/ruby
inst_ln src/client/ruby/one.rb lib/ruby
inst_ln src/client/ruby/client_utilities.rb lib/ruby
@ -115,6 +117,35 @@ inst_ln src/im_mad/host_probes/architecture.sh lib/im_probes
inst_ln src/im_mad/host_probes/cpu.sh lib/im_probes
inst_ln src/im_mad/host_probes/name.sh lib/im_probes
# -- Transfer manager --
inst_ln src/tm_mad/one_tm bin
inst_ln src/tm_mad/one_tm.rb bin
inst_ln src/tm_mad/TMScript.rb lib/ruby
inst_ln src/tm_mad/tm_common.sh libexec
inst_ln src/tm_mad/nfs/tm_nfs.conf etc/tm_nfs
inst_ln src/tm_mad/nfs/tm_nfsrc etc/tm_nfs
inst_ln src/tm_mad/nfs/tm_clone.sh lib/tm_commands/nfs
inst_ln src/tm_mad/nfs/tm_delete.sh lib/tm_commands/nfs
inst_ln src/tm_mad/nfs/tm_ln.sh lib/tm_commands/nfs
inst_ln src/tm_mad/nfs/tm_mkswap.sh lib/tm_commands/nfs
inst_ln src/tm_mad/nfs/tm_mkimage.sh lib/tm_commands/nfs
inst_ln src/tm_mad/nfs/tm_mv.sh lib/tm_commands/nfs
inst_ln src/tm_mad/ssh/tm_ssh.conf etc/tm_ssh
inst_ln src/tm_mad/ssh/tm_sshrc etc/tm_ssh
inst_ln src/tm_mad/ssh/tm_clone.sh lib/tm_commands/ssh
inst_ln src/tm_mad/ssh/tm_delete.sh lib/tm_commands/ssh
inst_ln src/tm_mad/ssh/tm_ln.sh lib/tm_commands/ssh
inst_ln src/tm_mad/ssh/tm_mkswap.sh lib/tm_commands/ssh
inst_ln src/tm_mad/ssh/tm_mkimage.sh lib/tm_commands/ssh
inst_ln src/tm_mad/ssh/tm_mv.sh lib/tm_commands/ssh
# --- Examples ---
inst_cp share/examples/vm.template share/examples

View File

@ -9,25 +9,42 @@
# HOST_MONITORING_INTERVAL: Time in seconds between host monitorization
# VM_POLLING_INTERVAL: Time in seconds between virtual machine monitorization
#
# VM_RDIR: The remote nodes must have access to $ONE_LOCATION/var, so this must
# be shared between the ONE server and the remote nodes. If the mount point of
# $ONE_LOCATION/var has a different path in the remote nodes than in the ONE server,
# set here the mount point of the _remote_ nodes
# VM_DIR: Remote path to store the VM images, it should be shared between all
# the cluster nodes to perform live migrations. This variable is the default
# for all the hosts in the cluster. You can set it in a per host basis when
# adding a host (onehost add)
#
# PORT: Port where oned will listen for xmlrpc calls.
#
# MAC_PREFIX: Default MAC prefix to generate virtual network MAC addresses
#
# NETWORK_SIZE: Default size fot virtual networks
#
# DEBUG_LEVEL: 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG
#-------------------------------------------------------------------------------
HOST_MONITORING_INTERVAL = 10
VM_POLLING_INTERVAL = 10
#VM_RDIR=/vCluster/var
#VM_DIR=/vCluster/var
PORT=2633
DEBUG_LEVEL=3
#-------------------------------------------------------------------------------
# Physical Networks configuration
#-------------------------------------------------------------------------------
# Here you can define the default size for the virtual networks
#
# Also, the default MAC prefix to be used to create the auto-generated MAC addresses
# is defined here (this can be overrided by the Virtual Network template)
#--------------------------------------------------------------------------------
MAC_PREFIX="00:01"
NETWORK_SIZE=254
#-------------------------------------------------------------------------------
# Information Driver Configuration
#-------------------------------------------------------------------------------
@ -106,4 +123,31 @@ VM_MAD = [
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# Transfer Manager Driver Configuration
#-------------------------------------------------------------------------------
# You can add more transfer managers with different configurations but make
# sure it has different names.
# name : name for this transfer manager
# executable: path of the transfer manager executable, can be an
# absolute path or a relative path from $ONE_LOCATION
# arguments : for the driver executable
# default : default values and configuration parameters for the driver
#-------------------------------------------------------------------------------
TM_MAD = [
name = "tm_nfs",
executable = "bin/one_tm",
arguments = "etc/tm_nfs/tm_nfs.conf",
default = "etc/tm_nfs/tm_nfs.conf" ]
#-------------------------------------------------------------------------------
# Physical Networks configuration
#-------------------------------------------------------------------------------
# Here you can define available physical networks by giving them a name
# and specifying which bridge of the physical hosts VMs should be tied to.
#
# Also, the default MAC prefix to be used to create the auto-generated MAC addresses
# is defined here (this can be overrided by the Virtual Network template)
#--------------------------------------------------------------------------------

View File

@ -0,0 +1,5 @@
NAME = "Private LAN"
TYPE = RANGED
BRIDGE = eth0
NETWORK_SIZE = 250
NETWORK_ADDRESS= 10.0.0.0

View File

@ -0,0 +1,9 @@
NAME = "Public LAN"
TYPE = FIXED
BRIDGE= eth1
LEASES= [IP=130.10.0.1,MAC=50:20:20:20:20:20]
LEASES= [IP=130.10.0.2,MAC=50:20:20:20:20:21]
LEASES= [IP=130.10.0.3,MAC=50:20:20:20:20:22]
LEASES= [IP=130.10.0.4]
LEASES= [IP=130.10.0.5]
LEASES= [IP=130.10.0.6]

View File

@ -42,12 +42,15 @@ FEATURES = [
#---------------------------------------
DISK = [
type = "floppy|disk|cdrom", #Optional, KVM
type = "floppy|disk|cdrom|swap", #Optional, KVM ,XEN(only swap)
source = "path_to_disk_image_file|physical_dev", #Mandatory, XEN, KVM
size = "size_in_GB", #Optional, KVM, XEN (only for swap, defaults 1G)
target = "device_to_map_disk", #Mandatory, XEN, KVM
bus = "ide|scsi|virtio|xen", #Optional, KVM
readonly = "yes|no" ] #Optional, XEN, KVM
readonly = "yes|no", #Optional, XEN, KVM
clone = "yes|no", #Optional, XEN, KVM
save = "path_to_disk_image_file" ] #Optional, XEN, KVM
#---------------------------------------
# Network Interfaces
#---------------------------------------

View File

@ -30,6 +30,9 @@ DISK = [
NIC = [ mac="00:ff:72:17:20:27"]
NIC = [ NETWORK="Private LAN"]
# --- VNC server ---
GRAPHICS = [

View File

@ -259,3 +259,23 @@ def get_host_id(host, name)
result
end
def get_vn_id(vn, name)
vn_id=vn.get_vn_id(name)
result=nil
if vn_id
if vn_id.kind_of?(Array)
puts "There are multiple virtual networks with name #{name}."
exit -1
else
result=vn_id
end
else
puts "Virtual networks named #{name} not found."
exit -1
end
result
end

View File

@ -33,17 +33,18 @@ module ONE
ONE_LOCATION=ENV["ONE_LOCATION"]
TABLES={
"vmpool" => %w{oid aid tid uid priority reschedule last_reschedule
last_poll template state lcm_state stime etime deploy_id memory
cpu net_tx net_rx},
"history" => %w{oid seq hostname vm_dir hid vmmad tmmad stime
"vm_pool" => %w{oid uid last_poll template_id state lcm_state
stime etime deploy_id memory cpu net_tx net_rx},
"history" => %w{vid seq host_name vm_dir hid vm_mad tm_mad stime
etime pstime petime rstime retime estime eetime reason},
"vm_template" => %w{id name type value},
"hostpool" => %w{hid host_name state im_mad vm_mad tm_mad
"vm_attributes" => %w{id name type value},
"host_pool" => %w{oid host_name state im_mad vm_mad tm_mad
last_mon_time managed},
"host_attributes" => %w{id name type value},
"hostshares" => %w{hsid endpoint disk_usage mem_usage
"host_shares" => %w{hid endpoint disk_usage mem_usage
cpu_usage max_disk max_mem max_cpu running_vms}
"network_pool" => %w{oid uid name type bridge},
"vn_template" => %w{id name type value}
}
@ -100,8 +101,6 @@ module ONE
@db.busy_handler do |data, retries|
if retries < 3
puts "Timeout connecting to the database, retrying. "+
"Tries left #{2-retries}"
sleep 1
1
else
@ -125,6 +124,7 @@ module ONE
res=result.collect {|row|
r=Hash.new
TABLES[table].each_with_index {|value, index|
r[value]=row[index]
}
@ -289,15 +289,25 @@ module ONE
def delete(*args)
self.action("finalize", args[0])
end
def get_db
if !@db
@db=Database.new
end
@db
end
def close_db
if @db
@db.close
@db=nil
end
end
def get(options=nil)
begin
@db=Database.new
res=get_db.select_table_with_names("vm_pool", options)
res=@db.select_table_with_names("vmpool", options)
@db.close
result=res
rescue
result=[false, "Error accessing database"]
@ -311,7 +321,7 @@ module ONE
if res[0]
res[1].each {|row|
hostname=self.get_history_host(row["oid"])
row["hostname"]=hostname
row["host_name"]=hostname
}
end
res
@ -323,47 +333,29 @@ module ONE
###########
def get_history_host(id, db=nil)
if db
my_db=db
else
my_db=Database.new
end
my_db=get_db
res=my_db.select_table_with_names("history", :where => "oid=#{id}")
my_db.close if !db
res=my_db.select_table_with_names("history", :where => "vid=#{id}")
if res and res[0] and res[1] and res[1][-1]
return hostname=res[1][-1]["hostname"]
return hostname=res[1][-1]["host_name"]
else
return nil
end
end
def get_history(id, db=nil)
if db
my_db=db
else
my_db=Database.new
end
my_db=get_db
res=my_db.select_table_with_names("history", :where => "oid=#{id}")
res=my_db.select_table_with_names("history", :where => "vid=#{id}")
my_db.close if !db
return res
end
def get_template(id, db=nil)
if db
my_db=db
else
my_db=Database.new
end
my_db=get_db
res=my_db.select_table_with_names("vm_template", :where => "id=#{id}")
my_db.close if !db
res=my_db.select_table_with_names("vm_attributes", :where => "id=#{id}")
if res && res[0]
template=Hash.new
@ -431,16 +423,16 @@ module ONE
# id if there is only one vm with that name
# array of ids if there is more than one vm
def get_vm_from_name(name)
db=Database.new
db=get_db
res_template=db.select_table_with_names(
"vm_template",
"vm_attributes",
:where => "name=\"NAME\" AND value=\"#{name}\"")
return nil if !res_template[0] or res_template[1].length<1
selected_vms=res_template[1].collect {|sel_template|
template_id=sel_template["id"]
res_vm=get(:where => "template=#{template_id} AND state<>6")
res_vm=get(:where => "template_id=#{template_id} AND state<>6")
if !res_vm[0] or res_vm[1].length<1
nil
else
@ -483,7 +475,7 @@ module ONE
"enable_" => [:to_i, nil]
}
end
def allocate(*args)
case args[4]
when /^true$/i, 1
@ -507,11 +499,7 @@ module ONE
def get_generic(table, options=nil)
begin
@db=Database.new
res=@db.select_table_with_names(table, options)
@db.close
res=get_db.select_table_with_names(table, options)
result=res
rescue
@ -522,7 +510,7 @@ module ONE
end
def get(options=nil)
get_generic("hostpool", options)
get_generic("host_pool", options)
end
def get_host_attributes(hid)
@ -530,13 +518,27 @@ module ONE
end
def get_host_share(hid)
get_generic("hostshares", :where => "hsid=#{hid}")
get_generic("host_shares", :where => "hid=#{hid}")
end
def prefix
"host"
end
def get_db
if !@db
@db=Database.new
end
@db
end
def close_db
if @db
@db.close
@db=nil
end
end
###########
# HELPERS #
@ -562,9 +564,90 @@ module ONE
return nil if !res[0] or res[1].length<1
if res[1].length==1
return res[1][0]["hid"]
return res[1][0]["oid"]
else
return res[1].collect {|host| host["hid"] }
return res[1].collect {|host| host["oid"] }
end
end
end
class VN < CommandContainer
def commands
{
"allocate_" => [:to_s],
"info" => [:to_i],
"delete" => [:to_i],
}
end
def allocate(*args)
begin
f=open(args[0], "r")
template=f.read
f.close
rescue
return [false, "Can not read template"]
end
self.allocate_(template)
end
def get_generic(table, options=nil)
begin
@db=Database.new
res=@db.select_table_with_names(table, options)
@db.close
result=res
rescue
result=[false, "Error accessing database"]
end
result
end
def get(options=nil)
get_generic("network_pool", options)
end
def get_vn_attributes(nid)
get_generic("vn_template", :where => "oid=#{nid}")
end
def get_vn_leases(nid)
get_generic("leases", :where => "oid=#{nid}")
end
def prefix
"vn"
end
###########
# HELPERS #
###########
def get_vn_id(name)
vn_id=name.strip
# Check if the name is not a number (is not an ID)
vn_id=get_vn_from_name(vn_id) if !vn_id.match(/^[0123456789]+$/)
return vn_id
end
def get_vn_from_name(name)
res=get(:where => "name=\"#{name}\"")
return nil if !res[0] or res[1].length<1
if res[1].length==1
return res[1][0]["oid"]
else
return res[1].collect {|vn| vn["oid"] }
end
end
end

View File

@ -37,7 +37,7 @@ ShowTableHost={
:name => "HID",
:desc => "ONE identifier for host",
:size => 4,
:proc => lambda {|d,e| d["hid"] }
:proc => lambda {|d,e| d["oid"] }
},
:name => {
:name => "NAME",
@ -123,7 +123,7 @@ class HostShow
result=res
header_host_small
res[1].each {|row|
res2=@host.get_host_attributes(row["hid"])
res2=@host.get_host_attributes(row["oid"])
if res2[0]
attributes=res2[1]
attributes.each {|a|
@ -133,7 +133,7 @@ class HostShow
}
end
res2=@host.get_host_share(row["hid"])
res2=@host.get_host_share(row["oid"])
if res2[0]
attributes=res2[1]
attributes.each {|a|
@ -142,7 +142,6 @@ class HostShow
row["hs_max_cpu"]=a["max_cpu"]
row["hs_mem_usage"]=a["mem_usage"]
row["hs_cpu_usage"]=a["cpu_usage"]
row["hs_running_vms"]=a["running_vms"]
}
end
}
@ -178,7 +177,7 @@ class OnehostParse < CommandParse
Commands:
* add (Adds a new machine to the pool)
onehost add <hostname> <im_mad> <vmm_mad>
onehost add <hostname> <im_mad> <vmm_mad> <tm_mad>
* show (Gets info from a host)
onehost show <host_id>
@ -216,7 +215,13 @@ EOT
end
server=ONE::Server.new
host=ONE::Host.new(server)
$host=host=ONE::Host.new(server)
def command_exit(code)
$host.close_db
exit(code)
end
onehost_opts=OnehostParse.new
onehost_opts.parse(ARGV)
@ -227,8 +232,8 @@ command=ARGV.shift
case command
when "add"
check_parameters("add", 3)
result=host.allocate(*[ARGV[0], ARGV[1], ARGV[2], "tm_mad", "true"])
check_parameters("add", 4)
result=host.allocate(*[ARGV[0], ARGV[1], ARGV[2], ARGV[3], "true"])
when "show"
check_parameters("show", 1)
@ -238,7 +243,7 @@ when "show"
puts result[1]
else
puts "Error: "+result[1]
exit -1
command_exit -1
end
when "delete"
@ -247,7 +252,7 @@ when "delete"
result=host.delete(host_id)
if result[0]
puts "Host deleted"
exit 0
command_exit 0
end
when "list"
@ -270,7 +275,7 @@ when "enable"
result=host.enable(host_id)
if result[0]
puts "Host enabled"
exit 0
command_exit 0
end
when "disable"
@ -279,15 +284,18 @@ when "disable"
result=host.disable(host_id)
if result[0]
puts "Host disabled"
exit 0
command_exit 0
end
else
onehost_opts.print_help
exit -1
command_exit -1
end
if !result[0]
puts "Error: " + result[1].to_s
exit -1
command_exit -1
end
command_exit 0

225
src/client/ruby/onenetwork Executable file
View File

@ -0,0 +1,225 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2008, Distributed Systems Architecture Group, Universidad #
# Complutense de Madrid (dsa-research.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
puts "ONE_LOCATION not set"
exit -1
end
$: << ONE_LOCATION+"/lib/ruby"
require 'one'
require 'client_utilities'
require 'command_parse'
ShowTableVN={
:nid => {
:name => "NID",
:desc => "ONE identifier for virtual network",
:size => 4,
:proc => lambda {|d,e| d["oid"] }
},
:name => {
:name => "NAME",
:desc => "name of the virtual network",
:size => 15,
:left => true,
:proc => lambda {|d,e| d["name"] }
},
:type => {
:name => "TYPE",
:desc => "NType of virtual network",
:size => 4,
:proc => lambda {|d,e| d["type"] }
},
:size => {
:name => "SIZE",
:desc => "Number of hosts (free + used) in the virtual network",
:size => 6,
:proc => lambda {|d,e| d["SIZE"] }
},
:bridge => {
:name => "BRIDGE",
:desc => "Bridge associated to the virtual network",
:size => 6,
:left => true,
:proc => lambda {|d,e| d["bridge"] }
},
:default => [:nid, :name, :type, :size, :bridge]
}
class VNShow
def initialize(vn)
@vn=vn
@table=ShowTable.new(ShowTableVN, :vn => @vn)
end
def close
end
def header_vn_small
scr_bold
scr_underline
puts @table.header_str
scr_restore
end
def list_short(options=nil)
res=@vn.get
if options
@table.columns=options[:columns] if options[:columns]
end
if res[0]
result=res
header_vn_small
res[1].each {|row|
res2=@vn.get_vn_attributes(row["oid"])
if res2[0]
attributes=res2[1]
attributes.each {|a|
if %w{SIZE}.include? a["name"]
row[a["name"]]=a["value"]
end
}
end
}
puts @table.data_str(result[1], options)
result
else
result=res
end
end
def top(options=nil)
delay=1
delay=options[:delay] if options && options[:delay]
result=nil
begin
while true
scr_cls
scr_move(0,0)
result=list_short(options)
sleep delay
end
rescue Exception
end
result
end
end
class OneVNParse < CommandParse
COMMANDS_HELP=<<-EOT
Commands:
* create (Creates a new virtual network)
onenetwork create <template>
template is a filename where the virtual network is described
* show (Gets info from a virtual network)
onenetwork show <network_id>
* delete (Removes a virtual network)
onehost delete <network_id>
* list (Lists virtual networks in the pool)
onehost list
EOT
def text_commands
COMMANDS_HELP
end
def text_command_name
"onenetwork"
end
def list_options
table=ShowTable.new(ShowTableVN)
table.print_help
end
end
server=ONE::Server.new
vn=ONE::VN.new(server)
onevn_opts=OneVNParse.new
onevn_opts.parse(ARGV)
result=[false, "Unknown error"]
command=ARGV.shift
case command
when "create"
check_parameters("create", 1)
result=vn.allocate(*ARGV)
if result[0]
puts "NID: " + result[1].to_s
exit 0
end
when "show"
check_parameters("show", 1)
vn_id=get_vn_id(vn, ARGV[0])
result=vn.info(vn_id)
if result[0]
puts result[1]
else
puts "Error: "+result[1]
exit -1
end
when "delete"
check_parameters("delete", 1)
vn_id=get_vn_id(vn, ARGV[0])
result=vn.delete(vn_id)
if result[0]
puts "Virtual Network deleted"
exit 0
end
when "list"
vnlist=VNShow.new(vn)
ops=onevn_opts.options
ops[:columns]=ops[:list] if ops[:list]
result=vnlist.list_short(ops)
vnlist.close
else
onevn_opts.print_help
exit -1
end
if !result[0]
puts "Error: " + result[1].to_s
exit -1
end

View File

@ -43,7 +43,7 @@ ShowTableVM={
:desc => "Name of the domain",
:size => 8,
:proc => lambda {|d,e|
tid=d["template"]
tid=d["template_id"]
template=e[:vm].get_template(tid)
template["NAME"]
}
@ -99,7 +99,7 @@ ShowTableHistory={
:name => "HOSTNAME",
:desc => "Name of the host where the VM was submited",
:size => 15,
:proc => lambda {|d,e| d["hostname"] }
:proc => lambda {|d,e| d["host_name"] }
},
:stime => {
:name => "STIME",
@ -176,7 +176,7 @@ class VmShow
puts "Template"
str=" %-20s: %-20s"
data.each {|key,value|
puts str % [key, value] if !%w{oid deploy_id state lcm_state memory cpu template}.include? key
puts str % [key, value] if !%w{oid deploy_id state lcm_state memory cpu template_id}.include? key
}
end
@ -362,9 +362,15 @@ end
server=ONE::Server.new
vm=ONE::VM.new(server)
$vm=vm=ONE::VM.new(server)
host=ONE::Host.new(server)
def command_exit(code)
$vm.close_db
exit(code)
end
onevm_opts=OnevmParse.new
onevm_opts.parse(ARGV)
@ -378,7 +384,7 @@ when "submit"
result=vm.allocate(*ARGV)
if result[0]
puts "ID: " + result[1].to_s
exit 0
command_exit 0
end
when "deploy"
@ -388,7 +394,7 @@ when "deploy"
result=vm.deploy(vm_id, host_id)
if result[0]
puts "Deploying VM"
exit 0
command_exit 0
end
when "shutdown"
@ -397,7 +403,7 @@ when "shutdown"
result=vm.shutdown(vm_id)
if result[0]
puts "Shutting down VM"
exit 0
command_exit 0
end
when "livemigrate"
@ -407,7 +413,7 @@ when "livemigrate"
result=vm.livemigrate(vm_id, host_id)
if result[0]
puts "Migrating VM"
exit 0
command_exit 0
end
when "migrate"
@ -417,7 +423,7 @@ when "migrate"
result=vm.migrate(vm_id, host_id)
if result[0]
puts "Migrating VM"
exit 0
command_exit 0
end
when "hold"
@ -426,7 +432,7 @@ when "hold"
result=vm.hold(vm_id)
if result[0]
puts "Setting VM to hold state"
exit 0
command_exit 0
end
when "release"
@ -435,7 +441,7 @@ when "release"
result=vm.release(vm_id)
if result[0]
puts "Releasing VM"
exit 0
command_exit 0
end
when "stop"
@ -444,7 +450,7 @@ when "stop"
result=vm.stop(vm_id)
if result[0]
puts "Stopping VM"
exit 0
command_exit 0
end
when "cancel"
@ -452,7 +458,7 @@ when "cancel"
result=vm.cancel(*ARGV)
if result[0]
puts "Cancelling VM"
exit 0
command_exit 0
end
when "suspend"
@ -461,7 +467,7 @@ when "suspend"
result=vm.suspend(vm_id)
if result[0]
puts "Suspending VM"
exit 0
command_exit 0
end
when "resume"
@ -470,7 +476,7 @@ when "resume"
result=vm.resume(vm_id)
if result[0]
puts "Resuming VM"
exit 0
command_exit 0
end
when "list"
@ -519,7 +525,7 @@ when "delete"
result=vm.delete(vm_id)
if result[0]
puts "VM correctly deleted"
exit 0
command_exit 0
end
when "show"
@ -556,18 +562,20 @@ when "show"
puts str % [key, value]
}
exit 0
command_exit 0
end
else
onevm_opts.print_help
exit -1
command_exit -1
end
if !result[0]
puts "Error: " + result[1].to_s
exit -1
command_exit -1
end
command_exit 0

View File

@ -54,7 +54,7 @@ string * VectorAttribute::marshall()
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VectorAttribute::unmarshall(string& sattr)
void VectorAttribute::unmarshall(const string& sattr)
{
size_t bpos=0,epos,mpos;
string tmp;
@ -86,6 +86,13 @@ void VectorAttribute::unmarshall(string& sattr)
tmp.substr(mpos+1)));
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VectorAttribute::replace(const map<string,string>& attr)
{
attribute_value = attr;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -280,7 +280,7 @@ int DispatchManager::release(
return -1;
}
oss << "Realising VM " << vid;
oss << "Releasing VM " << vid;
Nebula::log("DiM",Log::DEBUG,oss);
if (vm->get_state() == VirtualMachine::HOLD)
@ -524,12 +524,18 @@ int DispatchManager::finalize(
oss << "Finalizing VM " << vid;
Nebula::log("DiM",Log::DEBUG,oss);
vm->set_state(VirtualMachine::LCM_INIT);
vm->set_state(VirtualMachine::DONE);
vm->set_exit_time(time(0));
vmpool->update(vm);
vm->log("DiM", Log::INFO, "New VM state is DONE.");
vm->release_leases();
vmpool->remove(vm);
return 0;

View File

@ -106,7 +106,7 @@ error:
void DispatchManager::done_action(int vid)
{
VirtualMachine * vm;
VirtualMachine * vm;
vm = vmpool->get(vid,true);
@ -115,7 +115,7 @@ void DispatchManager::done_action(int vid)
return;
}
if (vm->get_state() == VirtualMachine::ACTIVE )
if ( vm->get_state() == VirtualMachine::ACTIVE )
{
vm->set_state(VirtualMachine::DONE);
@ -127,6 +127,8 @@ void DispatchManager::done_action(int vid)
vm->log("DiM", Log::INFO, "New VM state is DONE");
vm->release_leases();
vmpool->remove(vm);
}
else

View File

@ -56,13 +56,13 @@ Host::~Host(){};
/* Host :: Database Access Functions */
/* ************************************************************************** */
const char * Host::table = "hostpool";
const char * Host::table = "host_pool";
const char * Host::db_names = "(hid,host_name,state,im_mad,vm_mad,"
const char * Host::db_names = "(oid,host_name,state,im_mad,vm_mad,"
"tm_mad,last_mon_time,managed)";
const char * Host::db_bootstrap = "CREATE TABLE hostpool ("
"hid INTEGER PRIMARY KEY,host_name TEXT,state INTEGER,"
const char * Host::db_bootstrap = "CREATE TABLE host_pool ("
"oid INTEGER PRIMARY KEY,host_name TEXT,state INTEGER,"
"im_mad TEXT,vm_mad TEXT,tm_mad TEXT,last_mon_time INTEGER,"
"managed INTEGER)";
@ -71,7 +71,7 @@ const char * Host::db_bootstrap = "CREATE TABLE hostpool ("
int Host::unmarshall(int num, char **names, char ** values)
{
if ((values[HID] == 0) ||
if ((values[OID] == 0) ||
(values[HOST_NAME] == 0) ||
(values[STATE] == 0) ||
(values[IM_MAD] == 0) ||
@ -84,7 +84,7 @@ int Host::unmarshall(int num, char **names, char ** values)
return -1;
}
oid = atoi(values[HID]);
oid = atoi(values[OID]);
hostname = values[HOST_NAME];
state = static_cast<HostState>(atoi(values[STATE]));
@ -131,7 +131,7 @@ int Host::select(SqliteDB *db)
int rc;
int boid;
oss << "SELECT * FROM " << table << " WHERE hid = " << oid;
oss << "SELECT * FROM " << table << " WHERE oid = " << oid;
boid = oid;
oid = -1;
@ -258,7 +258,7 @@ int Host::drop(SqliteDB * db)
host_share.drop(db);
// Third, drop the host itself
oss << "DELETE FROM " << table << " WHERE hid=" << oid;
oss << "DELETE FROM " << table << " WHERE oid=" << oid;
return db->exec(oss);
}

View File

@ -89,7 +89,7 @@ int HostPool::discover(map<int, string> * discovered_hosts)
lock();
sql << "SELECT hid, im_mad FROM "
sql << "SELECT oid, im_mad FROM "
<< Host::table << " ORDER BY last_mon_time LIMIT 10";
rc = db->exec(sql,discover_cb,(void *) discovered_hosts);

View File

@ -50,13 +50,13 @@ HostShare::HostShare(
/* HostShare :: Database Access Functions */
/* ************************************************************************** */
const char * HostShare::table = "hostshares";
const char * HostShare::table = "host_shares";
const char * HostShare::db_names = "(hsid,endpoint,disk_usage,"
const char * HostShare::db_names = "(hid,endpoint,disk_usage,"
"mem_usage,cpu_usage,max_disk,max_mem,max_cpu,running_vms)";
const char * HostShare::db_bootstrap = "CREATE TABLE hostshares ("
"hsid INTEGER PRIMARY KEY, endpoint TEXT,"
const char * HostShare::db_bootstrap = "CREATE TABLE host_shares ("
"hid INTEGER PRIMARY KEY, endpoint TEXT,"
"disk_usage INTEGER,mem_usage INTEGER,cpu_usage INTEGER,"
"max_disk INTEGER,max_mem INTEGER,max_cpu INTEGER,running_vms INTEGER)";
@ -65,7 +65,7 @@ const char * HostShare::db_bootstrap = "CREATE TABLE hostshares ("
int HostShare::unmarshall(int num, char **names, char ** values)
{
if ((values[HSID] == 0) ||
if ((values[HID] == 0) ||
(values[ENDPOINT] == 0) ||
(values[DISK_USAGE] == 0) ||
(values[MEM_USAGE] == 0) ||
@ -79,7 +79,7 @@ int HostShare::unmarshall(int num, char **names, char ** values)
return -1;
}
hsid = atoi(values[HSID]);
hsid = atoi(values[HID]);
endpoint = values[ENDPOINT];
disk_usage = atoi(values[DISK_USAGE]);
mem_usage = atoi(values[MEM_USAGE]);
@ -121,7 +121,7 @@ int HostShare::select(SqliteDB * db)
int rc;
int bhsid;
oss << "SELECT * FROM " << table << " WHERE hsid = " << hsid;
oss << "SELECT * FROM " << table << " WHERE hid = " << hsid;
bhsid = hsid;
hsid = -1;
@ -186,7 +186,7 @@ int HostShare::drop(SqliteDB * db)
ostringstream oss;
// Drop the HostShare itself
oss << "DELETE FROM " << table << " WHERE hsid=" << hsid;
oss << "DELETE FROM " << table << " WHERE hid=" << hsid;
return db->exec(oss);
}
@ -197,7 +197,7 @@ int HostShare::drop(SqliteDB * db)
ostream& operator<<(ostream& os, HostShare& hs)
{
os << "\tHSID = " << hs.hsid << endl;
os << "\tHID = " << hs.hsid << endl;
os << "\tENDPOINT = " << hs.endpoint<< endl;
os << "\tMAX_CPU = " << hs.max_cpu << endl;

View File

@ -4,7 +4,7 @@ ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
puts "ONE_LOCATION not set"
exit -1
exit(-1)
end
$: << ONE_LOCATION+"/lib/ruby"
@ -49,6 +49,7 @@ class Sensor < SSHCommand
gen_identifier
@script_hash=gen_hash
super(script)
end
# Runs the sensor in some host
@ -219,31 +220,7 @@ class IM < ONEMad
init_actions
end
def start_action_thread
@action_thread=Thread.new {
while true
@action_mutex.lock
done=@actions.select{|a| a.finished }
@action_mutex.unlock
if done.length>0
done.each{|a|
tmp_result = a.get_result
STDOUT.puts tmp_result
STDOUT.flush
log(tmp_result,DEBUG)
}
@action_mutex.lock
@actions-=done
@action_mutex.unlock
end
sleep(1)
end
}
end
def action_init(args)
STDOUT.puts "INIT SUCCESS"
STDOUT.flush
@ -252,13 +229,28 @@ class IM < ONEMad
def action_monitor(args)
action=PollAction.new(args[1], args[2], @sensors)
send_ssh_action(args[1], args[2], action)
action.callback=lambda {|actions,number|
result=get_result(actions, number)
STDOUT.puts result
STDOUT.flush
log(result,DEBUG)
}
send_ssh_action(action)
end
#def action_finalize(args)
# STDOUT.puts "FINALIZE SUCCESS"
# exit 0
#end
def get_result(actions, number)
good_results=actions.select{|s| s.ok? }
if good_results.length>0
"MONITOR SUCCESS " + number.to_s + " " +
good_results.collect{|s| s.value }.join(',')
else
bad_results=actions.select{|s| !s.ok? && s.value }
err_text="Unknown error"
err_text=bad_results[0].value.to_s if bad_results.length>0
"MONITOR FAILURE " + number.to_s + " " + err_text
end
end
end
@ -267,7 +259,7 @@ im_conf=ARGV[0]
if !im_conf
puts "You need to specify config file."
exit -1
exit(-1)
end
im_conf=ONE_LOCATION+"/"+im_conf if im_conf[0] != ?/

View File

@ -37,11 +37,26 @@ void LifeCycleManager::deploy_action(int vid)
time_t thetime = time(0);
int cpu,mem,disk;
VirtualMachine::LcmState vm_state;
TransferManager::Actions tm_action;
//----------------------------------------------------
// PROLOG STATE
//----------------------------------------------------
vm_state = VirtualMachine::PROLOG;
tm_action = TransferManager::PROLOG;
if (vm->hasPreviousHistory())
{
if (vm->get_previous_reason() == History::STOP_RESUME)
{
vm_state = VirtualMachine::PROLOG_RESUME;
tm_action = TransferManager::PROLOG_RESUME;
}
}
vm->set_state(VirtualMachine::PROLOG);
vm->set_state(vm_state);
vmpool->update(vm);
@ -59,7 +74,7 @@ void LifeCycleManager::deploy_action(int vid)
//----------------------------------------------------
tm->trigger(TransferManager::PROLOG,vid);
tm->trigger(tm_action,vid);
}
else
{

View File

@ -68,7 +68,7 @@ void LifeCycleManager::save_success_action(int vid)
//----------------------------------------------------
tm->trigger(TransferManager::PROLOG,vid);
tm->trigger(TransferManager::PROLOG_MIGR,vid);
}
else if ( vm->get_lcm_state() == VirtualMachine::SAVE_SUSPEND)
{
@ -82,7 +82,7 @@ void LifeCycleManager::save_success_action(int vid)
//----------------------------------------------------
vm->set_running_etime(the_time);
vm->set_etime(the_time);
vm->set_reason(History::STOP_RESUME);
@ -108,12 +108,14 @@ void LifeCycleManager::save_success_action(int vid)
//----------------------------------------------------
vm->set_state(VirtualMachine::EPILOG_STOP);
vmpool->update(vm);
vm->set_epilog_stime(the_time);
vm->set_running_etime(the_time);
vm->set_reason(History::STOP_RESUME);
vmpool->update_history(vm);
@ -121,7 +123,7 @@ void LifeCycleManager::save_success_action(int vid)
//----------------------------------------------------
tm->trigger(TransferManager::EPILOG,vid);
tm->trigger(TransferManager::EPILOG_STOP,vid);
}
else
{
@ -181,7 +183,7 @@ void LifeCycleManager::save_failure_action(int vid)
// --- Add new record by copying the previous one
vm->cp_history();
vm->cp_previous_history();
vm->set_stime(the_time);
@ -453,19 +455,23 @@ void LifeCycleManager::prolog_success_action(int vid)
ostringstream os;
VirtualMachineManager::Actions action;
VirtualMachine::LcmState lcm_state;
vm = vmpool->get(vid, true);
if ( vm == 0 )
{
return;
}
lcm_state = vm->get_lcm_state();
if (vm->get_lcm_state()==VirtualMachine::PROLOG)
if (lcm_state == VirtualMachine::PROLOG)
{
action = VirtualMachineManager::DEPLOY;
}
else if (vm->get_lcm_state()==VirtualMachine::PROLOG_MIGRATE)
else if ( lcm_state == VirtualMachine::PROLOG_MIGRATE ||
lcm_state == VirtualMachine::PROLOG_RESUME )
{
action = VirtualMachineManager::RESTORE;
}

View File

@ -0,0 +1,116 @@
require 'thread'
=begin rdoc
Copyright 2002-2008, Distributed Systems Architecture Group, Universidad Complutense de Madrid (dsa-research.org)
This class manages a pool of threads with a maximun number of concurrent running jobs.
== Example
Creates 1000 threads that sleep 1 second and executes them with a concurrency of 100.
th=ThreadScheduler.new(100)
1000.times {
th.new_thread {
sleep 1
}
}
=end
class ThreadScheduler
# Creates a new thread pool
#
# +concurrent_number+ is the maximun number of threads that can run
# at the same time
def initialize(concurrent_number=10)
@concurrent_number=concurrent_number
@thread_queue=Array.new
@running_threads=0
@threads_mutex=Mutex.new
@threads_cond=ConditionVariable.new
start_thread_runner
end
# Creates a new job that will be placed on the queue. It will be scheduled
# when there is room at the selected concurrency level. Job is a block.
def new_thread(&block)
@threads_mutex.synchronize {
@thread_queue<<block
if @running_threads < @concurrent_number
# Awakes thread runner only if there is room for a new thread
@threads_cond.signal
end
}
end
# Kills the thread that manages job queues. Should be called before
# exiting
def shutdown
@thread_runner.kill!
end
private
# Selects new jobs to be run as threads
#
# NOTE: should be called inside a syncronize block
def run_new_thread
thread = @thread_queue.shift
if thread
@running_threads += 1
Thread.new {
thread.call
@threads_mutex.synchronize {
# Tell thread runner that the thread has finished
@running_threads -= 1
@threads_cond.signal
}
}
end
end
def start_thread_runner
@thread_runner=Thread.new {
while true
@threads_mutex.synchronize {
while ((@concurrent_number-@running_threads)==0) ||
@thread_queue.size==0
@threads_cond.wait(@threads_mutex)
end
run_new_thread
}
end
}
end
end
if __FILE__ == $0
th=ThreadScheduler.new(20)
100.times {|n|
100.times {|m|
th.new_thread {
puts "Starting #{m+n*100}"
sleep 1
#puts "Finishing #{m+n*100}"
}
}
}
th.new_thread {
sleep 4
th.shutdown
exit(0)
}
sleep 3600
end

View File

@ -15,6 +15,8 @@
# limitations under the License.
# --------------------------------------------------------------------------
require "thread"
# Author:: dsa-research.org
# Copyright:: (c) 2007 Universidad Computense de Madrid
# License:: Apache License
@ -51,6 +53,7 @@ class ONEMad
@num_params_out=num_params_out
end
@debug_level = -1
@send_mutex=Mutex.new
end
# Sends a message to the logger
@ -82,7 +85,7 @@ class ONEMad
# action associated to the message.
def loop
while true
exit -1 if STDIN.eof?
exit(-1) if STDIN.eof?
str=STDIN.gets
next if !str
@ -101,16 +104,26 @@ class ONEMad
# If the message is shorter than the number of parameters specified in the
# initialization more marameters will be added containing '-'.
def send_message(*args)
to_send=args
if args.length<@num_params_out
(@num_params_out-args.length).times{ to_send<<'-' }
end
STDOUT.puts to_send.join(' ')
STDOUT.flush
log(to_send.join(' '),DEBUG)
@send_mutex.synchronize {
to_send=args
if args.length<@num_params_out
(@num_params_out-args.length).times{ to_send<<'-' }
end
STDOUT.puts to_send.join(' ')
STDOUT.flush
log(to_send.join(' '),DEBUG)
}
end
# Sends a log message to ONE. The +message+ can be multiline, it will
# be automatically splitted by lines.
def mad_log(command, number, message)
msg=message.strip
msg.each_line {|line|
send_message("LOG", "-", number, line.strip)
}
end
# Proceses each message received, called by +loop+.
def process(args)
return nil if !args or !args[0]
@ -131,7 +144,7 @@ class ONEMad
# Default FINALIZE action. Exists the program.
def action_finalize(args)
exit 0
exit(0)
end
end

View File

@ -1,27 +1,44 @@
=begin rdoc
Here will be a description of SSH library and an example on
how to use it.
=end
require 'pp'
require 'open3'
require 'thread'
require 'ThreadScheduler'
# This class holds a command that will be executed on a remote host
# using ssh. Commands can have an associated callback that will be
# after they finish.
class SSHCommand
attr_accessor :value, :code, :stdout, :stderr, :command
attr_accessor :callback
# Creates a new command
def initialize(command)
@command=command
@callback=nil
end
# Runs the command on the specified host
def run(host)
(@stdout, @stderr)=execute(host, @command)
@code=get_exit_code(@stderr)
end
# Executes callback associated to this command
def exec_callback(num)
@callback.call(self, num) if @callback
if @callback
@callback.call(self, num)
end
end
private
# Gets exit code from STDERR
def get_exit_code(str)
tmp=str.scan(/^ExitCode: (\d*)$/)
@ -52,6 +69,7 @@ class SSHCommand
end
class SSHCommandList < Array
=begin
def clone_actions
new_array=Array.new
self.each {|s|
@ -59,15 +77,18 @@ class SSHCommandList < Array
}
new_array
end
=end
end
# An action is composed by one or more SSHCommands that will be executed in an
# specific host. It holds a number that is the command identifier for a MAD.
class SSHAction
attr_accessor :callback
def initialize(number, host, actions)
@number=number
@host=host
if actions.is_a? SSHCommandList
if actions.is_a?(SSHCommandList) || actions.is_a?(Array)
@actions=clone_actions(actions)
else
@actions=SSHCommandList.new
@ -83,14 +104,9 @@ class SSHAction
@finished
end
def run(action_mutex, action_cond)
@thread=Thread.new {
run_actions
@finished=true
action_mutex.synchronize {
action_cond.signal
}
}
def run
run_actions
@finished=true
end
def run_actions
@ -104,9 +120,12 @@ class SSHAction
a.exec_callback(@number)
}
@callback.call(@actions, @number) if @callback
if @callback
@callback.call(@actions, @number)
end
end
private
# Clone an array of sensors
def clone_actions(actions)
@ -116,40 +135,21 @@ end
module SSHActionController
def init_actions
@actions=Array.new
@action_mutex=Mutex.new
@action_cond=ConditionVariable.new
start_action_thread
def init_actions(num=10)
@thread_scheduler=ThreadScheduler.new(num)
end
def send_ssh_action(number, host, action)
@action_mutex.synchronize {
action.run(@action_mutex, @action_cond)
@actions << action
def send_ssh_action(action)
@thread_scheduler.new_thread {
action.run
action.exec_callbacks
}
end
def action_finalize(args)
@action_thread.kill!
@thread_scheduler.shutdown
super(args)
end
def start_action_thread
@action_thread=Thread.new {
while true
done_actions=nil
@action_mutex.synchronize {
@action_cond.wait(@action_mutex)
done_actions=@actions.select{|a| a.finished }
@actions-=done_actions if done_actions
}
if done_actions
done_actions.each {|action| action.exec_callbacks }
end
end
}
end
end
=begin
@ -180,4 +180,5 @@ def action_poll(args)
send_ssh_action(poll_action)
end
=end
=end

View File

@ -40,6 +40,7 @@ void Nebula::start()
int fd;
sigset_t mask;
int signal;
char hn[80];
const SingleAttribute * sattr;
vector<const Attribute *> attr;
@ -52,6 +53,13 @@ void Nebula::start()
}
nebula_location = nl;
if ( gethostname(hn,79) != 0 )
{
throw runtime_error("Error getting hostname");
}
hostname = hn;
// -----------------------------------------------------------
// Configuration
@ -142,9 +150,17 @@ void Nebula::start()
}
try
{
{
string mac_prefix;
int size;
vmpool = new VirtualMachinePool(db);
hpool = new HostPool(db);
nebula_configuration->get("MAC_PREFIX", mac_prefix);
nebula_configuration->get("NETWORK_SIZE", size);
vnpool = new VirtualNetworkPool(db,mac_prefix,size);
}
catch (exception&)
{
@ -155,6 +171,7 @@ void Nebula::start()
vmpool->bootstrap();
hpool->bootstrap();
vnpool->bootstrap();
// -----------------------------------------------------------
// Close stds, we no longer need them
@ -288,9 +305,9 @@ void Nebula::start()
{
vector<const Attribute *> tm_mads;
tm_mads.clear();
nebula_configuration->get("TM_MAD", tm_mads);
tm = new TransferManager(vmpool,tm_mads);
tm = new TransferManager(vmpool, hpool, tm_mads);
}
catch (bad_alloc&)
{
@ -324,22 +341,14 @@ void Nebula::start()
// ---- Request Manager ----
try
{
int rm_port=0;
int rm_port = 0;
attr.clear();
nebula_configuration->get("PORT", attr);
sattr = static_cast<const SingleAttribute *>(attr[0]);
is.clear();
is.str(sattr->value());
is >> rm_port;
nebula_configuration->get("PORT", rm_port);
rm = new RequestManager(
vmpool,
hpool,
vnpool,
rm_port,
nebula_location + "/var/one_xmlrpc.log");
}
@ -364,6 +373,7 @@ void Nebula::start()
im->load_mads(0);
vmm->load_mads(0);
tm->load_mads(0);
// -----------------------------------------------------------
// Wait for a SIGTERM or SIGINT signal

View File

@ -33,18 +33,10 @@ NebulaTemplate::NebulaTemplate(string& nebula_location)
ostringstream os;
SingleAttribute * attribute;
string value;
Nebula& nd = Nebula::instance();
conf_file = nebula_location + "/etc/";
conf_file += conf_name;
// VM_DIR
os << nebula_location << "/var";
value = os.str();
attribute = new SingleAttribute("VM_DIR",value);
conf_default.insert(make_pair(attribute->name(),attribute));
// POLL_INTERVAL
value = "300";
@ -69,10 +61,22 @@ NebulaTemplate::NebulaTemplate(string& nebula_location)
attribute = new SingleAttribute("PORT",value);
conf_default.insert(make_pair(attribute->name(),attribute));
//VM_RDIR
value = nd.get_nebula_location() + "/var";
//VM_DIR
value = nebula_location + "/var";
attribute = new SingleAttribute("VM_RDIR",value);
attribute = new SingleAttribute("VM_DIR",value);
conf_default.insert(make_pair(attribute->name(),attribute));
//MAC_PREFIX
value = "00:01";
attribute = new SingleAttribute("MAC_PREFIX",value);
conf_default.insert(make_pair(attribute->name(),attribute));
//NETWORK_SIZE
value = "254";
attribute = new SingleAttribute("NETWORK_SIZE",value);
conf_default.insert(make_pair(attribute->name(),attribute));
//DEBUG_LEVEL

View File

@ -20,7 +20,6 @@ env.Append(LIBS=[
'nebula_core',
'nebula_vmm',
'nebula_lcm',
'nebula_vm',
'nebula_im',
'nebula_rm',
'nebula_dm',
@ -29,6 +28,8 @@ env.Append(LIBS=[
'nebula_template',
'nebula_pool',
'nebula_host',
'nebula_vm',
'nebula_vnm',
'nebula_common',
'sqlite3',
'wwwxml',
@ -75,7 +76,6 @@ env.Append(LIBS=[
'nebula_core',
'nebula_vmm',
'nebula_lcm',
'nebula_vm',
'nebula_im',
'nebula_rm',
'nebula_dm',
@ -84,6 +84,8 @@ env.Append(LIBS=[
'nebula_template',
'nebula_pool',
'nebula_host',
'nebula_vnm',
'nebula_vm',
'nebula_common',
'sqlite3',
])
@ -91,4 +93,4 @@ env.Append(LIBS=[
env.ParseConfig('../../share/scons/get_xmlrpc_config server')
env.Program('oned.cc')
env.Program('oned.cc')

View File

@ -239,6 +239,15 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr host_enable(new
RequestManager::HostEnable(hpool));
xmlrpc_c::methodPtr vn_allocate(new
RequestManager::VirtualNetworkAllocate(vnpool));
xmlrpc_c::methodPtr vn_info(new
RequestManager::VirtualNetworkInfo(vnpool));
xmlrpc_c::methodPtr vn_delete(new
RequestManager::VirtualNetworkDelete(vnpool));
/* VM related methods */
@ -255,6 +264,12 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.hostdelete", host_delete);
RequestManagerRegistry.addMethod("one.hostenable", host_enable);
/* Network related methods*/
RequestManagerRegistry.addMethod("one.vnallocate", vn_allocate);
RequestManagerRegistry.addMethod("one.vninfo", vn_info);
RequestManagerRegistry.addMethod("one.vndelete", vn_delete);
};
/* -------------------------------------------------------------------------- */

View File

@ -71,7 +71,7 @@ void RequestManager::VirtualMachineDeploy::execute(
if (host->isManaged() == true)
{
nd.get_configuration_attribute("VM_RDIR",vmdir);
nd.get_configuration_attribute("VM_DIR",vmdir);
}
else
{

View File

@ -72,7 +72,7 @@ void RequestManager::VirtualMachineMigrate::execute(
if (host->isManaged() == true)
{
nd.get_configuration_attribute("VM_RDIR",vmdir);
nd.get_configuration_attribute("VM_DIR",vmdir);
}
else
{

View File

@ -0,0 +1,83 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::VirtualNetworkAllocate::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
string name;
string stemplate;
int nid;
int rc;
ostringstream oss;
/* -- RPC specific vars -- */
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
Nebula::log("ReM",Log::DEBUG,"VirtualNetworkAllocate method invoked");
// Get the parameters & host
session = xmlrpc_c::value_string(paramList.getString(0));
stemplate = xmlrpc_c::value_string(paramList.getString(1));
rc = vnpool->allocate(0,stemplate,&nid);
if ( rc != 0 )
{
goto error_vn_allocate;
}
//Result
arrayData.push_back(xmlrpc_c::value_boolean(true)); // SUCCESS
arrayData.push_back(xmlrpc_c::value_int(nid));
arrayresult = new xmlrpc_c::value_array(arrayData);
*retval = *arrayresult;
delete arrayresult;
return;
error_vn_allocate:
oss << "Error allocating VN with template: " << endl << stemplate;
Nebula::log("ReM",Log::ERROR,oss);
arrayData.push_back(xmlrpc_c::value_boolean(false));
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,85 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::VirtualNetworkDelete::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
string name;
int nid;
VirtualNetwork * vn;
int rc;
ostringstream oss;
/* -- RPC specific vars -- */
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
Nebula::log("ReM",Log::DEBUG,"VirtualNetworkDelete method invoked");
// Get the parameters & host
session = xmlrpc_c::value_string(paramList.getString(0));
nid = xmlrpc_c::value_int (paramList.getInt (1));
// Perform the allocation in the hostpool
vn = vnpool->get(nid,true);
if ( vn == 0 )
{
goto error_vn_get;
}
rc = vnpool->drop(vn);
// All nice, return the host info to the client
arrayData.push_back(xmlrpc_c::value_boolean( rc == 0 )); // SUCCESS
arrayresult = new xmlrpc_c::value_array(arrayData);
// Copy arrayresult into retval mem space
*retval = *arrayresult;
// and get rid of the original
delete arrayresult;
return;
error_vn_get:
oss << "Error getting Virtual Network with NID = " << nid;
Nebula::log ("Rem",Log::ERROR,oss);
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,89 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::VirtualNetworkInfo::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
int nid;
string info;
VirtualNetwork * vn;
ostringstream oss;
/* -- RPC specific vars -- */
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
Nebula::log("ReM",Log::DEBUG,"VirtualNetworkInfo method invoked");
// Get the parameters & host
session = xmlrpc_c::value_string(paramList.getString(0));
nid = xmlrpc_c::value_int (paramList.getInt (1));
vn = vnpool->get(nid,true);
if ( vn == 0 )
{
goto error_vn_get;
}
// All nice, return the Virtual Network info to the client
arrayData.push_back(xmlrpc_c::value_boolean(true)); // SUCCESS
oss.str("");
oss << *vn;
vn->unlock();
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
arrayresult = new xmlrpc_c::value_array(arrayData);
// Copy arrayresult into retval mem space
*retval = *arrayresult;
// and get rid of the original
delete arrayresult;
return;
error_vn_get:
oss << "Error getting Virtual Network with NID = " << nid;
goto error_common;
error_common:
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
Nebula::log("ReM",Log::ERROR,oss);
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -15,7 +15,10 @@ source_files=[
'RequestManagerHostAllocate.cc',
'RequestManagerHostDelete.cc',
'RequestManagerHostInfo.cc',
'RequestManagerHostEnable.cc',
'RequestManagerHostEnable.cc',
'RequestManagerVirtualNetworkAllocate.cc',
'RequestManagerVirtualNetworkInfo.cc',
'RequestManagerVirtualNetworkDelete.cc',
]
# Build library

View File

@ -69,8 +69,9 @@ env.Append(LIBS=[
'sqlite3',
lib_name,
'nebula_core',
'nebula_host',
'nebula_host',
'nebula_vm',
'nebula_vnm',
'nebula_pool',
'nebula_template',
'nebula_common',

View File

@ -157,7 +157,7 @@ void Template::marshall(string &str, const char delim)
/* -------------------------------------------------------------------------- */
int Template::get(
string& name,
const string& name,
vector<const Attribute*>& values) const
{
multimap<string, Attribute *>::const_iterator i;
@ -175,6 +175,28 @@ int Template::get(
return j;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Template::get(
const string& name,
vector<Attribute*>& values)
{
multimap<string, Attribute *>::iterator i;
pair<multimap<string, Attribute *>::iterator,
multimap<string, Attribute *>::iterator> index;
int j;
index = attributes.equal_range(name);
for ( i = index.first,j=0 ; i != index.second ; i++,j++ )
{
values.push_back(i->second);
}
return j;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -244,16 +244,16 @@ int TemplateSQL::drop(SqliteDB * db)
int TemplateSQL::replace_attribute(
SqliteDB * db,
string& name,
string& value)
const string& name,
const string& value)
{
ostringstream oss;
int rc;
ostringstream oss;
int rc;
multimap<string, Attribute *>::const_iterator i;
Attribute * attribute;
Attribute * attribute;
if ( id == -1 || name.empty() || name.empty() )
if ( id == -1 || name.empty() || value.empty() )
{
return -1;
}

View File

@ -6,7 +6,8 @@ lib_name='nebula_tm'
# Sources to generate the library
source_files=[
'TransferManager.cc'
'TransferManager.cc',
'TransferManagerDriver.cc'
]
# Build library

View File

@ -81,10 +81,22 @@ void TransferManager::trigger(Actions action, int _vid)
aname = "PROLOG";
break;
case PROLOG_MIGR:
aname = "PROLOG_MIGR";
break;
case PROLOG_RESUME:
aname = "PROLOG_RESUME";
break;
case EPILOG:
aname = "EPILOG";
break;
case EPILOG_STOP:
aname = "EPILOG_STOP";
break;
case CHECKPOINT:
aname = "CHECKPOINT";
break;
@ -95,7 +107,7 @@ void TransferManager::trigger(Actions action, int _vid)
default:
delete vid;
return;
return;
}
am.trigger(aname,vid);
@ -121,10 +133,22 @@ void TransferManager::do_action(const string &action, void * arg)
{
prolog_action(vid);
}
else if (action == "PROLOG_MIGR")
{
prolog_migr_action(vid);
}
else if (action == "PROLOG_RESUME")
{
prolog_resume_action(vid);
}
else if (action == "EPILOG")
{
epilog_action(vid);
}
else if (action == "EPILOG_STOP")
{
epilog_stop_action(vid);
}
else if (action == "CHECKPOINT")
{
checkpoint_action(vid);
@ -140,7 +164,7 @@ void TransferManager::do_action(const string &action, void * arg)
ostringstream oss;
oss << "Unknown action name: " << action;
Nebula::log("TrM", Log::ERROR, oss);
Nebula::log("TrM", Log::ERROR, oss);
}
}
@ -149,18 +173,554 @@ void TransferManager::do_action(const string &action, void * arg)
void TransferManager::prolog_action(int vid)
{
Nebula& nd = Nebula::instance();
ofstream xfr;
ostringstream os;
string xfr_name;
const VectorAttribute * disk;
string source;
string type;
string clon;
VirtualMachine * vm;
Nebula& nd = Nebula::instance();
const TransferManagerDriver * tm_md;
vector<const Attribute *> attrs;
int num;
// ------------------------------------------------------------------------
// Setup & Transfer script
// ------------------------------------------------------------------------
vm = vmpool->get(vid,true);
if (vm == 0)
{
return;
}
if (!vm->hasHistory())
{
goto error_history;
}
tm_md = get(vm->get_uid(),vm->get_tm_mad());
if ( tm_md == 0 )
{
goto error_driver;
}
xfr.open(vm->get_transfer_file().c_str(), ios::out | ios::trunc);
if (xfr.fail() == true)
{
goto error_file;
}
// ------------------------------------------------------------------------
// Swap and image Commands
// ------------------------------------------------------------------------
num = vm->get_template_attribute("DISK",attrs);
for (int i=0; i < num ;i++,source="",type="",clon="")
{
disk = dynamic_cast<const VectorAttribute *>(attrs[i]);
if ( disk == 0 )
{
continue;
}
type = disk->vector_value("TYPE");
if ( type.empty() == false)
{
transform(type.begin(),type.end(),type.begin(),(int(*)(int))toupper);
}
if ( type == "SWAP" )
{
string size = disk->vector_value("SIZE");
if (size.empty()==true)
{
size = "1";
}
xfr << "MKSWAP " << size << " " << vm->get_hostname() << ":"
<< vm->get_remote_dir() << "/disk." << i << endl;
}
else
{
source = disk->vector_value("SOURCE");
if ( source.empty() )
{
goto error_empty_disk;
}
clon = disk->vector_value("CLONE");
if ( clon.empty() == true )
{
clon = "YES"; //Clone by default
}
else
{
transform(clon.begin(),clon.end(),clon.begin(),(int(*)(int))toupper);
}
if (clon == "YES")
{
xfr << "CLONE ";
}
else
{
xfr << "LN ";
}
if ( source.find(":") == string::npos ) //Regular file
{
xfr << nd.get_nebula_hostname() << ":" << source << " ";
}
else //TM Plugin specific protocol
{
xfr << source << " ";
}
xfr << vm->get_hostname() << ":" << vm->get_remote_dir()
<< "/disk." << i << endl;
}
}
// ------------------------------------------------------------------------
// TODO: Context commands
// ------------------------------------------------------------------------
xfr.close();
tm_md->transfer(vid,vm->get_transfer_file());
vm->unlock();
return;
error_history:
os.str("");
os << "prolog, VM " << vid << " has no history";
goto error_common;
error_file:
os.str("");
os << "prolog, could not open file: " << vm->get_transfer_file();
goto error_common;
error_driver:
os.str("");
os << "prolog, error getting driver " << vm->get_tm_mad();
goto error_common;
error_empty_disk:
os.str("");
os << "prolog, undefined source disk image in VM template";
xfr.close();
goto error_common;
error_common:
(nd.get_lcm())->trigger(LifeCycleManager::PROLOG_FAILURE,vid);
vm->log("TM", Log::ERROR, os);
vm->unlock();
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void TransferManager::prolog_migr_action(int vid)
{
ofstream xfr;
ostringstream os;
VirtualMachine * vm;
Nebula& nd = Nebula::instance();
const TransferManagerDriver * tm_md;
// ------------------------------------------------------------------------
// Setup & Transfer script
// ------------------------------------------------------------------------
vm = vmpool->get(vid,true);
if (vm == 0)
{
return;
}
if (!vm->hasHistory())
{
goto error_history;
}
tm_md = get(vm->get_uid(),vm->get_tm_mad());
if ( tm_md == 0 )
{
goto error_driver;
}
xfr.open(vm->get_transfer_file().c_str(), ios::out | ios::trunc);
if (xfr.fail() == true)
{
goto error_file;
}
// ------------------------------------------------------------------------
// Move image directory
// ------------------------------------------------------------------------
xfr << "MV ";
xfr << vm->get_previous_hostname() << ":" << vm->get_remote_dir() << " ";
xfr << vm->get_hostname() << ":" << vm->get_remote_dir() << endl;
// ------------------------------------------------------------------------
// TODO: Context commands
// ------------------------------------------------------------------------
xfr.close();
tm_md->transfer(vid,vm->get_transfer_file());
vm->unlock();
return;
error_history:
os.str("");
os << "prolog_migr, VM " << vid << " has no history";
goto error_common;
error_file:
os.str("");
os << "prolog_migr, could not open file: " << vm->get_transfer_file();
goto error_common;
error_driver:
os.str("");
os << "prolog_migr, error getting driver " << vm->get_tm_mad();
goto error_common;
error_common:
(nd.get_lcm())->trigger(LifeCycleManager::PROLOG_FAILURE,vid);
vm->log("TM", Log::ERROR, os);
vm->unlock();
return;
(nd.get_lcm())->trigger(LifeCycleManager::PROLOG_SUCCESS,vid);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void TransferManager::prolog_resume_action(int vid)
{
ofstream xfr;
ostringstream os;
VirtualMachine * vm;
Nebula& nd = Nebula::instance();
const TransferManagerDriver * tm_md;
// ------------------------------------------------------------------------
// Setup & Transfer script
// ------------------------------------------------------------------------
vm = vmpool->get(vid,true);
if (vm == 0)
{
return;
}
if (!vm->hasHistory())
{
goto error_history;
}
tm_md = get(vm->get_uid(),vm->get_tm_mad());
if ( tm_md == 0 )
{
goto error_driver;
}
xfr.open(vm->get_transfer_file().c_str(), ios::out | ios::trunc);
if (xfr.fail() == true)
{
goto error_file;
}
// ------------------------------------------------------------------------
// Move image directory
// ------------------------------------------------------------------------
xfr << "MV ";
xfr << nd.get_nebula_hostname() << ":" << vm->get_local_dir() << "/images ";
xfr << vm->get_hostname() << ":" << vm->get_remote_dir() << endl;
// ------------------------------------------------------------------------
// TODO: Context commands
// ------------------------------------------------------------------------
xfr.close();
tm_md->transfer(vid,vm->get_transfer_file());
vm->unlock();
return;
error_history:
os.str("");
os << "prolog_resume, VM " << vid << " has no history";
goto error_common;
error_file:
os.str("");
os << "prolog_resume, could not open file: " << vm->get_transfer_file();
goto error_common;
error_driver:
os.str("");
os << "prolog_resume, error getting driver " << vm->get_tm_mad();
goto error_common;
error_common:
(nd.get_lcm())->trigger(LifeCycleManager::PROLOG_FAILURE,vid);
vm->log("TM", Log::ERROR, os);
vm->unlock();
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void TransferManager::epilog_action(int vid)
{
Nebula& nd = Nebula::instance();
ofstream xfr;
ostringstream os;
string xfr_name;
const VectorAttribute * disk;
string source;
string save;
string clon;
VirtualMachine * vm;
Nebula& nd = Nebula::instance();
const TransferManagerDriver * tm_md;
vector<const Attribute *> attrs;
int num;
// ------------------------------------------------------------------------
// Setup & Transfer script
// ------------------------------------------------------------------------
vm = vmpool->get(vid,true);
if (vm == 0)
{
return;
}
if (!vm->hasHistory())
{
goto error_history;
}
tm_md = get(vm->get_uid(),vm->get_tm_mad());
if ( tm_md == 0 )
{
goto error_driver;
}
xfr.open(vm->get_transfer_file().c_str(), ios::out | ios::trunc);
if (xfr.fail() == true)
{
goto error_file;
}
// ------------------------------------------------------------------------
// copy back VM image (DISK with SAVE="yes")
// ------------------------------------------------------------------------
num = vm->get_template_attribute("DISK",attrs);
for (int i=0; i < num ;i++,save="")
{
disk = dynamic_cast<const VectorAttribute *>(attrs[i]);
if ( disk == 0 )
{
continue;
}
save = disk->vector_value("SAVE");
if ( save.empty() == true)
{
continue;
}
transform(save.begin(),save.end(),save.begin(),(int(*)(int))toupper);
if ( save == "YES" )
{
xfr << "MV " << vm->get_hostname() << ":" << vm->get_remote_dir()
<< "/disk." << i << " "
<< nd.get_nebula_hostname() << ":" << vm->get_local_dir()
<< "/disk." << i << endl;
}
}
xfr << "DELETE " << vm->get_hostname() <<":"<< vm->get_remote_dir() << endl;
xfr.close();
tm_md->transfer(vid,vm->get_transfer_file());
vm->unlock();
return;
error_history:
os.str("");
os << "epilog, VM " << vid << " has no history";
goto error_common;
error_file:
os.str("");
os << "epilog, could not open file: " << vm->get_transfer_file();
goto error_common;
error_driver:
os.str("");
os << "epilog, error getting driver " << vm->get_vmm_mad();
goto error_common;
error_common:
(nd.get_lcm())->trigger(LifeCycleManager::PROLOG_FAILURE,vid);
vm->log("TM", Log::ERROR, os);
vm->unlock();
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void TransferManager::epilog_stop_action(int vid)
{
ofstream xfr;
ostringstream os;
VirtualMachine * vm;
Nebula& nd = Nebula::instance();
const TransferManagerDriver * tm_md;
// ------------------------------------------------------------------------
// Setup & Transfer script
// ------------------------------------------------------------------------
vm = vmpool->get(vid,true);
if (vm == 0)
{
return;
}
if (!vm->hasHistory())
{
goto error_history;
}
tm_md = get(vm->get_uid(),vm->get_tm_mad());
if ( tm_md == 0 )
{
goto error_driver;
}
xfr.open(vm->get_transfer_file().c_str(), ios::out | ios::trunc);
if (xfr.fail() == true)
{
goto error_file;
}
// ------------------------------------------------------------------------
// Move image directory
// ------------------------------------------------------------------------
xfr << "MV ";
xfr << vm->get_hostname() << ":" << vm->get_remote_dir() << " ";
xfr << nd.get_nebula_hostname() << ":" << vm->get_local_dir() << endl;
// ------------------------------------------------------------------------
// TODO: Context commands
// ------------------------------------------------------------------------
xfr.close();
tm_md->transfer(vid,vm->get_transfer_file());
vm->unlock();
return;
error_history:
os.str("");
os << "epilog_stop, VM " << vid << " has no history";
goto error_common;
error_file:
os.str("");
os << "epilog_stop, could not open file: " << vm->get_transfer_file();
goto error_common;
error_driver:
os.str("");
os << "epilog_stop, error getting driver " << vm->get_tm_mad();
goto error_common;
error_common:
(nd.get_lcm())->trigger(LifeCycleManager::EPILOG_FAILURE,vid);
vm->log("TM", Log::ERROR, os);
vm->unlock();
return;
(nd.get_lcm())->trigger(LifeCycleManager::EPILOG_SUCCESS,vid);
}
@ -171,3 +731,50 @@ void TransferManager::checkpoint_action(int vid)
{
}
/* ************************************************************************** */
/* MAD Loading */
/* ************************************************************************** */
void TransferManager::load_mads(int uid)
{
unsigned int i;
ostringstream oss;
const VectorAttribute * vattr;
int rc;
string name;
TransferManagerDriver * tm_driver = 0;
oss << "Loading Transfer Manager drivers.";
Nebula::log("TM",Log::INFO,oss);
for(i=0,oss.str("");i<mad_conf.size();i++,oss.str(""),tm_driver=0)
{
vattr = static_cast<const VectorAttribute *>(mad_conf[i]);
name = vattr->vector_value("NAME");
oss << "\tLoading driver: " << name;
Nebula::log("VMM", Log::INFO, oss);
tm_driver = new TransferManagerDriver(
uid,
vattr->value(),
(uid != 0),
vmpool);
if ( tm_driver == 0 )
continue;
rc = add(tm_driver);
if ( rc == 0 )
{
oss.str("");
oss << "\tDriver " << name << " loaded.";
Nebula::log("TM",Log::INFO,oss);
}
}
}

View File

@ -0,0 +1,222 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "TransferManagerDriver.h"
#include "Nebula.h"
#include "LifeCycleManager.h"
#include <sstream>
TransferManagerDriver::TransferManagerDriver(
int userid,
const map<string,string>& attrs,
bool sudo,
VirtualMachinePool * pool):
Mad(userid,attrs,sudo),driver_conf(true),vmpool(pool)
{
map<string,string>::const_iterator it;
char * error_msg = 0;
const char * cfile;
string file;
int rc;
it = attrs.find("DEFAULT");
if ( it != attrs.end() )
{
if (it->second[0] != '/') //Look in ONE_LOCATION
{
Nebula& nd = Nebula::instance();
file = nd.get_nebula_location() + "/" + it->second;
cfile = file.c_str();
}
else //Absolute Path
{
cfile = it->second.c_str();
}
rc = driver_conf.parse(cfile, &error_msg);
if ( rc != 0 )
{
ostringstream oss;
if ( error_msg != 0 )
{
oss << "Error loading driver configuration file " << cfile <<
" : " << error_msg;
free(error_msg);
}
else
{
oss << "Error loading driver configuration file " << cfile;
}
Nebula::log("TM", Log::ERROR, oss);
}
}
}
/* ************************************************************************** */
/* Driver ASCII Protocol Implementation */
/* ************************************************************************** */
void TransferManagerDriver::transfer (
const int oid,
const string& xfr_file) const
{
ostringstream os;
os << "TRANSFER " << oid << " " << xfr_file << endl;
write(os);
};
/* ************************************************************************** */
/* MAD Interface */
/* ************************************************************************** */
void TransferManagerDriver::protocol(
string& message)
{
istringstream is(message);
ostringstream os;
string action;
string result;
int id;
VirtualMachine * vm;
os << "Message received: " << message;
Nebula::log("TM", Log::DEBUG, os);
// Parse the driver message
if ( is.good() )
is >> action >> ws;
else
return;
if ( is.good() )
is >> result >> ws;
else
return;
if ( is.good() )
is >> id >> ws;
else
return;
// Get the VM from the pool
vm = vmpool->get(id,true);
if ( vm == 0 )
{
return;
}
// Driver Actions
if (action == "TRANSFER")
{
Nebula &ne = Nebula::instance();
LifeCycleManager * lcm = ne.get_lcm();
LifeCycleManager::Actions lcm_action;
if (result == "SUCCESS")
{
switch (vm->get_lcm_state())
{
case VirtualMachine::PROLOG:
case VirtualMachine::PROLOG_MIGRATE:
case VirtualMachine::PROLOG_RESUME:
lcm_action = LifeCycleManager::PROLOG_SUCCESS;
break;
case VirtualMachine::EPILOG:
case VirtualMachine::EPILOG_STOP:
lcm_action = LifeCycleManager::EPILOG_SUCCESS;
break;
default:
goto error_state;
}
}
else
{
string info;
getline(is,info);
os.str("");
os << "Error excuting image transfer script: " << info;
vm->log("TM",Log::ERROR,os);
switch (vm->get_lcm_state())
{
case VirtualMachine::PROLOG:
case VirtualMachine::PROLOG_MIGRATE:
case VirtualMachine::PROLOG_RESUME:
lcm_action = LifeCycleManager::PROLOG_FAILURE;
break;
case VirtualMachine::EPILOG:
case VirtualMachine::EPILOG_STOP:
lcm_action = LifeCycleManager::EPILOG_FAILURE;
break;
default:
goto error_state;
}
}
lcm->trigger(lcm_action, id);
}
else if (action == "LOG")
{
string info;
getline(is,info);
vm->log("TM",Log::INFO,info.c_str());
}
vm->unlock();
return;
error_state:
os.str("");
os << "Wrong state in TM answer for VM " << id;
vm->log("TM",Log::ERROR,os);
vm->unlock();
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void TransferManagerDriver::recover()
{
Nebula::log("TM",Log::INFO,"Recovering TM drivers");
}

237
src/tm_mad/TMScript.rb Normal file
View File

@ -0,0 +1,237 @@
require 'pp'
require 'open3'
require 'ftools'
=begin rdoc
TMPlugin holds the name of the scripts that will be used for each
TransferManager script command. It is basically a hash where keys
are the names of the commands (uppercase) and contain the path of
the script that will be executed for that command.
It also contains some methods to execute the scripts, get the output
of the script (success/failure, error and log messages). The protocol
for scripts to do so is as follows:
* Log messages will be sent to STDOUT
* The script will return 0 if it succeded or any other value
if there was a failure
* In case of failure the cause of the error will be written to STDERR
wrapped by start and end marks as follows:
ERROR MESSAGE --8<------
error message for the failure
ERROR MESSAGE ------>8--
=end
class TMPlugin < Hash
# If a +scripts_file+ is supplied commands are loaded from it.
def initialize(scripts_file=nil)
super
load_scripts(scripts_file) if scripts_file
end
# Sets the script path for the specific +command+
def set(command, script)
self[command]=script
end
# Executes the script associated with the +command+ using
# specified arguments. +logger+ is a proc that takes a message
# as its unique argument.
#
# Returns:
# * It will return +nil+ if the +command+ is not defined.
# * String with stderr output of the string (exit code and
# error message in case of failure)
#
# Note: the exit code will be written like this:
# ExitCode: 0
def execute(logger, command, *args)
# Command is not defined
return nil if !self[command]
# Generates the line to call the script with all the
# arguments provided.
cmd=[self[command], *args].join(" ")
exec_local_command(cmd, logger)
end
private
# Executes the command, get its exit code and logs every line that
# comes from stdout. Returns whatever came from stderr.
def exec_local_command(command, logger)
cmd="#{command} ; echo ExitCode: $? 1>&2"
stderr=""
std=Open3.popen3(cmd) {|stdin, stdout, stderr_|
# TODO: this should be sent to ONE and not to STDERR
while !stdout.eof?
log(stdout.readline, logger)
end
stderr_.read
}
end
# Uses +logger+ to send +message+ to ONE
def log(message, logger=nil)
return nil if !logger
logger.call(message)
end
def load_scripts(scripts_file)
scripts_text=""
if File.exist?(scripts_file)
scripts_text=open(scripts_file).read
else
STDERR.puts("Can not open #{scripts_file}")
STDERR.flush
return
end
one_location=ENV['ONE_LOCATION']
scripts_text.each_line {|line|
case line
when /^\s*(#.*)?$/
# skip empty or commented lines
next
when /^\s*(\w+)\s*=\s*(.*)\s*$/
# TODO: add ONE_LOCATION if it is not FQDM
command=$1.strip.upcase
path=$2.strip
# Substitutes ONE_LOCATION by the envionment variable
path.gsub!(/ONE_LOCATION/, one_location)
# Prepend ONE_LOCATION if the path does not
# start with /
path=one_location+"/"+path if path[0]!=?/
self[command]=path
else
STDERR.puts("Can not parse line: #{line}")
end
}
end
end
# This class will parse and execute TransferManager scripts.
class TMScript
attr_accessor :lines
# +script_text+ contains the script to be executed.
# +logger+ is a lambda that receives a message and sends it
# to ONE server
def initialize(script_text, logger=nil)
@lines=Array.new
@logger=logger
parse_script(script_text)
end
# Executes the script using the TMPlugin specified by +plugin+.
# Returns an array where first element tells if succeded and the
# second one is the error message in case of failure.
def execute(plugin)
result=@lines.each {|line|
res=plugin.execute(@logger, *line)
if !res
log "COMMAND not found for: #{line.join(" ")}."
res=[false, "COMMAND not found for: #{line.join(" ")}."]
else
res=parse_output(res)
end
# do not continue if command failed
break res if !res[0]
}
result
end
private
# Sends a log +message+ to ONE using +@logger+
def log(message)
@logger.call(message) if @logger
end
# Gets commands from the script and populates +@lines+
def parse_script(script_text)
script_text.each_line {|line|
# skip if the line is commented
next if line.match(/^\s*#/)
# skip if the line is empty
next if line.match(/^\s*$/)
command=line.split(" ")
command[0].upcase!
@lines<< command
}
end
# Gets exit code and error message (if failed) from
# +stderr+
def parse_output(err)
exit_code=get_exit_code(err)
if exit_code==0
[true, ""]
else
[false, get_error_message(err)]
end
end
# Gets exit code from STDERR
def get_exit_code(str)
tmp=str.scan(/^ExitCode: (\d*)$/)
return nil if !tmp[0]
tmp[0][0].to_i
end
# Parses error message from +stderr+ output
def get_error_message(str)
tmp=str.scan(/^ERROR MESSAGE --8<------\n(.*?)ERROR MESSAGE ------>8--$/m)
return "Error message not available" if !tmp[0]
tmp[0][0].strip
end
end
if $0 == __FILE__
require 'one_log'
logger=ONELog.new
log_proc=lambda{|message|
logger.log("TRANSFER", "0", message)
}
log_proc.call(<<-EOT)
Multiple
lines log
thingy
EOT
script_text="
CLONE localhost:/tmp/source.img ursa:/tmp/one_jfontan/0/hda.img
CLONE localhost:/tmp/source.img ursa:/tmp/one_jfontan/1/hda.img
"
plugin=TMPlugin.new
plugin["CLONE"]="./tm_clone.sh"
scr=TMScript.new(script_text, log_proc)
pp scr.lines
scr.execute(plugin)
end

33
src/tm_mad/nfs/tm_clone.sh Executable file
View File

@ -0,0 +1,33 @@
#!/bin/bash
SRC=$1
DST=$2
. $ONE_LOCATION/libexec/tm_common.sh
SRC_PATH=`arg_path $SRC`
DST_PATH=`arg_path $DST`
log "$1 $2"
log "DST: $DST_PATH"
DST_DIR=`dirname $DST_PATH`
log "Creating directory $DST_DIR"
exec_and_log "mkdir -p $DST_DIR"
exec_and_log "chmod a+w $DST_DIR"
case $SRC in
http://*)
log "Downloading $SRC"
exec_and_log "wget -O $DST_PATH $SRC"
;;
*)
log "Cloning $SRC_PATH"
exec_and_log "cp $SRC_PATH $DST_PATH"
;;
esac
exec_and_log "chmod a+w $DST_PATH"

11
src/tm_mad/nfs/tm_delete.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
SRC=$1
DST=$2
. $ONE_LOCATION/libexec/tm_common.sh
SRC_PATH=`arg_path $SRC`
log "Deleting $SRC_PATH"
exec_and_log "rm -rf $SRC_PATH"

12
src/tm_mad/nfs/tm_ln.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
SRC=$1
DST=$2
. $ONE_LOCATION/libexec/tm_common.sh
SRC_PATH=`arg_path $SRC`
DST_PATH=`arg_path $DST`
log "Link $SRC_PATH"
exec_and_log "ln -s $SRC_PATH $DST_PATH"

5
src/tm_mad/nfs/tm_mkimage.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
. $ONE_LOCATION/libexec/tm_common.sh
log "mkimage placeholder"

17
src/tm_mad/nfs/tm_mkswap.sh Executable file
View File

@ -0,0 +1,17 @@
#!/bin/bash
SIZE=$1
DST=$2
. $ONE_LOCATION/libexec/tm_common.sh
DST_PATH=`arg_path $DST`
log "Creating ${SIZE}Mb image in $DST_PATH"
exec_and_log "dd if=/dev/zero of=$DST_PATH bs=1 count=1 seek=${SIZE}M"
log "Initializing swap space"
exec_and_log "mkswap $DST_PATH"
exec_and_log "chmod a+w $DST_PATH"

23
src/tm_mad/nfs/tm_mv.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash
SRC=$1
DST=$2
. $ONE_LOCATION/libexec/tm_common.sh
SRC_PATH=`arg_path $SRC`
DST_PATH=`arg_path $DST`
if [ "$SRC_PATH" == "$DST_PATH" ]; then
log "Will not move, source and destination are equal"
else
# Is saving a disk image?
echo "$DST_PATH" | egrep -e "^$ONE_LOCATION/var/.+/disk\..+$"
if [ "x$?" == "x0" ]; then
log "Moving $SRC_PATH"
exec_and_log "mv $SRC_PATH $DST_PATH"
else
log "Will not move, is not saving image"
fi
fi

View File

@ -0,0 +1,6 @@
CLONE = ONE_LOCATION/lib/tm_commands/nfs/tm_clone.sh
LN = ONE_LOCATION/lib/tm_commands/nfs/tm_ln.sh
MKSWAP = ONE_LOCATION/lib/tm_commands/nfs/tm_mkswap.sh
MKIMAGE = ONE_LOCATION/lib/tm_commands/nfs/tm_mkimage.sh
DELETE = ONE_LOCATION/lib/tm_commands/nfs/tm_delete.sh
MV = ONE_LOCATION/lib/tm_commands/nfs/tm_mv.sh

16
src/tm_mad/nfs/tm_nfsrc Normal file
View File

@ -0,0 +1,16 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2008, Distributed Systems Architecture Group, Universidad #
# Complutense de Madrid (dsa-research.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #

25
src/tm_mad/one_tm Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
if [ -z "${ONE_LOCATION}" ]; then
echo "Please, set ONE_LOCATION variable."
exit -1
fi
. $ONE_LOCATION/libexec/madcommon.sh
# Export the im_mad specific rc
DRIVER_NAME=`basename $1 | cut -d. -f1`
export_rc_vars $ONE_LOCATION/etc/${DRIVER_NAME}/${DRIVER_NAME}rc
# Go to ONE_LOCATION
cd $ONE_LOCATION
LOG_FILE=$DRIVER_NAME
# Execute the actual MAD
execute_mad $*

84
src/tm_mad/one_tm.rb Executable file
View File

@ -0,0 +1,84 @@
#!/usr/bin/env ruby
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
puts "ONE_LOCATION not set"
exit(-1)
end
$: << ONE_LOCATION+"/lib/ruby"
require 'pp'
require 'one_mad'
require 'ThreadScheduler'
require 'TMScript'
class TM < ONEMad
def initialize(plugin)
@thread_scheduler=ThreadScheduler.new(10)
@plugin=plugin
# Messages with 3 input elements and 4 output elements:
#
# in: TRANSFER 65 /something/var/65/tmscript.0
# out: TRANSFER 65 FAILURE error message
super(3,4)
set_logger(STDERR, 1)
end
def action_init(args)
STDOUT.puts "INIT SUCCESS"
STDOUT.flush
log("INIT SUCCESS",DEBUG)
end
def action_transfer(args)
number=args[1]
script_file=args[2]
script_text=""
# Create the lambda that will be used to log
mad_logger=lambda {|message|
mad_log("TRANSFER", number, message)
}
open(script_file) {|f|
script_text=f.read
}
script=TMScript.new(script_text, mad_logger)
@thread_scheduler.new_thread {
res=script.execute(@plugin)
if res[0]
send_message("TRANSFER", "SUCCESS", number)
else
send_message("TRANSFER", "FAILURE", number, res[1])
end
}
end
def action_finalize(args)
@thread_scheduler.shutdown
super(args)
end
end
tm_conf=ARGV[0]
if !tm_conf
puts "You need to specify config file."
exit(-1)
end
tm_conf=ONE_LOCATION+"/"+tm_conf if tm_conf[0] != ?/
plugin=TMPlugin.new(tm_conf)
tm=TM.new(plugin)
tm.loop

36
src/tm_mad/ssh/tm_clone.sh Executable file
View File

@ -0,0 +1,36 @@
#!/bin/bash
SRC=$1
DST=$2
. $ONE_LOCATION/libexec/tm_common.sh
SRC_PATH=`arg_path $SRC`
DST_PATH=`arg_path $DST`
SRC_HOST=`arg_host $SRC`
DST_HOST=`arg_host $DST`
log "$1 $2"
log "DST: $DST_PATH"
DST_DIR=`dirname $DST_PATH`
log "Creating directory $DST_DIR"
exec_and_log "ssh $DST_HOST mkdir -p $DST_DIR"
case $SRC in
http://*)
log "Downloading $SRC"
exec_and_log "ssh $DST_HOST wget -O $DST_PATH $SRC_PATH"
;;
*)
log "Cloning $SRC"
exec_and_log "scp $SRC $DST"
;;
esac
exec_and_log "ssh $DST_HOST chmod a+w $DST_PATH"

12
src/tm_mad/ssh/tm_delete.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
SRC=$1
DST=$2
. $ONE_LOCATION/libexec/tm_common.sh
SRC_PATH=`arg_path $SRC`
SRC_HOST=`arg_host $SRC`
log "Deleting $SRC_PATH"
exec_and_log "ssh $SRC_HOST rm -rf $SRC_PATH"

11
src/tm_mad/ssh/tm_ln.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
SRC=$1
DST=$2
. $ONE_LOCATION/libexec/tm_common.sh
log "Link $SRC_PATH (non shared dir, will clone)"
#exec_and_log "ln -s $SRC_PATH $DST_PATH"
exec $ONE_LOCATION/lib/tm_commands/ssh/tm_clone.sh $SRC $DST

5
src/tm_mad/ssh/tm_mkimage.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
. $ONE_LOCATION/libexec/tm_common.sh
log "mkimage placeholder"

21
src/tm_mad/ssh/tm_mkswap.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash
SIZE=$1
DST=$2
. $ONE_LOCATION/libexec/tm_common.sh
DST_PATH=`arg_path $DST`
DST_HOST=`arg_host $DST`
DST_DIR=`dirname $DST_PATH`
log "Creating ${SIZE}Mb image in $DST_PATH"
exec_and_log "ssh $DST_HOST mkdir -p $DST_DIR"
exec_and_log "ssh $DST_HOST dd if=/dev/zero of=$DST_PATH bs=1 count=1 seek=${SIZE}M"
log "Initializing swap space"
exec_and_log "ssh $DST_HOST mkswap $DST_PATH"
exec_and_log "ssh $DST_HOST chmod a+w $DST_PATH"

19
src/tm_mad/ssh/tm_mv.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/bash
SRC=$1
DST=$2
. $ONE_LOCATION/libexec/tm_common.sh
SRC_PATH=`arg_path $SRC`
DST_PATH=`arg_path $DST`
SRC_HOST=`arg_host $SRC`
DST_HOST=`arg_host $DST`
DST_DIR=`dirname $DST_PATH`
log "Moving $SRC_PATH"
exec_and_log "ssh $DST_HOST mkdir -p $DST_DIR"
exec_and_log "scp -r $SRC $DST"
exec_and_log "ssh $SRC_HOST rm -rf $SRC_PATH"

6
src/tm_mad/ssh/tm_ssh.conf Executable file
View File

@ -0,0 +1,6 @@
CLONE = ONE_LOCATION/lib/tm_commands/ssh/tm_clone.sh
LN = ONE_LOCATION/lib/tm_commands/ssh/tm_ln.sh
MKSWAP = ONE_LOCATION/lib/tm_commands/ssh/tm_mkswap.sh
MKIMAGE = ONE_LOCATION/lib/tm_commands/ssh/tm_mkimage.sh
DELETE = ONE_LOCATION/lib/tm_commands/ssh/tm_delete.sh
MV = ONE_LOCATION/lib/tm_commands/ssh/tm_mv.sh

16
src/tm_mad/ssh/tm_sshrc Normal file
View File

@ -0,0 +1,16 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2008, Distributed Systems Architecture Group, Universidad #
# Complutense de Madrid (dsa-research.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #

96
src/tm_mad/tm_common.sh Normal file
View File

@ -0,0 +1,96 @@
# Used for log messages
SCRIPT_NAME=`basename $0`
# Formats date for logs
function log_date
{
date +"%a %b %d %T %Y"
}
# Logs a message
function log
{
echo "$SCRIPT_NAME: $1"
}
# Logs an error message
function log_error
{
log "ERROR: $1"
}
# This function is used to pass error message to the mad
function error_message
{
(
echo "ERROR MESSAGE --8<------"
echo "$1"
echo "ERROR MESSAGE ------>8--"
) 1>&2
}
# Gets the host from an argument
function arg_host
{
echo $1 | sed -e 's/^\([^:]*\):.*$/\1/'
}
# Gets the path from an argument
function arg_path
{
echo $1 | sed -e 's/^[^:]*:\(.*\)$/\1/'
}
# Executes a command, if it fails return error message and exits
function exec_and_log
{
output=`$1 2>&1 1>/dev/null`
if [ "x$?" != "x0" ]; then
log_error "Command \"$1\" failed."
log_error "$output"
error_message "$output"
exit -1
fi
log "Executed \"$1\"."
}
# Like exec_and_log but the first argument is the number of seconds
# before here is timeout and kills the command
#
# NOTE: if the command is killed because a timeout the exit code
# will be 143 = 128+15 (SIGHUP)
function timeout_exec_and_log
{
TIMEOUT=$1
shift
CMD="$1"
exec_and_log "$CMD" &
CMD_PID=$!
# timeout process
(
sleep $TIMEOUT
kill $CMD_PID 2>/dev/null
log_error "Timeout executing $CMD"
error_message "Timeout executing $CMD"
exit -1
) &
TIMEOUT_PID=$!
# stopts the exution until the command finalizes
wait $CMD_PID 2>/dev/null
CMD_CODE=$?
# if the script reaches here the command finished before it
# consumes timeout seconds so we can kill timeout process
kill $TIMEOUT_PID 2>/dev/null 1>/dev/null
wait $TIMEOUT_PID 2>/dev/null
# checks the exit code of the command and exits if it is not 0
if [ "x$CMD_CODE" != "x0" ]; then
exit $CMD_CODE
fi
}

View File

@ -16,6 +16,7 @@
/* -------------------------------------------------------------------------- */
#include "VirtualMachine.h"
#include "Nebula.h"
#include <iostream>
#include <sstream>
@ -25,14 +26,14 @@
const char * History::table = "history";
const char * History::db_names = "(oid,seq,hostname,vm_dir,hid,vmmad,tmmad,stime,"
const char * History::db_names = "(vid,seq,host_name,vm_dir,hid,vm_mad,tm_mad,stime,"
"etime,pstime,petime,rstime,retime,estime,eetime,reason)";
const char * History::db_bootstrap = "CREATE TABLE history (oid INTEGER,"
"seq INTEGER,hostname TEXT,vm_dir TEXT,hid INTEGER,vmmad TEXT,tmmad TEXT,"
const char * History::db_bootstrap = "CREATE TABLE history (vid INTEGER,"
"seq INTEGER,host_name TEXT,vm_dir TEXT,hid INTEGER,vm_mad TEXT,tm_mad TEXT,"
"stime INTEGER,etime INTEGER,pstime INTEGER,petime INTEGER,rstime INTEGER,"
"retime INTEGER,estime INTEGER,eetime INTEGER,reason INTEGER,"
"PRIMARY KEY(oid,seq))";
"PRIMARY KEY(vid,seq))";
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -43,7 +44,7 @@ History::History(
oid(_oid),
seq(_seq),
hostname(""),
vm_rdir(""),
vm_dir(""),
hid(-1),
vmm_mad_name(""),
tm_mad_name(""),
@ -64,13 +65,13 @@ History::History(
int _seq,
int _hid,
string& _hostname,
string& _vm_rdir,
string& _vm_dir,
string& _vmm,
string& _tm):
oid(_oid),
seq(_seq),
hostname(_hostname),
vm_rdir(_vm_rdir),
vm_dir(_vm_dir),
hid(_hid),
vmm_mad_name(_vmm),
tm_mad_name(_tm),
@ -93,41 +94,37 @@ History::History(
void History::non_persistent_data()
{
ostringstream os;
const char * nl = getenv("ONE_LOCATION");
if (nl == 0)
{
nl = "/var/tmp";
}
Nebula& nd = Nebula::instance();
// ----------- Local Locations ------------
os << nl << "/var/" << oid;
os.str("");
os << nd.get_nebula_location() << "/var/" << oid;
vm_lhome = os.str();
os.str("");
os << vm_lhome << "/deployment." << seq;
deployment_lfile = os.str();
os << "/deployment." << seq;
deployment_file = os.str();
os.str("");
os << vm_lhome << "/transfer." << seq;
transfer_file = os.str();
// ----------- Remote Locations ------------
os.str("");
os << vm_rdir;
os << "/" << oid;
os << vm_dir << "/" << oid << "/images";
vm_rhome = os.str();
os << "/" << "checkpoint";
os << "/checkpoint";
checkpoint_file = os.str();
os.str("");
os << vm_rhome << "/deployment." << seq;
deployment_rfile = os.str();
rdeployment_file = os.str();
}
/* -------------------------------------------------------------------------- */
@ -147,7 +144,7 @@ int History::insert(SqliteDB * db)
oid << "," <<
seq << "," <<
"'" << hostname << "',"<<
"'" << vm_rdir << "'," <<
"'" << vm_dir << "'," <<
hid << "," <<
"'" << vmm_mad_name << "'," <<
"'" << tm_mad_name << "'," <<
@ -171,7 +168,7 @@ int History::insert(SqliteDB * db)
int History::unmarshall(int num, char **names, char ** values)
{
if ((values[OID] == 0) ||
if ((values[VID] == 0) ||
(values[SEQ] == 0) ||
(values[HOSTNAME] == 0) ||
(values[VM_DIR] == 0) ||
@ -192,11 +189,11 @@ int History::unmarshall(int num, char **names, char ** values)
return -1;
}
oid = atoi(values[OID]);
oid = atoi(values[VID]);
seq = atoi(values[SEQ]);
hostname = values[HOSTNAME];
vm_rdir = values[VM_DIR];
vm_dir = values[VM_DIR];
hid = atoi(values[HID]);
@ -255,12 +252,12 @@ int History::select(SqliteDB * db)
if ( seq == -1)
{
oss << "SELECT * FROM history WHERE oid = "<< oid <<
" AND seq=(SELECT MAX(seq) FROM history WHERE oid = " << oid << ")";
oss << "SELECT * FROM history WHERE vid = "<< oid <<
" AND seq=(SELECT MAX(seq) FROM history WHERE vid = " << oid << ")";
}
else
{
oss << "SELECT * FROM history WHERE oid = "<< oid <<" AND seq = "<< seq;
oss << "SELECT * FROM history WHERE vid = "<< oid <<" AND seq = "<< seq;
}
rc = db->exec(oss,history_select_cb,(void *) this);
@ -280,7 +277,7 @@ int History::drop(SqliteDB * db)
{
ostringstream oss;
oss << "DELETE FROM " << table << " WHERE oid= "<< oid;
oss << "DELETE FROM " << table << " WHERE vid= "<< oid;
return db->exec(oss);
}

View File

@ -25,6 +25,9 @@
#include <sstream>
#include "VirtualMachine.h"
#include "VirtualNetworkPool.h"
#include "Nebula.h"
/* ************************************************************************** */
@ -33,12 +36,7 @@
VirtualMachine::VirtualMachine(int id):
PoolObjectSQL(id),
aid(-1),
tid(-1),
uid(-1),
priority(INT_MIN),
reschedule(false),
last_reschedule(0),
last_poll(0),
vm_template(),
state(INIT),
@ -73,17 +71,15 @@ VirtualMachine::~VirtualMachine()
/* Virtual Machine :: Database Access Functions */
/* ************************************************************************** */
const char * VirtualMachine::table = "vmpool";
const char * VirtualMachine::table = "vm_pool";
const char * VirtualMachine::db_names = "(oid,aid,tid,uid,priority,reschedule"
",last_reschedule,last_poll,template,state"
const char * VirtualMachine::db_names = "(oid,uid,last_poll,template_id,state"
",lcm_state,stime,etime,deploy_id"
",memory,cpu,net_tx,net_rx)";
const char * VirtualMachine::db_bootstrap = "CREATE TABLE vmpool ("
"oid INTEGER PRIMARY KEY,aid INTEGER,tid INTEGER,uid INTEGER,"
"priority INTEGER,reschedule INTEGER,last_reschedule INTEGER,"
"last_poll INTEGER, template INTEGER,state INTEGER,lcm_state INTEGER,"
const char * VirtualMachine::db_bootstrap = "CREATE TABLE vm_pool ("
"oid INTEGER PRIMARY KEY,uid INTEGER,"
"last_poll INTEGER, template_id INTEGER,state INTEGER,lcm_state INTEGER,"
"stime INTEGER,etime INTEGER,deploy_id TEXT,memory INTEGER,cpu INTEGER,"
"net_tx INTEGER,net_rx INTEGER)";
@ -93,12 +89,7 @@ const char * VirtualMachine::db_bootstrap = "CREATE TABLE vmpool ("
int VirtualMachine::unmarshall(int num, char **names, char ** values)
{
if ((values[OID] == 0) ||
(values[AID] == 0) ||
(values[TID] == 0) ||
(values[UID] == 0) ||
(values[PRIORITY] == 0) ||
(values[RESCHEDULE] == 0) ||
(values[LAST_RESCHEDULE] == 0) ||
(values[LAST_POLL] == 0) ||
(values[TEMPLATE_ID] == 0) ||
(values[STATE] == 0) ||
@ -115,15 +106,9 @@ int VirtualMachine::unmarshall(int num, char **names, char ** values)
}
oid = atoi(values[OID]);
aid = atoi(values[AID]);
tid = atoi(values[TID]);
uid = atoi(values[UID]);
priority = atoi(values[PRIORITY]);
reschedule = static_cast<bool>(atoi(values[RESCHEDULE]));
last_reschedule = static_cast<time_t>(atoi(values[LAST_RESCHEDULE]));
last_poll = static_cast<time_t>(atoi(values[LAST_POLL]));
last_poll = static_cast<time_t>(atoi(values[LAST_POLL]));
state = static_cast<VmState>(atoi(values[STATE]));
lcm_state = static_cast<LcmState>(atoi(values[LCM_STATE]));
@ -292,9 +277,23 @@ error_previous_history:
/* -------------------------------------------------------------------------- */
int VirtualMachine::insert(SqliteDB * db)
{
int rc;
string name;
{
int rc;
string name;
int num_nics;
vector<Attribute * > nics;
VirtualNetworkPool * vnpool;
VirtualNetwork * vn;
VectorAttribute * nic;
map<string,string> new_nic;
string ip;
string mac;
string bridge;
string network;
ostringstream vnid;
//Set a name if the VM has not got one
@ -311,15 +310,65 @@ int VirtualMachine::insert(SqliteDB * db)
name_attr = new SingleAttribute("NAME",name);
vm_template.set(name_attr);
}
}
// Set the networking attributes.
Nebula& nd = Nebula::instance();
vnpool = nd.get_vnpool();
num_nics = vm_template.get("NIC",nics);
for(int i=0; i<num_nics; i++,vnid.str(""))
{
new_nic.erase(new_nic.begin(),new_nic.end());
nic = dynamic_cast<VectorAttribute * >(nics[i]);
if ( nic == 0 )
{
continue;
}
network = nic->vector_value("NETWORK");
if ( network.empty() )
{
continue;
}
vn = vnpool->get(network,true);
if ( vn == 0 )
{
continue;
}
if ( vn->get_lease(oid, ip, mac, bridge) != 0 )
{
goto error_leases;
}
vn->unlock();
vnid << vn->get_oid();
new_nic.insert(make_pair("NETWORK",network));
new_nic.insert(make_pair("MAC" ,mac));
new_nic.insert(make_pair("BRIDGE" ,bridge));
new_nic.insert(make_pair("VNID" ,vnid.str()));
new_nic.insert(make_pair("IP" ,ip));
nic->replace(new_nic);
}
// Insert the template first, so we get a valid template ID
rc = vm_template.insert(db);
if ( rc != 0 )
{
log("ONE", Log::ERROR, "Can not insert template");
return -1;
goto error_template;
}
//Insert the VM
@ -327,13 +376,24 @@ int VirtualMachine::insert(SqliteDB * db)
if ( rc != 0 )
{
log("ONE", Log::ERROR, "Can not update vm");
vm_template.drop(db);
return -1;
goto error_update;
}
return 0;
error_update:
log("ONE", Log::ERROR, "Can not update vm");
vm_template.drop(db);
return -1;
error_template:
log("ONE", Log::ERROR, "Can not insert template");
return -1;
error_leases:
log("ONE", Log::ERROR, "Could not get lease for VM");
vn->unlock();
return -1;
}
/* -------------------------------------------------------------------------- */
@ -346,12 +406,7 @@ int VirtualMachine::update(SqliteDB * db)
oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES ("<<
oid << "," <<
aid << "," <<
tid << "," <<
uid << "," <<
priority << "," <<
reschedule << "," <<
last_reschedule << "," <<
last_poll << "," <<
vm_template.id << "," <<
state << "," <<
@ -417,7 +472,7 @@ void VirtualMachine::cp_history()
history->seq + 1,
history->hid,
history->hostname,
history->vm_rdir,
history->vm_dir,
history->vmm_mad_name,
history->tm_mad_name);
@ -447,7 +502,7 @@ void VirtualMachine::cp_previous_history()
history->seq + 1,
previous_history->hid,
previous_history->hostname,
previous_history->vm_rdir,
previous_history->vm_dir,
previous_history->vmm_mad_name,
previous_history->tm_mad_name);
@ -489,6 +544,59 @@ void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk)
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::release_leases()
{
Nebula& nd = Nebula::instance();
VirtualNetworkPool * vnpool = nd.get_vnpool();
string vnid;
string ip;
int num_nics;
vector<Attribute const * > nics;
VirtualNetwork * vn;
num_nics = get_template_attribute("NIC",nics);
for(int i=0; i<num_nics; i++)
{
VectorAttribute const * nic = dynamic_cast<VectorAttribute const * >(nics[i]);
if ( nic == 0 )
{
continue;
}
vnid = nic->vector_value("VNID");
if ( vnid.empty() )
{
continue;
}
ip = nic->vector_value("IP");
if ( ip.empty() )
{
continue;
}
vn = vnpool->get(atoi(vnid.c_str()),true);
if ( vn == 0 )
{
continue;
}
vn->release_lease(ip);
vn->unlock();
}
}
/* ************************************************************************** */
/* Virtual Machine :: Misc */
/* ************************************************************************** */
@ -496,17 +604,12 @@ void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk)
ostream& operator<<(ostream& os, VirtualMachine& vm)
{
os << "VID : " << vm.oid << endl;
os << "AID : " << vm.aid << endl;
os << "TID : " << vm.tid << endl;
os << "UID : " << vm.uid << endl;
os << "STATE : " << vm.state << endl;
os << "LCM STATE : " << vm.lcm_state << endl;
os << "DEPLOY ID : " << vm.deploy_id << endl;
os << "MEMORY : " << vm.memory << endl;
os << "CPU : " << vm.cpu << endl;
os << "PRIORITY : " << vm.priority << endl;
os << "RESCHEDULE : " << vm.reschedule << endl;
os << "LAST RESCHEDULE : " << vm.last_reschedule << endl;
os << "LAST POLL : " << vm.last_poll << endl;
os << "START TIME : " << vm.stime << endl;
os << "STOP TIME : " << vm.etime << endl;

View File

@ -25,10 +25,11 @@ int VirtualMachinePool::allocate (
int * oid,
bool on_hold)
{
VirtualMachine * vm;
char * error_msg;
int rc;
VirtualMachine * vm;
char * error_msg;
int rc;
// Build a new Virtual Machine object
vm = new VirtualMachine;
@ -60,6 +61,11 @@ int VirtualMachinePool::allocate (
// Insert the Object in the pool
*oid = PoolSQL::allocate(vm);
if ( *oid == -1 )
{
return -1;
}
return 0;
}

View File

@ -17,8 +17,8 @@
#include "VirtualMachineTemplate.h"
const char * VirtualMachineTemplate::table = "vm_template";
const char * VirtualMachineTemplate::table = "vm_attributes";
const char * VirtualMachineTemplate::db_bootstrap = "CREATE TABLE vm_template"
const char * VirtualMachineTemplate::db_bootstrap = "CREATE TABLE vm_attributes"
" (id INTEGER, name TEXT, type INTEGER, value TEXT)";

View File

@ -45,7 +45,6 @@ int LibVirtDriver::deployment_description(
const VectorAttribute * disk;
string type = "";
string source = "";
string target = "";
string bus = "";
string ro = "";
@ -230,7 +229,7 @@ int LibVirtDriver::deployment_description(
num = vm->get_template_attribute("DISK",attrs);
for (int i=0; i < num ;i++,source="",target="",ro="")
for (int i=0; i < num ;i++,target="",ro="")
{
disk = dynamic_cast<const VectorAttribute *>(attrs[i]);
@ -240,12 +239,11 @@ int LibVirtDriver::deployment_description(
}
type = disk->vector_value("TYPE");
source = disk->vector_value("SOURCE");
target = disk->vector_value("TARGET");
ro = disk->vector_value("READONLY");
bus = disk->vector_value("BUS");
if ( source.empty() || target.empty())
if (target.empty())
{
goto error_disk;
}
@ -268,8 +266,8 @@ int LibVirtDriver::deployment_description(
}
file << "\t\t<disk type='file' device='" << type << "'>" << endl;
file << "\t\t\t<source file='" << source << "'/>" << endl;
file << "\t\t\t<source file='" << vm->get_remote_dir() << "/disk." << i
<< "'/>" << endl;
file << "\t\t\t<target dev='" << target << "'";
if (!bus.empty())
@ -506,7 +504,7 @@ error_boot:
return -1;
error_disk:
vm->log("VMM", Log::ERROR, "Wrong source or target value in DISK.");
vm->log("VMM", Log::ERROR, "Wrong target value in DISK.");
file.close();
return -1;
}

View File

@ -243,11 +243,11 @@ void VirtualMachineManager::deploy_action(int vid)
//Generate VM description file
os.str("");
os << "Generating deployment file: " << vm->get_deployment_lfile();
os << "Generating deployment file: " << vm->get_deployment_file();
vm->log("VMM", Log::INFO, os);
rc = vmd->deployment_description(vm,vm->get_deployment_lfile());
rc = vmd->deployment_description(vm,vm->get_deployment_file());
if (rc != 0)
{
@ -255,7 +255,7 @@ void VirtualMachineManager::deploy_action(int vid)
}
// Invoke driver method
vmd->deploy(vid,vm->get_hostname(),vm->get_deployment_rfile());
vmd->deploy(vid,vm->get_hostname(),vm->get_remote_deployment_file());
vm->unlock();
@ -273,7 +273,7 @@ error_driver:
error_file:
os.str("");
os << "deploy_action, error generating deployment file: " << vm->get_deployment_lfile();
os << "deploy_action, error generating deployment file: " << vm->get_deployment_file();
goto error_common;
error_common:

View File

@ -50,17 +50,24 @@ VirtualMachineManagerDriver::VirtualMachineManagerDriver(
}
rc = driver_conf.parse(cfile, &error_msg);
if (( rc != 0 ) && ( error_msg != 0))
if ( rc != 0 )
{
ostringstream oss;
oss << "Error loading driver configuration file " << cfile <<
ostringstream oss;
if ( error_msg != 0 )
{
oss << "Error loading driver configuration file " << cfile <<
" : " << error_msg;
Nebula::log("VMM", Log::ERROR, oss);
free(error_msg);
free(error_msg);
}
else
{
oss << "Error loading driver configuration file " << cfile;
}
Nebula::log("VMM", Log::ERROR, oss);
}
}
}

View File

@ -42,8 +42,7 @@ int XenDriver::deployment_description(
string root = "";
const VectorAttribute * disk;
string source = "";
string target = "";
string ro = "";
string mode;
@ -184,7 +183,7 @@ int XenDriver::deployment_description(
file << "disk = [" << endl;
for (int i=0; i < num ;i++,source="",target="",ro="")
for (int i=0; i < num ;i++,target="",ro="")
{
disk = dynamic_cast<const VectorAttribute *>(attrs[i]);
@ -193,11 +192,10 @@ int XenDriver::deployment_description(
continue;
}
source = disk->vector_value("SOURCE");
target = disk->vector_value("TARGET");
ro = disk->vector_value("READONLY");
if ( source.empty() || target.empty())
if ( target.empty() )
{
goto error_disk;
}
@ -214,8 +212,10 @@ int XenDriver::deployment_description(
}
}
// TODO: "file" method to specify disk images in xen is deprecated.
// The new method is using "tap:aio:" instead of "file:"
file << " "
<< "'file:" << source << ","
<< "'file:" << vm->get_remote_dir() << "/disk." << i << ","
<< target << ","
<< mode
<< "'," << endl;
@ -364,7 +364,7 @@ error_root:
return -1;
error_disk:
vm->log("VMM", Log::ERROR, "Wrong source or target value in DISK.");
vm->log("VMM", Log::ERROR, "Wrong target value in DISK.");
file.close();
return -1;
}

View File

@ -30,7 +30,7 @@ class DM < ONEMad
set_logger(STDERR,DEBUG_LEVEL)
end
init_actions
init_actions(50)
end
def action_init(args)
@ -42,11 +42,21 @@ class DM < ONEMad
# Get local deployment file
one_location=ENV["ONE_LOCATION"]
m=args[3].match(/.*?\/(\d+)\/(deployment.\d+)$/)
m=args[3].match(/.*?\/(\d+)\/images\/(deployment.\d+)$/)
# If matched the we can read the file and get more configuration values
if m
local_deployment_file="#{one_location}/var/#{m[1]}/#{m[2]}"
# TODO: review this way of copying files
# This command copies deployment file to remote machine
# when shared directories are not used
copy_deploy="scp #{local_deployment_file} #{args[2]}:#{args[3]}"
copy_deploy_exit=system(copy_deploy)
STDERR.puts("Command: #{copy_deploy}")
STDERR.puts(copy_deploy_exit)
STDERR.flush
# TODO: check for error
file=open(local_deployment_file)
@ -62,7 +72,12 @@ class DM < ONEMad
credits=credits[1] if credits
# Get the name of the VM (used to set credit scheduling)
vm_name=f.match(/^name = '(.*?)'$/)[1]
match_name=f.match(/^name = '(.*?)'$/)
if match_name
vm_name=match_name[1]
else
credits=nil
end
end
action_number=args[1]
@ -83,11 +98,11 @@ class DM < ONEMad
end
action=SSHAction.new(action_number, action_host, cmd)
send_ssh_action(action_number, action_host, action)
send_ssh_action(action)
end
def action_shutdown(args)
std_action("SHUTDOWN", "shutdown #{args[3]}", args)
std_action("SHUTDOWN", "shutdown #{args[3]} \\&\\& sudo #{XM_PATH} destroy #{args[3]} \\&\\& sleep 4", args)
end
def action_cancel(args)
@ -146,7 +161,7 @@ class DM < ONEMad
end # End of callback
action=SSHAction.new(action_number, action_host, cmd)
send_ssh_action(action_number, action_host, action)
send_ssh_action(action)
end
###########################
@ -163,7 +178,7 @@ class DM < ONEMad
end
action=SSHAction.new(action_number, action_host, cmd)
send_ssh_action(action_number, action_host, action)
send_ssh_action(action)
end
def write_response(action, stdout, stderr, args)

188
src/vnm/FixedLeases.cc Normal file
View File

@ -0,0 +1,188 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "FixedLeases.h"
#include "Nebula.h"
FixedLeases::FixedLeases(
SqliteDB * db,
int _oid,
unsigned int _mac_prefix,
vector<const Attribute*>& vector_leases):
Leases(db,_oid,0),mac_prefix(_mac_prefix),current(leases.begin())
{
const VectorAttribute * single_attr_lease;
string _mac;
string _ip;
size = vector_leases.size();
for (unsigned long i=0; i < size ;i++)
{
single_attr_lease = dynamic_cast<const VectorAttribute *>
(vector_leases[i]);
if( single_attr_lease )
{
_ip = single_attr_lease->vector_value("IP");
_mac = single_attr_lease->vector_value("MAC");
add(_ip,_mac,-1,false);
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int FixedLeases::add(const string& ip, const string& mac, int vid, bool used)
{
ostringstream oss;
unsigned int _ip;
unsigned int _mac [2];
int rc;
if ( Leases::Lease::ip_to_number(ip,_ip) )
{
goto error_ip;
}
if (mac.empty())
{
_mac[Lease::PREFIX] = mac_prefix;
_mac[Lease::SUFFIX] = _ip;
}
else if (Leases::Lease::mac_to_number(mac,_mac))
{
goto error_mac;
}
oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES (" <<
oid << "," <<
_ip << "," <<
_mac[Lease::PREFIX] << "," <<
_mac[Lease::SUFFIX] << "," <<
vid << "," <<
used << ")";
rc = db->exec(oss);
if ( rc == 0 )
{
leases.insert(make_pair(_ip,new Lease(_ip,_mac,vid,used)));
}
return rc;
error_mac:
oss.str("");
oss << "Error inserting lease, MAC = " << mac;
goto error_common;
error_ip:
oss.str("");
oss << "Error inserting lease, IP = " << ip;
error_common:
Nebula::log("VNM", Log::ERROR, oss);
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int FixedLeases::del(const string& ip)
{
unsigned int _ip;
ostringstream oss;
map<unsigned int, Lease *>::iterator it_ip;
// Remove lease from leases map
if ( Leases::Lease::ip_to_number(ip,_ip) )
{
return 0; //Wrong format, not leased
}
it_ip = leases.find(_ip);
if (it_ip == leases.end())
{
return 0; //Not in the map, not leased
}
// Flip used flag to false
it_ip->second->used = false;
it_ip->second->vid = -1;
oss << "UPDATE " << table << " SET used='0', vid='-1' "
<< " WHERE ip='" << _ip <<"'";
return db->exec(oss);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int FixedLeases::get(int vid, string& ip, string& mac)
{
int rc = -1;
if (leases.empty())
{
return -1;
}
for(unsigned int i=0 ;i<size; i++,current++)
{
if (current == leases.end())
{
current = leases.begin();
}
if (current->second->used == false)
{
ostringstream oss;
oss << "UPDATE " << table << " SET used='1', vid='" << vid
<< "' WHERE ip='" << current->second->ip <<"'";
rc = db->exec(oss);
if ( rc == 0 )
{
current->second->used = true;
current->second->vid = vid;
current->second->to_string(ip,mac);
current++;
}
break;
}
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

407
src/vnm/Leases.cc Normal file
View File

@ -0,0 +1,407 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "Leases.h"
#include "Nebula.h"
/* ************************************************************************** */
/* ************************************************************************** */
/* Lease class */
/* ************************************************************************** */
/* ************************************************************************** */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Leases::Lease::to_string(string &_ip,
string &_mac)
{
mac_to_string(mac, _mac);
ip_to_string(ip, _ip);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Leases::Lease::ip_to_number(const string& _ip, unsigned int& i_ip)
{
istringstream iss;
size_t pos=0;
int count = 0;
unsigned int tmp;
string ip = _ip;
while ( (pos = ip.find('.')) != string::npos )
{
ip.replace(pos,1," ");
count++;
}
if (count != 3)
{
return -1;
}
iss.str(ip);
i_ip = 0;
for (int i=0;i<4;i++)
{
iss >> dec >> tmp >> ws;
i_ip <<= 8;
i_ip += tmp;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Leases::Lease::ip_to_string(const unsigned int i_ip, string& ip)
{
unsigned int temp_byte;
ostringstream oss;
// Convert the IP from unsigned int to string
for (int index=0;index<4;index++)
{
temp_byte = i_ip;
temp_byte >>= (24-index*8);
temp_byte &= 255;
oss << temp_byte;
if(index!=3)
{
oss << ".";
}
}
ip = oss.str();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Leases::Lease::mac_to_number(const string& _mac, unsigned int i_mac[])
{
istringstream iss;
size_t pos=0;
int count = 0;
unsigned int tmp;
string mac = _mac;
while ( (pos = mac.find(':')) != string::npos )
{
mac.replace(pos,1," ");
count++;
}
if (count != 5)
{
return -1;
}
iss.str(mac);
i_mac[PREFIX] = 0;
i_mac[SUFFIX] = 0;
iss >> hex >> i_mac[PREFIX] >> ws >> hex >> tmp >> ws;
i_mac[PREFIX] <<= 8;
i_mac[PREFIX] += tmp;
for (int i=0;i<4;i++)
{
iss >> hex >> tmp >> ws;
i_mac[SUFFIX] <<= 8;
i_mac[SUFFIX] += tmp;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Leases::Lease::mac_to_string(const unsigned int i_mac[], string& mac)
{
ostringstream oss;
unsigned int temp_byte;
oss.str("");
for (int i=5;i>=0;i--)
{
if ( i < 4 )
{
temp_byte = i_mac[SUFFIX];
temp_byte >>= i*8;
}
else
{
temp_byte = i_mac[PREFIX];
temp_byte >>= (i%4)*8;
}
temp_byte &= 255;
oss.width(2);
oss.fill('0');
oss << hex << temp_byte;
if(i!=0)
{
oss << ":";
}
}
mac = oss.str();
}
ostream& operator<<(ostream& os, Leases::Lease& _lease)
{
string ip;
string mac;
_lease.to_string(ip,mac);
ip = "IP = " + ip;
mac = "MAC = " + mac;
os.width(20);
os << left << ip;
os.width(24);
os << left << mac;
os << left << " USED = " << _lease.used;
os << left << " VID = " << _lease.vid;
return os;
}
/* ************************************************************************** */
/* ************************************************************************** */
/* Leases class */
/* ************************************************************************** */
/* ************************************************************************** */
const char * Leases::table = "leases";
const char * Leases::db_names = "(oid,ip,mac_prefix,mac_suffix,vid,used)";
const char * Leases::db_bootstrap = "CREATE TABLE leases ("
"oid INTEGER,ip INTEGER, mac_prefix INTEGER,mac_suffix INTEGER,"
"vid INTEGER, used INTEGER, PRIMARY KEY(oid,ip))";
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Leases::unmarshall(int num, char **names, char ** values)
{
if ( (values[OID] == 0) ||
(values[IP] == 0) ||
(values[MAC_PREFIX] == 0) ||
(values[MAC_SUFFIX] == 0) ||
(values[VID] == 0) ||
(values[USED]== 0) ||
(num != LIMIT ))
{
return -1;
}
unsigned int mac[2];
unsigned int ip;
int vid;
bool used;
istringstream iss;
iss.str(values[IP]);
iss >> ip;
iss.clear();
iss.str(values[MAC_PREFIX]);
iss >> mac[Lease::PREFIX];
iss.clear();
iss.str(values[MAC_SUFFIX]);
iss >> mac[Lease::SUFFIX];
iss.clear();
iss.str(values[VID]);
iss >> vid;
iss.clear();
iss.str(values[USED]);
iss >> used;
leases.insert(make_pair(ip,new Lease(ip,mac,vid,used)));
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
extern "C" int leases_select_cb (
void * _leases,
int num,
char ** values,
char ** names)
{
Leases * leases;
leases = static_cast<Leases *>(_leases);
if (leases == 0)
{
return -1;
}
return leases->unmarshall(num,names,values);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Leases::select(SqliteDB * db)
{
ostringstream oss;
int rc;
oss << "SELECT * FROM " << table << " WHERE oid = " << oid;
rc = db->exec(oss,leases_select_cb,(void *) this);
if (rc != 0)
{
goto error_id;
}
return 0;
error_id:
oss.str("");
oss << "Error getting leases for network nid: " << oid;
Nebula::log("VNM", Log::ERROR, oss);
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Leases::drop(SqliteDB * db)
{
ostringstream oss;
// Drop all the leases
oss << "DELETE FROM " << table << " WHERE oid=" << oid;
return db->exec(oss);
}
int Leases::insert(SqliteDB * db)
{
Nebula::log("VNM", Log::ERROR, "Should not access to Leases.insert()");
return -1;
}
int Leases::update(SqliteDB * db)
{
Nebula::log("VNM", Log::ERROR, "Should not access to Leases.update()");
return -1;
}
/* ************************************************************************** */
/* Leases :: Interface Methods */
/* ************************************************************************** */
bool Leases::check(const string& ip)
{
map<unsigned int,Lease *>::iterator it;
unsigned int _ip;
Leases::Lease::ip_to_number(ip,_ip);
it=leases.find(_ip);
if (it!=leases.end())
{
return it->second->used;
}
else
{
return false;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
bool Leases::check(unsigned int ip)
{
map<unsigned int,Lease *>::iterator it;
it=leases.find(ip);
if (it!=leases.end())
{
return it->second->used;
}
else
{
return false;
}
}
/* ************************************************************************** */
/* Leases :: Misc */
/* ************************************************************************** */
ostream& operator<<(ostream& os, Leases& _leases)
{
map<unsigned int, Leases::Lease *>::iterator it;
os << "NID : " << _leases.oid << endl;
os << "SIZE : " << _leases.size << endl;
os << "Leases:" << endl;
// Iterate all the leases
for(it=_leases.leases.begin();it!=_leases.leases.end();it++)
{
os << *(it->second) << endl;
}
return os;
};

155
src/vnm/RangedLeases.cc Normal file
View File

@ -0,0 +1,155 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RangedLeases.h"
#include "Nebula.h"
#include <cmath>
/* ************************************************************************** */
/* Ranged Leases class */
/* ************************************************************************** */
RangedLeases::RangedLeases(
SqliteDB * db,
int _oid,
unsigned long _size,
unsigned int _mac_prefix,
const string& _network_address):
Leases(db,_oid,_size),mac_prefix(_mac_prefix),current(1)
{
unsigned int net_addr;
Leases::Lease::ip_to_number(_network_address,net_addr);
//size is the number of hosts in the network
size = _size + 2;
network_address = 0xFFFFFFFF << (int) ceil(log(size)/log(2));
network_address &= net_addr;
}
/* ************************************************************************** */
/* Ranged Leases :: Methods */
/* ************************************************************************** */
int RangedLeases::get(int vid, string& ip, string& mac)
{
unsigned int num_ip;
int rc = -1;
for (unsigned int i=0; i<size; i++, current++)
{
num_ip = network_address + (current%(size-2)) + 1;
if (check(num_ip) == false)
{
unsigned int num_mac[2];
num_mac[Lease::PREFIX] = mac_prefix;
num_mac[Lease::SUFFIX] = num_ip;
rc = add(num_ip,num_mac,vid);
if (rc==0)
{
Leases::Lease::ip_to_string(num_ip,ip);
Leases::Lease::mac_to_string(num_mac,mac);
break;
}
}
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int RangedLeases::add(
unsigned int ip,
unsigned int mac[],
int vid,
bool used)
{
ostringstream oss;
int rc;
//Insert the lease in the database
oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES ("<<
oid << "," <<
ip << "," <<
mac[Lease::PREFIX] << "," <<
mac[Lease::SUFFIX] << "," <<
vid << "," <<
used << ")";
rc = db->exec(oss);
if ( rc == 0 )
{
leases.insert(make_pair(ip,new Lease(ip,mac,vid,used)));
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int RangedLeases::del(const string& ip)
{
unsigned int _ip;
ostringstream oss;
int rc;
map<unsigned int, Lease *>::iterator it_ip;
// Remove lease from leases map
if ( Lease::ip_to_number(ip,_ip) )
{
return 0;
}
it_ip = leases.find(_ip);
if (it_ip == leases.end())
{
return 0; //Not in the map, not leased
}
// Erase it from DB
oss << "DELETE FROM " << table << " WHERE oid='" << oid
<< "' AND ip='" << _ip << "'";
rc = db->exec(oss);
if ( rc == 0 )
{
delete it_ip->second;
leases.erase(it_ip);
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

19
src/vnm/SConstruct Normal file
View File

@ -0,0 +1,19 @@
# SConstruct for src/vnm
Import('env')
lib_name='nebula_vnm'
# Sources to generate the library
source_files=[
'Leases.cc',
'FixedLeases.cc',
'RangedLeases.cc',
'VirtualNetwork.cc',
'VirtualNetworkTemplate.cc',
'VirtualNetworkPool.cc',
]
# Build library
env.StaticLibrary(lib_name, source_files)

414
src/vnm/VirtualNetwork.cc Normal file
View File

@ -0,0 +1,414 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "VirtualNetwork.h"
#include "Nebula.h"
#include "RangedLeases.h"
#include "FixedLeases.h"
/* ************************************************************************** */
/* Virtual Network :: Constructor/Destructor */
/* ************************************************************************** */
VirtualNetwork::VirtualNetwork(unsigned int mp, int ds):
PoolObjectSQL(-1),
name(""),
uid(-1),
bridge(""),
type(UNINITIALIZED),
leases(0),
mac_prefix(mp),
default_size(ds)
{
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VirtualNetwork::~VirtualNetwork()
{
if (leases != 0)
{
delete leases;
}
}
/* ************************************************************************** */
/* Virtual Network :: Database Access Functions */
/* ************************************************************************** */
const char * VirtualNetwork::table = "network_pool";
const char * VirtualNetwork::db_names = "(oid,uid,name,type,bridge)";
const char * VirtualNetwork::db_bootstrap = "CREATE TABLE network_pool ("
"oid INTEGER,uid INTEGER, name TEXT PRIMARY KEY,type INTEGER, bridge TEXT)";
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualNetwork::unmarshall(int num, char **names, char ** values)
{
if ((values[OID] == 0) ||
(values[UID] == 0) ||
(values[NAME] == 0) ||
(values[TYPE] == 0) ||
(values[BRIDGE] == 0) ||
(num != LIMIT ))
{
return -1;
}
oid = atoi(values[OID]);
uid = atoi(values[UID]);
name = values[NAME];
type = (NetworkType)atoi(values[TYPE]);
bridge = values[BRIDGE];
// Virtual Network template ID is the Network ID
vn_template.id = oid;
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
extern "C" int vn_select_cb (
void * _vn,
int num,
char ** values,
char ** names)
{
VirtualNetwork * vn;
vn = static_cast<VirtualNetwork *>(_vn);
if (vn == 0)
{
return -1;
}
return vn->unmarshall(num,names,values);
};
/* -------------------------------------------------------------------------- */
int VirtualNetwork::select(SqliteDB * db)
{
ostringstream oss;
ostringstream ose;
int rc;
int boid;
string network_address;
oss << "SELECT * FROM " << table << " WHERE oid = " << oid;
boid = oid;
oid = -1;
rc = db->exec(oss,vn_select_cb,(void *) this);
if ((rc != 0) || (oid != boid ))
{
goto error_id;
}
//Get the template
rc = vn_template.select(db);
if (rc != 0)
{
goto error_template;
}
//Get the leases
if (type == RANGED)
{
string nclass = "";
int size = 0;
// retrieve specific information from template
get_template_attribute("NETWORK_ADDRESS",network_address);
if (network_address.empty())
{
goto error_addr;
}
get_template_attribute("NETWORK_SIZE",nclass);
if ( nclass == "B" )
{
size = 65534;
}
else if ( nclass == "C" )
{
size = 254;
}
else if (!nclass.empty()) //Assume its a number
{
istringstream iss(nclass);
iss >> size;
}
if (size == 0)
{
size = default_size;
}
leases = new RangedLeases::RangedLeases(db,
oid,
size,
mac_prefix,
network_address);
}
else if(type == FIXED)
{
leases = new FixedLeases(db,
oid,
mac_prefix);
}
else
{
goto error_type;
}
if (leases == 0)
{
goto error_leases;
}
return leases->select(db);
error_id:
ose << "Error getting Virtual Network nid: " << oid;
goto error_common;
error_template:
ose << "Can not get template for Virtual Network nid: " << oid;
goto error_common;
error_leases:
ose << "Error getting Virtual Network leases nid: " << oid;
goto error_common;
error_type:
ose << "Wrong type of Virtual Network: " << type;
goto error_common;
error_addr:
ose << "Network address is not defined nid: " << oid;
error_common:
Nebula::log("VNM", Log::ERROR, ose);
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualNetwork::insert(SqliteDB * db)
{
ostringstream ose;
int rc;
if ( vn_template.id == -1 )
{
vn_template.id = oid;
}
// Insert the template first
rc = vn_template.insert(db);
if ( rc != 0 )
{
goto error_template;
}
// Insert the Virtual Network
rc = update(db);
if ( rc != 0 )
{
goto error_update;
}
//Get the leases
if (type == VirtualNetwork::RANGED)
{
string nclass = "";
string naddr = "";
int size = 0;
// retrieve specific information from template
get_template_attribute("NETWORK_ADDRESS",naddr);
if (naddr.empty())
{
goto error_addr;
}
get_template_attribute("NETWORK_SIZE",nclass);
if ( nclass == "B" )
{
size = 65534;
}
else if ( nclass == "C" )
{
size = 254;
}
else if (!nclass.empty())//Assume its a number
{
istringstream iss(nclass);
iss >> size;
}
if (size == 0)
{
size = default_size;
}
leases = new RangedLeases::RangedLeases(db,
oid,
size,
mac_prefix,
naddr);
}
else if(type == VirtualNetwork::FIXED)
{
vector<const Attribute *> vector_leases;
get_template_attribute("LEASES",vector_leases);
leases = new FixedLeases::FixedLeases(db,
oid,
mac_prefix,
vector_leases);
}
else
{
goto error_type;
}
if (leases == 0)
{
goto error_null_leases;
}
return 0;
error_template:
ose << "Can not insert in DB template for Virtual Network id " << oid;
goto error_common;
error_update:
ose << "Can not update Virtual Network id " << oid;
vn_template.drop(db);
goto error_common;
error_type:
ose << "Wrong type of Virtual Network: " << type;
goto error_leases;
error_addr:
ose << "Network address is not defined nid: " << oid;
goto error_leases;
error_null_leases:
ose << "Error getting Virtual Network leases nid: " << oid;
error_leases:
vn_template.drop(db);
vn_drop(db);
error_common:
Nebula::log("VNM", Log::ERROR, ose);
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualNetwork::update(SqliteDB * db)
{
ostringstream oss;
int rc;
oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES ("<<
oid << "," <<
uid << "," <<
"'" << name << "'," <<
type << "," <<
"'" << bridge << "')";
rc = db->exec(oss);
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualNetwork::vn_drop(SqliteDB * db)
{
ostringstream oss;
int rc;
oss << "DELETE FROM " << table << " WHERE OID=" << oid;
rc = db->exec(oss);
return rc;
}
/* ************************************************************************** */
/* Virtual Network :: Misc */
/* ************************************************************************** */
ostream& operator<<(ostream& os, VirtualNetwork& vn)
{
os << "NID : " << vn.oid << endl;
os << "UID : " << vn.uid << endl;
os << "Network Name : " << vn.name << endl;
os << "Type : ";
if ( vn.type==VirtualNetwork::RANGED )
{
os << "Ranged" << endl;
}
else
{
os << "Fixed" << endl;
}
os << "Size : " << vn.get_size() << endl;
os << "Bridge : " << vn.bridge << endl;
os << "Template" << endl << vn.vn_template << endl;
os << "Leases" << endl << *(vn.leases) << endl;
return os;
};

View File

@ -0,0 +1,173 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "Nebula.h"
#include "VirtualNetworkPool.h"
#include <sstream>
VirtualNetworkPool::VirtualNetworkPool(SqliteDB * db,
const string& prefix,
int _default_size):
PoolSQL(db,VirtualNetwork::table),
mac_prefix(0),
default_size(_default_size)
{
istringstream iss;
size_t pos = 0;
int count = 0;
unsigned int tmp;
string mac = prefix;
while ( (pos = mac.find(':')) != string::npos )
{
mac.replace(pos,1," ");
count++;
}
if (count != 1)
{
Nebula::log("VNM",Log::ERROR,"Wrong MAC prefix format, using default");
mac_prefix = 1; //"00:01"
return;
}
iss.str(mac);
iss >> hex >> mac_prefix >> ws >> hex >> tmp >> ws;
mac_prefix <<= 8;
mac_prefix += tmp;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualNetworkPool::allocate (
int uid,
const string& stemplate,
int * oid)
{
VirtualNetwork * vn;
char * error_msg;
int rc;
ostringstream oss;
string name;
string bridge;
string str_type;
// Build a new Virtual Network object
vn = new VirtualNetwork(mac_prefix, default_size);
vn->uid = uid;
rc = vn->vn_template.parse(stemplate,&error_msg);
if ( rc != 0 )
{
oss << error_msg;
Nebula::log("VNM", Log::ERROR, oss);
free(error_msg);
return -1;
}
// Information about the VN needs to be extracted from the template
vn->get_template_attribute("TYPE",str_type);
if ( str_type == "RANGED")
{
vn->type = VirtualNetwork::RANGED;
}
else
{
vn->type = VirtualNetwork::FIXED;
}
vn->get_template_attribute("NAME",name);
vn->name = name;
vn->get_template_attribute("BRIDGE",bridge);
vn->bridge = bridge;
// Insert the VN in the pool so we have a valid OID
*oid = PoolSQL::allocate(vn);
if ( *oid == -1 )
{
return -1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
extern "C"
{
static int select_name_cb(
void * _value,
int num,
char ** values,
char ** names)
{
int * oid;
oid = static_cast<int *>(_value);
if ( oid == 0 || values == 0 || values[0] == 0 )
{
return -1;
}
*oid = atoi(values[0]);
return 0;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
VirtualNetwork * VirtualNetworkPool::get(const string& name, bool lock)
{
ostringstream oss;
int oid;
int rc;
oss << "SELECT oid FROM " << VirtualNetwork::table << " WHERE name = '"
<< name << "'";
rc = db->exec(oss, select_name_cb, (void *) (&oid));
if (rc != 0)
{
return 0;
}
return get(oid,lock);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,24 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2008, Distributed Systems Architecture Group, Universidad */
/* Complutense de Madrid (dsa-research.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "VirtualNetworkTemplate.h"
const char * VirtualNetworkTemplate::table = "vn_template";
const char * VirtualNetworkTemplate::db_bootstrap = "CREATE TABLE vn_template"
" (id INTEGER, name TEXT, type INTEGER, value TEXT)";