1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-27 03:21:29 +03:00

Merge branch 'feature-200'

This commit is contained in:
Ruben S. Montero 2010-07-08 00:56:25 +02:00
commit 0139994dcf
57 changed files with 6100 additions and 454 deletions

View File

@ -52,6 +52,7 @@ main_env.Append(LIBPATH=[
cwd+'/src/tm',
cwd+'/src/dm',
cwd+'/src/im',
cwd+'/src/image',
cwd+'/src/rm',
cwd+'/src/vnm',
cwd+'/src/hm',
@ -154,6 +155,7 @@ build_scripts=[
'src/rm/SConstruct',
'src/tm/SConstruct',
'src/im/SConstruct',
'src/image/SConstruct',
'src/dm/SConstruct',
'src/scheduler/SConstruct',
'src/vnm/SConstruct',

453
include/Image.h Normal file
View File

@ -0,0 +1,453 @@
/* ------------------------------------------------------------------------ */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------*/
#ifndef IMAGE_H_
#define IMAGE_H_
#include "PoolSQL.h"
#include "ImageTemplate.h"
#include "NebulaLog.h"
using namespace std;
/**
* The Image class.
*/
class Image : public PoolObjectSQL
{
public:
/**
* Type of Images
*/
enum ImageType
{
OS = 0, /** < Base OS image */
CDROM = 1, /** < An ISO9660 image */
DATABLOCK = 2 /** < User persistent data device */
};
/**
* Image State
*/
enum ImageState
{
INIT = 0, /** < Initialization state */
LOCKED = 1, /** < FS operation on the image in progress, don't use */
READY = 2, /** < Image ready to use */
USED = 3, /** < Image in use */
DISABLED = 4 /** < Image can not be instantiated by a VM */
};
/**
* Function to write an Image on an output stream
*/
friend ostream& operator<<(ostream& os, Image& i);
// *************************************************************************
// Image Public Methods
// *************************************************************************
/**
* Function to print the Image object into a string in plain text
* @param str the resulting string
* @return a reference to the generated string
*/
string& to_str(string& str) const;
/**
* Function to print the Image object into a string in XML format
* @param xml the resulting XML string
* @return a reference to the generated string
*/
string& to_xml(string& xml) const;
/**
* Get the Image unique identifier IID, that matches the OID of the object
* @return IID Image identifier
*/
int get_iid() const
{
return oid;
};
/**
* Gets the uid of the owner of the Image
* @return uid
**/
int get_uid()
{
return uid;
}
/**
* Returns Image's name
* @return name Image's name
*/
const string& get_name() const
{
return name;
};
/**
* Returns true if the image is public
* @return true if the image is public
*/
bool is_public()
{
return (public_img == 1);
};
/**
* Set enum type
* @return 0 on success, -1 otherwise
*/
int set_type(const string& _type)
{
int rc = 0;
if ( _type == "OS" )
{
type = OS;
}
else if ( _type == "CDROM" )
{
type = CDROM;
}
else if ( _type == "DATABLOCK" )
{
type = DATABLOCK;
}
else
{
rc = -1;
}
return rc;
}
/**
* Get an image to be used in a VM, and updates its state.
* @param overwrite true if the image is going to be overwritten
* @return 0 if success
*/
int acquire_image(bool overwrite);
/**
* Releases an image being used by a VM
*/
void release_image();
/**
* Enables the image
* @param to_enable true will enable the image.
* @return 0 on success
*/
int enable(bool to_enable)
{
int rc = 0;
if ((to_enable == true) && (state == DISABLED))
{
state = READY;
}
else if ((to_enable == false) && (state == READY))
{
state = DISABLED;
}
else
{
rc = -1;
}
return rc;
}
/**
* Publish or unpublish an image
* @param pub true to publish the image
* @return 0 on success
*/
void publish(bool pub)
{
if (pub == true)
{
public_img = 1;
}
else
{
public_img = 0;
}
}
/**
* Modifies the given disk attribute adding the following attributes:
* * SOURCE: the file-path.
* * BUS: will only be set if the Image's definition includes it.
* * TARGET: the value set depends on:
* - OS images will be mounted at prefix + a: hda, sda.
* - Prefix + b is reserved for the contex cdrom.
* - CDROM images will be at prefix + c: hdc, sdc.
* - Several DATABLOCK images can be mounted, they will be set to
* prefix + (d + index) : hdd, hde, hdf...
* @param disk attribute for the VM template
*/
int disk_attribute(VectorAttribute * disk, int * index);
// ------------------------------------------------------------------------
// 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 image_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 image_template.get(str,values);
};
/**
* Gets a string based Image 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;
image_template.get(str,value);
}
/**
* Gets a string based Image 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;
image_template.get(str,value);
}
/**
* Removes an Image attribute
* @param name of the attribute
*/
int remove_template_attribute(SqlDB * db, const string& name)
{
return image_template.remove_attribute(db, name);
}
private:
// -------------------------------------------------------------------------
// Friends
// -------------------------------------------------------------------------
friend class ImagePool;
// -------------------------------------------------------------------------
// Image Description
// -------------------------------------------------------------------------
/**
* Owner if the image
*/
int uid;
/**
* The name of the Image
*/
string name;
/**
* Type of the Image
*/
ImageType type;
/**
* Public scope of the Image
*/
int public_img;
/**
* Registration time
*/
time_t regtime;
/**
* Path to the image
*/
string source;
/**
* Image state
*/
ImageState state;
/**
* Number of VMs using the image
*/
int running_vms;
// -------------------------------------------------------------------------
// Image Attributes
// -------------------------------------------------------------------------
/**
* The Image template, holds the Image attributes.
*/
ImageTemplate image_template;
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************
/**
* Execute an INSERT or REPLACE Sql query.
* @param db The SQL DB
* @param replace Execute an INSERT or a REPLACE
* @return 0 on success
*/
int insert_replace(SqlDB *db, bool replace);
/**
* Callback function to unmarshall a Image object (Image::select)
* @param num the number of columns read from the DB
* @param names the column names
* @param values the column values
* @return 0 on success
*/
int select_cb(void *nil, int num, char **values, char **names);
/**
* Bootstraps the database table(s) associated to the Image
*/
static void bootstrap(SqlDB * db)
{
ostringstream oss_image(Image::db_bootstrap);
ostringstream oss_templ(ImageTemplate::db_bootstrap);
db->exec(oss_image);
db->exec(oss_templ);
};
/**
* "Encrypts" the password with SHA1 digest
* @param password
* @return sha1 encrypted password
*/
string sha1_digest(const string& pass);
protected:
// *************************************************************************
// Constructor
// *************************************************************************
Image(int id=-1);
virtual ~Image();
// *************************************************************************
// DataBase implementation
// *************************************************************************
enum ColNames
{
OID = 0, /* Image identifier (IID) */
UID = 1, /* Image owner id */
NAME = 2, /* Image name */
TYPE = 3, /* 0) OS 1) CDROM 2) DATABLOCK */
PUBLIC = 4, /* Public scope (YES OR NO) */
REGTIME = 5, /* Time of registration */
SOURCE = 6, /* Path to the image */
STATE = 7, /* 0) INIT 1) ALLOCATED */
/* 2) READY 3) USED */
RUNNING_VMS = 8, /* Number of VMs using the img */
LIMIT = 9
};
static const char * db_names;
static const char * db_bootstrap;
static const char * table;
/**
* Reads the Image (identified with its OID=IID) from the database.
* @param db pointer to the db
* @return 0 on success
*/
virtual int select(SqlDB *db);
/**
* Writes the Image in the database.
* @param db pointer to the db
* @return 0 on success
*/
virtual int insert(SqlDB *db);
/**
* Writes/updates the Images data fields in the database.
* @param db pointer to the db
* @return 0 on success
*/
virtual int update(SqlDB *db);
/**
* Drops Image and associated template from the database
* @param db pointer to the db
* @return 0 on success
*/
virtual int drop(SqlDB *db);
/**
* Function to output an Image object in to an stream in XML format
* @param oss the output stream
* @param num the number of columns read from the DB
* @param names the column names
* @param vaues the column values
* @return 0 on success
*/
static int dump(ostringstream& oss, int num, char **values, char **names);
};
#endif /*IMAGE_H_*/

269
include/ImagePool.h Normal file
View File

@ -0,0 +1,269 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef IMAGE_POOL_H_
#define IMAGE_POOL_H_
#include "PoolSQL.h"
#include "Image.h"
#include "NebulaLog.h"
#include <time.h>
#include <sstream>
#include <iostream>
#include <vector>
using namespace std;
/**
* The Image Pool class.
*/
class ImagePool : public PoolSQL
{
public:
ImagePool(SqlDB * db,
const string& _source_prefix,
const string& _default_type,
const string& _default_dev_prefix);
~ImagePool(){};
/**
* Function to allocate a new Image object
* @param uid the user id of the image's owner
* @param stemplate template associated with the image
* @param oid the id assigned to the Image
* @return the oid assigned to the object,
* -1 in case of failure
* -2 in case of template parse failure
*/
int allocate (
int uid,
const string& stemplate,
int * oid);
/**
* Function to get a Image from the pool, if the object is not in memory
* it is loaded from the DB
* @param oid Image unique id
* @param lock locks the Image mutex
* @return a pointer to the Image, 0 if the Image could not be loaded
*/
Image * get(
int oid,
bool lock)
{
return static_cast<Image *>(PoolSQL::get(oid,lock));
};
/**
* Function to get an Image from the pool using the image name
* @param name of the image
* @param lock locks the User mutex
* @return a pointer to the Image, 0 if the User could not be loaded
*/
Image * get(
const string& name,
bool lock)
{
map<string, int>::iterator index;
index = image_names.find(name);
if ( index != image_names.end() )
{
return get((int)index->second,lock);
}
return 0;
}
/** Update a particular Image
* @param image pointer to Image
* @return 0 on success
*/
int update(Image * image)
{
return image->update(db);
};
/** Drops an image from the DB, the image mutex MUST BE locked
* @param image pointer to Image
* @return 0 on success
*/
int drop(Image * image)
{
int rc = PoolSQL::drop(image);
if ( rc == 0)
{
image_names.erase(image->get_name());
}
return rc;
};
/** Modify an image attribute in the template (Image MUST be locked)
* @param image pointer to Image
* @param name of the attribute to be changed
* @param new value for the attribute
* @return 0 on success, -1 otherwise
*/
int replace_attribute(
Image * image,
const string& name,
const string& value)
{
SingleAttribute * sattr = new SingleAttribute(name,value);
return image->image_template.replace_attribute(db,sattr);
}
/** Delete an image attribute in the template (Image MUST be locked)
* @param image pointer to Image
* @param name of the attribute to be removed
* @return 0 on success, -1 otherwise
*/
int remove_attribute(
Image * image,
const string& name)
{
return image->image_template.remove_attribute(db, name);
}
/**
* Bootstraps the database table(s) associated to the Image pool
*/
static void bootstrap(SqlDB *_db)
{
Image::bootstrap(_db);
};
/**
* Dumps the Image pool in XML format. A filter can be also added to the
* query
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where);
/**
* Generates a DISK attribute for VM templates using the Image metadata
* @param disk the disk to be generated
* @return 0 on success, -1 error, -2 not using the pool
*/
int disk_attribute(VectorAttribute * disk, int * index)
{
string source;
Image * img;
source = disk->vector_value("NAME");
if (source.empty())
{
return -2;
}
img = get(source,true);
if (img == 0)
{
return -1;
}
int rc = img->disk_attribute(disk,index);
img->unlock();
return rc;
}
static const string& source_prefix()
{
return _source_prefix;
};
static const string& default_type()
{
return _default_type;
};
static const string& default_dev_prefix()
{
return _default_dev_prefix;
};
private:
//--------------------------------------------------------------------------
// Configuration Attributes for Images
// -------------------------------------------------------------------------
/**
* Path to the image repository
**/
static string _source_prefix;
/**
* Default image type
**/
static string _default_type;
/**
* Default device prefix
**/
static string _default_dev_prefix;
//--------------------------------------------------------------------------
// Pool Attributes
// -------------------------------------------------------------------------
/**
* This map stores the association between IIDs and Image names
*/
map<string, int> image_names;
/**
* Factory method to produce Image objects
* @return a pointer to the new Image
*/
PoolObjectSQL * create()
{
return new Image;
};
/**
* Callback function to get output the image pool in XML format
* (Image::dump)
* @param num the number of columns read from the DB
* @param names the column names
* @param vaues the column values
* @return 0 on success
*/
int dump_cb(void * _oss, int num, char **values, char **names);
/**
* Callback function to build the image_names map
* @param num the number of columns read from the DB
* @param names the column names
* @param vaues the column values
* @return 0 on success
*/
int init_cb(void *nil, int num, char **values, char **names);
};
#endif /*IMAGE_POOL_H_*/

48
include/ImageTemplate.h Normal file
View File

@ -0,0 +1,48 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef IMAGE_TEMPLATE_H_
#define IMAGE_TEMPLATE_H_
#include "TemplateSQL.h"
using namespace std;
/**
* Image Template class, it represents the attributes of a Host
*/
class ImageTemplate : public TemplateSQL
{
public:
ImageTemplate(int tid = -1,
const char separator = '='):
TemplateSQL(table,tid,true,separator,"TEMPLATE"){};
~ImageTemplate(){};
private:
friend class Image;
friend class ImagePool;
static const char * table;
static const char * db_bootstrap;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#endif /*IMAGE_TEMPLATE_H_*/

View File

@ -69,6 +69,11 @@ public:
return upool;
};
ImagePool * get_ipool()
{
return ipool;
};
// --------------------------------------------------------------
// Manager Accessors
// --------------------------------------------------------------
@ -212,32 +217,32 @@ private:
// -----------------------------------------------------------------------
Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0),upool(0),
lcm(0),vmm(0),im(0),tm(0),dm(0),rm(0)
ipool(0),lcm(0),vmm(0),im(0),tm(0),dm(0),rm(0)
{
const char * nl = getenv("ONE_LOCATION");
const char * nl = getenv("ONE_LOCATION");
if (nl == 0) //OpenNebula installed under root directory
{
nebula_location = "/";
nebula_location = "/";
mad_location = "/usr/lib/one/mads/";
etc_location = "/etc/one/";
log_location = "/var/log/one/";
var_location = "/var/lib/one/";
mad_location = "/usr/lib/one/mads/";
etc_location = "/etc/one/";
log_location = "/var/log/one/";
var_location = "/var/lib/one/";
}
else
{
nebula_location = nl;
nebula_location = nl;
if ( nebula_location.at(nebula_location.size()-1) != '/' )
{
nebula_location += "/";
}
if ( nebula_location.at(nebula_location.size()-1) != '/' )
{
nebula_location += "/";
}
mad_location = nebula_location + "lib/mads/";
etc_location = nebula_location + "etc/";
log_location = nebula_location + "var/";
var_location = nebula_location + "var/";
mad_location = nebula_location + "lib/mads/";
etc_location = nebula_location + "etc/";
log_location = nebula_location + "var/";
var_location = nebula_location + "var/";
}
};
@ -263,6 +268,11 @@ private:
delete upool;
}
if ( ipool != 0)
{
delete ipool;
}
if ( vmm != 0)
{
delete vmm;
@ -340,6 +350,7 @@ private:
HostPool * hpool;
VirtualNetworkPool * vnpool;
UserPool * upool;
ImagePool * ipool;
// ---------------------------------------------------------------
// Nebula Managers

View File

@ -22,6 +22,7 @@
#include "HostPool.h"
#include "UserPool.h"
#include "VirtualNetworkPool.h"
#include "ImagePool.h"
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
@ -42,10 +43,11 @@ public:
HostPool * _hpool,
VirtualNetworkPool * _vnpool,
UserPool * _upool,
ImagePool * _ipool,
int _port,
string _xml_log_file)
:vmpool(_vmpool),hpool(_hpool),vnpool(_vnpool),upool(_upool),
port(_port),socket_fd(-1),xml_log_file(_xml_log_file)
ipool(_ipool),port(_port),socket_fd(-1),xml_log_file(_xml_log_file)
{
am.addListener(this);
};
@ -118,6 +120,11 @@ private:
* Pointer to the User Pool, to access users
*/
UserPool * upool;
/**
* Pointer to the Image Pool, to access images
*/
ImagePool * ipool;
/**
* Port number where the connection will be open
@ -536,6 +543,32 @@ private:
VirtualNetworkPool * vnpool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class VirtualNetworkPublish: public xmlrpc_c::method
{
public:
VirtualNetworkPublish(
VirtualNetworkPool * _vnpool,
UserPool * _upool):
vnpool(_vnpool),
upool(_upool)
{
_signature="A:sib";
_help="Enables/Disables a virtual network";
};
~VirtualNetworkPublish(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
VirtualNetworkPool * vnpool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
@ -639,7 +672,7 @@ private:
UserPoolInfo(UserPool * _upool):upool(_upool)
{
_signature="A:s";
_help="Creates a new user";
_help="Returns content of the user pool";
};
~UserPoolInfo(){};
@ -651,8 +684,212 @@ private:
private:
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
/* Image Pool Interface */
/* ---------------------------------------------------------------------- */
class ImageAllocate: public xmlrpc_c::method
{
public:
ImageAllocate(ImagePool * _ipool,
UserPool * _upool):
ipool(_ipool),
upool(_upool)
{
_signature="A:ss";
_help="Creates a new image";
};
~ImageAllocate(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
ImagePool * ipool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class ImageDelete: public xmlrpc_c::method
{
public:
ImageDelete(ImagePool * _ipool,
UserPool * _upool):
ipool(_ipool),
upool(_upool)
{
_signature="A:si";
_help="Deletes an image";
};
~ImageDelete(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
ImagePool * ipool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class ImageInfo: public xmlrpc_c::method
{
public:
ImageInfo(ImagePool * _ipool,
UserPool * _upool):
ipool(_ipool),
upool(_upool)
{
_signature="A:si";
_help="Returns information for an image";
};
~ImageInfo(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
ImagePool * ipool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class ImageUpdate: public xmlrpc_c::method
{
public:
ImageUpdate(ImagePool * _ipool,
UserPool * _upool):
ipool(_ipool),
upool(_upool)
{
_signature="A:siss";
_help="Modifies image attribute";
};
~ImageUpdate(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
ImagePool * ipool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class ImageRemoveAttribute: public xmlrpc_c::method
{
public:
ImageRemoveAttribute(ImagePool * _ipool,
UserPool * _upool):
ipool(_ipool),
upool(_upool)
{
_signature="A:sis";
_help="Removes image attribute";
};
~ImageRemoveAttribute(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
ImagePool * ipool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class ImagePublish: public xmlrpc_c::method
{
public:
ImagePublish(ImagePool * _ipool,
UserPool * _upool):
ipool(_ipool),
upool(_upool)
{
_signature="A:sib";
_help="Publish/Unpublish the Image";
};
~ImagePublish(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
ImagePool * ipool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class ImageEnable: public xmlrpc_c::method
{
public:
ImageEnable(ImagePool * _ipool,
UserPool * _upool):
ipool(_ipool),
upool(_upool)
{
_signature="A:sib";
_help="Enables/Disables the Image";
};
~ImageEnable(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
ImagePool * ipool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class ImagePoolInfo: public xmlrpc_c::method
{
public:
ImagePoolInfo(ImagePool * _ipool,
UserPool * _upool):
ipool(_ipool),
upool(_upool)
{
_signature="A:si";
_help="Returns content of image pool attending to the filter flag";
};
~ImagePoolInfo(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
ImagePool * ipool;
UserPool * upool;
};
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -117,6 +117,14 @@ public:
const string& name,
vector<Attribute *>& values);
/**
* Removes an attribute from the template, and frees the attributes.
* @param name of the attribute
* @returns the number of attributes removed
*/
virtual int erase(const string& name);
/**
* Gets all the attributes with the given name.
* @param name the attribute name.

View File

@ -85,18 +85,18 @@ protected:
* @param db pointer to the database.
*/
int drop(SqlDB *db);
/**
* Execute an INSERT or REPLACE Sql query.
* Execute an INSERT or REPLACE Sql query.
* @param db The SQL DB
* @param replace Execute an INSERT or a REPLACE
* @param replace Execute an INSERT or a REPLACE
* @return 0 one success
*/
*/
int insert_replace(SqlDB *db, bool replace);
/**
* Removes a template attribute from the DB. If there are multiple
* attributes with the same name, only one will be replaced. The
* attributes with the same name, only one will be replaced. The
* attribute MUST be allocated in the heap.
* @param db pointer to the database.
* @param attribute pointer to the new attribute.
@ -112,9 +112,11 @@ protected:
int insert_attribute(SqlDB * db, Attribute * attribute);
/**
* Callback to set the template id (TemplateSQL::insert)
* Remove a given attribute from the template and the DB.
* @param db pointer to the database.
* @param name name of the attribute
*/
int insert_cb(void *nil, int num, char **values, char **names);
int remove_attribute(SqlDB * db, const string& name);
/**
* Callback to recover template attributes (TemplateSQL::select)
@ -125,4 +127,4 @@ protected:
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#endif /*TEMPLATE_SQL_H_*/
#endif /*TEMPLATE_SQL_H_*/

View File

@ -21,6 +21,7 @@
#include "PoolSQL.h"
#include "History.h"
#include "Log.h"
#include "NebulaLog.h"
#include <time.h>
#include <sstream>
@ -695,7 +696,7 @@ public:
void get_requirements (int& cpu, int& memory, int& disk);
// ------------------------------------------------------------------------
// Network Leases
// Network Leases & Disk Images
// ------------------------------------------------------------------------
/**
* Get all network leases for this Virtual Machine
@ -708,6 +709,17 @@ public:
*/
void release_network_leases();
/**
* Get all disk images for this Virtual Machine
* @return 0 if success
*/
int get_disk_images();
/**
* Releases all disk images taken by this Virtual Machine
*/
void release_disk_images();
// ------------------------------------------------------------------------
// Context related functions
// ------------------------------------------------------------------------
@ -989,18 +1001,17 @@ protected:
UID = 1,
NAME = 2,
LAST_POLL = 3,
TEMPLATE_ID = 4,
STATE = 5,
LCM_STATE = 6,
STIME = 7,
ETIME = 8,
DEPLOY_ID = 9,
MEMORY = 10,
CPU = 11,
NET_TX = 12,
NET_RX = 13,
LAST_SEQ = 14,
LIMIT = 15
STATE = 4,
LCM_STATE = 5,
STIME = 6,
ETIME = 7,
DEPLOY_ID = 8,
MEMORY = 9,
CPU = 10,
NET_TX = 11,
NET_RX = 12,
LAST_SEQ = 13,
LIMIT = 14
};
static const char * table;
@ -1031,24 +1042,14 @@ protected:
virtual int update(SqlDB * db);
/**
* Deletes a VM from the database and all its associated information:
* - History records
* - VM template
* Deletes a VM from the database and all its associated information
* @param db pointer to the db
* @return 0 on success
* @return -1
*/
virtual int drop(SqlDB * db)
{
int rc;
rc = vm_template.drop(db);
if ( history != 0 )
{
rc += history->drop(db);
}
return rc;
NebulaLog::log("ONE",Log::ERROR, "VM Drop not implemented!");
return -1;
}
/**

View File

@ -67,6 +67,32 @@ public:
return uid;
}
/**
* Returns true if the Virtual Network is public
* @return true if the Virtual Network is public
*/
bool is_public()
{
return (public_vnet == 1);
};
/**
* Publish or unpublish a virtual network
* @param pub true to publish the image
* @return 0 on success
*/
void publish(bool pub)
{
if (pub == true)
{
public_vnet = 1;
}
else
{
public_vnet = 0;
}
}
/**
* Gets a new lease for a specific VM
* @param vid VM identifier
@ -135,6 +161,17 @@ public:
*/
string& to_xml(string& xml) const;
/**
* Modifies the given nic attribute adding the following attributes:
* * IP: leased from network
* * MAC: leased from network
* * BRIDGE: for this virtual network
* @param nic attribute for the VM template
* @param vid of the VM getting the lease
* @return 0 on success
*/
int nic_attribute(VectorAttribute * nic, int vid);
//------------------------------------------------------------------------
// Template
// ------------------------------------------------------------------------
@ -233,6 +270,11 @@ private:
*/
NetworkType type;
/**
* Public scope of this Virtual Network
*/
int public_vnet;
/**
* Pointer to leases class, can be fixed or ranged.
* Holds information on given (and, optionally, possible) leases
@ -244,20 +286,6 @@ private:
*/
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)
// *************************************************************************
@ -334,7 +362,7 @@ protected:
// Constructor
//**************************************************************************
VirtualNetwork(unsigned int _mac_prefix, int _default_size);
VirtualNetwork();
~VirtualNetwork();
@ -349,7 +377,8 @@ protected:
NAME = 2,
TYPE = 3,
BRIDGE = 4,
LIMIT = 5
PUBLIC = 5,
LIMIT = 6
};
static const char * table;

View File

@ -80,6 +80,39 @@ public:
// Virtual Network DB access functions
//--------------------------------------------------------------------------
/**
* Generates a NIC attribute for VM templates using the VirtualNetwork
* metadata
* @param nic the nic attribute to be generated
* @param vid of the VM requesting the lease
* @return 0 on success, -1 error, -2 not using the pool
*/
int nic_attribute(VectorAttribute * nic, int vid)
{
string network;
VirtualNetwork * vnet;
network = nic->vector_value("NETWORK");
if (network.empty())
{
return -2;
}
vnet = get(network,true);
if (vnet == 0)
{
return -1;
}
int rc = vnet->nic_attribute(nic,vid);
vnet->unlock();
return rc;
}
/**
* Updates the template of a VN, adding a new attribute (replacing it if
* already defined), the VN's mutex SHOULD be locked
@ -114,16 +147,34 @@ public:
*/
int dump(ostringstream& oss, const string& where);
/**
* Get the mac prefix
* @return the mac prefix
*/
static const unsigned int& mac_prefix()
{
return _mac_prefix;
};
/**
* Get the default network size
* @return the size
*/
static const unsigned int& default_size()
{
return _default_size;
};
private:
/**
* Holds the system-wide MAC prefix
*/
unsigned int mac_prefix;
static unsigned int _mac_prefix;
/**
* Default size for Virtual Networks
*/
unsigned int default_size;
static unsigned int _default_size;
/**
* Factory method to produce VN objects
@ -131,7 +182,7 @@ private:
*/
PoolObjectSQL * create()
{
return new VirtualNetwork(mac_prefix, default_size);
return new VirtualNetwork();
};
/**
@ -155,4 +206,4 @@ private:
int get_cb(void * _oss, int num, char **values, char **names);
};
#endif /*VIRTUAL_NETWORK_POOL_H_*/
#endif /*VIRTUAL_NETWORK_POOL_H_*/

View File

@ -255,6 +255,7 @@ BIN_FILES="src/nebula/oned \
src/cli/onehost \
src/cli/onevnet \
src/cli/oneuser \
src/cli/oneimage \
share/scripts/one"
#-------------------------------------------------------------------------------
@ -291,6 +292,8 @@ RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/OpenNebula/Host.rb \
src/oca/ruby/OpenNebula/VirtualMachinePool.rb \
src/oca/ruby/OpenNebula/VirtualNetwork.rb \
src/oca/ruby/OpenNebula/VirtualNetworkPool.rb \
src/oca/ruby/OpenNebula/Image.rb \
src/oca/ruby/OpenNebula/ImagePool.rb \
src/oca/ruby/OpenNebula/XMLUtils.rb"
#-------------------------------------------------------------------------------
# Driver executable files, to be installed under $LIB_LOCATION/mads
@ -611,13 +614,6 @@ if [ "$UNINSTALL" = "no" ] ; then
for d in $CHOWN_DIRS; do
chown -R $ONEADMIN_USER:$ONEADMIN_GROUP $DESTDIR$d
done
# Create library links
if [ "$CLIENT" = "no" ] ; then
ln -s $DESTDIR$LIB_LOCATION/liboneapi.so \
$DESTDIR$LIB_LOCATION/liboneapi.so.1
ln -s $DESTDIR$LIB_LOCATION/liboneapi.so.1 \
$DESTDIR$LIB_LOCATION/liboneapi.so.1.4
fi
else
for d in `echo $DELETE_DIRS | awk '{for (i=NF;i>=1;i--) printf $i" "}'`; do
rmdir $d

View File

@ -64,6 +64,28 @@ NETWORK_SIZE = 254
MAC_PREFIX = "02:00"
#*******************************************************************************
# Image Repository Configuration
#*******************************************************************************
# IMAGE_REPOSITORY_PATH: Define the path to the image repository, by default
# is set to $ONE_LOCATION/var
#
# DEFAULT_IMAGE_TYPE: This can take values
# OS Image file holding an operating system
# CDROM Image file holding a CDROM
# DATABLOCK Image file holding a datablock,
# always created as an empty block
# DEFAULT_DEVICE_PREFIX: This can be set to
# hd IDE prefix
# sd SCSI
# xvd XEN Virtual Disk
# vd KVM virtual disk
#*******************************************************************************
#IMAGE_REPOSITORY_PATH =
DEFAULT_IMAGE_TYPE = "OS"
DEFAULT_DEVICE_PREFIX = "hd"
#*******************************************************************************
# Information Driver Configuration
#*******************************************************************************
@ -236,6 +258,28 @@ TM_MAD = [
HM_MAD = [
executable = "one_hm" ]
#-------------------------------- Image Hook -----------------------------------
# This hook is used to handle image saving and overwriting when virtual machines
# reach the DONE state after being shutdown.
#
# Uncomment one of the following:
#
# Self-contained (substitute [ONE_LOCATION] with its proper path)
# VM_HOOK = [
# name = "image",
# on = "SHUTDOWN",
# command = "[ONE_LOCATION]/share/hooks/image.rb",
# arguments = "$VMID" ]
#
# System-wide
# VM_HOOK = [
# name = "image",
# on = "SHUTDOWN",
# command = "/usr/share/doc/opennebula/hooks/image.rb",
# arguments = "$VMID" ]
#-------------------------------------------------------------------------------
#-------------------------------- Hook Examples --------------------------------
#VM_HOOK = [

82
share/hooks/image.rb Executable file
View File

@ -0,0 +1,82 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
VMDIR="/var/lib/one"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
VMDIR=ONE_LOCATION+"/var"
end
$: << RUBY_LIB_LOCATION
require 'OpenNebula'
require 'client_utilities'
require 'ftools'
TYPES=%w{OS CDROM DATABLOCK}
if !(vm_id=ARGV[0])
exit -1
end
vm=OpenNebula::VirtualMachine.new_with_id(vm_id, get_one_client)
vm.info
template=vm.to_hash
template=template['VM']['TEMPLATE']
disks=[template['DISK']].flatten if template['DISK']
disks.each_with_index do |disk,i|
source_path=VMDIR+"/#{vm_id}/disk.#{i}"
if disk["NAME"] and File.exists?(source_path)
if disk["SAVE_AS"]
# Get Type
image=OpenNebula::Image.new_with_id(disk['IID'], get_one_client)
image.info
type=image['TYPE']
# Perform the allocate if all goes well
image=OpenNebula::Image.new(
OpenNebula::Image.build_xml, get_one_client)
template="NAME=#{disk['SAVE_AS']}\n"
template+="TYPE=#{TYPES[type.to_i]}\n" if type
result=image.allocate(template)
# Get the allocated image
image=OpenNebula::Image.new_with_id(image.id, get_one_client)
image.info
template=image.to_hash
template=template['IMAGE']['TEMPLATE']
if !is_successful?(result)
exit -1
end
elsif disk["OVERWRITE"]
# Get the allocated image
image=OpenNebula::Image.new_with_id(disk['IID'], get_one_client)
image.info
image.disable
end
# Perform the copy to the image repo if needed
if File.copy(source_path, image['SOURCE'])
result=image.enable
end
end
end

View File

@ -285,6 +285,10 @@ def get_user_id(name)
get_entity_id(name, OpenNebula::UserPool)
end
def get_image_id(name)
get_entity_id(name, OpenNebula::ImagePool)
end
def str_running_time(data)
stime=Time.at(data["stime"].to_i)
if data["etime"]=="0"
@ -297,6 +301,11 @@ def str_running_time(data)
"%02d %02d:%02d:%02d" % [dtime.yday-1, dtime.hour, dtime.min, dtime.sec]
end
def str_register_time(data)
regtime=Time.at(data["REGTIME"].to_i).getgm
regtime.strftime("%b %d, %Y %H:%M")
end
REG_RANGE=/(.*)\[(\d+)([+-])(\d+)\](.*)/

562
src/cli/oneimage Executable file
View File

@ -0,0 +1,562 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
require 'OpenNebula'
require 'CommandManager'
require 'client_utilities'
require 'command_parse'
require 'ftools'
ShowTableImage={
:id => {
:name => "ID",
:desc => "ONE identifier for the Image",
:size => 4,
:proc => lambda {|d,e| d.id }
},
:user=> {
:name => "USER",
:desc => "Name of the owner",
:size => 8,
:proc => lambda {|d,e|
d["USERNAME"]
}
},
:name => {
:name => "NAME",
:desc => "Name of the Image",
:size => 20,
:proc => lambda {|d,e|
d.name
}
},
:type => {
:name => "TYPE",
:desc => "Type of the Image",
:size => 4,
:proc => lambda {|d,e|
d.short_type_str
}
},
:regtime => {
:name => "REGTIME",
:desc => "Registration time of the Image",
:size => 20,
:proc => lambda {|d,e|
str_register_time(d)
}
},
:public => {
:name => "PUBLIC",
:desc => "Whether the Image is public or not",
:size => 3,
:proc => lambda {|d,e|
if d["PUBLIC"].to_i == 1 then "Yes" else "No" end}
},
:state => {
:name => "STAT",
:desc => "State of the Image",
:size => 4,
:proc => lambda {|d,e|
d.short_state_str
}
},
:runningvms => {
:name => "#VMS",
:desc => "Number of VMs currently running from this Image",
:size => 5,
:proc => lambda {|d,e| d['RUNNING_VMS'] }
},
:default => [:id, :user, :name, :type, :regtime,
:public, :state, :runningvms]
}
class ImageShow
def initialize(client, filter_flag="-2")
@imagepool=OpenNebula::ImagePool.new(client, filter_flag.to_i)
@table=ShowTable.new(ShowTableImage)
end
def header_image_small
scr_bold
scr_underline
print @table.header_str
scr_restore
puts ""
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
def list_short(options=nil)
res=@imagepool.info()
if options
@table.columns=options[:columns] if options[:columns]
end
if OpenNebula.is_error?(res)
result=res
puts res.message
exit -1
else
if options[:filter_flag]
vms=@imagepool.select{|element|
element['USERNAME']==options[:filter_flag] }
else
vms=@imagepool
end
result=[true, ""]
header_image_small
if options
puts @table.data_str(vms, options)
else
puts @table.data_str(vms)
end
result
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
##########################
## COMMAND LINE PARSING ##
##########################
class OneImageParse < CommandParse
COMMANDS_HELP=<<-EOT
Commands:
* register (Registers an image, copying it to the repository if it applies)
oneimage register <template>
template is a file name where the Image description is located
* update (Modifies an image attribute)
oneimage update <image_id> <attribute_name> <attribute_value>
* rmattr (Deletes an Image attribute)
oneimage rmattr <image_id> <attribute_name>
* enable (Enabled an Image)
oneimage enable <image_id>
* disable (Disabled an Image)
oneimage disable <image_id>
* publish (Publish an Image)
oneimage publish <image_id>
* unpublish (Unpublish an Image)
oneimage unpublish <image_id>
* list (Shows Images in the pool)
oneimage list <filter_flag>
where filter_flag can be
a, all --> all the known Images (admin users)
m, mine --> the Images belonging to the user in ONE_AUTH
and all the Public Images
uid --> Images of the user identified by this uid (admin users)
user --> Images of the user identified by the username (admin users)
* top (Lists Images continuously)
onevm top
* show (Gets information about an specific Image)
oneimage show <image_id>
* delete (Deletes an already deployed Image)
oneimage delete <image_id>
EOT
def text_commands
COMMANDS_HELP
end
def text_command_name
"oneimage"
end
def list_options
table=ShowTable.new(ShowTableImage)
table.print_help
end
end
def get_user_flags
ops=Hash.new
if ARGV[0]
case ARGV[0]
when "a", "all"
ops[:filter_user]="-2"
when "m", "mine"
ops[:filter_user]="-1"
else
if !ARGV[0].match(/^[0123456789]+$/)
ops[:filter_user]="-2"
ops[:filter_flag]=ARGV[0]
else
ops[:filter_user]=ARGV[0]
end
end
else
ops[:filter_user]="-2"
end
ops
end
def get_type_and_path(image_template_file)
image_text = open(image_template_file).read
result=Hash.new
image_text.each_line {|line|
case line
when /^\s*(#.*)?$/
# skip empty or commented lines
next
when /^\s*(\w+)\s*=\s*(.*)\s*$/
name = $1.strip.upcase
if name == "PATH" || name == "TYPE" ||
name == "SIZE" || name == "FSTYPE"
result[name] = $2.strip
end
end
}
result
end
oneimage_opts=OneImageParse.new
oneimage_opts.parse(ARGV)
ops=oneimage_opts.options
result=[false, "Unknown error"]
command=ARGV.shift
case command
when "register", "create", "add"
check_parameters("register", 1)
# First, let's check we have everything we need in the template
# Get the path and type from the template file
parser_result = get_type_and_path(ARGV[0])
if parser_result['TYPE']
type = parser_result['TYPE'].upcase
else
type = "OS"
end
result = true
case type
when "OS", "CDROM"
if !parser_result['PATH']
result=OpenNebula::Error.new(
"Image path not present, aborting.")
elsif !File.exists?(parser_result['PATH'])
result=OpenNebula::Error.new(
"Image file could not be found, aborting.")
end
when "DATABLOCK"
if parser_result['PATH'] and !File.exists?(parser_result['PATH'])
if !parser_result['SIZE'] || !parser_result['FSTYPE']
result=OpenNebula::Error.new(
"No image file present for DATABLOCK, " +
"size and/or fstype also missing, aborting.")
end
end
end
if !is_successful?(result)
puts result.message
exit -1
end
# Perform the allocate if all goes well
image=OpenNebula::Image.new(
OpenNebula::Image.build_xml, get_one_client)
begin
template=File.read(ARGV[0])
result=image.allocate(template)
rescue
result=OpenNebula::Error.new("Can not read template: #{ARGV[0]}")
end
if !is_successful?(result)
exit -1
end
# Get the allocated image
image=OpenNebula::Image.new_with_id(image.id, get_one_client)
image.info
template=image.to_hash
template=template['IMAGE']['TEMPLATE']
# Perform the copy to the image repo if needed
if template['PATH']
if File.copy(template['PATH'], image['SOURCE'])
result = image.enable
else
result=OpenNebula::Error.new(
"Cannot copy image, aborting.")
image.delete
end
elsif parser_result['SIZE'] and parser_result['FSTYPE']
local_command=LocalCommand.run(
"dd if=/dev/zero of=#{image['SOURCE']} ibs=1 count=1 " \
"obs=1048576 oseek=#{parser_result['SIZE']}")
if local_command.code!=0
result=OpenNebula::Error.new(
"Cannot create datablock, aborting.")
image.delete
else
local_command=LocalCommand.run(
"mkfs -t #{parser_result['FSTYPE']} -F #{image['SOURCE']}")
if local_command.code!=0
result=OpenNebula::Error.new(
"Cannot format datablock, aborting.")
image.delete
else
image.enable
end
end
end
if is_successful?(result)
puts "ID: " + image.id.to_s if ops[:verbose]
exit 0
end
when "update"
check_parameters("update", 3)
image_id=get_image_id(ARGV[0])
image=OpenNebula::Image.new_with_id(image_id, get_one_client)
result=image.update(ARGV[1],ARGV[2])
if is_successful?(result)
puts "Modified image" if ops[:verbose]
end
when "rmattr"
check_parameters("rmattr", 2)
image_id=get_image_id(ARGV[0])
image=OpenNebula::Image.new_with_id(image_id, get_one_client)
result=image.remove_attr(ARGV[1])
if is_successful?(result)
puts "Removed image atrribute" if ops[:verbose]
end
when "enable"
check_parameters("enable", 1)
image_id=get_image_id(ARGV[0])
image=OpenNebula::Image.new_with_id(image_id, get_one_client)
result=image.enable
if is_successful?(result)
puts "Image enabled" if ops[:verbose]
end
when "disable"
check_parameters("disable", 1)
image_id=get_image_id(ARGV[0])
image=OpenNebula::Image.new_with_id(image_id, get_one_client)
result=image.disable
if is_successful?(result)
puts "Image disabled" if ops[:verbose]
end
when "publish"
check_parameters("publish", 1)
image_id=get_image_id(ARGV[0])
image=OpenNebula::Image.new_with_id(image_id, get_one_client)
result=image.publish
if is_successful?(result)
puts "Image published" if ops[:verbose]
end
when "unpublish"
check_parameters("unpublish", 1)
image_id=get_image_id(ARGV[0])
image=OpenNebula::Image.new_with_id(image_id, get_one_client)
result=image.unpublish
if is_successful?(result)
puts "Image unpublished" if ops[:verbose]
end
when "list"
ops.merge!(get_user_flags)
if !ops[:xml]
imagelist=ImageShow.new(get_one_client, ops[:filter_user].to_i)
ops[:columns]=ops[:list] if ops[:list]
result=imagelist.list_short(ops)
else
imagepool=OpenNebula::ImagePool.new(get_one_client,
ops[:filter_user].to_i)
imagepool.info
puts imagepool.to_xml
end
when "top"
ops.merge!(get_user_flags)
imagelist=ImageShow.new(get_one_client, ops[:filter_user].to_i)
ops[:columns]=ops[:list] if ops[:list]
result=imagelist.top(ops)
when "show"
check_parameters("get_info", 1)
args=expand_args(ARGV)
args.each do |param|
image_id=get_image_id(param)
image=OpenNebula::Image.new_with_id(image_id, get_one_client)
image.info
if !ops[:xml]
str="%-15s: %-20s"
str_h1="%-80s"
print_header(str_h1, "IMAGE #{image[:id]} INFORMATION", true)
puts str % ["ID", image[:id]]
puts str % ["NAME", image[:name]]
puts str % ["TYPE", image.type_str]
value=image[:regtime].to_i
if value==0
value='-'
else
value=Time.at(value).strftime("%m/%d %H:%M:%S")
end
puts str % ["REGISTER TIME", value]
if image[:public].to_i == 1
public_str = "Yes"
else
public_str = "No"
end
puts str % ["PUBLIC", public_str]
puts str % ["SOURCE", image[:source]]
puts str % ["STATE", image.short_state_str]
puts str % ["RUNNING_VMS", image[:runningvms]]
puts
print_header(str_h1,"IMAGE TEMPLATE",false)
puts image.template_str
else
puts image.to_xml
end
end
when "delete"
check_parameters("delete", 1)
args=expand_args(ARGV)
args.each do |param|
image_id=get_image_id(param)
image=OpenNebula::Image.new_with_id(image_id, get_one_client)
result=image.delete
if is_successful?(result)
puts "Image correctly deleted" if ops[:verbose]
else
break
end
end
else
oneimage_opts.print_help
exit -1
end
if OpenNebula.is_error?(result)
puts "Error: " + result.message
exit -1
end

View File

@ -79,6 +79,12 @@ ShowTableVN={
:size => 6,
:proc => lambda {|d,e| d["bridge"] }
},
:public => {
:name => "PUBLIC",
:desc => "Whether the Image is public or not",
:size => 1,
:proc => lambda {|d,e| if d["PUBLIC"].to_i == 1 then "Y" else "N" end}
},
:totalleases => {
:name => "#LEASES",
:desc => "Number of this virtual network's given leases",
@ -86,7 +92,7 @@ ShowTableVN={
:proc => lambda {|d,e| d["TOTAL_LEASES"] }
},
:default => [:id, :user, :name, :type, :bridge, :totalleases]
:default => [:id, :user, :name, :type, :bridge, :public, :totalleases]
}
class VNShow
@ -159,6 +165,12 @@ Commands:
* show (Gets info from a virtual network)
onevnet show <network_id>
* publish (Publish a virtual network)
onevnet publish <network_id>
* unpublish (Unpublish a virtual network)
onevnet unpublish <network_id>
* delete (Removes a virtual network)
onevnet delete <network_id>
@ -223,6 +235,12 @@ when "show"
puts str % ["ID: ",vn.id.to_s]
puts str % ["UID: ",vn["UID"]]
if vn[:public].to_i == 1
public_str = "Y"
else
public_str = "N"
end
puts str % ["PUBLIC", public_str]
puts
print_header(str_h1,"VIRTUAL NETWORK TEMPLATE",false)
@ -244,6 +262,28 @@ when "show"
end
end
when "publish"
check_parameters("publish", 1)
vn_id=get_vn_id(ARGV[0])
vn=OpenNebula::VirtualNetwork.new_with_id(vn_id, get_one_client)
result=vn.publish
if is_successful?(result)
puts "VirtualNetwork published" if ops[:verbose]
end
when "unpublish"
check_parameters("unpublish", 1)
vn_id=get_vn_id(ARGV[0])
vn=OpenNebula::VirtualNetwork.new_with_id(vn_id, get_one_client)
result=vn.unpublish
if is_successful?(result)
puts "VirtualNetwork unpublished" if ops[:verbose]
end
when "delete"
check_parameters("delete", 1)
args=expand_args(ARGV)

View File

@ -592,6 +592,8 @@ int DispatchManager::finalize(
vm->release_network_leases();
vm->release_disk_images();
vm->log("DiM", Log::INFO, "New VM state is DONE.");
break;

View File

@ -117,6 +117,8 @@ void DispatchManager::done_action(int vid)
vm->log("DiM", Log::INFO, "New VM state is DONE");
vm->release_network_leases();
vm->release_disk_images();
}
else
{

View File

@ -197,7 +197,7 @@ int Host::update(SqlDB *db)
{
int rc;
// Update the Template
// Update the Template needed by the monitoring action from IM
rc = host_template.update(db);
if ( rc != 0 )

687
src/image/Image.cc Normal file
View File

@ -0,0 +1,687 @@
/* ------------------------------------------------------------------------ */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* ------------------------------------------------------------------------ */
#include <limits.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <openssl/evp.h>
#include <iomanip>
#include "Image.h"
#include "ImagePool.h"
/* ************************************************************************ */
/* Image :: Constructor/Destructor */
/* ************************************************************************ */
Image::Image(int _uid):
PoolObjectSQL(-1),
uid(_uid),
name(""),
type(OS),
regtime(time(0)),
source(""),
state(INIT),
running_vms(0)
{};
Image::~Image(){};
/* ************************************************************************ */
/* Image :: Database Access Functions */
/* ************************************************************************ */
const char * Image::table = "image_pool";
const char * Image::db_names = "(oid, uid, name, type, public, regtime, "
"source, state, running_vms)";
const char * Image::db_bootstrap = "CREATE TABLE IF NOT EXISTS image_pool ("
"oid INTEGER PRIMARY KEY, uid INTEGER, name VARCHAR(128), "
"type INTEGER, public INTEGER, regtime INTEGER, source TEXT, state INTEGER, "
"running_vms INTEGER, UNIQUE(name) )";
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::select_cb(void * nil, int num, char **values, char ** names)
{
if ((!values[OID]) ||
(!values[UID]) ||
(!values[NAME]) ||
(!values[TYPE]) ||
(!values[PUBLIC]) ||
(!values[REGTIME]) ||
(!values[SOURCE]) ||
(!values[STATE]) ||
(!values[RUNNING_VMS]) ||
(num != LIMIT ))
{
return -1;
}
oid = atoi(values[OID]);
uid = atoi(values[UID]);
name = values[NAME];
type = static_cast<ImageType>(atoi(values[TYPE]));
public_img = atoi(values[PUBLIC]);
regtime = static_cast<time_t>(atoi(values[REGTIME]));
source = values[SOURCE];
state = static_cast<ImageState>(atoi(values[STATE]));
running_vms = atoi(values[RUNNING_VMS]);
image_template.id = oid;
return 0;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::select(SqlDB *db)
{
ostringstream oss;
int rc;
int boid;
set_callback(static_cast<Callbackable::Callback>(&Image::select_cb));
oss << "SELECT * FROM " << table << " WHERE oid = " << oid;
boid = oid;
oid = -1;
rc = db->exec(oss, this);
if ((rc != 0) || (oid != boid ))
{
return -1;
}
// Get the template
rc = image_template.select(db);
if ( rc != 0 )
{
return -1;
}
return 0;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::insert(SqlDB *db)
{
int rc;
string source_att;
string type_att;
string public_attr;
string dev_prefix;
ostringstream tmp_hashstream;
ostringstream tmp_sourcestream;
// ---------------------------------------------------------------------
// Check default image attributes
// ---------------------------------------------------------------------
// ------------ NAME --------------------
get_template_attribute("NAME", name);
if ( name.empty() == true )
{
goto error_name;
}
// ------------ TYPE --------------------
get_template_attribute("TYPE", type_att);
transform (type_att.begin(), type_att.end(), type_att.begin(),
(int(*)(int))toupper);
if ( type_att.empty() == true )
{
type_att = ImagePool::default_type();
}
if (set_type(type_att) != 0)
{
goto error_type;
}
// ------------ PUBLIC --------------------
get_template_attribute("PUBLIC", public_attr);
image_template.erase("PUBLIC");
transform (public_attr.begin(), public_attr.end(), public_attr.begin(),
(int(*)(int))toupper);
public_img = (public_attr == "YES");
// ------------ PREFIX --------------------
get_template_attribute("DEV_PREFIX", dev_prefix);
if( dev_prefix.empty() )
{
SingleAttribute * dev_att = new SingleAttribute("DEV_PREFIX",
ImagePool::default_dev_prefix());
image_template.set(dev_att);
}
// ------------ SOURCE (path to store the image)--------------------
tmp_hashstream << uid << ":" << name;
tmp_sourcestream << ImagePool::source_prefix() << "/";
tmp_sourcestream << sha1_digest(tmp_hashstream.str());
source = tmp_sourcestream.str();
// Set up the template ID, to insert it
if ( image_template.id == -1 )
{
image_template.id = oid;
}
state = DISABLED;
// Insert the Template
rc = image_template.insert(db);
if ( rc != 0 )
{
return rc;
}
//Insert the Image
rc = insert_replace(db, false);
if ( rc != 0 )
{
image_template.drop(db);
return rc;
}
return 0;
error_name:
NebulaLog::log("IMG", Log::ERROR, "NAME not present in image template");
goto error_common;
error_type:
NebulaLog::log("IMG", Log::ERROR, "Incorrect TYPE in image template");
goto error_common;
error_common:
return -1;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::update(SqlDB *db)
{
return insert_replace(db, true);;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::insert_replace(SqlDB *db, bool replace)
{
ostringstream oss;
int rc;
char * sql_name;
char * sql_source;
// Update the Image
sql_name = db->escape_str(name.c_str());
if ( sql_name == 0 )
{
goto error_name;
}
sql_source = db->escape_str(source.c_str());
if ( sql_source == 0 )
{
goto error_source;
}
if(replace)
{
oss << "REPLACE";
}
else
{
oss << "INSERT";
}
// Construct the SQL statement to Insert or Replace
oss <<" INTO "<< table <<" "<< db_names <<" VALUES ("
<< oid << ","
<< uid << ","
<< "'" << sql_name << "',"
<< type << ","
<< public_img << ","
<< regtime << ","
<< "'" << sql_source << "',"
<< state << ","
<< running_vms << ")";
rc = db->exec(oss);
db->free_str(sql_name);
db->free_str(sql_source);
return rc;
error_source:
db->free_str(sql_name);
error_name:
return -1;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::dump(ostringstream& oss, int num, char **values, char **names)
{
if ((!values[OID]) ||
(!values[UID]) ||
(!values[NAME]) ||
(!values[TYPE]) ||
(!values[PUBLIC]) ||
(!values[REGTIME]) ||
(!values[SOURCE]) ||
(!values[STATE]) ||
(!values[RUNNING_VMS]) ||
(num != LIMIT + 1))
{
return -1;
}
oss <<
"<IMAGE>" <<
"<ID>" << values[OID] << "</ID>" <<
"<UID>" << values[UID] << "</UID>" <<
"<USERNAME>" << values[LIMIT] << "</USERNAME>" <<
"<NAME>" << values[NAME] << "</NAME>" <<
"<TYPE>" << values[TYPE] << "</TYPE>" <<
"<PUBLIC>" << values[PUBLIC] << "</PUBLIC>" <<
"<REGTIME>" << values[REGTIME] << "</REGTIME>" <<
"<SOURCE>" << values[SOURCE] << "</SOURCE>" <<
"<STATE>" << values[STATE] << "</STATE>" <<
"<RUNNING_VMS>" << values[RUNNING_VMS] << "</RUNNING_VMS>" <<
"</IMAGE>";
return 0;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::drop(SqlDB * db)
{
ostringstream oss;
int rc;
// Only delete the VM
if (running_vms != 0)
{
return -1;
}
image_template.drop(db);
oss << "DELETE FROM " << table << " WHERE oid=" << oid;
rc = db->exec(oss);
if ( rc == 0 )
{
set_valid(false);
}
return rc;
}
/* ************************************************************************ */
/* Image :: Misc */
/* ************************************************************************ */
ostream& operator<<(ostream& os, Image& image)
{
string image_str;
os << image.to_xml(image_str);
return os;
};
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
string& Image::to_xml(string& xml) const
{
string template_xml;
ostringstream oss;
oss <<
"<IMAGE>" <<
"<ID>" << oid << "</ID>" <<
"<UID>" << uid << "</UID>" <<
"<NAME>" << name << "</NAME>" <<
"<TYPE>" << type << "</TYPE>" <<
"<PUBLIC>" << public_img << "</PUBLIC>" <<
"<REGTIME>" << regtime << "</REGTIME>" <<
"<SOURCE>" << source << "</SOURCE>" <<
"<STATE>" << state << "</STATE>" <<
"<RUNNING_VMS>" << running_vms << "</RUNNING_VMS>" <<
image_template.to_xml(template_xml) <<
"</IMAGE>";
xml = oss.str();
return xml;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
string& Image::to_str(string& str) const
{
string template_str;
ostringstream os;
os <<
"ID = " << oid << endl <<
"UID = " << uid << endl <<
"NAME = " << name << endl <<
"TYPE = " << type << endl <<
"PUBLIC = " << public_img << endl <<
"REGTIME = " << regtime << endl <<
"SOURCE = " << source << endl <<
"STATE = " << state << endl <<
"RUNNING_VMS = " << running_vms << endl <<
"TEMPLATE" << endl
<< image_template.to_str(template_str)
<< endl;
str = os.str();
return str;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::acquire_image(bool overwrite)
{
int rc = 0;
switch (state)
{
case READY:
running_vms++;
if ( overwrite == true)
{
state = LOCKED;
}
else
{
state = USED;
}
break;
case USED:
if ( overwrite == true)
{
rc = -1;
}
else
{
running_vms++;
}
break;
case DISABLED:
case LOCKED:
default:
rc = -1;
break;
}
return rc;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
void Image::release_image()
{
switch (state)
{
case USED:
case LOCKED:
running_vms--;
if ( running_vms == 0)
{
state = READY;
}
break;
case DISABLED:
case READY:
default:
break;
}
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::disk_attribute(VectorAttribute * disk, int * index)
{
string overwrite;
string saveas;
string name;
string bus;
ostringstream iid;
name = disk->vector_value("NAME");
overwrite = disk->vector_value("OVERWRITE");
saveas = disk->vector_value("SAVE_AS");
bus = disk->vector_value("BUS");
iid << oid;
transform(overwrite.begin(), overwrite.end(), overwrite.begin(),
(int(*)(int))toupper);
string template_bus;
string prefix;
get_template_attribute("BUS", template_bus);
get_template_attribute("DEV_PREFIX", prefix);
//--------------------------------------------------------------------------
// Acquire the image
//--------------------------------------------------------------------------
if ( acquire_image(overwrite == "YES") != 0 )
{
return -1;
}
//---------------------------------------------------------------------------
// NEW DISK ATTRIBUTES
//---------------------------------------------------------------------------
map<string,string> new_disk;
new_disk.insert(make_pair("NAME",name));
new_disk.insert(make_pair("IID", iid.str()));
new_disk.insert(make_pair("SOURCE", source));
if (!overwrite.empty())
{
new_disk.insert(make_pair("OVERWRITE",overwrite));
}
if (!saveas.empty())
{
new_disk.insert(make_pair("SAVE_AS",saveas));
}
if (bus.empty())
{
if (!template_bus.empty())
{
new_disk.insert(make_pair("BUS",template_bus));
}
}
else
{
new_disk.insert(make_pair("BUS",bus));
}
//---------------------------------------------------------------------------
// TYPE, READONLY, CLONE, and SAVE attributes
//---------------------------------------------------------------------------
switch(type)
{
case OS:
case DATABLOCK:
new_disk.insert(make_pair("TYPE","DISK"));
new_disk.insert(make_pair("READONLY","NO"));
if (overwrite == "YES")
{
new_disk.insert(make_pair("CLONE","NO"));
new_disk.insert(make_pair("SAVE","YES"));
}
else if (!saveas.empty())
{
new_disk.insert(make_pair("CLONE","YES"));
new_disk.insert(make_pair("SAVE","YES"));
}
else
{
new_disk.insert(make_pair("CLONE","YES"));
new_disk.insert(make_pair("SAVE","NO"));
}
break;
case CDROM:
new_disk.insert(make_pair("TYPE","CDROM"));
new_disk.insert(make_pair("READONLY","YES"));
new_disk.insert(make_pair("CLONE","YES"));
new_disk.insert(make_pair("SAVE","NO"));
break;
}
//---------------------------------------------------------------------------
// TARGET attribute
//---------------------------------------------------------------------------
switch(type)
{
case OS:
prefix += "a";
break;
case CDROM:
prefix += "c"; // b is for context
break;
case DATABLOCK:
prefix += static_cast<char>(('d'+ *index));
*index = *index + 1;
break;
}
new_disk.insert(make_pair("TARGET", prefix));
disk->replace(new_disk);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string Image::sha1_digest(const string& pass)
{
EVP_MD_CTX mdctx;
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len;
ostringstream oss;
EVP_MD_CTX_init(&mdctx);
EVP_DigestInit_ex(&mdctx, EVP_sha1(), NULL);
EVP_DigestUpdate(&mdctx, pass.c_str(), pass.length());
EVP_DigestFinal_ex(&mdctx,md_value,&md_len);
EVP_MD_CTX_cleanup(&mdctx);
for(unsigned int i = 0; i<md_len; i++)
{
oss << setfill('0') << setw(2) << hex << nouppercase
<< (unsigned short) md_value[i];
}
return oss.str();
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

189
src/image/ImagePool.cc Normal file
View File

@ -0,0 +1,189 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
/* ************************************************************************** */
/* Image Pool */
/* ************************************************************************** */
#include "ImagePool.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string ImagePool::_source_prefix;
string ImagePool::_default_type;
string ImagePool::_default_dev_prefix;
int ImagePool::init_cb(void *nil, int num, char **values, char **names)
{
if ( num == 0 || values == 0 || values[0] == 0 )
{
return -1;
}
image_names.insert(make_pair(values[1],atoi(values[0])));
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
ImagePool::ImagePool( SqlDB * db,
const string& __source_prefix,
const string& __default_type,
const string& __default_dev_prefix):
PoolSQL(db,Image::table)
{
ostringstream sql;
int rc;
// Init static defaults
_source_prefix = __source_prefix;
_default_type = __default_type;
_default_dev_prefix = __default_dev_prefix;
// Set default type
if (_default_type != "OS" &&
_default_type != "CDROM" &&
_default_type != "DATABLOCK" )
{
NebulaLog::log("IMG", Log::ERROR,
"Bad default for image type, setting OS");
_default_type = "OS";
}
// Read from the DB the existing images, and build the ID:Name map
set_callback(static_cast<Callbackable::Callback>(&ImagePool::init_cb));
sql << "SELECT oid, name FROM " << Image::table;
rc = db->exec(sql, this);
unset_callback();
if ( rc != 0 )
{
NebulaLog::log("IMG", Log::ERROR,
"Could not load the existing images from the DB.");
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ImagePool::allocate (
int uid,
const string& stemplate,
int * oid)
{
int rc;
Image * img;
string name;
char * error_msg;
// ---------------------------------------------------------------------
// Build a new Image object
// ---------------------------------------------------------------------
img = new Image(uid);
// ---------------------------------------------------------------------
// Parse template
// ---------------------------------------------------------------------
rc = img->image_template.parse(stemplate, &error_msg);
if ( rc != 0 )
{
ostringstream oss;
oss << "ImagePool template parse error: " << error_msg;
NebulaLog::log("IMG", Log::ERROR, oss);
free(error_msg);
delete img;
return -1;
}
img->get_template_attribute("NAME", name);
// ---------------------------------------------------------------------
// Insert the Object in the pool
// ---------------------------------------------------------------------
*oid = PoolSQL::allocate(img);
if ( *oid == -1 )
{
return -1;
}
// ---------------------------------------------------------------------
// Add the image name to the map of image_names
// ---------------------------------------------------------------------
image_names.insert(make_pair(name, *oid));
return *oid;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ImagePool::dump_cb(void * _oss, int num, char **values, char **names)
{
ostringstream * oss;
oss = static_cast<ostringstream *>(_oss);
return Image::dump(*oss, num, values, names);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ImagePool::dump(ostringstream& oss, const string& where)
{
int rc;
ostringstream cmd;
oss << "<IMAGE_POOL>";
set_callback(static_cast<Callbackable::Callback>(&ImagePool::dump_cb),
static_cast<void *>(&oss));
cmd << "SELECT " << Image::table << ".*, user_pool.user_name FROM "
<< Image::table
<< " LEFT OUTER JOIN (SELECT oid, user_name FROM user_pool) "
<< "AS user_pool ON " << Image::table << ".uid = user_pool.oid";
if ( !where.empty() )
{
cmd << " WHERE " << where;
}
rc = db->exec(cmd, this);
oss << "</IMAGE_POOL>";
unset_callback();
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

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

31
src/image/SConstruct Normal file
View File

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

View File

@ -0,0 +1,832 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include <string>
#include <iostream>
#include <stdlib.h>
#include "ImagePool.h"
#include "PoolTest.h"
using namespace std;
const int uids[] = {0,1,2};
const string names[] = {"Image one", "Second Image", "The third image"};
const string templates[] =
{
"NAME = \"Image one\"\n"
"ORIGINAL_PATH = /tmp/image_test\n"
"DESCRIPTION = \"This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.\"\n",
"NAME = \"Second Image\"\n"
"ORIGINAL_PATH = /tmp/image_second_test\n"
"PUBLIC = YES\n"
"DESCRIPTION = \"This is a rather short description.\"\n",
"NAME = \"The third image\"\n"
"ORIGINAL_PATH = /tmp/image_test\n"
"# DESCRIPTION = \"An image description\"\n"
"BUS = SCSI\n"
"PROFILE = STUDENT\n"
};
const string xmls[] =
{
"<IMAGE><ID>0</ID><UID>0</UID><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Image one]]></NAME><ORIGINAL_PATH><![CDATA[/tmp/image_test]]></ORIGINAL_PATH></TEMPLATE></IMAGE>",
"<IMAGE><ID>1</ID><UID>1</UID><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f3</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a rather short description.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Second Image]]></NAME><ORIGINAL_PATH><![CDATA[/tmp/image_second_test]]></ORIGINAL_PATH></TEMPLATE></IMAGE>",
"<IMAGE><ID>0</ID><UID>2</UID><NAME>The third image</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/e50b0c738be9d431475bf5859629e5580301a7d6</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><BUS><![CDATA[SCSI]]></BUS><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[The third image]]></NAME><ORIGINAL_PATH><![CDATA[/tmp/image_test]]></ORIGINAL_PATH><PROFILE><![CDATA[STUDENT]]></PROFILE></TEMPLATE></IMAGE>"
};
// This xml dump result has the STIMEs modified to 0000000000
const string xml_dump =
"<IMAGE_POOL><IMAGE><ID>0</ID><UID>0</UID><USERNAME>one_user_test</USERNAME><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS></IMAGE><IMAGE><ID>1</ID><UID>1</UID><USERNAME>A user</USERNAME><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f3</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS></IMAGE><IMAGE><ID>2</ID><UID>2</UID><USERNAME>B user</USERNAME><NAME>The third image</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/e50b0c738be9d431475bf5859629e5580301a7d6</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS></IMAGE></IMAGE_POOL>";
const string xml_dump_where =
"<IMAGE_POOL><IMAGE><ID>0</ID><UID>0</UID><USERNAME>one_user_test</USERNAME><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS></IMAGE><IMAGE><ID>1</ID><UID>1</UID><USERNAME>A user</USERNAME><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f3</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS></IMAGE></IMAGE_POOL>";
const string replacement = "0000000000";
/* ************************************************************************* */
/* ************************************************************************* */
class ImagePoolTest : public PoolTest
{
CPPUNIT_TEST_SUITE (ImagePoolTest);
ALL_POOLTEST_CPPUNIT_TESTS();
CPPUNIT_TEST ( names_initialization );
CPPUNIT_TEST ( update );
CPPUNIT_TEST ( get_using_name );
CPPUNIT_TEST ( wrong_get_name );
CPPUNIT_TEST ( duplicates );
CPPUNIT_TEST ( extra_attributes );
CPPUNIT_TEST ( wrong_templates );
CPPUNIT_TEST ( target_generation );
CPPUNIT_TEST ( bus_source_assignment );
CPPUNIT_TEST ( public_attribute );
CPPUNIT_TEST ( disk_overwrite );
CPPUNIT_TEST ( dump );
CPPUNIT_TEST ( dump_where );
CPPUNIT_TEST_SUITE_END ();
protected:
void bootstrap(SqlDB* db)
{
ImagePool::bootstrap(db);
};
PoolSQL* create_pool(SqlDB* db)
{
return new ImagePool(db, "source_prefix", "OS", "hd");
};
int allocate(int index)
{
int oid;
return ((ImagePool*)pool)->allocate(uids[index],
templates[index],
&oid);
};
void check(int index, PoolObjectSQL* obj)
{
CPPUNIT_ASSERT( obj != 0 );
string xml_str = "";
// Get the xml and replace the REGTIME to 0, so we can compare
// it.
((Image*)obj)->to_xml(xml_str);
xml_str.replace( xml_str.find("<REGTIME>")+9, 10, replacement);
//cout << endl << xml_str << endl << xmls[index] << endl;
CPPUNIT_ASSERT( ((Image*)obj)->get_name() == names[index] );
CPPUNIT_ASSERT( xml_str == xmls[index]);
};
void set_up_user_pool()
{
// The UserPool constructor checks if the DB contains at least
// one user, and adds one automatically from the ONE_AUTH file.
// So the ONE_AUTH environment is forced to point to a test one_auth
// file.
ostringstream oss;
oss << getenv("PWD") << "/one_auth";
setenv("ONE_AUTH", oss.str().c_str(), 1);
UserPool::bootstrap(db);
UserPool * user_pool = new UserPool(db);
int uid_1, uid_2;
string username_1 = "A user";
string username_2 = "B user";
string pass_1 = "A pass";
string pass_2 = "B pass";
user_pool->allocate(&uid_1, username_1, pass_1, true);
user_pool->allocate(&uid_2, username_2, pass_2, true);
delete user_pool;
};
public:
ImagePoolTest(){};
~ImagePoolTest(){};
/* ********************************************************************* */
void names_initialization()
{
ImagePool * imp;
Image * img;
// Allocate 2 users, so they are written to the DB.
allocate(0);
allocate(2);
// Create a new pool, using the same DB. This new pool should read the
// allocated images.
imp = new ImagePool(db, "source_prefix", "OS", "hd");
img = imp->get(names[0], false);
CPPUNIT_ASSERT( img != 0 );
img = imp->get(names[1], false);
CPPUNIT_ASSERT( img == 0 );
img = imp->get(names[2], false);
CPPUNIT_ASSERT( img != 0 );
delete imp;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void update()
{
string description_name = "DESCRIPTION";
string description_val = "";
string new_description = "A new description";
string attr_name = "NEW_ATTRIBUTE";
string attr_val = "";
string new_attr_value = "New value";
string no_value = "Some random value";
ImagePool * ip;
Image * img;
int oid_1;
ip = static_cast<ImagePool *>(pool);
oid_1 = allocate(0);
img = ip->get(oid_1, true);
CPPUNIT_ASSERT( img != 0 );
// Image object should be cached. Let's change some template attributes
ip->replace_attribute(img, description_name, new_description);
ip->replace_attribute(img, attr_name, new_attr_value);
ip->remove_attribute(img, "ORIGINAL_PATH");
img->unlock();
img = ip->get(oid_1,false);
CPPUNIT_ASSERT( img != 0 );
img->get_template_attribute("DESCRIPTION", description_val);
img->get_template_attribute("NEW_ATTRIBUTE", attr_val);
img->get_template_attribute("ORIGINAL_PATH", no_value);
CPPUNIT_ASSERT( description_val == new_description );
CPPUNIT_ASSERT( attr_val == new_attr_value );
CPPUNIT_ASSERT( no_value == "" );
//Now force access to DB
pool->clean();
img = ip->get(oid_1,false);
CPPUNIT_ASSERT( img != 0 );
description_val = "";
attr_val = "";
no_value = "Random value";
img->get_template_attribute("DESCRIPTION", description_val);
img->get_template_attribute("NEW_ATTRIBUTE", attr_val);
img->get_template_attribute("ORIGINAL_PATH", no_value);
CPPUNIT_ASSERT( description_val == new_description );
CPPUNIT_ASSERT( attr_val == new_attr_value );
CPPUNIT_ASSERT( no_value == "" );
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void get_using_name()
{
int oid_0, oid_1;
ImagePool * imp = static_cast<ImagePool *>(pool);
// Allocate two objects
oid_0 = allocate(0);
oid_1 = allocate(1);
// ---------------------------------
// Get first object and check its integrity
obj = pool->get(oid_0, false);
CPPUNIT_ASSERT( obj != 0 );
check(0, obj);
// Get using its name
obj = imp->get(names[1], true);
CPPUNIT_ASSERT( obj != 0 );
obj->unlock();
check(1, obj);
// ---------------------------------
// Clean the cache, forcing the pool to read the objects from the DB
pool->clean();
// Get first object and check its integrity
obj = imp->get(names[0], false);
check(0, obj);
// Get using its name
obj = imp->get(oid_1, false);
check(1, obj);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void wrong_get_name()
{
ImagePool * imp = static_cast<ImagePool *>(pool);
// The pool is empty
// Non existing name
obj = imp->get("Wrong name", true);
CPPUNIT_ASSERT( obj == 0 );
// Allocate an object
allocate(0);
// Ask again for a non-existing name
obj = imp->get("Non existing name", true);
CPPUNIT_ASSERT( obj == 0 );
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void duplicates()
{
int rc, oid;
ImagePool * imp = static_cast<ImagePool *>(pool);
// Allocate an image.
rc = imp->allocate(uids[0], templates[0], &oid);
CPPUNIT_ASSERT( oid == 0 );
CPPUNIT_ASSERT( oid == rc );
// Try to allocate twice the same image, should fail
rc = imp->allocate(uids[0], templates[0], &oid);
CPPUNIT_ASSERT( rc == -1 );
CPPUNIT_ASSERT( oid == rc );
// Try again, with different uid
rc = imp->allocate(uids[1], templates[0], &oid);
CPPUNIT_ASSERT( rc == -1 );
CPPUNIT_ASSERT( oid == rc );
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void extra_attributes()
{
int oid;
string value = "";
Image * img;
// The third template doen't have a description, but has some
// extra attibutes
oid = allocate(2);
CPPUNIT_ASSERT( oid == 0 );
pool->clean();
img = ((ImagePool*)pool)->get(oid, false);
check(2, img);
img->get_template_attribute("DESCRIPTION", value);
CPPUNIT_ASSERT( value == "" );
img->get_template_attribute("PROFILE", value);
CPPUNIT_ASSERT( value == "STUDENT" );
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void wrong_templates()
{
int rc;
ImagePool * imp = static_cast<ImagePool *>(pool);
string templates[] =
{
"ORIGINAL_PATH = /tmp/image_test\n"
"DESCRIPTION = \"This template lacks name!\"\n",
"NAME = \"name A\"\n"
"ORIGINAL_PATH = /tmp/image_test\n"
"TYPE = WRONG\n",
"NAME \"PARSE ERROR\"\n"
"TYPE = WRONG\n",
"END"
};
int results[] = { -1, -1, -1 };
int i = 0;
while( templates[i] != "END" )
{
imp->allocate(0, templates[i], &rc);
//cout << endl << i << " - rc: " << rc << " expected: "
// << results[i] << endl;
CPPUNIT_ASSERT( rc == results[i] );
i++;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void target_generation()
{
ImagePool * imp = static_cast<ImagePool *>(pool);
Image * img;
VectorAttribute * disk;
int oid;
string value;
int index=0;
disk = new VectorAttribute("DISK");
// Allocate an OS type image
oid = allocate(0);
img = imp->get(oid, false);
CPPUNIT_ASSERT( img != 0 );
CPPUNIT_ASSERT( oid == 0 );
img->enable(true);
img->disk_attribute(disk, &index);
value = disk->vector_value("TARGET");
CPPUNIT_ASSERT( value == "hda" );
// clean up
delete disk;
value = "";
disk = new VectorAttribute("DISK");
// Allocate a CDROM type image
string templ = "NAME = \"name A\" TYPE = CDROM ORIGINAL_PATH = /tmp";
imp->allocate(0, templ, &oid);
CPPUNIT_ASSERT(oid >= 0);
img = imp->get(oid, false);
img->enable(true);
img->disk_attribute(disk, &index);
value = disk->vector_value("TARGET");
CPPUNIT_ASSERT(value == "hdc");
// clean up
delete disk;
value = "";
disk = new VectorAttribute("DISK");
// Allocate a DATABLOCK type image
templ = "NAME = \"name B\" TYPE = DATABLOCK";
imp->allocate(0, templ, &oid);
CPPUNIT_ASSERT(oid >= 0);
img = imp->get(oid, false);
img->enable(true);
img->disk_attribute(disk, &index);
value = disk->vector_value("TARGET");
CPPUNIT_ASSERT(value == "hdd");
// clean up
delete disk;
value = "";
disk = new VectorAttribute("DISK");
// Allocate a DATABLOCK type image
templ = "NAME = \"name C\" TYPE = DATABLOCK DEV_PREFIX = \"sd\"";
imp->allocate(0, templ, &oid);
CPPUNIT_ASSERT(oid >= 0);
img = imp->get(oid, false);
img->enable(true);
img->disk_attribute(disk, &index);
value = disk->vector_value("TARGET");
CPPUNIT_ASSERT(value == "sde");
// clean up
delete disk;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void bus_source_assignment()
{
ImagePool * imp = static_cast<ImagePool *>(pool);
Image * img;
VectorAttribute * disk;
int oid;
string value;
int index = 0;
// Allocate an OS type image
oid = allocate(0);
img = imp->get(oid, false);
// ---------------------------------------------------------------------
// A disk without a BUS attribute should not have it added.
disk = new VectorAttribute("DISK");
img->enable(true);
img->disk_attribute(disk, &index);
value = "";
value = disk->vector_value("BUS");
CPPUNIT_ASSERT( value == "" );
value = "";
value = disk->vector_value("SOURCE");
CPPUNIT_ASSERT( value ==
"source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198" );
// clean up
delete disk;
// ---------------------------------------------------------------------
// A disk with a BUS attribute should not have it overwritten.
disk = new VectorAttribute("DISK");
disk->replace("BUS", "SCSI");
img->enable(true);
img->disk_attribute(disk, &index);
value = disk->vector_value("BUS");
CPPUNIT_ASSERT( value == "SCSI" );
value = "";
value = disk->vector_value("SOURCE");
CPPUNIT_ASSERT( value ==
"source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198" );
// clean up
delete disk;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void disk_overwrite()
{
ImagePool * imp = static_cast<ImagePool *>(pool);
Image * img;
VectorAttribute * disk;
int oid, rc;
string value;
int index = 0;
// ---------------------------------------------------------------------
// Allocate an OS type image
oid = allocate(0);
CPPUNIT_ASSERT( oid > -1 );
img = imp->get(oid, false);
// Disk with overwrite=yes, save_as empty
disk = new VectorAttribute("DISK");
disk->replace("OVERWRITE", "yes");
img->enable(true);
rc = img->disk_attribute(disk, &index);
CPPUNIT_ASSERT( rc == 0 );
value = disk->vector_value("OVERWRITE");
CPPUNIT_ASSERT( value == "YES" );
value = "";
value = disk->vector_value("SAVE_AS");
CPPUNIT_ASSERT( value == "" );
value = "";
value = disk->vector_value("CLONE");
CPPUNIT_ASSERT( value == "NO" );
value = "";
value = disk->vector_value("SAVE");
CPPUNIT_ASSERT( value == "YES" );
value = "";
value = disk->vector_value("READONLY");
CPPUNIT_ASSERT( value == "NO" );
// clean up
delete disk;
// ---------------------------------------------------------------------
// Allocate an OS type image
oid = allocate(1);
CPPUNIT_ASSERT( oid > -1 );
img = imp->get(oid, false);
// Disk with overwrite=no, save_as not empty
disk = new VectorAttribute("DISK");
disk->replace("OVERWRITE", "NO");
disk->replace("SAVE_AS", "path_to_save");
img->enable(true);
rc = img->disk_attribute(disk, &index);
CPPUNIT_ASSERT( rc == 0 );
value = "";
value = disk->vector_value("OVERWRITE");
CPPUNIT_ASSERT( value == "NO" );
value = "";
value = disk->vector_value("SAVE_AS");
CPPUNIT_ASSERT( value == "path_to_save" );
value = "";
value = disk->vector_value("CLONE");
CPPUNIT_ASSERT( value == "YES" );
value = "";
value = disk->vector_value("SAVE");
CPPUNIT_ASSERT( value == "YES" );
value = "";
value = disk->vector_value("READONLY");
CPPUNIT_ASSERT( value == "NO" );
// clean up
delete disk;
// ---------------------------------------------------------------------
// Allocate an OS type image
oid = allocate(2);
CPPUNIT_ASSERT( oid > -1 );
img = imp->get(oid, false);
// Disk with overwrite=no, save_as not present
disk = new VectorAttribute("DISK");
disk->replace("OVERWRITE", "NO");
img->enable(true);
rc = img->disk_attribute(disk, &index);
CPPUNIT_ASSERT( rc == 0 );
value = "";
value = disk->vector_value("OVERWRITE");
CPPUNIT_ASSERT( value == "NO" );
value = "";
value = disk->vector_value("SAVE_AS");
CPPUNIT_ASSERT( value == "" );
value = "";
value = disk->vector_value("CLONE");
CPPUNIT_ASSERT( value == "YES" );
value = "";
value = disk->vector_value("SAVE");
CPPUNIT_ASSERT( value == "NO" );
value = "";
value = disk->vector_value("READONLY");
CPPUNIT_ASSERT( value == "NO" );
// clean up
delete disk;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void public_attribute()
{
int oid;
ImagePool * imp = static_cast<ImagePool *>(pool);
Image * img;
string templates[] =
{
// false
"NAME = \"name A\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n",
// true
"NAME = \"name B\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PUBLIC = YES",
// false
"NAME = \"name C\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PUBLIC = NO",
// false
"NAME = \"name D\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PUBLIC = 1",
// true
"NAME = \"name E\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PUBLIC = Yes",
// false
"NAME = \"name F\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PUBLIC = TRUE",
// true
"NAME = \"name G\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PUBLIC = yes",
// false
"NAME = \"name H\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PUBLIC = 'YES'",
// true
"NAME = \"name I\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PUBLIC = \"YES\"",
"END"
};
bool results[] = { false, true, false, false,
true, false, true, false, true };
int i = 0;
while( templates[i] != "END" )
{
imp->allocate(0, templates[i], &oid);
CPPUNIT_ASSERT( oid >= 0 );
img = imp->get( oid, false );
CPPUNIT_ASSERT( img != 0 );
//cout << endl << i << " : exp. " << results[i] << " got " << img->is_public();
CPPUNIT_ASSERT( img->is_public() == results[i] );
i++;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void dump()
{
ImagePool * imp = static_cast<ImagePool*>(pool);
ostringstream oss;
int rc;
string nan;
set_up_user_pool();
allocate(0);
allocate(1);
allocate(2);
rc = imp->dump(oss,nan);
CPPUNIT_ASSERT(rc == 0);
string result = oss.str();
result.replace(138, 10, replacement);
result.replace(403, 10, replacement);
result.replace(671, 10, replacement);
CPPUNIT_ASSERT( result == xml_dump );
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void dump_where()
{
ImagePool * imp = static_cast<ImagePool*>(pool);
int rc;
ostringstream oss;
ostringstream where;
set_up_user_pool();
allocate(0);
allocate(1);
allocate(2);
where << "uid < 2";
rc = imp->dump(oss, where.str());
CPPUNIT_ASSERT(rc == 0);
string result = oss.str();
result.replace(138, 10, replacement);
result.replace(403, 10, replacement);
CPPUNIT_ASSERT( result == xml_dump_where );
}
/* ********************************************************************* */
};
/* ************************************************************************* */
/* ************************************************************************* */
int main(int argc, char ** argv)
{
return PoolTest::main(argc, argv, ImagePoolTest::suite());
}

102
src/image/test/SConstruct Normal file
View File

@ -0,0 +1,102 @@
# --------------------------------------------------------------------------
# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org)
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# --------------------------------------------------------------------------
import os
import sys
import shutil
sys.path.append("../../../share/scons")
from lex_bison import *
# This is the absolute path where the project is located
cwd="../../../"
# Environment that will be applied to each scons child
main_env=Environment()
main_env['ENV']['PATH']=os.environ['PATH']
# Add builders for flex and bison
add_lex(main_env)
add_bison(main_env)
# Include dirs
main_env.Append(CPPPATH=[
cwd + '/include',
cwd + '/include/test',
'/usr/include/cppunit/',
])
# Library dirs
main_env.Append(LIBPATH=[
cwd + '/src/common',
cwd + '/src/log',
cwd + '/src/nebula',
cwd + '/src/sql',
cwd + '/src/pool',
cwd + '/src/template',
cwd + '/src/vm',
cwd + '/src/hm',
cwd + '/src/mad',
cwd + '/src/vnm',
cwd + '/src/um',
cwd + '/src/image',
'/usr/include/openssl/',
])
main_env.Append(LIBS=[
'nebula_image',
'nebula_um',
'nebula_vm',
'nebula_mad',
'nebula_hm',
'nebula_vnm',
'nebula_template',
'nebula_pool',
'nebula_common',
'nebula_log',
'nebula_core',
'nebula_sql',
'cppunit',
'dl',
'pthread',
'crypto',
])
# MYSQL
main_env.Append(LIBPATH=["/usr/lib/mysql"])
main_env.Append(CPPPATH=["/usr/include/mysql"])
sqlite=ARGUMENTS.get('sqlite', 'yes')
if sqlite=='yes':
main_env.Append(CPPFLAGS=["-DSQLITE_DB"])
main_env.Append(LIBS=[ 'sqlite3', ])
# MySQL
mysql=ARGUMENTS.get('mysql', 'no')
if mysql=='yes':
main_env.Append(CPPFLAGS=["-DMYSQL_DB"])
main_env.Append(LIBS=[ 'mysqlclient', ])
# Compile flags
main_env.Append(CPPFLAGS=[
"-g",
"-Wall"
])
# Linking flags
main_env.Append(LDFLAGS=["-g "])
main_env.Program('test','ImagePoolTest.cc')

1
src/image/test/one_auth Normal file
View File

@ -0,0 +1 @@
one_user_test:password

View File

@ -205,6 +205,7 @@ void Nebula::start()
HostPool::bootstrap(db);
VirtualNetworkPool::bootstrap(db);
UserPool::bootstrap(db);
ImagePool::bootstrap(db);
}
catch (exception&)
{
@ -213,8 +214,11 @@ void Nebula::start()
try
{
string mac_prefix;
int size;
string mac_prefix;
int size;
string repository_path;
string default_image_type;
string default_device_prefix;
vector<const Attribute *> vm_hooks;
@ -229,6 +233,22 @@ void Nebula::start()
vnpool = new VirtualNetworkPool(db,mac_prefix,size);
upool = new UserPool(db);
nebula_configuration->get("IMAGE_REPOSITORY_PATH", repository_path);
if (repository_path.empty()) // Defaults to ONE_LOCATION/var
{
repository_path = var_location;
}
nebula_configuration->get("DEFAULT_IMAGE_TYPE", default_image_type);
nebula_configuration->get("DEFAULT_DEVICE_PREFIX",
default_device_prefix);
ipool = new ImagePool(db,
repository_path,
default_image_type,
default_device_prefix);
}
catch (exception&)
{
@ -389,6 +409,7 @@ void Nebula::start()
hpool,
vnpool,
upool,
ipool,
rm_port,
log_location + "one_xmlrpc.log");
}

View File

@ -42,6 +42,7 @@ env.Append(LIBS=[
'nebula_um',
'nebula_mad',
'nebula_template',
'nebula_image',
'nebula_pool',
'nebula_host',
'nebula_vnm',

View File

@ -13,6 +13,8 @@ require 'OpenNebula/VirtualMachine'
require 'OpenNebula/VirtualMachinePool'
require 'OpenNebula/VirtualNetwork'
require 'OpenNebula/VirtualNetworkPool'
require 'OpenNebula/Image'
require 'OpenNebula/ImagePool'
require 'OpenNebula/User'
require 'OpenNebula/UserPool'
require 'OpenNebula/Host'

View File

@ -0,0 +1,163 @@
require 'OpenNebula/Pool'
module OpenNebula
class Image < PoolElement
# ---------------------------------------------------------------------
# Constants and Class Methods
# ---------------------------------------------------------------------
IMAGE_METHODS = {
:info => "image.info",
:allocate => "image.allocate",
:update => "image.update",
:rmattr => "image.rmattr",
:enable => "image.enable",
:publish => "image.publish",
:delete => "image.delete"
}
IMAGE_STATES=%w{INIT LOCKED READY USED DISABLED}
SHORT_IMAGE_STATES={
"INIT" => "init",
"LOCKED" => "lock",
"READY" => "rdy",
"USED" => "used",
"DISABLED" => "disa"
}
IMAGE_TYPES=%w{OS CDROM DATABLOCK}
SHORT_IMAGE_TYPES={
"OS" => "OS",
"CDROM" => "CD",
"DATABLOCK" => "DB"
}
# Creates an Image description with just its identifier
# this method should be used to create plain Image objects.
# +id+ the id of the image
#
# Example:
# image = Image.new(Image.build_xml(3),rpc_client)
#
def Image.build_xml(pe_id=nil)
if pe_id
image_xml = "<IMAGE><ID>#{pe_id}</ID></IMAGE>"
else
image_xml = "<IMAGE></IMAGE>"
end
XMLUtilsElement.initialize_xml(image_xml, 'IMAGE')
end
# Class constructor
def initialize(xml, client)
super(xml,client)
@client = client
end
#######################################################################
# XML-RPC Methods for the Image Object
#######################################################################
def info()
super(IMAGE_METHODS[:info], 'IMAGE')
end
def allocate(description)
super(IMAGE_METHODS[:allocate],description)
end
def update(name, value)
super(IMAGE_METHODS[:update], name, value)
end
def remove_attr(name)
do_rm_attr(name)
end
def enable
set_enabled(true)
end
def disable
set_enabled(false)
end
def publish
set_publish(true)
end
def unpublish
set_publish(false)
end
def delete()
super(IMAGE_METHODS[:delete])
end
#######################################################################
# Helpers to get Image information
#######################################################################
# Returns the state of the Image (numeric value)
def state
self['STATE'].to_i
end
# Returns the state of the Image (string value)
def state_str
IMAGE_STATES[state]
end
# Returns the state of the Image (string value)
def short_state_str
SHORT_IMAGE_STATES[state_str]
end
# Returns the type of the Image (numeric value)
def type
self['TYPE'].to_i
end
# Returns the type of the Image (string value)
def type_str
IMAGE_TYPES[type]
end
# Returns the state of the Image (string value)
def short_type_str
SHORT_IMAGE_TYPES[type_str]
end
private
def set_enabled(enabled)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(IMAGE_METHODS[:enable], @pe_id, enabled)
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
def set_publish(published)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(IMAGE_METHODS[:publish], @pe_id, published)
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
def do_rm_attr(name)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(IMAGE_METHODS[:rmattr], @pe_id, name)
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
end
end

View File

@ -0,0 +1,38 @@
require 'OpenNebula/Pool'
module OpenNebula
class ImagePool < Pool
#######################################################################
# Constants and Class attribute accessors
#######################################################################
IMAGE_POOL_METHODS = {
:info => "imagepool.info"
}
#######################################################################
# Class constructor & Pool Methods
#######################################################################
# +client+ a Client object that represents a XML-RPC connection
# +user_id+ is to refer to a Pool with Images from that user
def initialize(client, user_id=0)
super('IMAGE_POOL','IMAGE',client)
@user_id = user_id
end
# Default Factory Method for the Pools
def factory(element_xml)
OpenNebula::Image.new(element_xml,@client)
end
#######################################################################
# XML-RPC Methods for the Image Object
#######################################################################
def info()
super(IMAGE_POOL_METHODS[:info],@user_id)
end
end
end

View File

@ -129,6 +129,21 @@ module OpenNebula
return rc
end
# Calls to the corresponding update method to modify
# the object's template
# xml_method:: _String_ the name of the XML-RPC method
# name:: _String_ the name of the property to be modified
# value:: _String_ the new value of the property to be modified
# [return] nil in case of success or an Error object
def update(xml_method, name, value)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(xml_method,@pe_id, name, value)
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
# Calls to the corresponding delete method to remove this element
# from the OpenNebula core

View File

@ -8,6 +8,7 @@ module OpenNebula
VN_METHODS = {
:info => "vn.info",
:allocate => "vn.allocate",
:publish => "vn.publish",
:delete => "vn.delete"
}
@ -46,9 +47,28 @@ module OpenNebula
def allocate(description)
super(VN_METHODS[:allocate],description)
end
def publish
set_publish(true)
end
def unpublish
set_publish(false)
end
def delete()
super(VN_METHODS[:delete])
end
private
def set_publish(published)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(VN_METHODS[:publish], @pe_id, published)
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
end
end

View File

@ -254,6 +254,9 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr vnpool_info(new
RequestManager::VirtualNetworkPoolInfo(vnpool,upool));
xmlrpc_c::methodPtr vn_publish(new
RequestManager::VirtualNetworkPublish(vnpool, upool));
xmlrpc_c::methodPtr vn_delete(new
RequestManager::VirtualNetworkDelete(vnpool, upool));
@ -269,6 +272,30 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr userpool_info(new
RequestManager::UserPoolInfo(upool));
xmlrpc_c::methodPtr image_allocate(new
RequestManager::ImageAllocate(ipool, upool));
xmlrpc_c::methodPtr image_delete(new
RequestManager::ImageDelete(ipool, upool));
xmlrpc_c::methodPtr image_info(new
RequestManager::ImageInfo(ipool, upool));
xmlrpc_c::methodPtr image_update(new
RequestManager::ImageUpdate(ipool, upool));
xmlrpc_c::methodPtr image_rm_attribute(new
RequestManager::ImageRemoveAttribute(ipool, upool));
xmlrpc_c::methodPtr image_publish(new
RequestManager::ImagePublish(ipool, upool));
xmlrpc_c::methodPtr image_enable(new
RequestManager::ImageEnable(ipool, upool));
xmlrpc_c::methodPtr imagepool_info(new
RequestManager::ImagePoolInfo(ipool, upool));
/* VM related methods */
@ -293,6 +320,7 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.vn.allocate", vn_allocate);
RequestManagerRegistry.addMethod("one.vn.info", vn_info);
RequestManagerRegistry.addMethod("one.vn.publish", vn_publish);
RequestManagerRegistry.addMethod("one.vn.delete", vn_delete);
RequestManagerRegistry.addMethod("one.vnpool.info", vnpool_info);
@ -306,6 +334,18 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.userpool.info", userpool_info);
/* Image related methods*/
RequestManagerRegistry.addMethod("one.image.allocate",image_allocate);
RequestManagerRegistry.addMethod("one.image.delete", image_delete);
RequestManagerRegistry.addMethod("one.image.info", image_info);
RequestManagerRegistry.addMethod("one.image.update", image_update);
RequestManagerRegistry.addMethod("one.image.rmattr", image_rm_attribute);
RequestManagerRegistry.addMethod("one.image.publish", image_publish);
RequestManagerRegistry.addMethod("one.image.enable", image_enable);
RequestManagerRegistry.addMethod("one.imagepool.info", imagepool_info);
};
/* -------------------------------------------------------------------------- */

View File

@ -50,7 +50,7 @@ void RequestManager::HostInfo::execute(
goto error_authenticate;
}
// Perform the allocation in the hostpool
// Get the host from the HostPool
host = HostInfo::hpool->get(hid,true);
if ( host == 0 )

View File

@ -0,0 +1,107 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "NebulaLog.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::ImageAllocate::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
string image_template;
int iid;
int uid;
int rc;
ostringstream oss;
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
NebulaLog::log("ReM",Log::DEBUG,"ImageAllocate invoked");
session = xmlrpc_c::value_string(paramList.getString(0));
image_template = xmlrpc_c::value_string(paramList.getString(1));
image_template += "\n";
// First, we need to authenticate the user
rc = ImageAllocate::upool->authenticate(session);
if ( rc == -1 )
{
goto error_authenticate;
}
uid = rc;
rc = ImageAllocate::ipool->allocate(uid,image_template,&iid);
if ( rc < 0 )
{
goto error_allocate;
}
arrayData.push_back(xmlrpc_c::value_boolean(true));
arrayData.push_back(xmlrpc_c::value_int(iid));
// Copy arrayresult into retval mem space
arrayresult = new xmlrpc_c::value_array(arrayData);
*retval = *arrayresult;
delete arrayresult; // and get rid of the original
return;
error_authenticate:
oss << "User not authenticated, aborting ImageAllocate call.";
goto error_common;
error_allocate:
if (rc == -1)
{
oss << "Error allocating image, check oned.log";
}
else
{
oss << "Error parsing image template";
}
goto error_common;
error_common:
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
NebulaLog::log("ReM",Log::ERROR,oss);
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,123 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "NebulaLog.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::ImageDelete::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
int iid;
int uid;
int rc;
Image * image;
ostringstream oss;
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
NebulaLog::log("ReM",Log::DEBUG,"ImageDelete invoked");
session = xmlrpc_c::value_string(paramList.getString(0));
iid = xmlrpc_c::value_int (paramList.getInt(1));
// First, we need to authenticate the user
rc = ImageDelete::upool->authenticate(session);
if ( rc == -1 )
{
goto error_authenticate;
}
uid = rc;
// Get image from the ImagePool
image = ImageDelete::ipool->get(iid,true);
if ( image == 0 )
{
goto error_image_get;
}
if ( uid != 0 && uid != image->get_uid() )
{
goto error_authorization;
}
rc = ImageDelete::ipool->drop(image);
if ( rc < 0 )
{
goto error_delete;
}
image->unlock();
arrayData.push_back(xmlrpc_c::value_boolean(true));
arrayData.push_back(xmlrpc_c::value_int(iid));
// Copy arrayresult into retval mem space
arrayresult = new xmlrpc_c::value_array(arrayData);
*retval = *arrayresult;
delete arrayresult; // and get rid of the original
return;
error_authenticate:
oss << "User not authenticated, aborting ImageDelete call.";
goto error_common;
error_image_get:
oss << "Error getting image with ID = " << iid;
goto error_common;
error_authorization:
oss << "User not authorized to delete image, aborting ImageDelete call.";
goto error_common;
error_delete:
oss << "Cannot delete image, VMs might be running on it.";
goto error_common;
error_common:
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
NebulaLog::log("ReM",Log::ERROR,oss);
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,129 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "NebulaLog.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::ImageEnable::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
int iid;
bool enable_flag;
int uid;
int rc;
Image * image;
ostringstream oss;
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
NebulaLog::log("ReM",Log::DEBUG,"ImageEnable invoked");
session = xmlrpc_c::value_string (paramList.getString(0));
iid = xmlrpc_c::value_int (paramList.getInt(1));
enable_flag = xmlrpc_c::value_boolean(paramList.getBoolean(2));
// First, we need to authenticate the user
rc = ImageEnable::upool->authenticate(session);
if ( rc == -1 )
{
goto error_authenticate;
}
uid = rc;
// Get image from the ImagePool
image = ImageEnable::ipool->get(iid,true);
if ( image == 0 )
{
goto error_image_get;
}
if ( uid != 0 && uid != image->get_uid() )
{
goto error_authorization;
}
rc = image->enable(enable_flag);
if ( rc < 0 )
{
goto error_enable;
}
ImageEnable::ipool->update(image);
image->unlock();
arrayData.push_back(xmlrpc_c::value_boolean(true));
arrayData.push_back(xmlrpc_c::value_int(iid));
// Copy arrayresult into retval mem space
arrayresult = new xmlrpc_c::value_array(arrayData);
*retval = *arrayresult;
delete arrayresult; // and get rid of the original
return;
error_authenticate:
oss << "[ImageEnable] User not authenticated, aborting call.";
goto error_common;
error_image_get:
oss << "[ImageEnable] Error getting image with ID = " << iid;
goto error_common;
error_authorization:
oss << "[ImageEnable] User not authorized to enable/disable image" <<
" attributes, aborting call.";
image->unlock();
goto error_common;
error_enable:
oss << "[ImageEnable] Cannot enable/disable image [" << iid << "]";
image->unlock();
goto error_common;
error_common:
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
NebulaLog::log("ReM",Log::ERROR,oss);
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,105 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "NebulaLog.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::ImageInfo::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
int iid;
int uid;
int rc;
Image * image;
ostringstream oss;
/* -- RPC specific vars -- */
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
NebulaLog::log("ReM",Log::DEBUG,"ImageInfo method invoked");
// Get the parameters
session = xmlrpc_c::value_string(paramList.getString(0));
iid = xmlrpc_c::value_int (paramList.getInt(1));
// Get image from the ImagePool
image = ImageInfo::ipool->get(iid,true);
if ( image == 0 )
{
goto error_image_get;
}
uid = image->get_uid();
// Check if it is a valid user
rc = ImageInfo::upool->authenticate(session);
if ( rc != 0 && rc != uid && !image->is_public())
{
goto error_authenticate;
}
oss << *image;
image->unlock();
// All nice, return the host info to the client
arrayData.push_back(xmlrpc_c::value_boolean(true)); // SUCCESS
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
// Copy arrayresult into retval mem space
arrayresult = new xmlrpc_c::value_array(arrayData);
*retval = *arrayresult;
delete arrayresult; // and get rid of the original
return;
error_image_get:
oss << "Error getting image with ID = " << iid;
goto error_common;
error_authenticate:
oss << "User doesn't exist, or not authorized to use image with " <<
"ID = " << iid << " , ImageInfo call aborted.";
image->unlock();
goto error_common;
error_common:
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
NebulaLog::log("ReM",Log::ERROR,oss);
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,142 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "NebulaLog.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::ImagePoolInfo::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
ostringstream oss;
ostringstream where_string;
int rc;
int uid;
int filter_flag;
/* -- RPC specific vars -- */
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
NebulaLog::log("ReM",Log::DEBUG,"ImagePoolInfo method invoked");
// Get the parameters
session = xmlrpc_c::value_string(paramList.getString(0));
filter_flag = xmlrpc_c::value_int(paramList.getInt(1));
// Check if it is a valid user
rc = ImagePoolInfo::upool->authenticate(session);
if ( rc == -1 )
{
goto error_authenticate;
}
uid = rc;
where_string.str("");
/** Filter flag meaning table
* -2 :: All Images (just for oneadmin)
* -1 :: User's Images AND public images belonging to any user
* >= 0 :: UID User's Images (just for oneadmin)
**/
if ( filter_flag < -2 )
{
goto error_filter_flag;
}
switch(filter_flag)
{
case -2:
if ( uid != 0 )
{
goto error_authorization;
}
// where remains empty.
break;
case -1:
where_string << "UID=" << uid << " OR public = 'YES'";
break;
default:
// Only oneadmin or the user can list a specific user's images.
if ( uid != 0 && uid != filter_flag )
{
goto error_authorization;
}
where_string << "UID=" << filter_flag;
}
// Call the image pool dump
rc = ImagePoolInfo::ipool->dump(oss,where_string.str());
if ( rc != 0 )
{
goto error_dump;
}
// All nice, return pool info to the client
arrayData.push_back(xmlrpc_c::value_boolean(true)); // SUCCESS
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_authenticate:
oss << "User not authenticated, ImagePoolInfo call aborted.";
goto error_common;
error_authorization:
oss << "User not authorized to perform this operation.";
goto error_common;
error_filter_flag:
oss << "Incorrect filter_flag, must be >= -2.";
goto error_common;
error_dump:
oss << "Error getting image pool";
goto error_common;
error_common:
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
NebulaLog::log("ReM",Log::ERROR,oss);
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,118 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "NebulaLog.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::ImagePublish::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
int iid;
bool publish_flag;
int uid;
int rc;
Image * image;
ostringstream oss;
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
NebulaLog::log("ReM",Log::DEBUG,"ImagePublish invoked");
session = xmlrpc_c::value_string (paramList.getString(0));
iid = xmlrpc_c::value_int (paramList.getInt(1));
publish_flag = xmlrpc_c::value_boolean(paramList.getBoolean(2));
// First, we need to authenticate the user
rc = ImagePublish::upool->authenticate(session);
if ( rc == -1 )
{
goto error_authenticate;
}
uid = rc;
// Get image from the ImagePool
image = ImagePublish::ipool->get(iid,true);
if ( image == 0 )
{
goto error_image_get;
}
if ( uid != 0 && uid != image->get_uid() )
{
goto error_authorization;
}
image->publish(publish_flag);
ImagePublish::ipool->update(image);
image->unlock();
arrayData.push_back(xmlrpc_c::value_boolean(true));
arrayData.push_back(xmlrpc_c::value_int(iid));
// Copy arrayresult into retval mem space
arrayresult = new xmlrpc_c::value_array(arrayData);
*retval = *arrayresult;
delete arrayresult; // and get rid of the original
return;
error_authenticate:
oss << "[ImagePublish] User not authenticated, aborting call.";
goto error_common;
error_image_get:
oss << "[ImagePublish] Error getting image with ID = " << iid;
goto error_common;
error_authorization:
oss << "[ImagePublish] User not authorized to publish/unpublish image" <<
", aborting call.";
image->unlock();
goto error_common;
error_common:
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
NebulaLog::log("ReM",Log::ERROR,oss);
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,129 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "NebulaLog.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::ImageRemoveAttribute::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
string name;
int iid;
int uid;
int rc;
Image * image;
ostringstream oss;
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
NebulaLog::log("ReM",Log::DEBUG,"ImageRemoveAttribute invoked");
session = xmlrpc_c::value_string(paramList.getString(0));
iid = xmlrpc_c::value_int (paramList.getInt(1));
name = xmlrpc_c::value_string(paramList.getString(2));
// First, we need to authenticate the user
rc = ImageRemoveAttribute::upool->authenticate(session);
if ( rc == -1 )
{
goto error_authenticate;
}
uid = rc;
// Get image from the ImagePool
image = ImageRemoveAttribute::ipool->get(iid,true);
if ( image == 0 )
{
goto error_image_get;
}
if ( uid != 0 && uid != image->get_uid() )
{
goto error_authorization;
}
rc = ImageRemoveAttribute::ipool->remove_attribute(image, name);
if ( rc < 0 )
{
goto error_remove_attribute;
}
image->unlock();
arrayData.push_back(xmlrpc_c::value_boolean(true));
arrayData.push_back(xmlrpc_c::value_int(iid));
// Copy arrayresult into retval mem space
arrayresult = new xmlrpc_c::value_array(arrayData);
*retval = *arrayresult;
delete arrayresult; // and get rid of the original
return;
error_authenticate:
oss << "[ImageRemoveAttribute] User not authenticated, aborting call.";
goto error_common;
error_image_get:
oss << "[ImageRemoveAttribute] Error getting image with ID = " << iid;
goto error_common;
error_authorization:
oss << "[ImageRemoveAttribute] User not authorized to remove image" <<
" attributes aborting call.";
image->unlock();
goto error_common;
error_remove_attribute:
oss << "[ImageRemoveAttribute] Cannot remove attribute with name = "
<< name << " for image [" << iid << "]";
image->unlock();
goto error_common;
error_common:
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
NebulaLog::log("ReM",Log::ERROR,oss);
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,134 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "NebulaLog.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::ImageUpdate::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
int iid;
int uid;
string name;
string value;
int rc;
Image * image;
ostringstream oss;
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
NebulaLog::log("ReM",Log::DEBUG,"ImageUpdate invoked");
session = xmlrpc_c::value_string(paramList.getString(0));
iid = xmlrpc_c::value_int (paramList.getInt(1));
name = xmlrpc_c::value_string(paramList.getString(2));
value = xmlrpc_c::value_string(paramList.getString(3));
// First, we need to authenticate the user
rc = ImageUpdate::upool->authenticate(session);
if ( rc == -1 )
{
goto error_authenticate;
}
uid = rc;
// Get image from the ImagePool
image = ImageUpdate::ipool->get(iid,true);
if ( image == 0 )
{
goto error_image_get;
}
if ( uid != 0 && uid != image->get_uid() )
{
goto error_authorization;
}
// This will perform the update on the DB as well,
// so no need to do it manually
rc = ImageUpdate::ipool->replace_attribute(image, name, value);
if ( rc < 0 )
{
goto error_update;
}
image->unlock();
arrayData.push_back(xmlrpc_c::value_boolean(true));
arrayData.push_back(xmlrpc_c::value_int(iid));
// Copy arrayresult into retval mem space
arrayresult = new xmlrpc_c::value_array(arrayData);
*retval = *arrayresult;
delete arrayresult; // and get rid of the original
return;
error_authenticate:
oss << "User not authenticated, aborting ImageUpdate call.";
goto error_common;
error_image_get:
oss << "Error getting image with ID = " << iid;
goto error_common;
error_authorization:
oss << "User not authorized to modify image attributes " <<
", aborting ImageUpdate call.";
image->unlock();
goto error_common;
error_update:
oss << "Cannot modify image [" << iid << "] attribute with name = " << name;
image->unlock();
goto error_common;
error_common:
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
NebulaLog::log("ReM",Log::ERROR,oss);
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,118 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "NebulaLog.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void RequestManager::VirtualNetworkPublish::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
int nid;
bool publish_flag;
int uid;
int rc;
VirtualNetwork * vn;
ostringstream oss;
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
NebulaLog::log("ReM",Log::DEBUG,"VirtualNetworkPublish invoked");
session = xmlrpc_c::value_string (paramList.getString(0));
nid = xmlrpc_c::value_int (paramList.getInt(1));
publish_flag = xmlrpc_c::value_boolean(paramList.getBoolean(2));
// First, we need to authenticate the user
rc = VirtualNetworkPublish::upool->authenticate(session);
if ( rc == -1 )
{
goto error_authenticate;
}
uid = rc;
// Get virtual network from the VirtualNetworkPool
vn = VirtualNetworkPublish::vnpool->get(nid,true);
if ( vn == 0 )
{
goto error_vn_get;
}
if ( uid != 0 && uid != vn->get_uid() )
{
goto error_authorization;
}
vn->publish(publish_flag);
VirtualNetworkPublish::vnpool->update(vn);
vn->unlock();
arrayData.push_back(xmlrpc_c::value_boolean(true));
arrayData.push_back(xmlrpc_c::value_int(nid));
// Copy arrayresult into retval mem space
arrayresult = new xmlrpc_c::value_array(arrayData);
*retval = *arrayresult;
delete arrayresult; // and get rid of the original
return;
error_authenticate:
oss << "[VirtualNetworkPublish] User not authenticated, aborting call.";
goto error_common;
error_vn_get:
oss << "[VirtualNetworkPublish] Error getting VN with ID = " << nid;
goto error_common;
error_authorization:
oss << "[VirtualNetworkPublish] User not authorized to (un)publish VN" <<
", aborting call.";
vn->unlock();
goto error_common;
error_common:
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
NebulaLog::log("ReM",Log::ERROR,oss);
xmlrpc_c::value_array arrayresult_error(arrayData);
*retval = arrayresult_error;
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -34,9 +34,18 @@ source_files=[
'RequestManagerHostInfo.cc',
'RequestManagerHostPoolInfo.cc',
'RequestManagerHostEnable.cc',
'RequestManagerImageAllocate.cc',
'RequestManagerImageDelete.cc',
'RequestManagerImageInfo.cc',
'RequestManagerImageUpdate.cc',
'RequestManagerImageRemoveAttribute.cc',
'RequestManagerImagePublish.cc',
'RequestManagerImageEnable.cc',
'RequestManagerImagePoolInfo.cc',
'RequestManagerVirtualNetworkAllocate.cc',
'RequestManagerVirtualNetworkInfo.cc',
'RequestManagerVirtualNetworkPoolInfo.cc',
'RequestManagerVirtualNetworkPublish.cc',
'RequestManagerVirtualNetworkDelete.cc',
'RequestManagerUserAllocate.cc',
'RequestManagerUserInfo.cc',

View File

@ -45,7 +45,7 @@ pthread_mutex_t Template::mutex = PTHREAD_MUTEX_INITIALIZER;
extern "C"
{
typedef struct yy_buffer_state * YY_BUFFER_STATE;
extern FILE *template_in, *template_out;
int template_parse(Template * tmpl, char ** errmsg);
@ -205,6 +205,33 @@ int Template::remove(const string& name, vector<Attribute *>& values)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Template::erase(const string& name)
{
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++ )
{
Attribute * attr = i->second;
delete attr;
}
attributes.erase(index.first,index.second);
return j;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Template::get(
const string& name,
vector<const Attribute*>& values) const
@ -355,9 +382,9 @@ string& Template::to_str(string& str) const
ostream& operator << (ostream& os, const Template& t)
{
string str;
os << t.to_str(str);
return os;
}

View File

@ -27,43 +27,11 @@ const char * TemplateSQL::db_names = "(id,name,type,value)";
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int TemplateSQL::insert_cb(void *nil, int num, char **values, char **names)
{
if ( num<=0 )
{
return -1;
}
if ( values[0] == 0 )
{
id = 0;
}
else
{
id = atoi(values[0]) + 1;
}
return 0;
}
/* ------------------------------------------------------------------------ */
int TemplateSQL::insert(SqlDB * db)
{
ostringstream oss;
int rc;
// Get next id from the DB table
set_callback(
static_cast<Callbackable::Callback>(&TemplateSQL::insert_cb));
oss << "SELECT MAX(id) FROM " << table;
rc = db->exec(oss,this);
unset_callback();
if ( rc != 0 )
if ( id == -1)
{
return -1;
}
@ -78,10 +46,10 @@ int TemplateSQL::insert(SqlDB * db)
int TemplateSQL::update(SqlDB * db)
{
int rc;
rc = insert_replace(db, true);
return rc;
return rc;
}
/* ------------------------------------------------------------------------ */
@ -120,7 +88,7 @@ int TemplateSQL::insert_replace(SqlDB *db, bool replace)
{
continue;
}
if(replace)
{
oss << "REPLACE";
@ -262,8 +230,6 @@ int TemplateSQL::replace_attribute(SqlDB * db, Attribute * attribute)
{
ostringstream oss;
int rc;
string * astr;
char * sql_attr;
multimap<string, Attribute *>::iterator i;
@ -272,45 +238,14 @@ int TemplateSQL::replace_attribute(SqlDB * db, Attribute * attribute)
return -1;
}
i = attributes.find(attribute->name());
rc = remove_attribute(db, attribute->name());
if ( i != attributes.end() )
if (rc == 0)
{
astr = i->second->marshall();
if ( astr == 0 )
{
return -1;
}
sql_attr = db->escape_str((*astr).c_str());
delete astr;
if ( sql_attr == 0 )
{
return -1;
}
oss << "DELETE FROM " << table << " WHERE id=" << id
<< " AND name='" << attribute->name() << "' AND value='"
<< sql_attr << "'";
rc = db->exec(oss);
db->free_str(sql_attr);
if (rc != 0 )
{
return rc;
}
delete i->second;
attributes.erase(i);
rc = insert_attribute(db,attribute);
}
return insert_attribute(db,attribute);
return rc;
}
/* ------------------------------------------------------------------------ */
@ -365,3 +300,62 @@ int TemplateSQL::insert_attribute(SqlDB * db, Attribute * attribute)
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int TemplateSQL::remove_attribute(SqlDB * db, const string& name)
{
ostringstream oss;
int rc;
string * astr;
char * sql_attr;
multimap<string, Attribute *>::iterator i;
if ( id == -1 )
{
return -1;
}
i = attributes.find(name);
if ( i != attributes.end() )
{
astr = i->second->marshall();
if ( astr == 0 )
{
return -1;
}
sql_attr = db->escape_str((*astr).c_str());
delete astr;
if ( sql_attr == 0 )
{
return -1;
}
oss << "DELETE FROM " << table << " WHERE id=" << id
<< " AND name='" << name << "' AND value='"
<< sql_attr << "'";
rc = db->exec(oss);
db->free_str(sql_attr);
if (rc != 0 )
{
return rc;
}
delete i->second;
attributes.erase(i);
}
return 0;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

View File

@ -278,6 +278,40 @@ public:
CPPUNIT_ASSERT(tr_xml == xml);
}
/* --------------------------------------------------------------------- */
void test_erase()
{
// There are Single and Vector type attributes, and any att. can be
// unique within the template, or not.
int n;
// Non-existing attribute
n = t1->erase("NON_EXISTING_ATT");
CPPUNIT_ASSERT( n == 0 );
// CPU is a Unique & Single Att.
n = t1->erase("CPU");
CPPUNIT_ASSERT( n == 1 );
// GRAPHICS is a Unique & Vector Att.
n = t1->erase("GRAPHICS");
CPPUNIT_ASSERT( n == 1 );
// MEMORY is now a Multiple & Single Att.
SingleAttribute* satt = new SingleAttribute("MEMORY", "123");
t1->set(satt);
n = t1->erase("MEMORY");
CPPUNIT_ASSERT( n == 2 );
// DISK is a Multiple & Vector Att.
n = t1->erase("DISK");
CPPUNIT_ASSERT( n == 2 );
}
/* ********************************************************************* */
/* ********************************************************************* */
@ -312,6 +346,11 @@ public:
ts->addTest(new CppUnit::TestCaller<TemplateTest>(
"set() Test",
&TemplateTest::test_set));
ts->addTest(new CppUnit::TestCaller<TemplateTest>(
"erase() Test",
&TemplateTest::test_erase));
return ts;
}
};

View File

@ -1,17 +1,20 @@
#include "TemplateSQL.h"
#include "SqliteDB.h"
#include "SqlDB.h"
#include "MySqlDB.h"
#include "Log.h"
#include <string>
#include <iostream>
#include <unistd.h>
#include <getopt.h>
#include <TestFixture.h>
#include <TestAssert.h>
#include <TestSuite.h>
#include <TestCaller.h>
#include <ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
using namespace std;
@ -34,7 +37,7 @@ public:
TemplateSQL(_table,template_id,replace,separator,xml_root){}
~TSQL(){}
/* --------------------------------------------------------------------- */
int insert(SqlDB * db){return TemplateSQL::insert(db);}
int update(SqlDB * db){return TemplateSQL::update(db);}
@ -46,43 +49,52 @@ public:
{return TemplateSQL::replace_attribute(db,attr);}
int insert_attribute(SqlDB * db, Attribute * attr)
{return TemplateSQL::insert_attribute(db,attr);}
int remove_attribute(SqlDB * db, const string& name)
{return TemplateSQL::remove_attribute(db,name);};
/* --------------------------------------------------------------------- */
int id(){return TemplateSQL::id;};
void sid(int i){TemplateSQL::id = i;}
};
/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */
class TemplateSQLTest : public CppUnit::TestFixture
class TemplateSQLTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE (TemplateSQLTest);
CPPUNIT_TEST (test_insert);
CPPUNIT_TEST (test_update);
CPPUNIT_TEST (test_select);
CPPUNIT_TEST (test_drop);
CPPUNIT_TEST (test_replace_attribute);
CPPUNIT_TEST (test_insert_attribute);
CPPUNIT_TEST (test_remove_attribute);
CPPUNIT_TEST_SUITE_END ();
private:
SqlDB *db;
string filename;
string db_name;
string template_ok;
string template_xml;
static void log(
const char * module,
const Log::MessageType type,
const ostringstream& message,
const char * filename = 0,
Log::MessageType clevel = Log::ERROR)
{
cerr << message.str() << endl;
};
public:
// Global flag to use either Sqlite or MySQL
static bool mysql;
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
TemplateSQLTest()
{
filename = "template_sql.db";
db_name = "ONE_test_database";
template_ok =
template_ok =
"#This line is a comment\n"
" # Other comment\n"
"MEMORY=345 # more comments behind an attribute\n"
@ -110,31 +122,65 @@ public:
void setUp()
{
ostringstream db_bs("CREATE TABLE template (id INTEGER, name TEXT,"
" type INTEGER, value TEXT)");
db = new SqliteDB(filename);
CPPUNIT_ASSERT(db->exec(db_bs)== 0);
if (mysql)
{
db = new MySqlDB("localhost","oneadmin","oneadmin",NULL);
ostringstream oss1;
oss1 << "DROP DATABASE IF EXISTS " << db_name;
db->exec(oss1);
ostringstream oss;
oss << "CREATE DATABASE " << db_name;
db->exec(oss);
ostringstream oss2;
oss2 << "use " << db_name;
db->exec(oss2);
}
else
{
unlink(db_name.c_str());
db = new SqliteDB(db_name);
}
ostringstream db_bs(
"CREATE TABLE IF NOT EXISTS template (id INTEGER, "
"name TEXT, type INTEGER, value TEXT)");
CPPUNIT_ASSERT(db->exec(db_bs) == 0);
}
void tearDown()
{
delete db;
unlink(filename.c_str());
if (mysql)
{
ostringstream oss;
oss << "DROP DATABASE IF EXISTS " << db_name;
db->exec(oss);
}
else
{
unlink(db_name.c_str());
}
if( db != 0 )
delete db;
}
/* ********************************************************************* */
/* ********************************************************************* */
void test_insert()
{
char * error = 0;
int rc;
string tmp;
TSQL t("template");
rc = t.parse(template_ok,&error);
if ( error != 0 )
{
cerr << error << endl;
@ -143,14 +189,52 @@ public:
CPPUNIT_ASSERT( rc == 0);
t.sid(0);
CPPUNIT_ASSERT( t.insert(db) == 0 );
CPPUNIT_ASSERT( t.id() == 0 );
t.sid(1);
CPPUNIT_ASSERT( t.insert(db) == 0 );
CPPUNIT_ASSERT( t.id() == 1 );
}
CPPUNIT_ASSERT( t.insert(db) == 0 );
CPPUNIT_ASSERT( t.id() == 2 );
/* --------------------------------------------------------------------- */
void test_update()
{
int rc;
string att_name = "NEW_ATT";
string value = "";
ostringstream db_bs(
"CREATE TABLE IF NOT EXISTS template_replace (id INTEGER, "
"name VARCHAR(256), type INTEGER, value TEXT, PRIMARY KEY(id,name))");
CPPUNIT_ASSERT(db->exec(db_bs) == 0);
TSQL t ("template_replace",0);
TSQL t2("template_replace",0);
// Insert template t into the DB
t.insert(db);
// Add a new vector attribute to t, and insert it into the DB
SingleAttribute * s_att = new SingleAttribute(att_name, "some value");
t.insert_attribute(db, ((Attribute*)s_att));
// Now replace the attribute's value
s_att->replace("a new value");
// And update the DB
t.update(db);
// Read from the DB to t2
rc = t2.select(db);
CPPUNIT_ASSERT( rc == 0 );
t2.get(att_name, value);
CPPUNIT_ASSERT( value == "a new value" );
}
/* --------------------------------------------------------------------- */
@ -160,10 +244,38 @@ public:
char * error = 0;
TSQL t("template");
TSQL t2("template",0);
TSQL t2("template",23);
string t2_xml;
t.sid(23);
t.parse(template_ok,&error);
int rc = t.insert(db);
CPPUNIT_ASSERT( rc == 0 );
if ( error != 0 )
{
free(error);
}
CPPUNIT_ASSERT( t2.select(db) == 0 );
t2.to_xml(t2_xml);
CPPUNIT_ASSERT( t2_xml == template_xml );
}
/* --------------------------------------------------------------------- */
void test_drop()
{
char * error = 0;
string str = "";
TSQL t ("template",0);
TSQL t2("template",0);
t.parse(template_ok,&error);
t.insert(db);
@ -171,47 +283,188 @@ public:
{
free(error);
}
// Drop the template from the DB
t.drop(db);
// Try to read it from the DB
CPPUNIT_ASSERT( t2.select(db) == 0 );
t2.to_xml(t2_xml);
CPPUNIT_ASSERT( t2_xml == template_xml );
// It should be empty
CPPUNIT_ASSERT( t2.to_str(str) == "" );
}
/* ********************************************************************* */
/* ********************************************************************* */
/* --------------------------------------------------------------------- */
static CppUnit::TestSuite * suite()
void test_replace_attribute()
{
CppUnit::TestSuite *ts=new CppUnit::TestSuite("TemplateSQL Tests");
ts->addTest(new CppUnit::TestCaller<TemplateSQLTest>(
"bootstrap() Test",
&TemplateSQLTest::test_insert));
ts->addTest(new CppUnit::TestCaller<TemplateSQLTest>(
"insert() Test",
&TemplateSQLTest::test_insert));
int rc;
string att_name = "NEW_ATT";
string value = "";
ts->addTest(new CppUnit::TestCaller<TemplateSQLTest>(
"select() Test",
&TemplateSQLTest::test_select));
return ts;
TSQL t ("template",0);
TSQL t2("template",0);
// Add a new vector attribute to t, and insert it into the DB
VectorAttribute * v_att = new VectorAttribute(att_name);
v_att->replace("A", "A value");
v_att->replace("B", "B value");
v_att->replace("C", "C value");
t.insert(db);
t.insert_attribute(db, ((Attribute*)v_att));
// Now replace its value, with a single value attribute
SingleAttribute * s_att = new SingleAttribute(att_name, "some value");
t.replace_attribute(db, ((Attribute*)s_att) );
// Read from the DB to t2
rc = t2.select(db);
CPPUNIT_ASSERT( rc == 0 );
t2.get(att_name, value);
CPPUNIT_ASSERT( value == "some value" );
}
/* --------------------------------------------------------------------- */
void test_insert_attribute()
{
Attribute * att;
int rc;
string att_name = "NEW_ATT";
string value = "";
TSQL t ("template",0);
TSQL t2("template",0);
// Add a new attribute to t, and insert it into the DB
att = new SingleAttribute(att_name, "some value");
t.insert(db);
t.insert_attribute(db, att);
// Read from the DB to t2
rc = t2.select(db);
CPPUNIT_ASSERT( rc == 0 );
t2.get(att_name, value);
CPPUNIT_ASSERT( value == "some value" );
}
/* --------------------------------------------------------------------- */
void test_remove_attribute()
{
Attribute * att;
int rc;
string att_name = "NEW_ATT";
string value = "";
TSQL t ("template",0);
TSQL t2("template",0);
// Add a new attribute to t, and insert it into the DB
att = new SingleAttribute(att_name, "some value");
t.insert(db);
t.insert_attribute(db, att);
t.remove_attribute(db, att_name);
// Read from the DB to t2
rc = t2.select(db);
CPPUNIT_ASSERT( rc == 0 );
t2.get(att_name, value);
CPPUNIT_ASSERT( value == "" );
}
};
/* ************************************************************************* */
bool TemplateSQLTest::mysql;
/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */
static void show_options ()
{
cout << "Options:\n";
cout << " -h --help Show this help\n"
" -s --sqlite Run Sqlite tests (default)\n"
" -m --mysql Run MySQL tests\n"
" -l --log Keep the log file, test.log\n";
}
int main(int argc, char ** argv)
{
// Option flags
bool sqlite_flag = true;
bool log_flag = false;
// Long options
const struct option long_opt[] =
{
{ "sqlite", 0, NULL, 's'},
{ "mysql", 0, NULL, 'm'},
{ "log", 0, NULL, 'l'},
{ "help", 0, NULL, 'h'}
};
int c;
while ((c = getopt_long (argc, argv, "smlh", long_opt, NULL)) != -1)
switch (c)
{
case 'm':
sqlite_flag = false;
break;
case 'l':
log_flag = true;
break;
case 'h':
show_options();
return 0;
}
CppUnit::TextUi::TestRunner tr;
tr.addTest(TemplateSQLTest::suite());
NebulaLog::init_log_system(NebulaLog::FILE, Log::DEBUG, "test.log");
NebulaLog::log("Test", Log::INFO, "Test started");
if (sqlite_flag)
{
TemplateSQLTest::mysql = false;
NebulaLog::log("Test", Log::INFO, "Running Sqlite tests...");
cout << "\nRunning Sqlite tests...\n";
}
else
{
TemplateSQLTest::mysql = true;
NebulaLog::log("Test", Log::INFO, "Running MySQL tests...");
cout << "\nRunning MySQL tests...\n";
}
tr.run();
if (!log_flag)
remove("test.log");
NebulaLog::finalize_log_system();
return 0;
}

View File

@ -83,13 +83,13 @@ VirtualMachine::~VirtualMachine()
const char * VirtualMachine::table = "vm_pool";
const char * VirtualMachine::db_names =
"(oid,uid,name,last_poll,template_id,state,lcm_state,stime,etime,deploy_id"
",memory,cpu,net_tx,net_rx,last_seq)";
"(oid,uid,name,last_poll, state,lcm_state,stime,etime,deploy_id"
",memory,cpu,net_tx,net_rx,last_seq)";
const char * VirtualMachine::db_bootstrap = "CREATE TABLE IF NOT EXISTS "
"vm_pool ("
"oid INTEGER PRIMARY KEY,uid INTEGER,name TEXT,"
"last_poll INTEGER, template_id INTEGER,state INTEGER,lcm_state INTEGER,"
"last_poll INTEGER, state INTEGER,lcm_state INTEGER,"
"stime INTEGER,etime INTEGER,deploy_id TEXT,memory INTEGER,cpu INTEGER,"
"net_tx INTEGER,net_rx INTEGER, last_seq INTEGER)";
@ -99,20 +99,19 @@ const char * VirtualMachine::db_bootstrap = "CREATE TABLE IF NOT EXISTS "
int VirtualMachine::select_cb(void *nil, int num, char **values, char **names)
{
if ((values[OID] == 0) ||
(values[UID] == 0) ||
(values[NAME] == 0) ||
(values[LAST_POLL] == 0) ||
(values[TEMPLATE_ID] == 0) ||
(values[STATE] == 0) ||
(values[LCM_STATE] == 0) ||
(values[STIME] == 0) ||
(values[ETIME] == 0) ||
(values[MEMORY] == 0) ||
(values[CPU] == 0) ||
(values[NET_TX] == 0) ||
(values[NET_RX] == 0) ||
(values[LAST_SEQ] == 0) ||
(num != LIMIT ))
(values[UID] == 0) ||
(values[NAME] == 0) ||
(values[LAST_POLL] == 0) ||
(values[STATE] == 0) ||
(values[LCM_STATE] == 0) ||
(values[STIME] == 0) ||
(values[ETIME] == 0) ||
(values[MEMORY] == 0) ||
(values[CPU] == 0) ||
(values[NET_TX] == 0) ||
(values[NET_RX] == 0) ||
(values[LAST_SEQ] == 0) ||
(num != LIMIT ))
{
return -1;
}
@ -140,7 +139,8 @@ int VirtualMachine::select_cb(void *nil, int num, char **values, char **names)
net_rx = atoi(values[NET_RX]);
last_seq = atoi(values[LAST_SEQ]);
vm_template.id = atoi(values[TEMPLATE_ID]);
// Virtual Machine template ID is the VM ID
vm_template.id = oid;
return 0;
}
@ -267,6 +267,14 @@ int VirtualMachine::insert(SqlDB * db)
string value;
ostringstream oss;
// -----------------------------------------------------------------------
// Set a template ID if it wasn't already assigned
// ------------------------------------------------------------------------
if ( vm_template.id == -1 )
{
vm_template.id = oid;
}
// -----------------------------------------------------------------------
// Set a name if the VM has not got one and VM_ID
// ------------------------------------------------------------------------
@ -277,7 +285,6 @@ int VirtualMachine::insert(SqlDB * db)
vm_template.set(attr);
get_template_attribute("NAME",name);
if ( name.empty() == true )
@ -300,13 +307,24 @@ int VirtualMachine::insert(SqlDB * db)
if ( rc != 0 )
{
goto error_leases;
goto error_leases;
}
// ------------------------------------------------------------------------
// Parse the context & requirements
// Get disk images
// ------------------------------------------------------------------------
rc = get_disk_images();
if ( rc != 0 )
{
goto error_images;
}
// -------------------------------------------------------------------------
// Parse the context & requirements
// -------------------------------------------------------------------------
rc = parse_context();
if ( rc != 0 )
@ -346,26 +364,31 @@ int VirtualMachine::insert(SqlDB * db)
error_update:
NebulaLog::log("ONE",Log::ERROR, "Can not update VM in the database");
vm_template.drop(db);
return -1;
goto error_common;
error_template:
NebulaLog::log("ONE",Log::ERROR, "Can not insert template in the database");
release_network_leases();
return -1;
goto error_common;
error_leases:
NebulaLog::log("ONE",Log::ERROR, "Could not get network lease for VM");
release_network_leases();
return -1;
error_images:
NebulaLog::log("ONE",Log::ERROR, "Could not get disk image for VM");
goto error_common;
error_context:
NebulaLog::log("ONE",Log::ERROR, "Could not parse CONTEXT for VM");
release_network_leases();
return -1;
goto error_common;
error_requirements:
NebulaLog::log("ONE",Log::ERROR, "Could not parse REQUIREMENTS for VM");
error_common:
release_network_leases();
release_disk_images();
return -1;
}
@ -530,11 +553,7 @@ int VirtualMachine::parse_requirements()
int VirtualMachine::update(SqlDB * db)
{
int rc;
rc = insert_replace(db, true);
return rc;
return insert_replace(db, true);
}
/* ------------------------------------------------------------------------ */
@ -577,7 +596,6 @@ int VirtualMachine::insert_replace(SqlDB *db, bool replace)
<< uid << ","
<< "'" << sql_name << "',"
<< last_poll << ","
<< vm_template.id << ","
<< state << ","
<< lcm_state << ","
<< stime << ","
@ -771,103 +789,119 @@ void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk)
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::get_disk_images()
{
int num_disks, rc;
vector<Attribute * > disks;
ImagePool * ipool;
VectorAttribute * disk;
Nebula& nd = Nebula::instance();
ipool = nd.get_ipool();
num_disks = vm_template.get("DISK",disks);
for(int i=0, index=0; i<num_disks; i++)
{
disk = dynamic_cast<VectorAttribute * >(disks[i]);
if ( disk == 0 )
{
continue;
}
rc = ipool->disk_attribute(disk, &index);
if (rc == -1) // 0 OK, -2 not using the Image pool
{
return -1;
}
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::release_disk_images()
{
string iid;
int num_disks;
vector<Attribute const * > disks;
Image * img;
ImagePool * ipool;
Nebula& nd = Nebula::instance();
ipool = nd.get_ipool();
num_disks = get_template_attribute("DISK",disks);
for(int i=0; i<num_disks; i++)
{
VectorAttribute const * disk =
dynamic_cast<VectorAttribute const * >(disks[i]);
if ( disk == 0 )
{
continue;
}
iid = disk->vector_value("IID");
if ( iid.empty() )
{
continue;
}
img = ipool->get(atoi(iid.c_str()),true);
if ( img == 0 )
{
continue;
}
img->release_image();
img->unlock();
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::get_network_leases()
{
int num_nics, rc;
vector<Attribute * > nics;
VirtualNetworkPool * vnpool;
VirtualNetwork * vn;
VectorAttribute * nic;
map<string,string> new_nic;
string ip;
string mac;
string bridge;
string network;
string model;
ostringstream vnid;
// Set the networking attributes.
int num_nics, rc;
vector<Attribute * > nics;
VirtualNetworkPool * vnpool;
VectorAttribute * nic;
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(""))
for(int i=0; i<num_nics; i++)
{
nic = dynamic_cast<VectorAttribute * >(nics[i]);
nic = dynamic_cast<VectorAttribute * >(nics[i]);
if ( nic == 0 )
{
continue;
}
network = nic->vector_value("NETWORK");
rc = vnpool->nic_attribute(nic, oid);
if ( network.empty() )
{
continue;
}
vn = vnpool->get(network,true);
if ( vn == 0 )
if (rc == -1)
{
return -1;
}
if ( vn->get_uid() != uid && vn->get_uid() != 0 && uid != 0)
{
ostringstream ose;
ose << "Owner " << uid << " of the VM doesn't have ownership of Virtual Network "
<< vn->get_uid();
NebulaLog::log("VMM", Log::ERROR, ose);
return -1;
}
ip = nic->vector_value("IP");
if (ip.empty())
{
rc = vn->get_lease(oid, ip, mac, bridge);
}
else
{
rc = vn->set_lease(oid, ip, mac, bridge);
}
vn->unlock();
if ( rc != 0 )
{
return -1;
}
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));
model = nic->vector_value("MODEL");
if ( !model.empty() )
{
new_nic.insert(make_pair("MODEL",model));
}
nic->replace(new_nic);
new_nic.erase(new_nic.begin(),new_nic.end());
}
return 0;

View File

@ -156,7 +156,6 @@ int VirtualMachinePool::allocate (
bool on_hold)
{
VirtualMachine * vm;
string name;
char * error_msg;
int rc;
@ -192,7 +191,7 @@ int VirtualMachinePool::allocate (
delete vm;
return -2;
return -1;
}
// ------------------------------------------------------------------------
@ -201,11 +200,6 @@ int VirtualMachinePool::allocate (
*oid = PoolSQL::allocate(vm);
if ( *oid == -1 )
{
return -1;
}
return *oid;
}

View File

@ -51,6 +51,7 @@ main_env.Append(LIBPATH=[
cwd + '/src/mad',
cwd + '/src/vnm',
cwd + '/src/um',
cwd + '/src/image',
'/usr/include/openssl/',
])
@ -62,6 +63,7 @@ main_env.Append(LIBS=[
'nebula_vnm',
'nebula_template',
'nebula_pool',
'nebula_image',
'nebula_common',
'nebula_log',
'nebula_core',

View File

@ -19,6 +19,7 @@
#include <stdlib.h>
#include "VirtualMachinePool.h"
#include "ImagePool.h"
#include "PoolTest.h"
using namespace std;

View File

@ -16,6 +16,8 @@
#include "VirtualNetwork.h"
#include "VirtualNetworkPool.h"
#include "NebulaLog.h"
#include "RangedLeases.h"
#include "FixedLeases.h"
@ -24,15 +26,13 @@
/* Virtual Network :: Constructor/Destructor */
/* ************************************************************************** */
VirtualNetwork::VirtualNetwork(unsigned int mp, int ds):
VirtualNetwork::VirtualNetwork():
PoolObjectSQL(-1),
name(""),
uid(-1),
bridge(""),
type(UNINITIALIZED),
leases(0),
mac_prefix(mp),
default_size(ds){};
leases(0){};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -49,14 +49,14 @@ VirtualNetwork::~VirtualNetwork()
/* Virtual Network :: Database Access Functions */
/* ************************************************************************** */
const char * VirtualNetwork::table = "network_pool";
const char * VirtualNetwork::table = "network_pool";
const char * VirtualNetwork::db_names = "(oid,uid,name,type,bridge)";
const char * VirtualNetwork::db_names = "(oid,uid,name,type,bridge,public)";
const char * VirtualNetwork::db_bootstrap = "CREATE TABLE IF NOT EXISTS"
const char * VirtualNetwork::db_bootstrap = "CREATE TABLE IF NOT EXISTS"
" network_pool ("
"oid INTEGER PRIMARY KEY, uid INTEGER, name VARCHAR(256), type INTEGER, "
"bridge TEXT, UNIQUE(name))";
"bridge TEXT, public INTEGER, UNIQUE(name))";
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -68,19 +68,22 @@ int VirtualNetwork::select_cb(void * nil, int num, char **values, char **names)
(!values[NAME]) ||
(!values[TYPE]) ||
(!values[BRIDGE]) ||
(!values[PUBLIC]) ||
(num != LIMIT ))
{
return -1;
}
oid = atoi(values[OID]);
uid = atoi(values[UID]);
oid = atoi(values[OID]);
uid = atoi(values[UID]);
name = values[NAME];
name = values[NAME];
type = (NetworkType)atoi(values[TYPE]);
type = (NetworkType)atoi(values[TYPE]);
bridge = values[BRIDGE];
bridge = values[BRIDGE];
public_vnet = atoi(values[PUBLIC]);
// Virtual Network template ID is the Network ID
vn_template.id = oid;
@ -101,6 +104,9 @@ int VirtualNetwork::select(SqlDB * db)
string network_address;
unsigned int default_size = VirtualNetworkPool::default_size();
unsigned int mac_prefix = VirtualNetworkPool::mac_prefix();
set_callback(
static_cast<Callbackable::Callback>(&VirtualNetwork::select_cb));
@ -222,6 +228,7 @@ int VirtualNetwork::dump(ostringstream& oss,
(!values[NAME]) ||
(!values[TYPE]) ||
(!values[BRIDGE])||
(!values[PUBLIC])||
(!values[LIMIT]) ||
(num != LIMIT + 2 ))
{
@ -236,6 +243,7 @@ int VirtualNetwork::dump(ostringstream& oss,
"<NAME>" << values[NAME] << "</NAME>" <<
"<TYPE>" << values[TYPE] << "</TYPE>" <<
"<BRIDGE>" << values[BRIDGE] << "</BRIDGE>" <<
"<PUBLIC>" << values[PUBLIC] << "</PUBLIC>" <<
"<TOTAL_LEASES>" << values[LIMIT]<< "</TOTAL_LEASES>" <<
"</VNET>";
@ -250,12 +258,69 @@ int VirtualNetwork::insert(SqlDB * db)
ostringstream ose;
int rc;
string pub;
string s_type;
unsigned int default_size = VirtualNetworkPool::default_size();
unsigned int mac_prefix = VirtualNetworkPool::mac_prefix();
//--------------------------------------------------------------------------
// VirtualNetwork Attributes from the template
//--------------------------------------------------------------------------
// ------------ TYPE ----------------------
get_template_attribute("TYPE",s_type);
transform(s_type.begin(),s_type.end(),s_type.begin(),(int(*)(int))toupper);
if (s_type == "RANGED")
{
type = VirtualNetwork::RANGED;
}
else if ( s_type == "FIXED")
{
type = VirtualNetwork::FIXED;
}
else
{
goto error_type;
}
// ------------ NAME ----------------------
get_template_attribute("NAME",name);
if (name.empty())
{
goto error_name;
}
// ------------ BRIDGE --------------------
get_template_attribute("BRIDGE",bridge);
if (bridge.empty())
{
goto error_bridge;
}
// ------------ PUBLIC --------------------
get_template_attribute("PUBLIC", pub);
transform (pub.begin(), pub.end(), pub.begin(), (int(*)(int))toupper);
public_vnet = (pub == "YES");
vn_template.erase("PUBLIC");
// ------------ TEMPLATE --------------------
if ( vn_template.id == -1 )
{
vn_template.id = oid;
}
// Insert the template first
rc = vn_template.insert(db);
if ( rc != 0 )
@ -263,7 +328,10 @@ int VirtualNetwork::insert(SqlDB * db)
goto error_template;
}
//--------------------------------------------------------------------------
// Insert the Virtual Network
//--------------------------------------------------------------------------
rc = insert_replace(db, false);
if ( rc != 0 )
@ -271,7 +339,10 @@ int VirtualNetwork::insert(SqlDB * db)
goto error_update;
}
//Get the leases
//--------------------------------------------------------------------------
// Get the leases
//--------------------------------------------------------------------------
if (type == VirtualNetwork::RANGED)
{
string nclass = "";
@ -314,7 +385,7 @@ int VirtualNetwork::insert(SqlDB * db)
mac_prefix,
naddr);
}
else if(type == VirtualNetwork::FIXED)
else // VirtualNetwork::FIXED
{
vector<const Attribute *> vector_leases;
@ -325,10 +396,6 @@ int VirtualNetwork::insert(SqlDB * db)
mac_prefix,
vector_leases);
}
else
{
goto error_type;
}
if (leases == 0)
{
@ -337,6 +404,18 @@ int VirtualNetwork::insert(SqlDB * db)
return 0;
error_type:
ose << "Wrong type in template for Virtual Network id " << oid;
goto error_common;
error_name:
ose << "No NAME in template for Virtual Network id " << oid;
goto error_common;
error_bridge:
ose << "No BRIDGE in template for Virtual Network id " << oid;
goto error_common;
error_template:
ose << "Can not insert in DB template for Virtual Network id " << oid;
goto error_common;
@ -346,10 +425,6 @@ error_update:
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;
@ -371,17 +446,7 @@ error_common:
int VirtualNetwork::update(SqlDB * db)
{
int rc;
// Update the template first
rc = vn_template.update(db);
if ( rc == 0 )
{
rc = insert_replace(db, true);
}
return rc;
return insert_replace(db, true);
}
int VirtualNetwork::insert_replace(SqlDB *db, bool replace)
@ -414,12 +479,13 @@ int VirtualNetwork::insert_replace(SqlDB *db, bool replace)
oss << "INSERT";
}
oss << " INTO " << table << " "<< db_names <<" VALUES ("<<
oid << "," <<
uid << "," <<
"'" << sql_name << "'," <<
type << "," <<
"'" << sql_bridge << "')";
oss << " INTO " << table << " "<< db_names <<" VALUES ("
<< oid << ","
<< uid << ","
<< "'" << sql_name << "',"
<< type << ","
<< "'" << sql_bridge << "',"
<< public_vnet << ")";
rc = db->exec(oss);
@ -483,14 +549,17 @@ string& VirtualNetwork::to_xml(string& xml) const
os <<
"<VNET>" <<
"<ID>" << oid << "</ID>" <<
"<UID>" << uid << "</UID>" <<
"<NAME>" << name << "</NAME>" <<
"<TYPE>" << type << "</TYPE>" <<
"<BRIDGE>"<< bridge<< "</BRIDGE>" <<
"<ID>" << oid << "</ID>" <<
"<UID>" << uid << "</UID>" <<
"<NAME>" << name << "</NAME>" <<
"<TYPE>" << type << "</TYPE>" <<
"<BRIDGE>" << bridge << "</BRIDGE>" <<
"<PUBLIC>" << public_vnet << "</PUBLIC>" <<
vn_template.to_xml(template_xml);
if (leases)
{
os << leases->to_xml(leases_xml);
}
os << "</VNET>";
xml = os.str();
@ -521,7 +590,8 @@ string& VirtualNetwork::to_str(string& str) const
os << "Fixed" << endl;
}
os << "Bridge : " << bridge << endl << endl;
os << "Bridge : " << bridge << endl;
os << "Public : " << public_vnet << endl << endl;
os << "....: Template :...." << vn_template.to_str(template_str) << endl << endl;
@ -537,3 +607,62 @@ string& VirtualNetwork::to_str(string& str) const
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualNetwork::nic_attribute(VectorAttribute *nic, int vid)
{
int rc;
string network;
string model;
string ip;
string mac;
ostringstream vnid;
map<string,string> new_nic;
network = nic->vector_value("NETWORK");
model = nic->vector_value("MODEL");
ip = nic->vector_value("IP");
vnid << oid;
//--------------------------------------------------------------------------
// GET NETWORK LEASE
//--------------------------------------------------------------------------
if (ip.empty())
{
rc = leases->get(vid,ip,mac);
}
else
{
rc = leases->set(vid,ip,mac);
}
if ( rc != 0 )
{
return -1;
}
//--------------------------------------------------------------------------
// NEW NIC ATTRIBUTES
//--------------------------------------------------------------------------
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));
if (!model.empty())
{
new_nic.insert(make_pair("MODEL",model));
}
nic->replace(new_nic);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -20,13 +20,18 @@
#include <sstream>
#include <ctype.h>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
unsigned int VirtualNetworkPool::_mac_prefix;
unsigned int VirtualNetworkPool::_default_size;
/* -------------------------------------------------------------------------- */
VirtualNetworkPool::VirtualNetworkPool(SqlDB * db,
const string& prefix,
int _default_size):
PoolSQL(db,VirtualNetwork::table),
mac_prefix(0),
default_size(_default_size)
int __default_size):
PoolSQL(db,VirtualNetwork::table)
{
istringstream iss;
size_t pos = 0;
@ -35,6 +40,9 @@ VirtualNetworkPool::VirtualNetworkPool(SqlDB * db,
string mac = prefix;
_mac_prefix = 0;
_default_size = __default_size;
while ( (pos = mac.find(':')) != string::npos )
{
mac.replace(pos,1," ");
@ -45,16 +53,16 @@ VirtualNetworkPool::VirtualNetworkPool(SqlDB * db,
{
NebulaLog::log("VNM",Log::ERROR,
"Wrong MAC prefix format, using default");
mac_prefix = 1; //"00:01"
_mac_prefix = 1; //"00:01"
return;
}
iss.str(mac);
iss >> hex >> mac_prefix >> ws >> hex >> tmp >> ws;
mac_prefix <<= 8;
mac_prefix += tmp;
iss >> hex >> _mac_prefix >> ws >> hex >> tmp >> ws;
_mac_prefix <<= 8;
_mac_prefix += tmp;
}
/* -------------------------------------------------------------------------- */
@ -68,59 +76,27 @@ int VirtualNetworkPool::allocate (
VirtualNetwork * vn;
char * error_msg;
int rc;
ostringstream oss;
string name;
string bridge;
string s_type;
// Build a new Virtual Network object
vn = new VirtualNetwork(mac_prefix, default_size);
vn = new VirtualNetwork();
vn->uid = uid;
vn->uid = uid;
rc = vn->vn_template.parse(stemplate,&error_msg);
if ( rc != 0 )
{
ostringstream oss;
oss << error_msg;
NebulaLog::log("VNM", Log::ERROR, oss);
free(error_msg);
delete vn;
return -2;
return -1;
}
// Information about the VN needs to be extracted from the template
vn->get_template_attribute("TYPE",s_type);
transform(s_type.begin(),s_type.end(),s_type.begin(),(int(*)(int))toupper);
if (s_type == "RANGED")
{
vn->type = VirtualNetwork::RANGED;
}
else if ( s_type == "FIXED")
{
vn->type = VirtualNetwork::FIXED;
}
else
{
NebulaLog::log("VNM", Log::ERROR, "Wrong type for VirtualNetwork "
"template");
delete vn;
return -3;
}
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);

View File

@ -41,7 +41,8 @@ const string templates[] =
"TYPE = RANGED\n"
"BRIDGE = br0\n"
"NETWORK_SIZE = C\n"
"NETWORK_ADDRESS = 192.168.0.0\n",
"NETWORK_ADDRESS = 192.168.0.0\n"
"PUBLIC = YES",
"NAME = \"Net number two\"\n"
"TYPE = fixed\n"
@ -68,45 +69,18 @@ const string templates[] =
const string xmls[] =
{
"<VNET><ID>0</ID><UID>123</UID><NAME>Net number one</NAME>"
"<TYPE>1</TYPE><BRIDGE>br1</BRIDGE><TEMPLATE><BRIDGE>"
"<![CDATA[br1]]></BRIDGE><LEASES><IP><![CDATA[130.10.0.1]]>"
"</IP><MAC><![CDATA[50:20:20:20:20:20]]></MAC></LEASES><NAME>"
"<![CDATA[Net number one]]></NAME><TYPE><![CDATA[FIXED]]></TYPE>"
"</TEMPLATE><LEASES>"
"<LEASE><IP>130.10.0.1</IP><MAC>50:20:20:20:20:20</MAC>"
"<USED>0</USED><VID>-1</VID></LEASE></LEASES></VNET>",
"<VNET><ID>0</ID><UID>123</UID><NAME>Net number one</NAME><TYPE>1</TYPE><BRIDGE>br1</BRIDGE><PUBLIC>0</PUBLIC><TEMPLATE><BRIDGE><![CDATA[br1]]></BRIDGE><LEASES><IP><![CDATA[130.10.0.1]]></IP><MAC><![CDATA[50:20:20:20:20:20]]></MAC></LEASES><NAME><![CDATA[Net number one]]></NAME><TYPE><![CDATA[FIXED]]></TYPE></TEMPLATE><LEASES><LEASE><IP>130.10.0.1</IP><MAC>50:20:20:20:20:20</MAC><USED>0</USED><VID>-1</VID></LEASE></LEASES></VNET>",
"<VNET><ID>1</ID><UID>261</UID><NAME>A virtual network</NAME>"
"<TYPE>0</TYPE><BRIDGE>br0</BRIDGE><TEMPLATE><BRIDGE>"
"<![CDATA[br0]]></BRIDGE><NAME><![CDATA[A virtual network]]>"
"</NAME><NETWORK_ADDRESS><![CDATA[192.168.0.0]]></NETWORK_ADDRESS>"
"<NETWORK_SIZE><![CDATA[C]]></NETWORK_SIZE><TYPE><![CDATA[RANGED]]>"
"</TYPE></TEMPLATE>"
"<LEASES></LEASES></VNET>",
"<VNET><ID>1</ID><UID>261</UID><NAME>A virtual network</NAME><TYPE>0</TYPE><BRIDGE>br0</BRIDGE><PUBLIC>1</PUBLIC><TEMPLATE><BRIDGE><![CDATA[br0]]></BRIDGE><NAME><![CDATA[A virtual network]]></NAME><NETWORK_ADDRESS><![CDATA[192.168.0.0]]></NETWORK_ADDRESS><NETWORK_SIZE><![CDATA[C]]></NETWORK_SIZE><TYPE><![CDATA[RANGED]]></TYPE></TEMPLATE><LEASES></LEASES></VNET>",
"<VNET><ID>0</ID><UID>133</UID><NAME>Net number two</NAME>"
"<TYPE>1</TYPE><BRIDGE>br1</BRIDGE><TEMPLATE><BRIDGE>"
"<![CDATA[br1]]></BRIDGE><LEASES><IP><![CDATA[130.10.2.1]]></IP>"
"<MAC><![CDATA[50:20:20:20:20:20]]></MAC></LEASES><NAME>"
"<![CDATA[Net number two]]></NAME><TYPE><![CDATA[fixed]]></TYPE>"
"</TEMPLATE>"
"<LEASES><LEASE><IP>130.10.2.1</IP>"
"<MAC>50:20:20:20:20:20</MAC><USED>0</USED><VID>-1</VID>"
"</LEASE></LEASES></VNET>"
"<VNET><ID>0</ID><UID>133</UID><NAME>Net number two</NAME><TYPE>1</TYPE><BRIDGE>br1</BRIDGE><PUBLIC>0</PUBLIC><TEMPLATE><BRIDGE><![CDATA[br1]]></BRIDGE><LEASES><IP><![CDATA[130.10.2.1]]></IP><MAC><![CDATA[50:20:20:20:20:20]]></MAC></LEASES><NAME><![CDATA[Net number two]]></NAME><TYPE><![CDATA[fixed]]></TYPE></TEMPLATE><LEASES><LEASE><IP>130.10.2.1</IP><MAC>50:20:20:20:20:20</MAC><USED>0</USED><VID>-1</VID></LEASE></LEASES></VNET>"
};
const string xml_dump =
"<VNET_POOL><VNET><ID>0</ID><UID>1</UID><USERNAME>A user</USERNAME><NAME>Ne"
"t number one</NAME><TYPE>1</TYPE><BRIDGE>br1</BRIDGE><TOTAL_LEASES>0</TOTA"
"L_LEASES></VNET><VNET><ID>1</ID><UID>2</UID><USERNAME>B user</USERNAME><NA"
"ME>A virtual network</NAME><TYPE>0</TYPE><BRIDGE>br0</BRIDGE><TOTAL_LEASES"
">0</TOTAL_LEASES></VNET></VNET_POOL>";
"<VNET_POOL><VNET><ID>0</ID><UID>1</UID><USERNAME>A user</USERNAME><NAME>Net number one</NAME><TYPE>1</TYPE><BRIDGE>br1</BRIDGE><PUBLIC>0</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES></VNET><VNET><ID>1</ID><UID>2</UID><USERNAME>B user</USERNAME><NAME>A virtual network</NAME><TYPE>0</TYPE><BRIDGE>br0</BRIDGE><PUBLIC>1</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES></VNET></VNET_POOL>";
const string xml_dump_where =
"<VNET_POOL><VNET><ID>1</ID><UID>2</UID><USERNAME>B user</USERNAME><NA"
"ME>A virtual network</NAME><TYPE>0</TYPE><BRIDGE>br0</BRIDGE><TOTAL_LEASES"
">0</TOTAL_LEASES></VNET></VNET_POOL>";
"<VNET_POOL><VNET><ID>1</ID><UID>2</UID><USERNAME>B user</USERNAME><NAME>A virtual network</NAME><TYPE>0</TYPE><BRIDGE>br0</BRIDGE><PUBLIC>1</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES></VNET></VNET_POOL>";
/* ************************************************************************* */
/* ************************************************************************* */
@ -132,6 +106,7 @@ class VirtualNetworkPoolTest : public PoolTest
CPPUNIT_TEST (overlapping_leases_rf);
CPPUNIT_TEST (overlapping_leases_rr);
CPPUNIT_TEST (drop_leases);
CPPUNIT_TEST (public_attribute);
CPPUNIT_TEST_SUITE_END ();
@ -218,15 +193,15 @@ public:
// Check template attribute
rc = allocate(3);
CPPUNIT_ASSERT( rc == -3 );
CPPUNIT_ASSERT( rc == -1 );
// Parser error for Vnet template
//TODO: Check memory leak for allocating strings in template parser
rc = allocate(4);
CPPUNIT_ASSERT( rc == -2 );
CPPUNIT_ASSERT( rc == -1 );
rc = allocate(5);
CPPUNIT_ASSERT( rc == -3 );
CPPUNIT_ASSERT( rc == -1 );
rc = allocate(6);
CPPUNIT_ASSERT( rc == -1 );
@ -832,6 +807,102 @@ public:
CPPUNIT_ASSERT(rc == 0);
CPPUNIT_ASSERT(results.size() == 0);
}
void public_attribute()
{
int oid;
VirtualNetworkPool * vnp = static_cast<VirtualNetworkPool *>(pool);
VirtualNetwork * vn;
string templates[] =
{
// false
"NAME = \"name A\"\n"
"TYPE = FIXED\n"
"BRIDGE = br1\n"
"LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]\n",
// true
"NAME = \"name B\"\n"
"TYPE = FIXED\n"
"BRIDGE = br1\n"
"LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]\n"
"PUBLIC = YES",
// false
"NAME = \"name C\"\n"
"TYPE = FIXED\n"
"BRIDGE = br1\n"
"LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]\n"
"PUBLIC = NO",
// false
"NAME = \"name D\"\n"
"TYPE = FIXED\n"
"BRIDGE = br1\n"
"LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]\n"
"PUBLIC = 1",
// true
"NAME = \"name E\"\n"
"TYPE = FIXED\n"
"BRIDGE = br1\n"
"LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]\n"
"PUBLIC = Yes",
// false
"NAME = \"name F\"\n"
"TYPE = FIXED\n"
"BRIDGE = br1\n"
"LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]\n"
"PUBLIC = TRUE",
// true
"NAME = \"name G\"\n"
"TYPE = FIXED\n"
"BRIDGE = br1\n"
"LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]\n"
"PUBLIC = yes",
// false
"NAME = \"name H\"\n"
"TYPE = FIXED\n"
"BRIDGE = br1\n"
"LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]\n"
"PUBLIC = 'YES'",
// true
"NAME = \"name I\"\n"
"TYPE = FIXED\n"
"BRIDGE = br1\n"
"LEASES = [IP=130.10.0.1, MAC=50:20:20:20:20:20]\n"
"PUBLIC = \"YES\"",
"END"
};
bool results[] = { false, true, false, false,
true, false, true, false, true };
int i = 0;
while( templates[i] != "END" )
{
vnp->allocate(0, templates[i], &oid);
CPPUNIT_ASSERT( oid >= 0 );
vn = vnp->get( oid, false );
CPPUNIT_ASSERT( vn != 0 );
//cout << endl << i << ":expected " << results[i] << " got " << vn->is_public();
CPPUNIT_ASSERT( vn->is_public() == results[i] );
i++;
}
}
};
/* ************************************************************************* */