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:
parent
d820054ec5
commit
ee411e7963
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
115
include/FixedLeases.h
Normal 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_*/
|
@ -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,
|
||||
|
@ -425,7 +425,7 @@ protected:
|
||||
|
||||
enum ColNames
|
||||
{
|
||||
HID = 0,
|
||||
OID = 0,
|
||||
HOST_NAME = 1,
|
||||
STATE = 2,
|
||||
IM_MAD = 3,
|
||||
|
@ -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
315
include/Leases.h
Normal 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_*/
|
||||
|
@ -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
|
||||
|
@ -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
101
include/RangedLeases.h
Normal 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_*/
|
@ -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;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -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
|
||||
*/
|
||||
|
84
include/TransferManagerDriver.h
Normal file
84
include/TransferManagerDriver.h
Normal 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_*/
|
||||
|
@ -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
349
include/VirtualNetwork.h
Normal 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_*/
|
144
include/VirtualNetworkPool.h
Normal file
144
include/VirtualNetworkPool.h
Normal 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_*/
|
47
include/VirtualNetworkTemplate.h
Normal file
47
include/VirtualNetworkTemplate.h
Normal 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_*/
|
33
install.sh
33
install.sh
@ -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
|
||||
|
@ -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)
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
5
share/examples/private.net
Normal file
5
share/examples/private.net
Normal file
@ -0,0 +1,5 @@
|
||||
NAME = "Private LAN"
|
||||
TYPE = RANGED
|
||||
BRIDGE = eth0
|
||||
NETWORK_SIZE = 250
|
||||
NETWORK_ADDRESS= 10.0.0.0
|
9
share/examples/public.net
Normal file
9
share/examples/public.net
Normal 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]
|
@ -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
|
||||
#---------------------------------------
|
||||
|
@ -30,6 +30,9 @@ DISK = [
|
||||
|
||||
NIC = [ mac="00:ff:72:17:20:27"]
|
||||
|
||||
NIC = [ NETWORK="Private LAN"]
|
||||
|
||||
|
||||
# --- VNC server ---
|
||||
|
||||
GRAPHICS = [
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
225
src/client/ruby/onenetwork
Executable 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
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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] != ?/
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
116
src/mad/ruby/ThreadScheduler.rb
Normal file
116
src/mad/ruby/ThreadScheduler.rb
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
83
src/rm/RequestManagerVirtualNetworkAllocate.cc
Normal file
83
src/rm/RequestManagerVirtualNetworkAllocate.cc
Normal 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;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
85
src/rm/RequestManagerVirtualNetworkDelete.cc
Normal file
85
src/rm/RequestManagerVirtualNetworkDelete.cc
Normal 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;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
89
src/rm/RequestManagerVirtualNetworkInfo.cc
Normal file
89
src/rm/RequestManagerVirtualNetworkInfo.cc
Normal 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;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
@ -15,7 +15,10 @@ source_files=[
|
||||
'RequestManagerHostAllocate.cc',
|
||||
'RequestManagerHostDelete.cc',
|
||||
'RequestManagerHostInfo.cc',
|
||||
'RequestManagerHostEnable.cc',
|
||||
'RequestManagerHostEnable.cc',
|
||||
'RequestManagerVirtualNetworkAllocate.cc',
|
||||
'RequestManagerVirtualNetworkInfo.cc',
|
||||
'RequestManagerVirtualNetworkDelete.cc',
|
||||
]
|
||||
|
||||
# Build library
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ lib_name='nebula_tm'
|
||||
|
||||
# Sources to generate the library
|
||||
source_files=[
|
||||
'TransferManager.cc'
|
||||
'TransferManager.cc',
|
||||
'TransferManagerDriver.cc'
|
||||
]
|
||||
|
||||
# Build library
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
222
src/tm/TransferManagerDriver.cc
Normal file
222
src/tm/TransferManagerDriver.cc
Normal 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
237
src/tm_mad/TMScript.rb
Normal 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
33
src/tm_mad/nfs/tm_clone.sh
Executable 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
11
src/tm_mad/nfs/tm_delete.sh
Executable 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
12
src/tm_mad/nfs/tm_ln.sh
Executable 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
5
src/tm_mad/nfs/tm_mkimage.sh
Executable 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
17
src/tm_mad/nfs/tm_mkswap.sh
Executable 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
23
src/tm_mad/nfs/tm_mv.sh
Executable 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
|
||||
|
6
src/tm_mad/nfs/tm_nfs.conf
Normal file
6
src/tm_mad/nfs/tm_nfs.conf
Normal 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
16
src/tm_mad/nfs/tm_nfsrc
Normal 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
25
src/tm_mad/one_tm
Executable 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
84
src/tm_mad/one_tm.rb
Executable 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
36
src/tm_mad/ssh/tm_clone.sh
Executable 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
12
src/tm_mad/ssh/tm_delete.sh
Executable 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
11
src/tm_mad/ssh/tm_ln.sh
Executable 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
5
src/tm_mad/ssh/tm_mkimage.sh
Executable 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
21
src/tm_mad/ssh/tm_mkswap.sh
Executable 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
19
src/tm_mad/ssh/tm_mv.sh
Executable 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
6
src/tm_mad/ssh/tm_ssh.conf
Executable 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
16
src/tm_mad/ssh/tm_sshrc
Normal 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
96
src/tm_mad/tm_common.sh
Normal 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
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)";
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
188
src/vnm/FixedLeases.cc
Normal 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
407
src/vnm/Leases.cc
Normal 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
155
src/vnm/RangedLeases.cc
Normal 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
19
src/vnm/SConstruct
Normal 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
414
src/vnm/VirtualNetwork.cc
Normal 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;
|
||||
};
|
173
src/vnm/VirtualNetworkPool.cc
Normal file
173
src/vnm/VirtualNetworkPool.cc
Normal 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);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
24
src/vnm/VirtualNetworkTemplate.cc
Normal file
24
src/vnm/VirtualNetworkTemplate.cc
Normal 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)";
|
||||
|
Loading…
Reference in New Issue
Block a user