1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-23 22:50:09 +03:00

Merge branch 'master' into feature-564

This commit is contained in:
Daniel Molina 2011-05-12 12:02:42 +02:00
commit 18a66bccf9
194 changed files with 9975 additions and 3089 deletions

View File

@ -63,6 +63,7 @@ main_env.Append(LIBPATH=[
cwd+'/src/pool',
cwd+'/src/template',
cwd+'/src/vm',
cwd+'/src/vm_template',
cwd+'/src/vmm',
cwd+'/src/lcm',
cwd+'/src/tm',
@ -127,15 +128,27 @@ else:
main_env.Append(parsers='no')
if not main_env.GetOption('clean'):
try:
if mysql=='yes':
main_env.ParseConfig('mysql_config --cflags --libs')
except Exception, e:
print ""
print "mysql_config was not found in the path"
print ""
print "Check that mysql development package is installed and"
print "mysql_config is in the path. If your mysql config tool"
print "is called mysql5_config make a symlink as mysql_config"
print "to a directory in the path."
print ""
exit(-1)
try:
main_env.ParseConfig(("LDFLAGS='%s' share/scons/get_xmlrpc_config"+
" server") % (os.environ['LDFLAGS'],))
main_env.ParseConfig(("LDFLAGS='%s' share/scons/get_xmlrpc_config"+
" client") % (os.environ['LDFLAGS'],))
if mysql=='yes':
main_env.ParseConfig('mysql_config --cflags --libs')
except Exception, e:
print ""
print "Error searching for xmlrpc-c libraries. Please check this"+\
@ -178,6 +191,7 @@ build_scripts=[
'src/nebula/SConstruct',
'src/pool/SConstruct',
'src/vm/SConstruct',
'src/vm_template/SConstruct',
'src/vmm/SConstruct',
'src/lcm/SConstruct',
'src/rm/SConstruct',
@ -228,6 +242,7 @@ if testing=='yes':
'src/vm/test/SConstruct',
'src/vnm/test/SConstruct',
'src/xml/test/SConstruct',
'src/vm_template/test/SConstruct',
])
else:
main_env.Append(testing='no')

View File

@ -39,6 +39,17 @@ public:
attribute_name.end(),
attribute_name.begin(),
(int(*)(int))toupper);
// FIX Attribute name if it does not conform XML element
// naming conventions
int size = attribute_name.size();
if ((size >0 && !isalpha(aname[0]))||
(size >=3 && (aname[0]=='X' && aname[1]=='M' && aname[2]=='L')))
{
attribute_name.insert(0,"ONE_");
}
};
virtual ~Attribute(){};
@ -82,8 +93,12 @@ public:
*/
virtual AttributeType type() = 0;
private:
/**
* Clones the current attribute
*/
virtual Attribute* clone() const = 0;
protected:
/**
* The attribute name.
*/
@ -107,6 +122,11 @@ public:
SingleAttribute(const string& name, const string& value):
Attribute(name),attribute_value(value){};
SingleAttribute(const SingleAttribute& sa):Attribute(sa.attribute_name)
{
attribute_value = sa.attribute_value;
};
~SingleAttribute(){};
/**
@ -173,6 +193,14 @@ public:
return SIMPLE;
};
/**
* Clones the current attribute
*/
Attribute* clone() const
{
return new SingleAttribute(*this);
};
private:
string attribute_value;
@ -195,6 +223,11 @@ public:
VectorAttribute(const string& name,const map<string,string>& value):
Attribute(name),attribute_value(value){};
VectorAttribute(const VectorAttribute& va):Attribute(va.attribute_name)
{
attribute_value = va.attribute_value;
};
~VectorAttribute(){};
/**
@ -256,6 +289,14 @@ public:
return VECTOR;
};
/**
* Clones the current attribute
*/
Attribute* clone() const
{
return new VectorAttribute(*this);
};
private:
static const char * magic_sep;

View File

@ -276,11 +276,12 @@ public:
*/
enum Operation
{
CREATE, /** Authorization to create an object (host, vm, net, image)*/
DELETE, /** Authorization to delete an object */
USE, /** Authorization to use an object */
MANAGE, /** Authorization to manage an object */
INFO /** Authorization to view an object */
CREATE, /** Authorization to create an object */
DELETE, /** Authorization to delete an object */
USE, /** Authorization to use an object */
MANAGE, /** Authorization to manage an object */
INFO, /** Authorization to view an object */
INSTANTIATE /** Authorization to instantiate a VM from a TEMPLATE */
};
/**
@ -293,7 +294,8 @@ public:
NET,
IMAGE,
USER,
CLUSTER
CLUSTER,
TEMPLATE
};
/**

View File

@ -181,63 +181,6 @@ public:
return 0;
};
// ------------------------------------------------------------------------
// 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 host_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 host_template.get(str,values);
};
/**
* Gets a string based host 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;
host_template.get(str,value);
}
/**
* Gets a string based host 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;
host_template.get(str,value);
}
// ------------------------------------------------------------------------
// Share functions
// ------------------------------------------------------------------------
@ -394,12 +337,6 @@ private:
// -------------------------------------------------------------------------
// Host Attributes
// -------------------------------------------------------------------------
/**
* The Host template, holds the Host attributes.
*/
HostTemplate host_template;
/**
* The Share represents the logical capacity associated with the host
*/

View File

@ -47,7 +47,9 @@ public:
INIT = 0, /** < Initialization state */
READY = 1, /** < Image ready to use */
USED = 2, /** < Image in use */
DISABLED = 3 /** < Image can not be instantiated by a VM */
DISABLED = 3, /** < Image can not be instantiated by a VM */
LOCKED = 4, /** < FS operation for the Image in process */
ERROR = 5 /** < Error state the operation FAILED*/
};
/**
@ -92,6 +94,74 @@ public:
return (persistent_img == 1);
};
/**
* Returns the source path of the image
* @return source of image
*/
const string& get_source()
{
return source;
}
/**
* Returns the source path of the image
* @return source of image
*/
void set_source(const string& _source)
{
source = _source;
}
/**
* Returns the type of the image
* @return type
*/
ImageType get_type()
{
return type;
}
/**
* Returns the image state
* @return state of image
*/
ImageState get_state()
{
return state;
}
/**
* Sets the image state
* @param state of image
*/
void set_state(ImageState _state)
{
state = _state;
}
/**
*
*/
int dec_running ()
{
return --running_vms;
}
/**
*
*/
int inc_running()
{
return ++running_vms;
}
/**
*
*/
int get_running()
{
return running_vms;
}
/**
* Set enum type
* @return 0 on success, -1 otherwise
@ -120,47 +190,6 @@ public:
return rc;
}
/**
* Get an image to be used in a VM, and updates its state.
* @return 0 if success
*/
int acquire_image();
/**
* Releases an image being used by a VM
* @return true if the image needs to be updated
*/
bool 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 )
{
if(state == DISABLED)
{
state = READY;
}
}
else if (state != USED) // to_enable == false
{
state = DISABLED;
}
else
{
rc = -1;
}
return rc;
}
/**
* Publish or unpublish an image
* @param pub true to publish the image
@ -230,93 +259,6 @@ public:
*/
int disk_attribute(VectorAttribute * disk, int* index, ImageType* img_type);
// ------------------------------------------------------------------------
// 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(const string& name)
{
return image_template->erase(name);
}
/**
* Adds a new attribute to the template (replacing it if
* already defined), the image's mutex SHOULD be locked
* @param name of the new attribute
* @param value of the new attribute
* @return 0 on success
*/
int replace_template_attribute(
const string& name,
const string& value)
{
SingleAttribute * sattr;
image_template->erase(name);
sattr = new SingleAttribute(name,value);
image_template->set(sattr);
return 0;
}
private:
// -------------------------------------------------------------------------
@ -369,16 +311,6 @@ private:
*/
int running_vms;
// -------------------------------------------------------------------------
// Image Attributes
// -------------------------------------------------------------------------
/**
* The Image template, holds the Image attributes.
*/
ImageTemplate * image_template;
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************
@ -401,13 +333,12 @@ private:
db->exec(oss_image);
};
/**
* "Encrypts" the password with SHA1 digest
* @param password
* @return sha1 encrypted password
*/
string sha1_digest(const string& pass);
static string sha1_digest(const string& pass);
protected:

204
include/ImageManager.h Normal file
View File

@ -0,0 +1,204 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef IMAGE_MANAGER_H_
#define IMAGE_MANAGER_H_
#include "MadManager.h"
#include "ActionManager.h"
#include "ImageManagerDriver.h"
using namespace std;
extern "C" void * image_action_loop(void *arg);
class Image;
class ImageManager : public MadManager, public ActionListener
{
public:
ImageManager(ImagePool * _ipool, vector<const Attribute*>& _mads):
MadManager(_mads), ipool(_ipool)
{
am.addListener(this);
};
~ImageManager(){};
/**
* This functions starts the associated listener thread, and creates a
* new thread for the Information Manager. This thread will wait in
* an action loop till it receives ACTION_FINALIZE.
* @return 0 on success.
*/
int start();
/**
* Loads the Image Driver defined in configuration file
* @param uid of the user executing the driver. When uid is 0 the nebula
* identity will be used. Otherwise the Mad will be loaded through the
* sudo application.
*/
void load_mads(int uid=0);
/**
* Gets the thread identification.
* @return pthread_t for the manager thread (that in the action loop).
*/
pthread_t get_thread_id() const
{
return imagem_thread;
};
/**
* Finalizes the Image Manager
*/
void finalize()
{
am.trigger(ACTION_FINALIZE,0);
};
/**************************************************************************/
/* Image Manager Actions */
/* Operates in a semi-sinchronous mode. Operations will be granted or not */
/* , when needed the image repository drivers will be used to perform FS */
/* operations in the background. */
/**************************************************************************/
/**
* Try to acquire an image from the repository for a VM.
* @param image_id id of image
* @return pointer to the image or 0 if could not be acquired
*/
Image * acquire_image(int image_id);
/**
* Try to acquire an image from the repository for a VM.
* @param name of the image
* @param id of owner
* @return pointer to the image or 0 if could not be acquired
*/
Image * acquire_image(const string& name, int uid);
/**
* Releases an image and triggers any needed operations in the repo
* @param iid image id of the image to be released
* @param disk_path base path for disk location
* @param disk number for this image in the VM
* @param saveid id of image to save the current image
*/
void release_image(const string& iid,
const string& disk_path,
int disk_num,
const string& saveid);
/**
* Moves a VM disk to the Image Repository
* @param disk_path base path for disk location
* @param disk number for this image in the VM
* @param saveid id of image to save the current image
*/
void disk_to_image(const string& disk_path,
int disk_num,
const string& save_id);
/**
* Enables the image
* @param to_enable true will enable the image.
* @return 0 on success
*/
int enable_image(int iid, bool to_enable);
/**
* Adds a new image to the repository copying or creating it as needed
* @param iid id of image
* @return 0 on success
*/
int register_image(int iid);
/**
* Deletes an image from the repository and the DB
* @param iid id of image
* @return 0 on success
*/
int delete_image(int iid);
private:
/**
* Generic name for the Image driver
*/
static const char * image_driver_name;
/**
* Thread id for the Transfer Manager
*/
pthread_t imagem_thread;
/**
* Pointer to the Image Pool to access VMs
*/
ImagePool * ipool;
/**
* Action engine for the Manager
*/
ActionManager am;
/**
* Returns a pointer to the Image Manager Driver used for the Repository
* @return the Image Manager driver or 0 in not found
*/
const ImageManagerDriver * get()
{
string name("NAME");
return static_cast<const ImageManagerDriver *>
(MadManager::get(0,name,image_driver_name));
};
/**
* Function to execute the Manager action loop method within a new pthread
* (requires C linkage)
*/
friend void * image_action_loop(void *arg);
/**
* The action function executed when an action is triggered.
* @param action the name of the action
* @param arg arguments for the action function
*/
void do_action(
const string & action,
void * arg);
/**
* Acquires an image updating its state.
* @param image pointer to image, it should be locked
* @return 0 on success
*/
int acquire_image(Image *img);
/**
* Moves a file to an image in the repository
* @param image to be updated (it's source attribute)
* @param source path of the disk file
*/
void move_image(Image *img, const string& source);
};
#endif /*IMAGE_MANAGER_H*/

View File

@ -0,0 +1,105 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef IMAGE_MANAGER_DRIVER_H_
#define IMAGE_MANAGER_DRIVER_H_
#include <map>
#include <string>
#include <sstream>
#include "Mad.h"
using namespace std;
//Forward definition of related classes
class ImagePool;
class ImageManager;
/**
* ImageManagerDriver represents the basic abstraction for Image Repository
* drivers. It implements the protocol and recover functions from the Mad
* interface.
*/
class ImageManagerDriver : public Mad
{
public:
ImageManagerDriver(int userid,
const map<string,string>& attrs,
bool sudo,
ImagePool* _ipool):
Mad(userid,attrs,sudo),ipool(_ipool){};
virtual ~ImageManagerDriver(){};
/**
* Implements the Image Manager driver protocol.
* @param message the string read from the driver
*/
void protocol(string& message);
/**
* TODO: What do we need here? Check on-going xfr?
*/
void recover();
private:
friend class ImageManager;
/**
* Reference to the ImagePool
*/
ImagePool * ipool;
/**
* Configuration file for the driver
*/
//Template driver_conf;
void cp(int oid, const string& source) const;
/**
* Sends a move request to the MAD: "MV IMAGE_ID SRC_PATH DST_PATH"
* @param oid the image id.
* @param destination is a driver specific location or "-" if not
* initialized
* @param size_mb of the image to be created
*/
void mv(int oid, const string& source, const string& destination) const;
/**
* Sends a make filesystem request to the MAD: "MKFS IMAGE_ID PATH SIZE_MB"
* @param oid the image id.
* @param fs type
* @param size_mb of the image to be created
*/
void mkfs(int oid,
const string& fs,
const string& size_mb) const;
/**
* Sends a delete request to the MAD: "DELETE IMAGE_ID PATH"
* @param oid the image id.
* @param destination is the path to the image to be removed
*/
void rm(int oid, const string& destination) const;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#endif /*IMAGE_MANAGER_DRIVER_H_*/

View File

@ -39,7 +39,6 @@ class ImagePool : public PoolSQL
public:
ImagePool(SqlDB * db,
const string& _source_prefix,
const string& _default_type,
const string& _default_dev_prefix);
@ -146,11 +145,6 @@ public:
*/
void authorize_disk(VectorAttribute * disk, int uid, AuthRequest * ar);
static const string& source_prefix()
{
return _source_prefix;
};
static const string& default_type()
{
return _default_type;
@ -165,10 +159,6 @@ private:
//--------------------------------------------------------------------------
// Configuration Attributes for Images
// -------------------------------------------------------------------------
/**
* Path to the image repository
**/
static string _source_prefix;
/**
* Default image type

View File

@ -26,6 +26,8 @@
#include <unistd.h>
#include "Log.h"
using namespace std;
/**
@ -68,12 +70,11 @@ protected:
{
string str;
const char * cstr;
size_t retval;
str = os.str();
cstr = str.c_str();
retval = ::write(nebula_mad_pipe, cstr, str.size());
::write(nebula_mad_pipe, cstr, str.size());
};
/**
@ -89,6 +90,32 @@ protected:
write(os);
};
/**
* Sets the log message type as specify by the driver.
* @param first character of the type string
* @return the message type
*/
Log::MessageType log_type(const char r)
{
Log::MessageType lt;
switch (r)
{
case 'E':
lt = Log::ERROR;
break;
case 'I':
lt = Log::INFO;
break;
case 'D':
lt = Log::DEBUG;
break;
default:
lt = Log::INFO;
}
return lt;
}
private:
friend class MadManager;
@ -141,7 +168,7 @@ private:
* @return 0 on success
*/
int reload();
/**
* Implements the driver specific protocol, this function should trigger
* actions on the associated manager.

View File

@ -43,11 +43,11 @@ class MySqlDB : public SqlDB
{
public:
MySqlDB(const string& server,
int port,
const string& user,
const string& password,
const char * database);
MySqlDB(const string& _server,
int _port,
const string& _user,
const string& _password,
const string& _database);
~MySqlDB();
@ -81,6 +81,19 @@ private:
*/
MYSQL * db;
/**
* MySQL Connection parameters
*/
string server;
int port;
string user;
string password;
string database;
/**
* Fine-grain mutex for DB access
*/
@ -113,7 +126,7 @@ public:
int port,
string user,
string password,
const char * database)
string database)
{
throw runtime_error("Aborting oned, MySQL support not compiled!");
};

View File

@ -25,6 +25,7 @@
#include "VirtualNetworkPool.h"
#include "HostPool.h"
#include "UserPool.h"
#include "VMTemplatePool.h"
#include "VirtualMachineManager.h"
#include "LifeCycleManager.h"
@ -34,6 +35,7 @@
#include "RequestManager.h"
#include "HookManager.h"
#include "AuthManager.h"
#include "ImageManager.h"
class Nebula
{
@ -80,6 +82,11 @@ public:
return cpool;
};
VMTemplatePool * get_tpool()
{
return tpool;
};
// --------------------------------------------------------------
// Manager Accessors
// --------------------------------------------------------------
@ -114,12 +121,16 @@ public:
return hm;
};
AuthManager * get_authm()
{
return authm;
};
ImageManager * get_imagem()
{
return imagem;
};
// --------------------------------------------------------------
// Environment & Configuration
// --------------------------------------------------------------
@ -228,8 +239,9 @@ private:
//Constructors and = are private to only access the class through instance
// -----------------------------------------------------------------------
Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0),upool(0),
ipool(0),cpool(0),lcm(0),vmm(0),im(0),tm(0),dm(0),rm(0),hm(0),authm(0)
Nebula():nebula_configuration(0),db(0),vmpool(0),hpool(0),vnpool(0),
upool(0),ipool(0),cpool(0),tpool(0),lcm(0),vmm(0),im(0),tm(0),dm(0),
rm(0),hm(0),authm(0),imagem(0)
{
const char * nl = getenv("ONE_LOCATION");
@ -294,6 +306,11 @@ private:
delete cpool;
}
if ( tpool != 0)
{
delete tpool;
}
if ( vmm != 0)
{
delete vmm;
@ -334,6 +351,11 @@ private:
delete authm;
}
if ( imagem != 0)
{
delete imagem;
}
if ( nebula_configuration != 0)
{
delete nebula_configuration;
@ -381,6 +403,7 @@ private:
UserPool * upool;
ImagePool * ipool;
ClusterPool * cpool;
VMTemplatePool * tpool;
// ---------------------------------------------------------------
// Nebula Managers
@ -394,6 +417,7 @@ private:
RequestManager * rm;
HookManager * hm;
AuthManager * authm;
ImageManager * imagem;
// ---------------------------------------------------------------
// Implementation functions

View File

@ -19,6 +19,7 @@
#include "ObjectSQL.h"
#include "ObjectXML.h"
#include "Template.h"
#include <pthread.h>
#include <string.h>
@ -32,14 +33,13 @@ using namespace std;
* implementation assumes that the mutex IS LOCKED when the class destructor
* is called.
*/
class PoolObjectSQL : public ObjectSQL, public ObjectXML
{
public:
PoolObjectSQL(int id, const string& _name, int _uid,const char *_table)
:ObjectSQL(),ObjectXML(),oid(id),name(_name),uid(_uid),
valid(true),table(_table)
valid(true),obj_template(0),table(_table)
{
pthread_mutex_init(&mutex,0);
};
@ -119,6 +119,110 @@ public:
*/
virtual int from_xml(const string &xml_str) = 0;
// ------------------------------------------------------------------------
// 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 obj_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 obj_template->get(str,values);
};
/**
* Gets a string based attribute (single)
* @param name of the attribute
* @param value of the attribute (a string), will be "" if not defined or
* not a single attribute
*/
void get_template_attribute(
const char * name,
string& value) const
{
string str=name;
obj_template->get(str,value);
}
/**
* Gets an int based attribute (single)
* @param name of the attribute
* @param value of the attribute (an int), will be 0 if not defined or
* not a single attribute
*/
void get_template_attribute(
const char * name,
int& value) const
{
string str=name;
obj_template->get(str,value);
}
/**
* Adds a new attribute to the template (replacing it if
* already defined), the object's mutex SHOULD be locked
* @param name of the new attribute
* @param value of the new attribute
* @return 0 on success
*/
int replace_template_attribute(
const string& name,
const string& value)
{
SingleAttribute * sattr = new SingleAttribute(name,value);
obj_template->erase(sattr->name());
obj_template->set(sattr);
return 0;
}
/**
* Generates a XML string for the template of the Object
* @param xml the string to store the XML description.
*/
void template_to_xml(string &xml) const
{
obj_template->to_xml(xml);
}
/**
* Removes an Image attribute
* @param name of the attribute
*/
int remove_template_attribute(const string& name)
{
return obj_template->erase(name);
}
/**
* Sets an error message for the VM in the template
* @param message
* @return 0 on success
*/
void set_template_error_message(const string& message);
protected:
/**
@ -198,6 +302,11 @@ protected:
*/
bool valid;
/**
* Template for this object, will be allocated if needed
*/
Template * obj_template;
private:
/**
@ -215,6 +324,11 @@ private:
* Pointer to the SQL table for the PoolObjectSQL
*/
const char * table;
/**
* Name for the error messages attribute
*/
static const char * error_attribute_name;
};
#endif /*POOL_OBJECT_SQL_H_*/

View File

@ -24,6 +24,7 @@
#include "VirtualNetworkPool.h"
#include "ImagePool.h"
#include "ClusterPool.h"
#include "VMTemplatePool.h"
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
@ -46,10 +47,11 @@ public:
UserPool * _upool,
ImagePool * _ipool,
ClusterPool * _cpool,
VMTemplatePool * _tpool,
int _port,
string _xml_log_file)
:vmpool(_vmpool),hpool(_hpool),vnpool(_vnpool),upool(_upool),
ipool(_ipool),cpool(_cpool),port(_port),socket_fd(-1),
ipool(_ipool),cpool(_cpool),tpool(_tpool),port(_port),socket_fd(-1),
xml_log_file(_xml_log_file)
{
am.addListener(this);
@ -130,10 +132,15 @@ private:
ImagePool * ipool;
/**
* Pointer to the Image Pool, to access images
* Pointer to the Cluster Pool, to access clusters
*/
ClusterPool * cpool;
/**
* Pointer to the Template Pool, to access templates
*/
VMTemplatePool * tpool;
/**
* Port number where the connection will be open
*/
@ -314,10 +321,12 @@ private:
VirtualMachinePool * _vmpool,
VirtualNetworkPool * _vnpool,
ImagePool * _ipool,
VMTemplatePool * _tpool,
UserPool * _upool):
vmpool(_vmpool),
vnpool(_vnpool),
ipool(_ipool),
tpool(_tpool),
upool(_upool)
{
_signature="A:ss";
@ -333,6 +342,7 @@ private:
VirtualMachinePool * vmpool;
VirtualNetworkPool * vnpool;
ImagePool * ipool;
VMTemplatePool * tpool;
UserPool * upool;
};
@ -459,8 +469,9 @@ private:
upool(_upool),
ipool(_ipool)
{
_signature="A:siii";
_help="Sets the disk to be saved in the given image.";
_signature="A:siis";
_help = "Sets the disk to be saved in a new Image with the given "
"name.";
};
~VirtualMachineSaveDisk(){};
@ -501,6 +512,185 @@ private:
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
/* Template Interface */
/* ---------------------------------------------------------------------- */
class TemplateAllocate: public xmlrpc_c::method
{
public:
TemplateAllocate(
VMTemplatePool * _tpool,
UserPool * _upool):
tpool(_tpool),
upool(_upool)
{
_signature="A:ss";
_help="Allocates a template in the pool";
};
~TemplateAllocate(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
VMTemplatePool * tpool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class TemplateDelete: public xmlrpc_c::method
{
public:
TemplateDelete(VMTemplatePool * _tpool,
UserPool * _upool):
tpool(_tpool),
upool(_upool)
{
_signature="A:si";
_help="Deletes a Template";
};
~TemplateDelete(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
VMTemplatePool * tpool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class TemplateInfo: public xmlrpc_c::method
{
public:
TemplateInfo(VMTemplatePool * _tpool,
UserPool * _upool):
tpool(_tpool),
upool(_upool)
{
_signature="A:si";
_help="Returns information for a Template";
};
~TemplateInfo(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
VMTemplatePool * tpool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class TemplateUpdate: public xmlrpc_c::method
{
public:
TemplateUpdate(VMTemplatePool * _tpool,
UserPool * _upool):
tpool(_tpool),
upool(_upool)
{
_signature="A:siss";
_help="Modifies Template attribute";
};
~TemplateUpdate(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
VMTemplatePool * tpool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class TemplateRemoveAttribute: public xmlrpc_c::method
{
public:
TemplateRemoveAttribute(VMTemplatePool * _tpool,
UserPool * _upool):
tpool(_tpool),
upool(_upool)
{
_signature="A:sis";
_help="Removes Template attribute";
};
~TemplateRemoveAttribute(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
VMTemplatePool * tpool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class TemplatePublish: public xmlrpc_c::method
{
public:
TemplatePublish(VMTemplatePool * _tpool,
UserPool * _upool):
tpool(_tpool),
upool(_upool)
{
_signature="A:sib";
_help="Publish/Unpublish the Template";
};
~TemplatePublish(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
VMTemplatePool * tpool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
class TemplatePoolInfo: public xmlrpc_c::method
{
public:
TemplatePoolInfo(
VMTemplatePool * _tpool,
UserPool * _upool):
tpool(_tpool),
upool(_upool)
{
_signature="A:sii";
_help="Returns the template pool";
};
~TemplatePoolInfo(){};
void execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP);
private:
VMTemplatePool * tpool;
UserPool * upool;
};
/* ---------------------------------------------------------------------- */
/* Host Interface */
/* ---------------------------------------------------------------------- */

View File

@ -47,6 +47,20 @@ public:
separator(_separator),
xml_root(_xml_root){};
Template(const Template& t)
{
multimap<string,Attribute *>::const_iterator it;
replace_mode = t.replace_mode;
separator = t.separator;
xml_root = t.xml_root;
for (it = t.attributes.begin() ; it != t.attributes.end() ; it++)
{
attributes.insert(make_pair(it->first,(it->second)->clone()));
}
}
/**
* The class destructor frees all the attributes conforming the template
*/
@ -161,8 +175,10 @@ public:
* @param name the attribute name.
* @param value the attribute value, an int, 0 if the attribute is not
* defined or not Single
*
* @returns True if the Single attribute was found
*/
virtual void get(
virtual bool get(
string& name,
int& value) const;

View File

@ -134,15 +134,6 @@ private:
*/
int insert_replace(SqlDB *db, bool replace);
/**
* Callback function to unmarshall a User object (User::select)
* @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 select_cb(void *nil, int num, char **values, char **names);
/**
* Bootstraps the database table(s) associated to the User
*/

190
include/VMTemplate.h Normal file
View File

@ -0,0 +1,190 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef VMTEMPLATE_H_
#define VMTEMPLATE_H_
#include "PoolObjectSQL.h"
#include "VirtualMachineTemplate.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/**
* The VMTemplate class.
*/
class VMTemplate : public PoolObjectSQL
{
public:
/**
* Function to write a VMTemplate on an output stream
*/
friend ostream& operator<<(ostream& os, VMTemplate& u);
/**
* Function to print the VMTemplate 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;
/**
* Returns true if the object is public
* @return true if the Virtual Network is public
*/
bool isPublic()
{
return (public_template == 1);
};
/**
* Publish or unpublish an object
* @param pub true to publish the object
* @return 0 on success
*/
bool publish(bool pub)
{
if (pub == true)
{
public_template = 1;
}
else
{
public_template = 0;
}
return true;
};
// ------------------------------------------------------------------------
// Template Contents
// ------------------------------------------------------------------------
/**
* Returns a copy of the VirtualMachineTemplate
* @return A copy of the VirtualMachineTemplate
*/
VirtualMachineTemplate * clone_template() const
{
return new VirtualMachineTemplate(
*(static_cast<VirtualMachineTemplate *>(obj_template)));
// TODO: Check if there is a more efficient way to do this copy.
/*string xml_str;
VirtualMachineTemplate * new_template = new VirtualMachineTemplate();
obj_template->to_xml(xml_str);
new_template->from_xml(xml_str);
return new_template;*/
};
private:
// -------------------------------------------------------------------------
// Friends
// -------------------------------------------------------------------------
friend class VMTemplatePool;
// -------------------------------------------------------------------------
// VMTemplate Attributes
// -------------------------------------------------------------------------
/**
* Owner's name
*/
string user_name;
/**
* Public scope of the VMTemplate
*/
int public_template;
/**
* Registration time
*/
time_t regtime;
// *************************************************************************
// 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 one success
*/
int insert_replace(SqlDB *db, bool replace);
/**
* Bootstraps the database table(s) associated to the VMTemplate
*/
static void bootstrap(SqlDB * db)
{
ostringstream oss(VMTemplate::db_bootstrap);
db->exec(oss);
};
/**
* Rebuilds the object from an xml formatted string
* @param xml_str The xml-formatted string
*
* @return 0 on success, -1 otherwise
*/
int from_xml(const string &xml_str);
protected:
// *************************************************************************
// Constructor
// *************************************************************************
VMTemplate(int id, int uid, string _user_name,
VirtualMachineTemplate * _template_contents);
~VMTemplate();
// *************************************************************************
// DataBase implementation
// *************************************************************************
static const char * db_names;
static const char * db_bootstrap;
static const char * table;
/**
* Writes the VMTemplate in the database.
* @param db pointer to the db
* @return 0 on success
*/
int insert(SqlDB *db, string& error_str);
/**
* Writes/updates the VMTemplate data fields in the database.
* @param db pointer to the db
* @return 0 on success
*/
int update(SqlDB *db)
{
return insert_replace(db, true);
};
};
#endif /*VMTEMPLATE_H_*/

146
include/VMTemplatePool.h Normal file
View File

@ -0,0 +1,146 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef VMTEMPLATE_POOL_H_
#define VMTEMPLATE_POOL_H_
#include "PoolSQL.h"
#include "VMTemplate.h"
/**
* The VMTemplate Pool class.
*/
class VMTemplatePool : public PoolSQL
{
public:
VMTemplatePool(SqlDB * db) : PoolSQL(db, VMTemplate::table){};
~VMTemplatePool(){};
/**
* Allocates a new object, writting it in the pool database. No memory is
* allocated for the object.
* @param uid user id (the owner of the Template)
* @param user_name Owner's user name
* @param template_contents a VM Template object
* @param oid the id assigned to the Template
* @param error_str Returns the error reason, if any
*
* @return the oid assigned to the object, -1 in case of failure
*/
int allocate(int uid,
string user_name,
VirtualMachineTemplate * template_contents,
int * oid,
string& error_str);
/**
* Gets an object from the pool (if needed the object is loaded from the
* database).
* @param oid the object unique identifier
* @param lock locks the object if true
*
* @return a pointer to the object, 0 in case of failure
*/
VMTemplate * get(int oid, bool lock)
{
return static_cast<VMTemplate *>(PoolSQL::get(oid,lock));
};
/**
* Gets an object from the pool (if needed the object is loaded from the
* database).
* @param name of the object
* @param uid id of owner
* @param lock locks the object if true
*
* @return a pointer to the object, 0 in case of failure
*/
VMTemplate * get(const string& name, int uid, bool lock)
{
return static_cast<VMTemplate *>(PoolSQL::get(name,uid,lock));
};
/**
* Updates the object's data in the data base. The object mutex SHOULD be
* locked.
* @param objsql a pointer to the object
*
* @return 0 on success.
*/
int update(VMTemplate * vm_template)
{
return vm_template->update(db);
};
/**
* Drops the object's data in the data base. The object mutex SHOULD be
* locked.
* @param objsql a pointer to the object
* @return 0 on success.
*/
int drop(VMTemplate * vm_template)
{
return PoolSQL::drop(vm_template);
};
/**
* Dumps the pool in XML format. A filter can be also added to the
* query
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where)
{
return PoolSQL::dump(oss, "VMTEMPLATE_POOL",VMTemplate::table,where);
};
/**
* Bootstraps the database table(s) associated to the pool
*/
static void bootstrap(SqlDB *_db)
{
VMTemplate::bootstrap(_db);
};
private:
//--------------------------------------------------------------------------
// Configuration Attributes for Images
// -------------------------------------------------------------------------
// TODO
//--------------------------------------------------------------------------
// Pool Attributes
// -------------------------------------------------------------------------
// TODO
/**
* Factory method to produce Image objects
* @return a pointer to the new Image
*/
PoolObjectSQL * create()
{
return new VMTemplate(-1,-1,"", 0);
};
};
#endif /*VMTEMPLATE_POOL_H_*/

View File

@ -532,93 +532,6 @@ public:
// ------------------------------------------------------------------------
// 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 vm_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 vm_template->get(str,values);
};
/**
* Gets a string based VM attribute (single)
* @param name of the attribute
* @param value of the attribute (a string), will be "" if not defined or
* not a single attribute
*/
void get_template_attribute(
const char * name,
string& value) const
{
string str=name;
vm_template->get(str,value);
}
/**
* Gets an int based VM attribute (single)
* @param name of the attribute
* @param value of the attribute (an int), will be 0 if not defined or
* not a single attribute
*/
void get_template_attribute(
const char * name,
int& value) const
{
string str=name;
vm_template->get(str,value);
}
/**
* Adds a new attribute to the template (replacing it if
* already defined), the vm's mutex SHOULD be locked
* @param name of the new attribute
* @param value of the new attribute
* @return 0 on success
*/
int replace_template_attribute(
string& name,
string& value)
{
SingleAttribute * sattr;
vm_template->erase(name);
sattr = new SingleAttribute(name,value);
vm_template->set(sattr);
return 0;
}
/**
* Generates a XML string for the template of the VM
* @param xml the string to store the XML description.
*/
void template_to_xml(string &xml) const
{
vm_template->to_xml(xml);
}
/**
* Parse a string and substitute variables (e.g. $NAME) using the VM
* template values:
@ -626,12 +539,11 @@ public:
* @param parsed, the resulting parsed string
* @return 0 on success.
*/
int parse_template_attribute(const string& attribute,
string& parsed);
int parse_template_attribute(const string& attribute, string& parsed);
// ------------------------------------------------------------------------
// States
// ------------------------------------------------------------------------
/**
* Returns the VM state (Dispatch Manager)
* @return the VM state
@ -743,7 +655,7 @@ public:
* @param img_id ID of the image this disk will be saved to.
* @return 0 if success
*/
int save_disk(int disk_id, int img_id);
int save_disk(int disk_id, int img_id, string& error_str);
private:
@ -775,14 +687,6 @@ private:
// -------------------------------------------------------------------------
// Virtual Machine Description
// -------------------------------------------------------------------------
/**
* The Virtual Machine template, holds the VM attributes.
*/
VirtualMachineTemplate* vm_template;
// Dynamic state of the Virtual Machine
/**
* The state of the virtual machine.
*/
@ -914,7 +818,6 @@ private:
return -1;
};
// -------------------------------------------------------------------------
// Attribute Parser
// -------------------------------------------------------------------------

View File

@ -41,8 +41,10 @@ public:
/**
* Function to allocate a new VM object
* @param uid user id (the owner of the VM)
* @param user_name Owner's user name
* @param vm_template a VM Template object describing the VM
* @param oid the id assigned to the VM (output)
* @param error_str Returns the error reason, if any
* @param on_hold flag to submit on hold
* @return oid on success, -1 error inserting in DB or -2 error parsing
* the template

View File

@ -19,6 +19,8 @@
#include "Template.h"
#include <string.h>
using namespace std;
/**
@ -32,6 +34,8 @@ public:
~VirtualMachineTemplate(){};
VirtualMachineTemplate(VirtualMachineTemplate& vmt):Template(vmt){};
private:
friend class VirtualMachine;
};

View File

@ -19,7 +19,6 @@
#include "PoolSQL.h"
#include "VirtualNetworkTemplate.h"
#include "Leases.h"
#include <vector>
@ -33,10 +32,11 @@ using namespace std;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class VirtualNetworkTemplate;
/**
* The Virtual Network class. It represents a Virtual Network at manages its leases.
* One lease is formed by one IP and one MAC address.
* The Virtual Network class. It represents a Virtual Network at manages its
* leases. One lease is formed by one IP and one MAC address.
* MAC address are derived from IP addresses.
*/
class VirtualNetwork : public PoolObjectSQL
@ -176,63 +176,6 @@ public:
*/
int nic_attribute(VectorAttribute * nic, int vid);
//------------------------------------------------------------------------
// Template
// ------------------------------------------------------------------------
/**
* Gets the values of a template attribute
* @param name of the attribute
* @param values of the attribute
* @return the number of values
*/
int get_template_attribute(
string& name,
vector<const Attribute*>& values) const
{
return vn_template->get(name,values);
};
/**
* Gets the values of a template attribute
* @param name of the attribute
* @param values of the attribute
* @return the number of values
*/
int get_template_attribute(
const char *name,
vector<const Attribute*>& values) const
{
string str=name;
return vn_template->get(str,values);
};
/**
* Gets a string based VN attribute
* @param name of the attribute
* @param value of the attribute (a string), will be "" if not defined
*/
void get_template_attribute(
const char * name,
string& value) const
{
string str=name;
vn_template->get(str,value);
}
/**
* Gets a string based VN attribute
* @param name of the attribute
* @param value of the attribute (an int), will be 0 if not defined
*/
void get_template_attribute(
const char * name,
int& value) const
{
string str=name;
vn_template->get(str,value);
}
private:
// -------------------------------------------------------------------------
@ -280,11 +223,6 @@ private:
*/
Leases * leases;
/**
* The Virtual Network template, holds the VNW attributes.
*/
VirtualNetworkTemplate * vn_template;
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************

View File

@ -26,6 +26,7 @@
#include "HostPool.h"
#include "UserPool.h"
#include "ClusterPool.h"
#include "VMTemplatePool.h"
#include "VirtualMachineManager.h"
#include "LifeCycleManager.h"
@ -35,6 +36,7 @@
#include "RequestManager.h"
#include "HookManager.h"
#include "AuthManager.h"
#include "ImageManager.h"
class NebulaTest
{
@ -42,7 +44,8 @@ protected:
NebulaTest():mysql(false), need_host_pool(false), need_vm_pool(false),
need_vnet_pool(false), need_image_pool(false),
need_user_pool(false), need_cluster_pool(false),need_vmm(false),
need_user_pool(false), need_cluster_pool(false),
need_template_pool(false),need_vmm(false),
need_im(false), need_tm(false),
need_lcm(false), need_dm(false),
need_rm(false), need_hm(false),
@ -62,6 +65,7 @@ public:
bool need_image_pool;
bool need_user_pool;
bool need_cluster_pool;
bool need_template_pool;
bool need_vmm;
bool need_im;
@ -71,6 +75,7 @@ public:
bool need_rm;
bool need_hm;
bool need_authm;
bool need_imagem;
static NebulaTest * instance()
{
@ -92,12 +97,13 @@ public:
virtual UserPool* create_upool(SqlDB* db);
virtual ImagePool* create_ipool( SqlDB* db,
string repository_path,
string default_image_type,
string default_device_prefix);
virtual ClusterPool* create_cpool(SqlDB* db);
virtual VMTemplatePool* create_tpool(SqlDB* db);
// ------------------------------------------------------------------------
// Managers
// ------------------------------------------------------------------------
@ -127,11 +133,14 @@ public:
UserPool * upool,
ImagePool * ipool,
ClusterPool * cpool,
VMTemplatePool * tpool,
string log_file);
virtual HookManager* create_hm(VirtualMachinePool * vmpool);
virtual AuthManager* create_authm(time_t timer_period);
virtual ImageManager* create_imagem(ImagePool * ipool);
};
#endif /*NEBULA_TEST_H_*/

View File

@ -57,7 +57,7 @@ public:
if (mysql)
{
db = new MySqlDB( "localhost",0,
"oneadmin","oneadmin",NULL);
"oneadmin","oneadmin",db_name);
ostringstream oss1;
oss1 << "DROP DATABASE IF EXISTS " << db_name;

View File

@ -193,7 +193,10 @@ LIB_DIRS="$LIB_LOCATION/ruby \
$LIB_LOCATION/remotes/im/xen.d \
$LIB_LOCATION/remotes/im/ganglia.d \
$LIB_LOCATION/remotes/vmm/xen \
$LIB_LOCATION/remotes/vmm/kvm"
$LIB_LOCATION/remotes/vmm/kvm \
$LIB_LOCATION/remotes/image \
$LIB_LOCATION/remotes/image/fs \
$LIB_LOCATION/sh"
VAR_DIRS="$VAR_LOCATION/remotes \
$VAR_LOCATION/remotes/im \
@ -201,7 +204,9 @@ VAR_DIRS="$VAR_LOCATION/remotes \
$VAR_LOCATION/remotes/im/xen.d \
$VAR_LOCATION/remotes/im/ganglia.d \
$VAR_LOCATION/remotes/vmm/xen \
$VAR_LOCATION/remotes/vmm/kvm"
$VAR_LOCATION/remotes/vmm/kvm \
$VAR_LOCATION/remotes/image \
$VAR_LOCATION/remotes/image/fs"
SUNSTONE_DIRS="$SUNSTONE_LOCATION/models \
$SUNSTONE_LOCATION/models/OpenNebulaJSON \
@ -253,6 +258,12 @@ INSTALL_FILES=(
LIB_FILES:$LIB_LOCATION
RUBY_LIB_FILES:$LIB_LOCATION/ruby
RUBY_OPENNEBULA_LIB_FILES:$LIB_LOCATION/ruby/OpenNebula
MAD_RUBY_LIB_FILES:$LIB_LOCATION/ruby
MAD_RUBY_LIB_FILES:$LIB_LOCATION/remotes
MAD_RUBY_LIB_FILES:$VAR_LOCATION/remotes
MAD_SH_LIB_FILES:$LIB_LOCATION/sh
MAD_SH_LIB_FILES:$LIB_LOCATION/remotes
MAD_SH_LIB_FILES:$VAR_LOCATION/remotes
MADS_LIB_FILES:$LIB_LOCATION/mads
IM_PROBES_FILES:$VAR_LOCATION/remotes/im
IM_PROBES_KVM_FILES:$VAR_LOCATION/remotes/im/kvm.d
@ -278,6 +289,8 @@ INSTALL_FILES=(
SSH_TM_COMMANDS_LIB_FILES:$LIB_LOCATION/tm_commands/ssh
DUMMY_TM_COMMANDS_LIB_FILES:$LIB_LOCATION/tm_commands/dummy
LVM_TM_COMMANDS_LIB_FILES:$LIB_LOCATION/tm_commands/lvm
IMAGE_DRIVER_FS_SCRIPTS:$LIB_LOCATION/remotes/image/fs
IMAGE_DRIVER_FS_SCRIPTS:$VAR_LOCATION/remotes/image/fs
EXAMPLE_SHARE_FILES:$SHARE_LOCATION/examples
TM_EXAMPLE_SHARE_FILES:$SHARE_LOCATION/examples/tm
HOOK_SHARE_FILES:$SHARE_LOCATION/hooks
@ -354,6 +367,7 @@ BIN_FILES="src/nebula/oned \
src/cli/oneuser \
src/cli/oneimage \
src/cli/onecluster \
src/cli/onetemplate \
share/scripts/one \
src/authm_mad/oneauth"
@ -396,11 +410,21 @@ RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/OpenNebula/Host.rb \
src/oca/ruby/OpenNebula/VirtualNetworkPool.rb \
src/oca/ruby/OpenNebula/Image.rb \
src/oca/ruby/OpenNebula/ImagePool.rb \
src/oca/ruby/OpenNebula/ImageRepository.rb \
src/oca/ruby/OpenNebula/Cluster.rb \
src/oca/ruby/OpenNebula/ClusterPool.rb \
src/oca/ruby/OpenNebula/Template.rb \
src/oca/ruby/OpenNebula/TemplatePool.rb \
src/oca/ruby/OpenNebula/XMLUtils.rb"
#-----------------------------------------------------------------------------
# MAD Script library files, to be installed under $LIB_LOCATION/<script lang>
# and remotes directory
#-----------------------------------------------------------------------------
MAD_SH_LIB_FILES="src/mad/sh/scripts_common.sh"
MAD_RUBY_LIB_FILES="src/mad/ruby/scripts_common.rb"
#-------------------------------------------------------------------------------
# Driver executable files, to be installed under $LIB_LOCATION/mads
#-------------------------------------------------------------------------------
@ -428,7 +452,9 @@ MADS_LIB_FILES="src/mad/sh/madcommon.sh \
src/hm_mad/one_hm.rb \
src/hm_mad/one_hm \
src/authm_mad/one_auth_mad.rb \
src/authm_mad/one_auth_mad"
src/authm_mad/one_auth_mad \
src/image_mad/one_image.rb \
src/image_mad/one_image"
#-------------------------------------------------------------------------------
# VMM SH Driver KVM scripts, to be installed under $REMOTES_LOCATION/vmm/kvm
@ -514,6 +540,16 @@ LVM_TM_COMMANDS_LIB_FILES="src/tm_mad/lvm/tm_clone.sh \
src/tm_mad/lvm/tm_mv.sh \
src/tm_mad/lvm/tm_context.sh"
#-------------------------------------------------------------------------------
# Image Repository drivers, to be installed under $REMOTES_LOCTION/image
# - FS based Image Repository, $REMOTES_LOCATION/image/fs
#-------------------------------------------------------------------------------
IMAGE_DRIVER_FS_SCRIPTS="src/image_mad/remotes/fs/cp \
src/image_mad/remotes/fs/mkfs \
src/image_mad/remotes/fs/mv \
src/image_mad/remotes/fs/fsrc \
src/image_mad/remotes/fs/rm"
#-------------------------------------------------------------------------------
# Configuration files for OpenNebula, to be installed under $ETC_LOCATION
#-------------------------------------------------------------------------------
@ -700,7 +736,8 @@ CLI_BIN_FILES="src/cli/onevm \
src/cli/onevnet \
src/cli/oneuser \
src/cli/oneimage \
src/cli/onecluster"
src/cli/onecluster \
src/cli/onetemplate"
#-----------------------------------------------------------------------------
# Sunstone files
@ -721,6 +758,7 @@ SUNSTONE_MODELS_JSON_FILES="src/sunstone/models/OpenNebulaJSON/ClusterJSON.rb \
src/sunstone/models/OpenNebulaJSON/PoolJSON.rb \
src/sunstone/models/OpenNebulaJSON/UserJSON.rb \
src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb \
src/sunstone/models/OpenNebulaJSON/TemplateJSON.rb \
src/sunstone/models/OpenNebulaJSON/VirtualNetworkJSON.rb"
SUNSTONE_TEMPLATE_FILES="src/sunstone/templates/index.html \
@ -736,6 +774,7 @@ SUNSTONE_PUBLIC_JS_PLUGINS_FILES="\
src/sunstone/public/js/plugins/dashboard-tab.js \
src/sunstone/public/js/plugins/hosts-tab.js \
src/sunstone/public/js/plugins/images-tab.js \
src/sunstone/public/js/plugins/templates-tab.js \
src/sunstone/public/js/plugins/users-tab.js \
src/sunstone/public/js/plugins/vms-tab.js \
src/sunstone/public/js/plugins/vnets-tab.js"
@ -809,6 +848,7 @@ MAN_FILES="share/man/oneauth.8.gz \
share/man/oneuser.8.gz \
share/man/onevm.8.gz \
share/man/onevnet.8.gz \
share/man/onetemplate.8.gz \
share/man/econe-describe-images.8.gz \
share/man/econe-describe-instances.8.gz \
share/man/econe-register.8.gz \

View File

@ -82,9 +82,6 @@ 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/images
#
# DEFAULT_IMAGE_TYPE: This can take values
# OS Image file holding an operating system
# CDROM Image file holding a CDROM
@ -96,8 +93,6 @@ MAC_PREFIX = "02:00"
# xvd XEN Virtual Disk
# vd KVM virtual disk
#*******************************************************************************
#IMAGE_REPOSITORY_PATH = /srv/cloud/var/images
DEFAULT_IMAGE_TYPE = "OS"
DEFAULT_DEVICE_PREFIX = "hd"
@ -285,6 +280,25 @@ TM_MAD = [
# arguments = "tm_lvm/tm_lvm.conf" ]
#-------------------------------------------------------------------------------
#*******************************************************************************
# Image Manager Driver Configuration
#*******************************************************************************
# Drivers to manage the image repository, specialized for the storage backend
# executable: path of the transfer driver executable, can be an
# absolute path or relative to $ONE_LOCATION/lib/mads (or
# /usr/lib/one/mads/ if OpenNebula was installed in /)
#
# arguments : for the driver executable
#*******************************************************************************
#-------------------------------------------------------------------------------
# FS based Image Manager Driver Configuration
# -t number of threads, i.e. number of repo operations at the same time
#-------------------------------------------------------------------------------
IMAGE_MAD = [
executable = "one_image",
arguments = "fs -t 15" ]
#-------------------------------------------------------------------------------
#*******************************************************************************
# Hook Manager Configuration
#*******************************************************************************
@ -339,16 +353,6 @@ 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.
VM_HOOK = [
name = "image",
on = "DONE",
command = "image.rb",
arguments = "$VMID" ]
#-------------------------------------------------------------------------------
#------------------------------ Fault Tolerance Hooks --------------------------

View File

@ -64,7 +64,7 @@ host.info
host_name = host.name
# Loop through all vms
vms = VirtualMachinePool.new(client)
vms = VirtualMachinePool.new(client, -2)
exit -1 if OpenNebula.is_error?(vms)
vms.info

View File

@ -69,24 +69,24 @@ main(int argc, char **) {
vector<xmlrpc_c::value> const paramArrayValue(resultArray.vectorValueValue());
//check posible Errors:
xmlrpc_c::value * firstvalue;
firstvalue = &(static_cast<xmlrpc_c::value>(paramArrayValue[0]));
xmlrpc_c::value_boolean * status = &(static_cast<xmlrpc_c::value_boolean>(*firstvalue));
xmlrpc_c::value firstvalue;
firstvalue = static_cast<xmlrpc_c::value>(paramArrayValue[0]);
xmlrpc_c::value_boolean status = static_cast<xmlrpc_c::value_boolean>(firstvalue);
xmlrpc_c::value * secondvalue;
secondvalue = &(static_cast<xmlrpc_c::value>(paramArrayValue[1]));
xmlrpc_c::value_string * valueS = &(static_cast<xmlrpc_c::value_string>(*secondvalue));
xmlrpc_c::value secondvalue;
secondvalue = static_cast<xmlrpc_c::value>(paramArrayValue[1]);
xmlrpc_c::value_string valueS = static_cast<xmlrpc_c::value_string>(secondvalue);
if(static_cast<bool>(*status)) {
if(static_cast<bool>(status)) {
//Success, returns the id assigned to the VM:
cout << "vmid returned: " << static_cast<string>(*valueS) << endl;
cout << "vmid returned: " << static_cast<string>(valueS) << endl;
return 0;
}
else{ //Failure:
string error_value=static_cast<string>(*valueS);
string error_value=static_cast<string>(valueS);
if (error_value.find("Error inserting",0)!=string::npos ) cout << "Error inserting VM in the database" << endl;
else if (error_value.find("Error parsing",0)!=string::npos ) cout << "Error parsing VM template" << endl;
else cout << "Unknown error " << static_cast<string>(*valueS) << endl;
else cout << "Unknown error " << static_cast<string>(valueS) << endl;
};
} catch (girerr::error const error) {
cerr << "Client threw error: " << error.what() << endl;

View File

@ -17,7 +17,8 @@ TESTS="$TWD_DIR/vnm/test \
$TWD_DIR/vm/test \
$TWD_DIR/um/test \
$TWD_DIR/lcm/test \
$TWD_DIR/pool/test"
$TWD_DIR/pool/test \
$TWD_DIR/vm_template/test"
#-------------------------------------------------------------------------------
# COMMAND LINE PARSING

View File

@ -86,9 +86,10 @@ void AuthRequest::add_auth(Object ob,
case IMAGE: oss << "IMAGE:" ; break;
case USER: oss << "USER:" ; break;
case CLUSTER: oss << "CLUSTER:" ; break;
case TEMPLATE: oss << "TEMPLATE:" ; break;
}
if (op == CREATE) //encode the ob_id, it is a template
if (op == CREATE || op == INSTANTIATE) //encode the ob_id, it is a template
{
string * encoded_id = base64_encode(ob_id);
@ -128,6 +129,10 @@ void AuthRequest::add_auth(Object ob,
case INFO:
oss << "INFO:" ;
break;
case INSTANTIATE:
oss << "INSTANTIATE:" ;
break;
}
oss << owner << ":" << pub;
@ -147,7 +152,14 @@ void AuthRequest::add_auth(Object ob,
switch (op)
{
case CREATE:
if ( ob == VM || ob == NET || ob == IMAGE )
if ( ob == VM || ob == NET || ob == IMAGE || ob == TEMPLATE )
{
auth = true;
}
break;
case INSTANTIATE:
if ( ob == VM )
{
auth = true;
}
@ -158,7 +170,7 @@ void AuthRequest::add_auth(Object ob,
break;
case USE:
if (ob == NET || ob == IMAGE)
if (ob == NET || ob == IMAGE || ob == TEMPLATE)
{
auth = (owner == uid) || pub;
}

View File

@ -91,7 +91,7 @@ void AuthManagerDriver::protocol(
{
is.clear();
getline(is,info);
NebulaLog::log("AuM",Log::INFO, info.c_str());
NebulaLog::log("AuM", log_type(result[0]), info.c_str());
}
return;

View File

@ -89,19 +89,43 @@ class Quota
# Checks if the user is below resource limits. If new_vm is defined
# checks if its requirements fit in limits
def check(user, new_vm=nil)
usage=@usage.total(user)
use=@usage.total(user)
use_after=use.clone
user_quota=get(user)
if new_vm
usage.cpu+=new_vm.cpu.to_f
usage.memory+=new_vm.memory.to_i
usage.num_vms+=1
use_after.cpu+=new_vm.cpu.to_f
use_after.memory+=new_vm.memory.to_i
use_after.num_vms+=1
end
STDERR.puts [user_quota, use_after, new_vm].inspect
error_message=""
if !(!user_quota[:cpu] || use_after.cpu<=user_quota[:cpu])
error_message<<"Cpu quota exceeded (Quota: #{user_quota[:cpu]}, "+
"Used: #{use.cpu}"
error_message<<", asked: #{new_vm.cpu.to_f}" if new_vm
error_message<<")."
end
if !(!user_quota[:memory] || use_after.memory<=user_quota[:memory])
error_message<<" Memory quota exceeded (Quota: "+
"#{user_quota[:memory]}, Used: #{use.memory}"
error_message<<", asked: #{new_vm.memory.to_i}" if new_vm
error_message<<")."
end
if !(!user_quota[:num_vms] || use_after.num_vms<=user_quota[:num_vms])
error_message<<" Num VMS quota exceeded (Quota: "+
"#{user_quota[:memory]}, Used: #{use.num_vms})."
end
if error_message==""
false
else
error_message.strip
end
STDERR.puts [user_quota, usage, new_vm].inspect
(!user_quota[:cpu] || usage.cpu<=user_quota[:cpu]) &&
(!user_quota[:memory] || usage.memory<=user_quota[:memory]) &&
(!user_quota[:num_vms] || usage.num_vms<=user_quota[:num_vms])
end
# Updates user resource consuption

View File

@ -48,7 +48,20 @@ class SimplePermissions
VmUsage.new(cpu, memory)
end
# Checks if the quota is enabled, and if it is not exceeded
def check_quota_enabled(uid, object, id, auth_result)
if @quota_enabled and object=='VM' and auth_result
STDERR.puts 'quota enabled'
@quota.update(uid.to_i)
if message=@quota.check(uid.to_i, get_vm_usage(id))
auth_result=message
end
end
return auth_result
end
# Method called by authorization driver
def auth(uid, tokens)
result=true
@ -71,21 +84,18 @@ class SimplePermissions
case action
when 'CREATE'
auth_result=true if %w{VM NET IMAGE}.include? object
if @quota_enabled and object=='VM' and auth_result
STDERR.puts 'quota enabled'
@quota.update(uid.to_i)
if !@quota.check(uid.to_i, get_vm_usage(id))
auth_result="Quota exceeded"
end
end
auth_result=true if %w{VM NET IMAGE TEMPLATE}.include? object
auth_result = check_quota_enabled(uid, object, id, auth_result)
when 'INSTANTIATE'
auth_result = true if %w{VM}.include? object
auth_result = check_quota_enabled(uid, object, id, auth_result)
when 'DELETE'
auth_result = (owner == uid)
when 'USE'
if %w{VM NET IMAGE}.include? object
if %w{VM NET IMAGE TEMPLATE}.include? object
auth_result = ((owner == uid) | (pub=='1'))
elsif object == 'HOST'
auth_result=true

View File

@ -60,8 +60,8 @@ describe 'Quota' do
it 'should check for quotas' do
@quota.update(0)
@quota.update(1)
@quota.check(0).should == true
@quota.check(1).should == true
@quota.check(0).should == false
@quota.check(1).should == false
vms=@quota.get_user(0)
vms[5]=VmUsage.new(40.0, 8192)
@ -69,13 +69,13 @@ describe 'Quota' do
vms=@quota.get_user(1)
vms[6]=VmUsage.new(40.0, 8192)
@quota.check(0).should == false
@quota.check(1).should == false
@quota.check(0).class.should == String
@quota.check(1).class.should == String
@quota.update(0)
@quota.update(1)
@quota.check(0).should == true
@quota.check(1).should == true
@quota.check(0).should == false
@quota.check(1).should == false
end
it 'should let update limits' do
@ -86,8 +86,8 @@ describe 'Quota' do
it 'should understand unlimited quotas' do
vms=@quota.get_user(0)
vms[7]=VmUsage.new(9999999999.0, 99999999999)
@quota.check(0).should == true
@quota.check(0, VmUsage.new(999999999.0, 99999999)).should == true
@quota.check(0).should == false
@quota.check(0, VmUsage.new(999999999.0, 99999999)).should == false
end
end

View File

@ -268,15 +268,19 @@ def get_entity_id(name, pool_class)
pool=pool_class.new(get_one_client)
result=pool.info
# TODO: Check for errors
class_name=pool_class.name.split('::').last.gsub(/Pool$/, '')
if( OpenNebula.is_error?(result) )
puts "Error: #{class_name} Pool info could not be retrieved. " +
result.message
exit -1
end
objects=pool.select {|object| object.name==name }
class_name=pool_class.name.split('::').last.gsub(/Pool$/, '')
if objects.length>0
if objects.length>1
puts "There are multiple #{class_name}'s with name #{name}."
puts "There are multiple #{class_name}s with name #{name}."
exit -1
else
result=objects.first.id
@ -313,6 +317,10 @@ def get_cluster_id(name)
get_entity_id(name, OpenNebula::ClusterPool)
end
def get_template_id(name)
get_entity_id(name, OpenNebula::TemplatePool)
end
def str_running_time(data)
stime=Time.at(data["STIME"].to_i)
if data["ETIME"]=="0"

View File

@ -321,8 +321,6 @@ result=[false, "Unknown error"]
command=ARGV.shift
img_repo = OpenNebula::ImageRepository.new
case command
when "register", "create", "add"
check_parameters("register", 1)
@ -330,7 +328,7 @@ when "register", "create", "add"
image = OpenNebula::Image.new(OpenNebula::Image.build_xml, get_one_client)
result = img_repo.create(image, template)
result = image.allocate(template)
if is_successful?(result)
puts "ID: " + image.id.to_s if ops[:verbose]
end
@ -506,7 +504,7 @@ when "delete"
OpenNebula::Image.build_xml(image_id),
get_one_client)
result = img_repo.delete(image)
result = image.delete
if is_successful?(result)
puts "Image correctly deleted" if ops[:verbose]
end

411
src/cli/onetemplate Executable file
View File

@ -0,0 +1,411 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
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'
ShowTableTemplate={
:id => {
:name => "ID",
:desc => "ONE identifier for the Template",
: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 Template",
:size => 20,
:proc => lambda {|d,e|
d.name
}
},
:regtime => {
:name => "REGTIME",
:desc => "Registration time of the Template",
:size => 20,
:proc => lambda {|d,e|
str_register_time(d)
}
},
:public => {
:name => "PUBLIC",
:desc => "Whether the Template is public or not",
:size => 3,
:proc => lambda {|d,e|
if d["PUBLIC"].to_i == 1 then "Yes" else "No" end}
},
:default => [:id, :user, :name, :regtime, :public]
}
class TemplateShow
def initialize(client, filter_flag="-2")
@templatepool=OpenNebula::TemplatePool.new(client, filter_flag.to_i)
@table=ShowTable.new(ShowTableTemplate)
end
def header_template_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=@templatepool.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]
objs=@templatepool.select{|element|
element['USERNAME']==options[:filter_flag] }
else
objs=@templatepool
end
result=[true, ""]
header_template_small
if options
puts @table.data_str(objs, options)
else
puts @table.data_str(objs)
end
result
end
end
end
##########################
## COMMAND LINE PARSING ##
##########################
class OneTemplateParse < CommandParse
COMMANDS_HELP=<<-EOT
Description:
This command enables the user to manage templates.
Commands:
* create (Registers a Template from a template file)
onetemplate create <file>
file is a file name where the Template description is located
* addattr (Add a new Template attribute)
onetemplate addattr <template_id> <attribute_name> <attribute_value>
* update (Modifies a Template attribute)
onetemplate update <template_id> <attribute_name> <attribute_value>
* rmattr (Deletes a Template attribute)
onetemplate rmattr <template_id> <attribute_name>
* publish (Publish a Template)
onetemplate publish <template_id>
* unpublish (Unpublish an Template)
onetemplate unpublish <template_id>
* list (Shows Templates in the pool)
onetemplate list <filter_flag>
where filter_flag can be
a, all --> all the known Templates
m, mine --> the Templates belonging to the user in ONE_AUTH
and all the Public Templates
uid --> Templates of the user identified by this uid
user --> Templates of the user identified by the username
* top (Lists Templates continuously)
onetemplate top
* show (Gets information about an specific Template)
onetemplate show <template_id>
* delete (Deletes a Template)
onetemplate delete <template_id>
EOT
def text_commands
COMMANDS_HELP
end
def text_command_name
"onetemplate"
end
def list_options
table=ShowTable.new(ShowTableTemplate)
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_template(template_path)
begin
template = File.read(ARGV[0])
rescue
result = OpenNebula::Error.new("Can not read template: #{ARGV[0]}")
end
if !is_successful?(result)
puts result.message
exit -1
end
return template
end
onetemplate_opts=OneTemplateParse.new
onetemplate_opts.parse(ARGV)
ops=onetemplate_opts.options
result=[false, "Unknown error"]
command=ARGV.shift
case command
when "create", "register", "add"
check_parameters("create", 1)
template_contents = get_template(ARGV[0])
template = OpenNebula::Template.new(OpenNebula::Template.build_xml, get_one_client)
result=template.allocate(template_contents)
if !OpenNebula.is_error?(result)
puts "ID: " + template.id.to_s if ops[:verbose]
exit 0
end
when "update", "addattr"
check_parameters("update", 3)
template_id = get_template_id(ARGV[0])
template = OpenNebula::Template.new_with_id(template_id, get_one_client)
result = template.update(ARGV[1],ARGV[2])
if is_successful?(result)
puts "Modified template" if ops[:verbose]
end
when "rmattr"
check_parameters("rmattr", 2)
template_id = get_template_id(ARGV[0])
template = OpenNebula::Template.new_with_id(template_id, get_one_client)
result = template.remove_attr(ARGV[1])
if is_successful?(result)
puts "Removed template attribute" if ops[:verbose]
end
when "publish"
check_parameters("publish", 1)
template_id = get_template_id(ARGV[0])
template = OpenNebula::Template.new_with_id(template_id, get_one_client)
result = template.publish
if is_successful?(result)
puts "Template published" if ops[:verbose]
end
when "unpublish"
check_parameters("unpublish", 1)
template_id = get_template_id(ARGV[0])
template = OpenNebula::Template.new_with_id(template_id, get_one_client)
result = template.unpublish
if is_successful?(result)
puts "Template unpublished" if ops[:verbose]
end
when "list"
ops.merge!(get_user_flags)
if !ops[:xml]
templatelist = TemplateShow.new(get_one_client, ops[:filter_user].to_i)
ops[:columns] = ops[:list] if ops[:list]
result = templatelist.list_short(ops)
else
templatepool = OpenNebula::TemplatePool.new(get_one_client,
ops[:filter_user].to_i)
templatepool.info
puts templatepool.to_xml
end
when "top"
ops.merge!(get_user_flags)
templatelist = TemplateShow.new(get_one_client, ops[:filter_user].to_i)
ops[:columns] = ops[:list] if ops[:list]
result = templatelist.top(ops)
when "show"
check_parameters("get_info", 1)
args = expand_args(ARGV)
args.each do |param|
template_id = get_template_id(param)
template = OpenNebula::Template.new_with_id(template_id, get_one_client)
result = template.info
if is_successful?(result)
if !ops[:xml]
str="%-15s: %-20s"
str_h1="%-80s"
print_header(str_h1, "TEMPLATE #{template[:id]} INFORMATION", true)
puts str % ["ID", template.id.to_s]
puts str % ["NAME", template.name]
value = template['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 template['PUBLIC'].to_i == 1
public_str = "Yes"
else
public_str = "No"
end
puts str % ["PUBLIC", public_str]
puts
print_header(str_h1,"TEMPLATE CONTENTS",false)
puts template.template_str
else
puts template.to_xml
end
end
end
when "delete"
check_parameters("delete", 1)
args = expand_args(ARGV)
args.each do |param|
template_id = get_template_id(param)
template = OpenNebula::Template.new(
OpenNebula::Template.build_xml(template_id),
get_one_client)
result = template.delete
if is_successful?(result)
puts "Template correctly deleted" if ops[:verbose]
end
end
else
onetemplate_opts.print_help
exit -1
end
if OpenNebula.is_error?(result)
puts "Error: " + result.message
exit -1
end

View File

@ -318,9 +318,15 @@ machine with the functionality present in onevm.
Commands:
* create (Submits a new virtual machine, adding it to the ONE VM pool)
onevm create <template>
onevm create [OPTION] {<template-file-path>, <template-id>, <template-name>}
template is a file name where the VM description is located
<template-file-path> is a file name where the VM description is located.
<template-id> is the numeric ID of a registered template (using onetemplate)
<template-name> is the name of a registered template (using onetemplate)
OPTION: -n STRING, --name=STRING
Replaces the NAME attribute if the VM is being created from a registered
Template
* deploy (Starts an existing VM in an specific host)
onevm deploy <vm_id> <host_id>
@ -462,6 +468,10 @@ EOT
"Image type") do |o|
options[:type]=o
end
opts.on_tail("-n vm_name", "--name vm_name", String,
"Set VM name") do |o|
options[:vm_name] = o
end
end
end
@ -502,12 +512,32 @@ when "submit", "create"
check_parameters("create", 1)
vm=OpenNebula::VirtualMachine.new(
OpenNebula::VirtualMachine.build_xml, get_one_client)
begin
template=File.read(ARGV[0])
result=vm.allocate(template)
rescue
result=OpenNebula::Error.new("Can not read template: #{ARGV[0]}")
template = ""
success = false
if( File.file?(ARGV[0]) )
# argument is a file path
begin
template = File.read(ARGV[0])
success = true
rescue
result = OpenNebula::Error.new("Can not read template: #{ARGV[0]}")
end
else
# argument could be a template ID or a template name
template_id = get_template_id(ARGV[0])
template = "TEMPLATE_ID = #{template_id}"
template << "\nNAME = #{ops[:vm_name]}" if ops[:vm_name]
success = true
end
if( success )
result = vm.allocate(template)
end
if is_successful?(result)
puts "ID: " + vm.id.to_s if ops[:verbose]
exit 0
@ -785,56 +815,17 @@ when "saveas"
exit -1
end
if ops[:type]
image_type = ops[:type]
else
image_id = vm["TEMPLATE/DISK[DISK_ID=\"#{disk_id}\"]/IMAGE_ID"]
if (image_id != nil)
if vm["TEMPLATE/DISK[DISK_ID=\"#{disk_id}\"]/SAVE_AS"]
puts "Error: The disk #{disk_id} is already" <<
" suppossed to be saved"
exit -1
end
# Get the image type
image = OpenNebula::Image.new(
OpenNebula::Image.build_xml(image_id),
get_one_client)
result = image.info
if !is_successful?(result)
puts result.message
exit -1
end
image_type = image.type_str
end
end
# Build the template and allocate the new Image
template = "NAME=\"#{image_name}\"\n"
template << "TYPE=#{image_type}\n" if image_type
image = OpenNebula::Image.new(
OpenNebula::Image.build_xml,
get_one_client)
result = image.allocate(template)
if !is_successful?(result)
puts result.message
if vm["TEMPLATE/DISK[DISK_ID=\"#{disk_id}\"]/SAVE_AS"]
puts "Error: The disk #{disk_id} is already" <<
" suppossed to be saved"
exit -1
end
result = vm.save_as(disk_id.to_i, image.id)
result = vm.save_as(disk_id.to_i, image_name)
if is_successful?(result)
puts "VM disk with ID #{disk_id} is prepared to be" <<
" saved" if ops[:verbose]
else
image.delete
end
when "show"
check_parameters("get_info", 1)

View File

@ -62,8 +62,6 @@ class CloudServer
@one_client = Client.new(nil,@config[:one_xmlrpc])
@user_pool = UserPool.new(@one_client)
@img_repo = OpenNebula::ImageRepository.new
end
#
@ -103,39 +101,6 @@ class CloudServer
return @user_pool["USER[NAME=\"#{name}\"]/PASSWORD"]
end
###########################################################################
# Repository Methods
###########################################################################
# Adds a new image to the repository and deletes the temp_file
# uid:: _Integer_ owner of the image
# path:: _String_ path of the tmp file
# metadata:: Additional metadata for the file
# [return] _Image_ Newly created image object
def add_image(image, file=nil)
template = image.to_one_template
if file
if file[:tempfile]
file_path = file[:tempfile].path
template << "\nPATH = #{file_path}"
else
error_msg = "Image not present, aborting."
error = OpenNebula::Error.new(error_msg)
return error
end
end
rc = @img_repo.create(image, template)
file[:tempfile].unlink if file
if OpenNebula.is_error?(rc)
return rc
end
return nil
end
# Finds out if a port is available on ip
# ip:: _String_ IP address where the port to check is

View File

@ -140,7 +140,7 @@ module EC2QueryClient
def upload_image(file_name, curb=true)
params = { "Action" => "UploadImage",
"SignatureVersion" => "2",
"SignatureMethod" => 'HmacSHA1',
"SignatureMethod" => 'HmacSHA256',
"AWSAccessKeyId" => @access_key_id,
"Version" => API_VERSION,
"Timestamp" => Time.now.getutc.iso8601 }

View File

@ -122,11 +122,16 @@ class EC2QueryServer < CloudServer
###########################################################################
def upload_image(params, one_client)
image = ImageEC2.new(Image.build_xml, one_client)
image = ImageEC2.new(Image.build_xml, one_client, params['file'])
rc = add_image(image, params['file'])
template = image.to_one_template
if OpenNebula.is_error?(template)
return OpenNebula::Error.new('Unsupported'), 400
end
rc = image.allocate(template)
if OpenNebula.is_error?(rc)
return OpenNebula::Error.new('Unsupported'),400
return OpenNebula::Error.new('Unsupported'), 400
end
erb_version = params['Version']

View File

@ -24,8 +24,21 @@ class ImageEC2 < Image
ONE_IMAGE = %q{
NAME = "ec2-<%= uuid %>"
TYPE = OS
<% if @image_file != nil %>
PATH = "<%= @image_file %>"
<% end %>
}.gsub(/^ /, '')
def initialize(xml, client, file=nil)
super(xml, client)
@image_info = nil
@image_file = file
if file && file[:tempfile]
@image_file = file[:tempfile].path
end
end
def to_one_template()
uuid = UUID.generate

View File

@ -1,25 +1,27 @@
<?xml version="1.0"?>
<DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/<%=erb_version%>/">
<imagesSet>
<imagesSet>
<% impool.each do |im| %>
<% im.info %>
<item>
<item>
<imageId>ami-<%= sprintf('%08i', im.id) %></imageId>
<imageLocation><%= im['SOURCE'].split('/').last %></imageLocation>
<% if im['STATE'] == '3' %>
<imageState>deregistered</imageState>
<% if im['STATE'] == '3' || im['STATE'] == '5' %>
<imageState>failed</imageState>
<% elsif im['STATE'] == '1' || im['STATE'] == '2' %>
<imageState>available</imageState>
<imageState>available</imageState>
<% elsif im['STATE'] == '4'%>
<imageState>pending</imageState>
<% end %>
<imageOwnerId><%= erb_user_name %></imageOwnerId>
<imageOwnerId><%= erb_user_name %></imageOwnerId>
<% if im['PUBLIC'] == '0' %>
<isPublic>false</isPublic>
<isPublic>false</isPublic>
<% elsif im['PUBLIC'] == '1' %>
<isPublic>true</isPublic>
<isPublic>true</isPublic>
<% end %>
<architecture>i386</architecture>
<imageType>machine</imageType>
</item>
<architecture>i386</architecture>
<imageType>machine</imageType>
</item>
<% end %>
</imagesSet>
</DescribeImagesResponse>
</imagesSet>
</DescribeImagesResponse>

View File

@ -30,7 +30,7 @@ class ImageOCCI < Image
<DESCRIPTION><%= self['TEMPLATE/DESCRIPTION'] %></DESCRIPTION>
<% end %>
<% if size != nil %>
<SIZE><%= size %></SIZE>
<SIZE><%= size.to_i / 1024 %></SIZE>
<% end %>
<% if fstype != nil %>
<FSTYPE><%= fstype %></FSTYPE>
@ -46,6 +46,9 @@ class ImageOCCI < Image
<% if @image_info['DESCRIPTION'] != nil %>
DESCRIPTION = "<%= @image_info['DESCRIPTION'] %>"
<% end %>
<% if @image_file != nil %>
PATH = "<%= @image_file %>"
<% end %>
<% if @image_info['PUBLIC'] != nil %>
PUBLIC = "<%= @image_info['PUBLIC'] %>"
<% end %>
@ -64,9 +67,14 @@ class ImageOCCI < Image
}.gsub(/^ /, '')
# Class constructor
def initialize(xml, client, xml_info=nil)
def initialize(xml, client, xml_info=nil, file=nil)
super(xml, client)
@image_info = nil
@image_file = file
if file && file[:tempfile]
@image_file = file[:tempfile].path
end
if xml_info != nil
xmldoc = XMLElement.build_xml(xml_info, 'STORAGE')

View File

@ -170,18 +170,18 @@ module OCCIClient
return error
end
if image_info.elements['URL'] == nil
if image_info.elements['URL']
file_path = image_info.elements['URL'].text
m = file_path.match(/^\w+:\/\/(.*)$/)
if m
file_path="/"+m[1]
end
elsif !image_info.elements['TYPE'] == "DATABLOCK"
return CloudClient::Error.new("Can not find URL")
end
file_path = image_info.elements['URL'].text
m = file_path.match(/^\w+:\/\/(.*)$/)
if m
file_path="/"+m[1]
end
if curb
if !CURL_LOADED
error_msg = "curb gem not loaded"
@ -197,10 +197,14 @@ module OCCIClient
curl.multipart_form_post = true
begin
curl.http_post(
Curl::PostField.content('occixml', xml),
Curl::PostField.file('file', file_path)
)
postfields = Array.new
postfields << Curl::PostField.content('occixml', xml)
if file_path
postfields << Curl::PostField.file('file', file_path)
end
curl.http_post(*postfields)
rescue Exception => e
return CloudClient::Error.new(e.message)
end
@ -213,11 +217,13 @@ module OCCIClient
return error
end
file=File.open(file_path)
params=Hash.new
params["file"]=UploadIO.new(file,
'application/octet-stream', file_path)
if file_path
file=File.open(file_path)
params["file"]=UploadIO.new(file,
'application/octet-stream', file_path)
end
params['occixml'] = xml
@ -231,8 +237,8 @@ module OCCIClient
http.request(req)
end
file.close
pp res
file.close if file_path
if CloudClient::is_error?(res)
return res
else

View File

@ -401,16 +401,18 @@ class OCCIServer < CloudServer
image = ImageOCCI.new(
Image.build_xml,
get_client(request.env),
occixml)
occixml,
request.params['file'])
rc = add_image(image, request.params['file'])
return rc, 500 if OpenNebula.is_error?(rc)
# --- Generate the template and Allocate the new Instance ---
template = image.to_one_template
return template, 500 if OpenNebula.is_error?(template)
# --- Enable the new Image ---
rc = image.enable
rc = image.allocate(template)
return rc, 500 if OpenNebula.is_error?(rc)
# --- Prepare XML Response ---
image.info
return to_occi_xml(image, 201)
end

View File

@ -26,7 +26,6 @@ env.Prepend(LIBS=[
'nebula_common',
'nebula_sql',
### TODO: delete not needed
'nebula_core_test',
'nebula_host',
@ -40,6 +39,7 @@ env.Prepend(LIBS=[
'nebula_mad',
'nebula_template',
'nebula_vm',
'nebula_vmtemplate',
'nebula_vnm',
'nebula_image',
'nebula_pool',

View File

@ -125,7 +125,7 @@ void HookManagerDriver::protocol(
is.clear();
getline(is,info);
NebulaLog::log("HKM",Log::INFO, info.c_str());
NebulaLog::log("HKM", log_type(result[0]), info.c_str());
}
return;
@ -156,19 +156,26 @@ void HookManagerDriver::protocol(
if ( is.good() )
{
is >> hook_name >> ws;
getline(is,hook_name);
}
getline (is,info);
if (result == "SUCCESS")
{
oss << "Hook " << hook_name << " successfully executed. " << info;
oss << "Success executing Hook: " << hook_name << ". " << info;
vm->log("HKM",Log::INFO,oss);
}
else
{
oss << "Error executing Hook: " << hook_name << ". " << info;
if ( !info.empty() && info[0] != '-' )
{
vm->set_template_error_message(oss.str());
vmpool->update(vm);
}
vm->log("HKM",Log::ERROR,oss);
}
}
@ -177,7 +184,7 @@ void HookManagerDriver::protocol(
string info;
getline(is,info);
vm->log("HKM",Log::INFO,info.c_str());
vm->log("HKM",log_type(result[0]),info.c_str());
}
vm->unlock();

View File

@ -28,14 +28,11 @@ end
$: << RUBY_LIB_LOCATION
require 'pp'
require 'OpenNebulaDriver'
require 'CommandManager'
class HookManagerDriver < OpenNebulaDriver
def initialize(num)
super(num, true)
super(num, true, 0)
register_action(:EXECUTE, method("action_execute"))
end
@ -51,13 +48,14 @@ class HookManagerDriver < OpenNebulaDriver
end
if cmd.code==0
send_message("EXECUTE", RESULT[:success], number, hook_name)
message = "#{hook_name}: #{cmd.stdout}"
send_message("EXECUTE", RESULT[:success], number, message)
else
send_message("EXECUTE", RESULT[:failure], number, hook_name)
message = "#{hook_name}: #{cmd.get_error_message}"
send_message("EXECUTE", RESULT[:failure], number, message)
end
end
end
hm=HookManagerDriver.new(15)
hm.start_driver

View File

@ -40,11 +40,18 @@ Host::Host(
vmm_mad_name(_vmm_mad_name),
tm_mad_name(_tm_mad_name),
last_monitored(0),
cluster(_cluster),
host_template()
{}
cluster(_cluster)
{
obj_template = new HostTemplate;
}
Host::~Host(){}
Host::~Host()
{
if ( obj_template != 0 )
{
delete obj_template;
}
}
/* ************************************************************************ */
/* Host :: Database Access Functions */
@ -167,7 +174,7 @@ int Host::update_info(string &parse_str)
char * error_msg;
int rc;
rc = host_template.parse(parse_str, &error_msg);
rc = obj_template->parse(parse_str, &error_msg);
if ( rc != 0 )
{
@ -222,7 +229,7 @@ string& Host::to_xml(string& xml) const
"<LAST_MON_TIME>" << last_monitored << "</LAST_MON_TIME>" <<
"<CLUSTER>" << cluster << "</CLUSTER>" <<
host_share.to_xml(share_xml) <<
host_template.to_xml(template_xml) <<
obj_template->to_xml(template_xml) <<
"</HOST>";
xml = oss.str();
@ -276,7 +283,7 @@ int Host::from_xml(const string& xml)
return -1;
}
rc += host_template.from_xml_node( content[0] );
rc += obj_template->from_xml_node( content[0] );
if (rc != 0)
{

View File

@ -386,7 +386,7 @@ public:
void scale_test()
{
time_t the_time, the_time2;
int oid,i,j,rc;
int oid,i,j;
ostringstream oss,ossdump;
string err;
@ -419,7 +419,7 @@ public:
the_time = time(0);
rc = hp->dump(ossdump, "");
hp->dump(ossdump, "");
cout <<"\t"<<i<<"\t"<<the_time2<<"\t"<<time(0)-the_time<< endl;

View File

@ -31,6 +31,7 @@ env.Prepend(LIBS=[
'nebula_mad',
'nebula_template',
'nebula_vm',
'nebula_vmtemplate',
'nebula_vnm',
'nebula_image',
'nebula_pool',

View File

@ -110,7 +110,7 @@ void InformationManagerDriver::protocol(
hinfo += "\n";
oss << "Host " << id << " successfully monitored."; //, info: "<< hinfo;
oss << "Host " << id << " successfully monitored.";
NebulaLog::log("InM",Log::DEBUG,oss);
rc = host->update_info(hinfo);
@ -136,22 +136,23 @@ void InformationManagerDriver::protocol(
string info;
getline(is,info);
NebulaLog::log("InM",Log::INFO,info.c_str());
NebulaLog::log("InM",log_type(result[0]),info.c_str());
}
return;
error_driver_info:
ess << "Error monitoring host " << id << " : " << is.str();
NebulaLog::log("InM", Log::ERROR, ess);
goto error_common_info;
error_parse_info:
ess << "Error parsing host information: " << hinfo;
NebulaLog::log("InM",Log::ERROR,ess);
goto error_common_info;
error_common_info:
NebulaLog::log("InM",Log::ERROR,ess);
host->set_template_error_message(ess.str());
host->touch(false);

View File

@ -51,7 +51,7 @@ class DummyInformationManager < OpenNebulaDriver
#---------------------------------------------------------------------------
def action_monitor(number, host, not_used)
results = "HYPERVISOR=dummy,"
results << "NAME=#{host},"
results << "HOSTNAME=#{host},"
results << "TOTALCPU=800,"
results << "CPUSPEED=2.2GHz,"

View File

@ -31,18 +31,18 @@ end
$: << RUBY_LIB_LOCATION
require 'OpenNebulaDriver'
require 'CommandManager'
require 'getoptlong'
#-------------------------------------------------------------------------------
# The Local Information Manager Driver
#-------------------------------------------------------------------------------
class InformationManager < OpenNebulaDriver
class InformationManagerDriverSH < OpenNebulaDriver
#---------------------------------------------------------------------------
# Init the driver
#---------------------------------------------------------------------------
def initialize(hypervisor, num)
super(num, true)
super(num, true, 0)
@config = read_configuration
@hypervisor = hypervisor
@ -57,29 +57,40 @@ class InformationManager < OpenNebulaDriver
# Execute the run_probes in the remote host
#---------------------------------------------------------------------------
def action_monitor(number, host, unused)
log_lambda=lambda do |message|
log(number, message)
end
cmd_string = "#{@cmd_path}/run_probes #{@hypervisor} #{host}"
monitor_exe = LocalCommand.run(cmd_string, log_lambda)
if monitor_exe.code == 0
send_message("MONITOR", RESULT[:success], number, monitor_exe.stdout)
else
send_message("MONITOR", RESULT[:failure], number,
"Could not monitor host #{host}.")
end
local_action(cmd_string, number, "MONITOR")
end
end
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# Information Manager main program
# IM Driver main program
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
hypervisor = ARGV[0]
im = InformationManager.new(hypervisor, 15)
opts = GetoptLong.new(
[ '--threads', '-t', GetoptLong::OPTIONAL_ARGUMENT ]
)
hypervisor = ''
threads = 15
begin
opts.each do |opt, arg|
case opt
when '--threads'
threads = arg.to_i
end
end
rescue Exception => e
exit(-1)
end
if ARGV.length >= 1
hypervisor = ARGV.shift
end
im = InformationManagerDriverSH.new(hypervisor,threads)
im.start_driver

View File

@ -31,25 +31,23 @@ end
$: << RUBY_LIB_LOCATION
require 'OpenNebulaDriver'
require 'CommandManager'
require 'getoptlong'
#-------------------------------------------------------------------------------
# The SSH Information Manager Driver
#-------------------------------------------------------------------------------
class InformationManager < OpenNebulaDriver
class InformationManagerDriverSSH < OpenNebulaDriver
#---------------------------------------------------------------------------
# Init the driver
#---------------------------------------------------------------------------
def initialize(hypervisor, threads, retries)
super(threads, true)
super(threads, true, retries)
@config = read_configuration
@hypervisor = hypervisor
@remote_dir = @config['SCRIPTS_REMOTE_DIR']
@retries = retries
# register actions
register_action(:MONITOR, method("action_monitor"))
@ -59,34 +57,19 @@ class InformationManager < OpenNebulaDriver
# Execute the run_probes in the remote host
#---------------------------------------------------------------------------
def action_monitor(number, host, do_update)
log_lambda=lambda do |message|
log(number, message)
end
if do_update == "1"
# Use SCP to sync:
sync_cmd = "scp -r #{REMOTES_LOCATION}/. #{host}:#{@remote_dir}"
# Use rsync to sync:
# sync_cmd = "rsync -Laz #{REMOTES_LOCATION} #{host}:#{@remote_dir}"
LocalCommand.run(sync_cmd, log_lambda)
LocalCommand.run(sync_cmd, log_method(number))
end
cmd_string = "#{@remote_dir}/im/run_probes #{@hypervisor} #{host}"
cmd = RemotesCommand.run(cmd_string,
host,
@remote_dir,
log_lambda,
@retries)
if cmd.code == 0
send_message("MONITOR", RESULT[:success], number, cmd.stdout)
else
send_message("MONITOR", RESULT[:failure], number,
"Could not monitor host #{host}.")
end
remotes_action(cmd_string, number, host, "MONITOR", @remote_dir)
end
end
#-------------------------------------------------------------------------------
@ -121,5 +104,5 @@ if ARGV.length >= 1
hypervisor = ARGV.shift
end
im = InformationManager.new(hypervisor, threads, retries)
im = InformationManagerDriverSSH.new(hypervisor, threads, retries)
im.start_driver

View File

@ -16,6 +16,8 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
source $(dirname $0)/../scripts_common.sh
export LANG=C
HYPERVISOR_DIR=$1.d
@ -32,7 +34,7 @@ function run_dir {
./$i $ARGUMENTS
EXIT_CODE=$?
if [ "x$EXIT_CODE" != "x0" ]; then
echo "Error executing $i" 1>&2
error_message "Error executing $i"
exit $EXIT_CODE
fi
fi

View File

@ -41,25 +41,25 @@ Image::Image(int _uid,
user_name(_user_name),
type(OS),
regtime(time(0)),
source(""),
source("-"),
state(INIT),
running_vms(0)
{
if (_image_template != 0)
{
image_template = _image_template;
obj_template = _image_template;
}
else
{
image_template = new ImageTemplate;
obj_template = new ImageTemplate;
}
}
Image::~Image()
{
if (image_template != 0)
if (obj_template != 0)
{
delete image_template;
delete obj_template;
}
}
@ -87,6 +87,7 @@ int Image::insert(SqlDB *db, string& error_str)
string public_attr;
string persistent_attr;
string dev_prefix;
string source_attr;
// ---------------------------------------------------------------------
// Check default image attributes
@ -116,7 +117,7 @@ int Image::insert(SqlDB *db, string& error_str)
get_template_attribute("PUBLIC", public_attr);
image_template->erase("PUBLIC");
obj_template->erase("PUBLIC");
TO_UPPER(public_attr);
@ -126,7 +127,7 @@ int Image::insert(SqlDB *db, string& error_str)
get_template_attribute("PERSISTENT", persistent_attr);
image_template->erase("PERSISTENT");
obj_template->erase("PERSISTENT");
TO_UPPER(persistent_attr);
@ -148,49 +149,51 @@ int Image::insert(SqlDB *db, string& error_str)
SingleAttribute * dev_att = new SingleAttribute("DEV_PREFIX",
ImagePool::default_dev_prefix());
image_template->set(dev_att);
obj_template->set(dev_att);
}
// ------------ PATH --------------------
get_template_attribute("PATH", path_attr);
// ------------ PATH & SOURCE --------------------
// ------------ SOURCE (path to store the image) --------------------
get_template_attribute("SOURCE", source);
get_template_attribute("PATH", path_attr);
get_template_attribute("SOURCE", source_attr);
// The template should contain PATH or SOURCE
if ( source.empty() && path_attr.empty() )
if ( source_attr.empty() && path_attr.empty() )
{
string size_attr;
string fstype_attr;
istringstream iss;
int size_mb;
get_template_attribute("SIZE", size_attr);
get_template_attribute("FSTYPE", fstype_attr);
// It could be an empty DATABLOCK image, if it declares SIZE and FSTYPE
if ( type_att != "DATABLOCK" || size_attr.empty() || fstype_attr.empty() )
// DATABLOCK image needs SIZE and FSTYPE
if (type != DATABLOCK || size_attr.empty() || fstype_attr.empty())
{
goto error_no_path;
}
iss.str(size_attr);
iss >> size_mb;
if (iss.fail() == true)
{
goto error_size_format;
}
}
else if ( !source.empty() && !path_attr.empty() )
else if ( !source_attr.empty() && !path_attr.empty() )
{
goto error_path_and_source;
}
if (source.empty())
else if ( !source_attr.empty() )
{
ostringstream tmp_hashstream;
ostringstream tmp_sourcestream;
tmp_hashstream << uid << ":" << name;
tmp_sourcestream << ImagePool::source_prefix() << "/";
tmp_sourcestream << sha1_digest(tmp_hashstream.str());
source = tmp_sourcestream.str();
source = source_attr;
}
state = DISABLED;
state = LOCKED; //LOCKED till the ImageManager copies it to the Repository
//--------------------------------------------------------------------------
// Insert the Image
@ -214,7 +217,7 @@ error_public_and_persistent:
goto error_common;
error_no_path:
if ( type_att == "DATABLOCK" )
if ( type == DATABLOCK )
{
error_str = "A DATABLOCK type IMAGE has to declare a PATH, or both "
"SIZE and FSTYPE.";
@ -225,6 +228,10 @@ error_no_path:
}
goto error_common;
error_size_format:
error_str = "Wrong number in SIZE.";
goto error_common;
error_path_and_source:
error_str = "Template malformed, PATH and SOURCE are mutuallly exclusive.";
goto error_common;
@ -337,7 +344,7 @@ string& Image::to_xml(string& xml) const
"<SOURCE>" << source << "</SOURCE>" <<
"<STATE>" << state << "</STATE>" <<
"<RUNNING_VMS>" << running_vms << "</RUNNING_VMS>" <<
image_template->to_xml(template_xml) <<
obj_template->to_xml(template_xml) <<
"</IMAGE>";
xml = oss.str();
@ -384,7 +391,7 @@ int Image::from_xml(const string& xml)
return -1;
}
rc += image_template->from_xml_node(content[0]);
rc += obj_template->from_xml_node(content[0]);
if (rc != 0)
{
@ -397,70 +404,6 @@ int Image::from_xml(const string& xml)
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::acquire_image()
{
int rc = 0;
switch (state)
{
case READY:
running_vms++;
state = USED;
break;
case USED:
if (persistent_img)
{
rc = -1;
}
else
{
running_vms++;
}
break;
case DISABLED:
default:
rc = -1;
break;
}
return rc;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
bool Image::release_image()
{
bool dirty = false;
switch (state)
{
case USED:
running_vms--;
if ( running_vms == 0)
{
state = READY;
}
dirty = true;
break;
case DISABLED:
case READY:
default:
break;
}
return dirty;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::disk_attribute( VectorAttribute * disk,
int * index,
ImageType* img_type)
@ -488,41 +431,22 @@ int Image::disk_attribute( VectorAttribute * disk,
get_template_attribute("DEV_PREFIX", prefix);
//--------------------------------------------------------------------------
// Acquire the image
//--------------------------------------------------------------------------
if ( acquire_image() != 0 )
{
return -1;
}
//---------------------------------------------------------------------------
// NEW DISK ATTRIBUTES
// BASE DISK ATTRIBUTES
//---------------------------------------------------------------------------
map<string,string> new_disk;
disk->replace("IMAGE", name);
disk->replace("IMAGE_ID", iid.str());
disk->replace("SOURCE", source);
new_disk.insert(make_pair("IMAGE", name));
new_disk.insert(make_pair("IMAGE_ID", iid.str()));
new_disk.insert(make_pair("SOURCE", source));
if (!bus.empty())
if (bus.empty() && !template_bus.empty()) //BUS in Image, not in DISK
{
new_disk.insert(make_pair("BUS",bus));
}
else if (!template_bus.empty())
{
new_disk.insert(make_pair("BUS",template_bus));
disk->replace("BUS",template_bus);
}
if (!driver.empty())
if (driver.empty() && !template_driver.empty())//DRIVER in Image,not in DISK
{
new_disk.insert(make_pair("DRIVER",driver));
}
else if (!template_driver.empty())
{
new_disk.insert(make_pair("DRIVER",template_driver));
disk->replace("DRIVER",template_driver);
}
//---------------------------------------------------------------------------
@ -531,28 +455,26 @@ int Image::disk_attribute( VectorAttribute * disk,
if ( persistent_img )
{
new_disk.insert(make_pair("CLONE","NO"));
new_disk.insert(make_pair("SAVE","YES"));
new_disk.insert(make_pair("SAVE_AS", iid.str())); // Tells the hook to overwrite
disk->replace("CLONE","NO");
disk->replace("SAVE","YES");
}
else
{
new_disk.insert(make_pair("CLONE","YES"));
new_disk.insert(make_pair("SAVE","NO"));
disk->replace("CLONE","YES");
disk->replace("SAVE","NO");
}
switch(type)
{
case OS:
case DATABLOCK:
new_disk.insert(make_pair("TYPE","DISK"));
new_disk.insert(make_pair("READONLY","NO"));
disk->replace("TYPE","DISK");
disk->replace("READONLY","NO");
break;
case CDROM:
new_disk.insert(make_pair("TYPE","CDROM"));
new_disk.insert(make_pair("READONLY","YES"));
disk->replace("TYPE","CDROM");
disk->replace("READONLY","YES");
break;
}
@ -560,67 +482,37 @@ int Image::disk_attribute( VectorAttribute * disk,
// TARGET attribute
//---------------------------------------------------------------------------
if (!target.empty())
if (target.empty()) //No TARGET in DISK attribute
{
new_disk.insert(make_pair("TARGET", target));
}
else if (!template_target.empty())
{
new_disk.insert(make_pair("TARGET", template_target));
}
else
{
switch(type)
if (!template_target.empty())
{
case OS:
prefix += "a";
break;
case CDROM:
prefix += "c"; // b is for context
break;
case DATABLOCK:
prefix += static_cast<char>(('e'+ *index));
*index = *index + 1;
break;
disk->replace("TARGET", template_target);
}
else
{
switch(type)
{
case OS:
prefix += "a";
break;
new_disk.insert(make_pair("TARGET", prefix));
case CDROM:
prefix += "c"; // b is for context
break;
case DATABLOCK:
prefix += static_cast<char>(('e'+ *index));
*index = *index + 1;
break;
}
disk->replace("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();
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

126
src/image/ImageManager.cc Normal file
View File

@ -0,0 +1,126 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "ImageManager.h"
#include "NebulaLog.h"
#include "ImagePool.h"
const char * ImageManager::image_driver_name = "image_exe";
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
extern "C" void * image_action_loop(void *arg)
{
ImageManager * im;
if ( arg == 0 )
{
return 0;
}
NebulaLog::log("ImM",Log::INFO,"Image Manager started.");
im = static_cast<ImageManager *>(arg);
im->am.loop(0,0);
NebulaLog::log("ImM",Log::INFO,"Image Manager stopped.");
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void ImageManager::load_mads(int uid)
{
ImageManagerDriver * imagem_mad;
ostringstream oss;
const VectorAttribute * vattr;
int rc;
NebulaLog::log("ImM",Log::INFO,"Loading Image Manager driver.");
vattr = static_cast<const VectorAttribute *>(mad_conf[0]);
if ( vattr == 0 )
{
NebulaLog::log("ImM",Log::INFO,"Failed to load Image Manager driver.");
return;
}
VectorAttribute image_conf("IMAGE_MAD",vattr->value());
image_conf.replace("NAME",image_driver_name);
imagem_mad = new ImageManagerDriver(0,image_conf.value(),false,ipool);
rc = add(imagem_mad);
if ( rc == 0 )
{
oss.str("");
oss << "\tImage Manager loaded";
NebulaLog::log("ImM",Log::INFO,oss);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ImageManager::start()
{
int rc;
pthread_attr_t pattr;
rc = MadManager::start();
if ( rc != 0 )
{
return -1;
}
NebulaLog::log("ImM",Log::INFO,"Starting Image Manager...");
pthread_attr_init (&pattr);
pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE);
rc = pthread_create(&imagem_thread,&pattr,image_action_loop,(void *) this);
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void ImageManager::do_action(const string &action, void * arg)
{
if (action == ACTION_FINALIZE)
{
NebulaLog::log("ImM",Log::INFO,"Stopping Image Manager...");
MadManager::stop();
}
else
{
ostringstream oss;
oss << "Unknown action name: " << action;
NebulaLog::log("ImM", Log::ERROR, oss);
}
}

View File

@ -0,0 +1,432 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "ImageManager.h"
#include "NebulaLog.h"
#include "ImagePool.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
Image * ImageManager::acquire_image(int image_id)
{
Image * img;
int rc;
img = ipool->get(image_id,true);
if ( img == 0 )
{
return 0;
}
rc = acquire_image(img);
if ( rc != 0 )
{
img->unlock();
img = 0;
}
return img;
}
/* -------------------------------------------------------------------------- */
Image * ImageManager::acquire_image(const string& name, int uid)
{
Image * img;
int rc;
img = ipool->get(name,uid,true);
if ( img == 0 )
{
return 0;
}
rc = acquire_image(img);
if ( rc != 0 )
{
img->unlock();
img = 0;
}
return img;
}
/* -------------------------------------------------------------------------- */
int ImageManager::acquire_image(Image *img)
{
int rc = 0;
switch (img->get_state())
{
case Image::READY:
img->inc_running();
img->set_state(Image::USED);
ipool->update(img);
break;
case Image::USED:
if (img->isPersistent())
{
rc = -1;
}
else
{
img->inc_running();
ipool->update(img);
}
break;
case Image::DISABLED:
case Image::LOCKED:
case Image::ERROR:
default:
rc = -1;
break;
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void ImageManager::move_image(Image *img, const string& source)
{
const ImageManagerDriver* imd = get();
ostringstream oss;
if ( imd == 0 )
{
NebulaLog::log("ImM",Log::ERROR,
"Could not get driver to update repository");
return;
}
oss << "Moving disk " << source << " to repository image "
<< img->get_oid();
imd->mv(img->get_oid(),source,img->get_source());
NebulaLog::log("ImM",Log::INFO,oss);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void ImageManager::disk_to_image(const string& disk_path,
int disk_num,
const string& save_id)
{
int sid;
istringstream iss;
Image * img;
ostringstream disk_file;
iss.str(save_id);
iss >> sid;
img = ipool->get(sid,true);
if ( img == 0 )
{
NebulaLog::log("ImM",Log::ERROR,"Could not get image to saveas disk.");
}
else
{
disk_file << disk_path << "/disk." << disk_num;
move_image(img,disk_file.str());
}
img->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void ImageManager::release_image(const string& image_id,
const string& disk_path,
int disk_num,
const string& save_id)
{
int rvms;
int iid;
int sid = -1;
istringstream iss;
Image * img;
ostringstream disk_file;
iss.str(image_id);
iss >> iid;
if ( save_id.empty() == false )
{
iss.clear();
iss.str(save_id);
iss >> sid;
}
img = ipool->get(iid,true);
if ( img == 0 )
{
return;
}
switch (img->get_state())
{
case Image::USED:
rvms = img->dec_running();
if ( img->isPersistent() )
{
disk_file << disk_path << "/disk." << disk_num;
img->set_state(Image::LOCKED);
move_image(img,disk_file.str());
ipool->update(img);
img->unlock();
}
else
{
if ( rvms == 0)
{
img->set_state(Image::READY);
}
ipool->update(img);
img->unlock();
if ( sid != -1 )
{
img = ipool->get(sid,true);
if ( img == 0 )
{
NebulaLog::log("ImM",Log::ERROR,
"Could not get image to saveas disk.");
}
else
{
disk_file << disk_path << "/disk." << disk_num;
move_image(img,disk_file.str());
}
img->unlock();
}
}
break;
case Image::DISABLED:
case Image::READY:
case Image::ERROR:
case Image::LOCKED:
NebulaLog::log("ImM",Log::ERROR,
"Trying to release image in wrong state.");
default:
img->unlock();
break;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ImageManager::enable_image(int iid, bool to_enable)
{
int rc = 0;
Image * img;
img = ipool->get(iid,true);
if ( img == 0 )
{
return -1;
}
if ( to_enable == true )
{
switch (img->get_state())
{
case Image::DISABLED:
case Image::ERROR:
img->set_state(Image::READY);
ipool->update(img);
case Image::READY:
break;
default:
rc = -1;
break;
}
}
else
{
switch (img->get_state())
{
case Image::READY:
case Image::ERROR:
img->set_state(Image::DISABLED);
ipool->update(img);
case Image::DISABLED:
break;
default:
rc = -1;
break;
}
}
img->unlock();
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ImageManager::delete_image(int iid)
{
Image * img;
img = ipool->get(iid,true);
if ( img == 0 )
{
return -1;
}
switch(img->get_state())
{
case Image::READY:
if ( img->get_running() != 0 )
{
img->unlock();
return -1; //Can not remove images in use
}
break;
case Image::USED:
img->unlock();
return -1; //Can not remove images in use
break;
case Image::INIT:
case Image::DISABLED:
case Image::LOCKED:
case Image::ERROR:
break;
}
const ImageManagerDriver* imd = get();
if ( imd == 0 )
{
return -1;
}
imd->rm(img->get_oid(),img->get_source());
img->unlock();
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ImageManager::register_image(int iid)
{
const ImageManagerDriver* imd = get();
ostringstream oss;
string path;
Image* img;
if ( imd == 0 )
{
NebulaLog::log("ImM",Log::ERROR,
"Could not get driver to update repository");
return -1;
}
img = ipool->get(iid,true);
if (img == 0)
{
return -1;
}
img->get_template_attribute("PATH",path);
if ( path.empty() == true ) //NO PATH -> USE SOURCE OR MKFS FOR DATABLOCK
{
string fs;
string size;
img->get_template_attribute("SIZE", size);
img->get_template_attribute("FSTYPE", fs);
if ( img->get_type() == Image::DATABLOCK &&
!size.empty() && !fs.empty() )
{
imd->mkfs(img->get_oid(), fs, size);
oss << "Creating disk at " << img->get_source() << " of "
<< size << "Mb with format " << fs;
}
else
{
img->set_state(Image::READY);
ipool->update(img);
oss << "Using source " << img->get_source()
<< " from template for image " << img->get_name();
}
}
else //PATH -> COPY TO REPOSITORY AS SOURCE
{
imd->cp(img->get_oid(), path);
oss << "Copying " << path <<" to repository for image "<<img->get_oid();
}
NebulaLog::log("ImM",Log::INFO,oss);
img->unlock();
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,306 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "ImageManagerDriver.h"
#include "ImagePool.h"
#include "NebulaLog.h"
#include "Nebula.h"
#include <sstream>
/* ************************************************************************** */
/* Driver ASCII Protocol Implementation */
/* ************************************************************************** */
void ImageManagerDriver::cp(int oid,
const string& source) const
{
ostringstream os;
os << "CP " << oid << " " << source << endl;
write(os);
}
/* -------------------------------------------------------------------------- */
void ImageManagerDriver::mv(int oid,
const string& source,
const string& destination) const
{
ostringstream os;
os << "MV " << oid << " " << source << " " << destination << endl;
write(os);
}
/* -------------------------------------------------------------------------- */
void ImageManagerDriver::mkfs(int oid,
const string& fs,
const string& size_mb) const
{
ostringstream os;
os << "MKFS " << oid << " " << fs << " " << size_mb << endl;
write(os);
}
/* -------------------------------------------------------------------------- */
void ImageManagerDriver::rm(int oid, const string& destination) const
{
ostringstream os;
os << "RM " << oid << " " << destination << endl;
write(os);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* ************************************************************************** */
/* MAD Interface */
/* ************************************************************************** */
void ImageManagerDriver::protocol(
string& message)
{
istringstream is(message);
ostringstream os;
string action;
string result;
int id;
Image * image;
string source;
string info;
os << "Message received: " << message;
NebulaLog::log("ImG", Log::DEBUG, os);
// Parse the driver message
if ( is.good() )
is >> action >> ws;
else
return;
if ( is.good() )
is >> result >> ws;
else
return;
if ( is.good() )
{
is >> id >> ws;
if ( is.fail() )
{
if ( action == "LOG" )
{
string info;
is.clear();
getline(is,info);
NebulaLog::log("ImG",log_type(result[0]), info.c_str());
}
return;
}
}
else
return;
// Get the image from the pool
image = ipool->get(id,true);
if ( image == 0 )
{
return;
}
// Driver Actions
if ( action == "CP" )
{
if ( result == "SUCCESS" )
{
string source;
if ( is.good() )
{
is >> source >> ws;
}
if ( is.fail() )
{
goto error_cp;
}
image->set_source(source);
image->set_state(Image::READY);
ipool->update(image);
NebulaLog::log("ImM", Log::INFO, "Image copied and ready to use.");
}
else
{
goto error_cp;
}
}
else if ( action == "MV" )
{
if ( result == "SUCCESS" )
{
if (image->get_source() == "-")
{
string source;
if ( is.good() )
{
is >> source >> ws;
}
if ( is.fail() )
{
goto error_mv;
}
image->set_source(source);
}
image->set_state(Image::READY);
ipool->update(image);
NebulaLog::log("ImM", Log::INFO, "Image saved and ready to use.");
}
else
{
goto error_mv;
}
}
else if ( action == "MKFS" )
{
if ( result == "SUCCESS" )
{
string source;
if ( is.good() )
{
is >> source >> ws;
}
if ( is.fail() )
{
goto error_mkfs;
}
image->set_source(source);
image->set_state(Image::READY);
ipool->update(image);
NebulaLog::log("ImM", Log::INFO, "Image created and ready to use");
}
else
{
goto error_mkfs;
}
}
else if ( action == "RM" )
{
int rc;
source = image->get_source();
rc = ipool->drop(image);
if ( rc < 0 )
{
NebulaLog::log("ImM",Log::ERROR,"Image could not be removed from DB");
}
if ( result == "SUCCESS" )
{
NebulaLog::log("ImM",Log::ERROR,"Image successfully removed.");
}
else
{
goto error_rm;
}
}
else if (action == "LOG")
{
getline(is,info);
NebulaLog::log("ImM", log_type(result[0]), info.c_str());
}
image->unlock();
return;
error_cp:
os.str("");
os << "Error copying image in the repository";
goto error_common;
error_mv:
os.str("");
os << "Error saving image to the repository";
goto error_common;
error_mkfs:
os.str("");
os << "Error creating datablock";
goto error_common;
error_rm:
os.str("");
os << "Error removing image from repository. Remove file " << source
<< " to completely delete image.";
error_common:
getline(is,info);
if (!info.empty() && (info[0] != '-'))
{
os << ": " << info;
image->set_template_error_message(os.str());
}
NebulaLog::log("ImM", Log::ERROR, os);
image->set_state(Image::ERROR);
ipool->update(image);
image->unlock();
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void ImageManagerDriver::recover()
{
NebulaLog::log("ImG",Log::INFO,"Recovering Image Repository drivers");
}

View File

@ -20,10 +20,10 @@
#include "ImagePool.h"
#include "AuthManager.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string ImagePool::_source_prefix;
string ImagePool::_default_type;
string ImagePool::_default_dev_prefix;
@ -31,7 +31,6 @@ string ImagePool::_default_dev_prefix;
/* -------------------------------------------------------------------------- */
ImagePool::ImagePool(SqlDB * db,
const string& __source_prefix,
const string& __default_type,
const string& __default_dev_prefix):
PoolSQL(db,Image::table)
@ -39,7 +38,6 @@ ImagePool::ImagePool(SqlDB * db,
ostringstream sql;
// Init static defaults
_source_prefix = __source_prefix;
_default_type = __default_type;
_default_dev_prefix = __default_dev_prefix;
@ -68,9 +66,6 @@ int ImagePool::allocate (
string name;
ostringstream oss;
// ---------------------------------------------------------------------
// Build a new Image object
// ---------------------------------------------------------------------
img = new Image(uid, user_name, img_template);
// Check name
@ -96,7 +91,6 @@ int ImagePool::allocate (
return *oid;
error_name:
oss << "NAME cannot be empty.";
goto error_common;
@ -128,6 +122,9 @@ int ImagePool::disk_attribute(VectorAttribute * disk,
ostringstream oss;
Nebula& nd = Nebula::instance();
ImageManager * imagem = nd.get_imagem();
source = disk->vector_value("IMAGE");
if (source.empty())
@ -144,7 +141,7 @@ int ImagePool::disk_attribute(VectorAttribute * disk,
if( !is.fail() )
{
img = get(image_id,true);
img = imagem->acquire_image(image_id);
if (img == 0)
{
@ -155,7 +152,7 @@ int ImagePool::disk_attribute(VectorAttribute * disk,
}
else
{
img = get(source,uid,true);
img = imagem->acquire_image(source,uid);
if (img == 0)
{
@ -167,7 +164,7 @@ int ImagePool::disk_attribute(VectorAttribute * disk,
{
string type = disk->vector_value("TYPE");
transform(type.begin(), type.end(), type.begin(), (int(*)(int))toupper);
transform(type.begin(),type.end(),type.begin(),(int(*)(int))toupper);
if( type == "SWAP" )
{
@ -187,12 +184,9 @@ int ImagePool::disk_attribute(VectorAttribute * disk,
}
else
{
rc = img->disk_attribute(disk, index, img_type);
img->disk_attribute(disk, index, img_type);
if ( rc == 0 )
{
update(img);
}
update(img);
img->unlock();
}

View File

@ -23,7 +23,10 @@ lib_name='nebula_image'
# Sources to generate the library
source_files=[
'Image.cc',
'ImagePool.cc'
'ImagePool.cc',
'ImageManagerDriver.cc',
'ImageManager.cc',
'ImageManagerActions.cc'
]
# Build library

View File

@ -31,17 +31,17 @@ const string names[] = {"Image one", "Second Image", "The third image"};
const string templates[] =
{
"NAME = \"Image one\"\n"
"ORIGINAL_PATH = /tmp/image_test\n"
"PATH = /tmp/image_test\n"
"PERSISTENT = YES\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"
"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"
"PATH = /tmp/image_test\n"
"# DESCRIPTION = \"An image description\"\n"
"BUS = SCSI\n"
"PROFILE = STUDENT\n"
@ -50,19 +50,19 @@ const string templates[] =
const string xmls[] =
{
"<IMAGE><ID>0</ID><UID>0</UID><USERNAME>A user</USERNAME><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198</SOURCE><STATE>3</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>0</ID><UID>0</UID><USERNAME>A user</USERNAME><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</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><PATH><![CDATA[/tmp/image_test]]></PATH></TEMPLATE></IMAGE>",
"<IMAGE><ID>1</ID><UID>1</UID><USERNAME>B user</USERNAME><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f3</SOURCE><STATE>3</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>1</ID><UID>1</UID><USERNAME>B user</USERNAME><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</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><PATH><![CDATA[/tmp/image_second_test]]></PATH></TEMPLATE></IMAGE>",
"<IMAGE><ID>0</ID><UID>2</UID><USERNAME>C user</USERNAME><NAME>The third image</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/e50b0c738be9d431475bf5859629e5580301a7d6</SOURCE><STATE>3</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>"
"<IMAGE><ID>0</ID><UID>2</UID><USERNAME>C user</USERNAME><NAME>The third image</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</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><PATH><![CDATA[/tmp/image_test]]></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>A user</USERNAME><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198</SOURCE><STATE>3</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><USERNAME>B user</USERNAME><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f3</SOURCE><STATE>3</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>2</ID><UID>2</UID><USERNAME>C user</USERNAME><NAME>The third image</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/e50b0c738be9d431475bf5859629e5580301a7d6</SOURCE><STATE>3</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></IMAGE_POOL>";
"<IMAGE_POOL><IMAGE><ID>0</ID><UID>0</UID><USERNAME>A user</USERNAME><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</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><PATH><![CDATA[/tmp/image_test]]></PATH></TEMPLATE></IMAGE><IMAGE><ID>1</ID><UID>1</UID><USERNAME>B user</USERNAME><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</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><PATH><![CDATA[/tmp/image_second_test]]></PATH></TEMPLATE></IMAGE><IMAGE><ID>2</ID><UID>2</UID><USERNAME>C user</USERNAME><NAME>The third image</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</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><PATH><![CDATA[/tmp/image_test]]></PATH><PROFILE><![CDATA[STUDENT]]></PROFILE></TEMPLATE></IMAGE></IMAGE_POOL>";
const string xml_dump_where =
"<IMAGE_POOL><IMAGE><ID>0</ID><UID>0</UID><USERNAME>A user</USERNAME><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198</SOURCE><STATE>3</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><USERNAME>B user</USERNAME><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>source_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f3</SOURCE><STATE>3</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_POOL>";
"<IMAGE_POOL><IMAGE><ID>0</ID><UID>0</UID><USERNAME>A user</USERNAME><NAME>Image one</NAME><TYPE>0</TYPE><PUBLIC>0</PUBLIC><PERSISTENT>1</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</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><PATH><![CDATA[/tmp/image_test]]></PATH></TEMPLATE></IMAGE><IMAGE><ID>1</ID><UID>1</UID><USERNAME>B user</USERNAME><NAME>Second Image</NAME><TYPE>0</TYPE><PUBLIC>1</PUBLIC><PERSISTENT>0</PERSISTENT><REGTIME>0000000000</REGTIME><SOURCE>-</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><PATH><![CDATA[/tmp/image_second_test]]></PATH></TEMPLATE></IMAGE></IMAGE_POOL>";
const string replacement = "0000000000";
@ -70,12 +70,10 @@ class ImagePoolFriend : public ImagePool
{
public:
ImagePoolFriend(SqlDB * db,
const string& _source_prefix,
const string& _default_type,
const string& _default_dev_prefix):
ImagePool( db,
_source_prefix,
_default_type,
_default_dev_prefix){};
@ -128,7 +126,10 @@ class ImagePoolTest : public PoolTest
CPPUNIT_TEST ( bus_source_assignment );
CPPUNIT_TEST ( public_attribute );
CPPUNIT_TEST ( persistence );
CPPUNIT_TEST ( imagepool_disk_attribute );
// Requires ImageManger, and NebulaTest
// CPPUNIT_TEST ( imagepool_disk_attribute );
CPPUNIT_TEST ( dump );
CPPUNIT_TEST ( dump_where );
@ -144,7 +145,7 @@ protected:
PoolSQL* create_pool(SqlDB* db)
{
ImagePoolFriend * imp =
new ImagePoolFriend(db, "source_prefix", "OS", "hd");
new ImagePoolFriend(db, "OS", "hd");
return imp;
};
@ -198,7 +199,7 @@ public:
// Create a new pool, using the same DB. This new pool should read the
// allocated images.
imp = new ImagePool(db, "source_prefix", "OS", "hd");
imp = new ImagePool(db,"OS", "hd");
img = imp->get(names[0], uids[0], false);
CPPUNIT_ASSERT( img != 0 );
@ -241,7 +242,7 @@ public:
// Image object should be cached. Let's change some template attributes
img->replace_template_attribute(description_name, new_description);
img->replace_template_attribute(attr_name, new_attr_value);
img->remove_template_attribute("ORIGINAL_PATH");
img->remove_template_attribute("PATH");
ip->update(img);
@ -253,7 +254,7 @@ public:
img->get_template_attribute("DESCRIPTION", description_val);
img->get_template_attribute("NEW_ATTRIBUTE", attr_val);
img->get_template_attribute("ORIGINAL_PATH", no_value);
img->get_template_attribute("PATH", no_value);
CPPUNIT_ASSERT( description_val == new_description );
CPPUNIT_ASSERT( attr_val == new_attr_value );
@ -271,7 +272,7 @@ public:
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);
img->get_template_attribute("PATH", no_value);
CPPUNIT_ASSERT( description_val == new_description );
CPPUNIT_ASSERT( attr_val == new_attr_value );
@ -398,11 +399,11 @@ public:
string templates[] =
{
"ORIGINAL_PATH = /tmp/image_test\n"
"PATH = /tmp/image_test\n"
"DESCRIPTION = \"This template lacks name!\"\n",
"NAME = \"name A\"\n"
"ORIGINAL_PATH = /tmp/image_test\n"
"PATH = /tmp/image_test\n"
"TYPE = WRONG\n",
"NAME \"PARSE ERROR\"\n"
@ -451,7 +452,7 @@ public:
CPPUNIT_ASSERT( img != 0 );
CPPUNIT_ASSERT( oid == 0 );
img->enable(true);
img->set_state(Image::READY);
img->disk_attribute(disk, &index, &img_type);
value = disk->vector_value("TARGET");
@ -466,7 +467,7 @@ public:
disk = new VectorAttribute("DISK");
// Allocate a CDROM type image
string templ = "NAME = \"name A\" TYPE = CDROM ORIGINAL_PATH = /tmp";
string templ = "NAME = \"name A\" TYPE = CDROM PATH = /tmp";
imp->allocate(0, templ, &oid);
CPPUNIT_ASSERT(oid >= 0);
@ -474,7 +475,7 @@ public:
img = imp->get(oid, false);
CPPUNIT_ASSERT( img != 0 );
img->enable(true);
img->set_state(Image::READY);
img->disk_attribute(disk, &index, &img_type);
value = disk->vector_value("TARGET");
@ -488,7 +489,7 @@ public:
disk = new VectorAttribute("DISK");
// Allocate a DATABLOCK type image
templ = "NAME = \"name B\" TYPE = DATABLOCK";
templ = "NAME = \"name B\" TYPE = DATABLOCK PATH=\"/dev/null\"";
imp->allocate(0, templ, &oid);
CPPUNIT_ASSERT(oid >= 0);
@ -496,7 +497,7 @@ public:
img = imp->get(oid, false);
CPPUNIT_ASSERT( img != 0 );
img->enable(true);
img->set_state(Image::READY);
img->disk_attribute(disk, &index, &img_type);
value = disk->vector_value("TARGET");
@ -510,7 +511,8 @@ public:
disk = new VectorAttribute("DISK");
// Allocate a DATABLOCK type image
templ = "NAME = \"name C\" TYPE = DATABLOCK DEV_PREFIX = \"sd\"";
templ = "NAME = \"name C\" TYPE = DATABLOCK DEV_PREFIX = \"sd\""
" SIZE=4 FSTYPE=ext3";
imp->allocate(0, templ, &oid);
CPPUNIT_ASSERT(oid >= 0);
@ -518,7 +520,7 @@ public:
img = imp->get(oid, false);
CPPUNIT_ASSERT( img != 0 );
img->enable(true);
img->set_state(Image::READY);
img->disk_attribute(disk, &index, &img_type);
value = disk->vector_value("TARGET");
@ -551,7 +553,7 @@ public:
// A disk without a BUS attribute should not have it added.
disk = new VectorAttribute("DISK");
img->enable(true);
img->set_state(Image::READY);
rc = img->disk_attribute(disk, &index, &img_type);
CPPUNIT_ASSERT( rc == 0 );
@ -561,11 +563,10 @@ public:
value = "";
value = disk->vector_value("SOURCE");
CPPUNIT_ASSERT( value ==
"source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198" );
CPPUNIT_ASSERT( value == "-" );
// clean up
img->release_image();
//img->release_image();
delete disk;
// ---------------------------------------------------------------------
@ -573,7 +574,7 @@ public:
disk = new VectorAttribute("DISK");
disk->replace("BUS", "SCSI");
img->enable(true);
img->set_state(Image::READY);
rc = img->disk_attribute(disk, &index, &img_type);
CPPUNIT_ASSERT( rc == 0 );
@ -582,8 +583,7 @@ public:
value = "";
value = disk->vector_value("SOURCE");
CPPUNIT_ASSERT( value ==
"source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198" );
CPPUNIT_ASSERT( value == "-" );
// clean up
delete disk;
@ -606,10 +606,12 @@ public:
// Allocate 2 images, with different dev_prefix
string template_0 = "NAME = \"Image 0\"\n"
"DEV_PREFIX = \"hd\"\n";
"DEV_PREFIX = \"hd\"\n"
"PATH = /dev/null\n";
string template_1 = "NAME = \"Image 1\"\n"
"DEV_PREFIX = \"sd\"\n";
"DEV_PREFIX = \"sd\"\n"
"PATH = /dev/null\n";
imp->allocate(0, template_0, &oid_0);
@ -621,11 +623,11 @@ public:
img = imp->get(oid_0, false);
CPPUNIT_ASSERT( img != 0 );
img->enable(true);
img->set_state(Image::READY);
img = imp->get(oid_1, false);
CPPUNIT_ASSERT( img != 0 );
img->enable(true);
img->set_state(Image::READY);
// Disk using image 0
@ -675,46 +677,46 @@ public:
{
// false
"NAME = \"name A\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n",
"PATH = \"/tmp/nothing\"\n",
// true
"NAME = \"name B\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PATH = \"/tmp/nothing\"\n"
"PUBLIC = YES",
// false
"NAME = \"name C\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PATH = \"/tmp/nothing\"\n"
"PUBLIC = NO",
// false
"NAME = \"name D\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PATH = \"/tmp/nothing\"\n"
"PUBLIC = 1",
// true
"NAME = \"name E\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PATH = \"/tmp/nothing\"\n"
"PUBLIC = Yes",
// false
"NAME = \"name F\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PATH = \"/tmp/nothing\"\n"
"PUBLIC = TRUE",
// true
"NAME = \"name G\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PATH = \"/tmp/nothing\"\n"
"PUBLIC = yes",
// false
"NAME = \"name H\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PATH = \"/tmp/nothing\"\n"
"PUBLIC = 'YES'",
// true
"NAME = \"name I\"\n"
"ORIGINAL_PATH = \"/tmp/nothing\"\n"
"PATH = \"/tmp/nothing\"\n"
"PUBLIC = \"YES\"",
"END"
@ -769,19 +771,23 @@ public:
{
"NAME = \"Image 1\"\n"
"PERSISTENT = NO\n"
"PUBLIC = NO\n",
"PUBLIC = NO\n"
"PATH = /dev/null\n",
"NAME = \"Image 2\"\n"
"PERSISTENT = NO\n"
"PUBLIC = YES\n",
"PUBLIC = YES\n"
"PATH = /dev/null\n",
"NAME = \"Image 3\"\n"
"PERSISTENT = YES\n"
"PUBLIC = NO\n",
"PUBLIC = NO\n"
"PATH = /dev/null\n",
"NAME = \"Image 4\"\n"
"PERSISTENT = YES\n"
"PUBLIC = YES\n",
"PUBLIC = YES\n"
"PATH = /dev/null\n",
"END"
};
@ -864,15 +870,15 @@ public:
string result = oss.str();
result.replace(157, 10, replacement);
result.replace(1147, 10, replacement);
result.replace(1677, 10, replacement);
result.replace(1076, 10, replacement);
result.replace(1535, 10, replacement);
/*
if( result != xml_dump )
{
cout << endl << result << endl << xml_dump << endl;
}
//*/
*/
CPPUNIT_ASSERT( result == xml_dump );
}
@ -899,14 +905,14 @@ public:
string result = oss.str();
result.replace(157, 10, replacement);
result.replace(1147, 10, replacement);
result.replace(1076, 10, replacement);
/*
if( result != xml_dump_where )
{
cout << endl << result << endl << xml_dump_where << endl;
}
//*/
CPPUNIT_ASSERT( result == xml_dump_where );
}

44
src/image_mad/one_image Executable file
View File

@ -0,0 +1,44 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
#Setup driver variables
DRIVER_NAME=`basename $0 | cut -d. -f1`
if [ -z "${ONE_LOCATION}" ]; then
DRIVERRC=/etc/one/${DRIVER_NAME}/${DRIVER_NAME}rc
MADCOMMON=/usr/lib/one/mads/madcommon.sh
VAR_LOCATION=/var/lib/one
else
DRIVERRC=$ONE_LOCATION/etc/${DRIVER_NAME}/${DRIVER_NAME}rc
MADCOMMON=$ONE_LOCATION/lib/mads/madcommon.sh
VAR_LOCATION=$ONE_LOCATION/var
fi
. $MADCOMMON
# Export the im_mad specific rc
export_rc_vars $DRIVERRC
# Go to var directory ONE_LOCATION/var or /var/lib/one
cd $VAR_LOCATION
LOG_FILE=$DRIVER_NAME
# Execute the actual MAD
execute_mad $*

116
src/image_mad/one_image.rb Executable file
View File

@ -0,0 +1,116 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- */
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# Licensed under the Apache License, Version 2.0 (the "License"); you may */
# not use this file except in compliance with the License. You may obtain */
# a copy of the License at */
# */
# http://www.apache.org/licenses/LICENSE-2.0 */
# */
# Unless required by applicable law or agreed to in writing, software */
# distributed under the License is distributed on an "AS IS" BASIS, */
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
# See the License for the specific language governing permissions and */
# limitations under the License. */
# -------------------------------------------------------------------------- */
# ----------------------------------------------------------------------------
# Set up the environment for the driver
# ----------------------------------------------------------------------------
ONE_LOCATION = ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION = "/usr/lib/one/ruby"
VAR_LOCATION = "/var/lib/one"
else
RUBY_LIB_LOCATION = ONE_LOCATION + "/lib/ruby"
VAR_LOCATION = ONE_LOCATION + "/var"
end
$: << RUBY_LIB_LOCATION
require "OpenNebulaDriver"
require 'getoptlong'
# This class provides basic messaging and logging functionality
# to implement Image Repository Drivers. A image repository driver
# is a program (or a set of) that specialize the OpenNebula behavior
# by interfacing with specific infrastructure storage solutions.
class ImageDriver < OpenNebulaDriver
# -------------------------------------------------------------------------
# Image Driver Protocol constants
# -------------------------------------------------------------------------
ACTION = {
:mv => "MV",
:cp => "CP",
:rm => "RM",
:mkfs => "MKFS",
:log => "LOG"
}
# -------------------------------------------------------------------------
# Register default actions for the protocol
# -------------------------------------------------------------------------
def initialize(fs_type, concurrency=10, threaded=true)
super(concurrency,threaded,0)
@actions_path = "#{VAR_LOCATION}/remotes/image/#{fs_type}"
register_action(ACTION[:mv].to_sym, method("mv"))
register_action(ACTION[:cp].to_sym, method("cp"))
register_action(ACTION[:rm].to_sym, method("rm"))
register_action(ACTION[:mkfs].to_sym, method("mkfs"))
end
# -------------------------------------------------------------------------
# Image Manager Protocol Actions (generic implementation
# -------------------------------------------------------------------------
def mv(id, src, dst)
local_action("#{@actions_path}/mv #{src} #{dst} #{id}",id,ACTION[:mv])
end
def cp(id, src)
local_action("#{@actions_path}/cp #{src} #{id}",id,ACTION[:cp])
end
def rm(id, dst)
local_action("#{@actions_path}/rm #{dst} #{id}",id,ACTION[:rm])
end
def mkfs(id, fs, size)
local_action("#{@actions_path}/mkfs #{fs} #{size} #{id}",id,ACTION[:mkfs])
end
end
# ---------------------------------------------------------------------------- #
# ImageDriver Main program
# ---------------------------------------------------------------------------- #
opts = GetoptLong.new(
[ '--threads', '-t', GetoptLong::OPTIONAL_ARGUMENT ]
)
fs_type = ''
threads = 15
begin
opts.each do |opt, arg|
case opt
when '--threads'
threads = arg.to_i
end
end
rescue Exception => e
exit(-1)
end
if ARGV.length >= 1
fs_type = ARGV.shift
else
exit(-1)
end
image_driver = ImageDriver.new(fs_type, threads)
image_driver.start_driver

57
src/image_mad/remotes/fs/cp Executable file
View File

@ -0,0 +1,57 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
###############################################################################
# This script is used to copy a VM image (SRC) to the image repository as DST
# Several SRC types are supported
###############################################################################
# -------- Set up the environment to source common tools & conf ------------
if [ -z "${ONE_LOCATION}" ]; then
LIB_LOCATION=/usr/lib/one
else
LIB_LOCATION=$ONE_LOCATION/lib
fi
. $LIB_LOCATION/sh/scripts_common.sh
source $(dirname $0)/fsrc
SRC=$1
ID=$2
DST=`generate_image_path`
# ------------ Copy the image to the repository -------------
case $SRC in
http://*)
log "Downloading $SRC to the image repository"
exec_and_log "$WGET -O $DST $SRC" \
"Error downloading $SRC"
;;
*)
log "Copying local image $SRC to the image repository"
exec_and_log "cp -f $SRC $DST" \
"Error copying $SRC to $DST"
;;
esac
exec_and_log "chmod 0660 $DST"
echo "$DST"

View File

@ -0,0 +1,37 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
#------------------------------------------------------------------------------
# Configuration File for File-System based Image Repositories
#------------------------------------------------------------------------------
export IMAGE_REPOSITORY_PATH=$ONE_LOCATION/var/images
#------------------------------------------------------------------------------
# Function used to generate Image names, you should not need to override this
#------------------------------------------------------------------------------
function generate_image_path {
CANONICAL_STR="`$DATE +%s`:$ID"
CANONICAL_MD5=$($MD5SUM - << EOF
$CANONICAL_STR
EOF
)
echo "$IMAGE_REPOSITORY_PATH/`echo $CANONICAL_MD5 | cut -d ' ' -f1`"
}

49
src/image_mad/remotes/fs/mkfs Executable file
View File

@ -0,0 +1,49 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
###############################################################################
# This script is used to create a VM image (SRC) of size (SIZE) and formatted
# as (FS)
###############################################################################
# ------------ Set up the environment to source common tools ------------
if [ -z "${ONE_LOCATION}" ]; then
LIB_LOCATION=/usr/lib/one
else
LIB_LOCATION=$ONE_LOCATION/lib
fi
. $LIB_LOCATION/sh/scripts_common.sh
source $(dirname $0)/fsrc
# ------------ Create the image to the repository ------------
FSTYPE=$1
SIZE=$2
ID=$3
DST=`generate_image_path`
exec_and_log "$DD if=/dev/zero of=$DST bs=1 count=1 seek=${SIZE}M" \
"Could not create image $DST"
exec_and_log "$MKFS -t $FSTYPE -F $DST" \
"Unable to create filesystem $FSTYPE in $DST"
exec_and_log "chmod 0660 $DST"
echo "$DST"

64
src/image_mad/remotes/fs/mv Executable file
View File

@ -0,0 +1,64 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
###############################################################################
# This script is used to move a VM image (SRC) to the image repository as DST
# Several SRC types are supported
###############################################################################
# ------------ Set up the environment to source common tools ------------
if [ -z "${ONE_LOCATION}" ]; then
LIB_LOCATION=/usr/lib/one
else
LIB_LOCATION=$ONE_LOCATION/lib
fi
. $LIB_LOCATION/sh/scripts_common.sh
source $(dirname $0)/fsrc
SRC=$1
DST=$2
ID=$3
# ------------ Generate a filename for the image ------------
if [ $DST -eq "-" ] ; then
DST=`generate_image_path`
fi
# ------------ Move the image to the repository ------------
case $SRC in
http://*)
log "Downloading $SRC to the image repository"
exec_and_log "$WGET -O $DST $SRC" \
"Error downloading $SRC"
;;
*)
log "Moving local image $SRC to the image repository"
exec_and_log "mv -f $SRC $DST" \
"Could not move $SRC to $DST"
;;
esac
exec_and_log "chmod 0660 $DST"
echo "$DST"

42
src/image_mad/remotes/fs/rm Executable file
View File

@ -0,0 +1,42 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
###############################################################################
# This script is used to remove a VM image (SRC) from the image repository
###############################################################################
# ------------ Set up the environment to source common tools ------------
if [ -z "${ONE_LOCATION}" ]; then
LIB_LOCATION=/usr/lib/one
else
LIB_LOCATION=$ONE_LOCATION/lib
fi
. $LIB_LOCATION/sh/scripts_common.sh
source $(dirname $0)/fsrc
# ------------ Remove the image to the repository ------------
SRC=$1
if [ -e $SRC ] ; then
log "Removing $SRC from the image repository"
exec_and_log "rm $SRC" \
"Error deleting $SRC"
fi

View File

@ -30,6 +30,7 @@ env.Prepend(LIBS=[
'nebula_mad',
'nebula_template',
'nebula_vm',
'nebula_vmtemplate',
'nebula_vnm',
'nebula_image',
'nebula_pool',

View File

@ -39,7 +39,6 @@ Mad::~Mad()
char buf[]="FINALIZE\n";
int status;
pid_t rp;
size_t retval;
if ( pid==-1)
{
@ -47,7 +46,7 @@ Mad::~Mad()
}
// Finish the driver
retval = ::write(nebula_mad_pipe, buf, strlen(buf));
::write(nebula_mad_pipe, buf, strlen(buf));
close(mad_nebula_pipe);
close(nebula_mad_pipe);
@ -68,7 +67,6 @@ int Mad::start()
{
int ne_mad_pipe[2];
int mad_ne_pipe[2];
size_t retval;
map<string,string>::iterator it;
@ -191,7 +189,7 @@ int Mad::start()
fcntl(nebula_mad_pipe, F_SETFD, FD_CLOEXEC);
fcntl(mad_nebula_pipe, F_SETFD, FD_CLOEXEC);
retval = ::write(nebula_mad_pipe, buf, strlen(buf));
::write(nebula_mad_pipe, buf, strlen(buf));
do
{
@ -291,11 +289,9 @@ int Mad::reload()
int status;
int rc;
pid_t rp;
size_t retval;
// Finish the driver
retval = ::write(nebula_mad_pipe, buf, strlen(buf));
::write(nebula_mad_pipe, buf, strlen(buf));
close(nebula_mad_pipe);
close(mad_nebula_pipe);

View File

@ -147,7 +147,6 @@ int MadManager::add(Mad *mad)
{
char buf = 'A';
int rc;
size_t retval;
if ( mad == 0 )
{
@ -167,7 +166,7 @@ int MadManager::add(Mad *mad)
mads.push_back(mad);
retval = write(pipe_w, &buf, sizeof(char));
write(pipe_w, &buf, sizeof(char));
unlock();
@ -216,7 +215,6 @@ void MadManager::listener()
int greater;
unsigned int i,j;
int rc,mrc;
size_t retval;
char c;
@ -264,7 +262,7 @@ void MadManager::listener()
{
if ( fd == pipe_r ) // Driver added, update the fd vector
{
retval = read(fd, (void *) &c, sizeof(char));
read(fd, (void *) &c, sizeof(char));
lock();

View File

@ -27,6 +27,20 @@ require 'stringio'
# * +stdout+: string of the standard output. Read-only
# * +stderr+: string of the standard error. Read-only
# * +command+: command to execute. Read-only
#
# The protocol for scripts to log is as follows:
#
# * Log messages will be sent to STDOUT
# * The script will return 0 if it succeded or any other value
# if there was a failure
# * In case of failure the cause of the error will be written to STDERR
# wrapped by start and end marks as follows:
#
# ERROR MESSAGE --8<------
# error message for the failure
# ERROR MESSAGE ------>8--
class GenericCommand
attr_reader :code, :stdout, :stderr, :command
@ -72,13 +86,20 @@ class GenericCommand
if @code!=0
log("Command execution fail: #{command}")
log("STDERR follows.")
log(@stderr)
end
log(@stderr)
return @code
end
# Parses error message from +stderr+ output
def get_error_message
tmp=@stderr.scan(/^ERROR MESSAGE --8<------\n(.*?)ERROR MESSAGE ------>8--$/m)
return "-" if !tmp[0]
tmp[0].join(' ').strip
end
private
# Gets exit code from STDERR
@ -158,14 +179,14 @@ class RemotesCommand < SSHCommand
cmd = self.new(cmd_string, host, logger, stdin)
cmd.run
if cmd.code == MAGIC_RC
cmd.update_remotes(host, remote_dir, logger)
@command = command
cmd.run
end
while cmd.code != 0 and retries != 0
sleep 1
cmd.run

View File

@ -12,10 +12,12 @@
# See the License for the specific language governing permissions and */
# limitations under the License. */
# -------------------------------------------------------------------------- */
require "ActionManager"
require "CommandManager"
# Author:: dsa-research.org
# Copyright:: (c) 2009 Universidad Computense de Madrid
# Copyright:: (c) OpenNebula Project Leads (OpenNebula.org)
# License:: Apache License
# This class provides basic messaging and logging functionality
@ -34,14 +36,18 @@ class OpenNebulaDriver < ActionManager
:failure => "FAILURE"
}
def initialize(concurrency=10, threaded=true)
def initialize(concurrency=10, threaded=true, retries=0)
super(concurrency,threaded)
register_action(:INIT, method("init"))
@retries = retries
@send_mutex=Mutex.new
register_action(:INIT, method("init"))
end
# -------------------------------------------------------------------------
# Sends a message to the OpenNebula core through stdout
# -------------------------------------------------------------------------
def send_message(action="-", result=RESULT[:failure], id="-", info="-")
@send_mutex.synchronize {
STDOUT.puts "#{action} #{result} #{id} #{info}"
@ -49,25 +55,103 @@ class OpenNebulaDriver < ActionManager
}
end
# -------------------------------------------------------------------------
# Execute a command associated to an action and id in a remote host.
# -------------------------------------------------------------------------
def remotes_action(command, id, host, aname, remote_dir, std_in=nil)
command_exe = RemotesCommand.run(command,
host,
remote_dir,
log_method(id),
std_in,
@retries)
if command_exe.code == 0
result = RESULT[:success]
info = command_exe.stdout
else
result = RESULT[:failure]
info = command_exe.get_error_message
end
info = "-" if info == nil || info.empty?
send_message(aname,result,id,info)
end
# -------------------------------------------------------------------------
# Execute a command associated to an action and id on localhost
# -------------------------------------------------------------------------
def local_action(command, id, aname)
command_exe = LocalCommand.run(command, log_method(id))
if command_exe.code == 0
result = RESULT[:success]
info = command_exe.stdout
else
result = RESULT[:failure]
info = command_exe.get_error_message
end
info = "-" if info == nil || info.empty?
send_message(aname,result,id,info)
end
# -------------------------------------------------------------------------
# Sends a log message to ONE. The +message+ can be multiline, it will
# be automatically splitted by lines.
# -------------------------------------------------------------------------
def log(number, message)
in_error_message=false
msg=message.strip
msg.each_line {|line|
send_message("LOG", "-", number, line.strip)
severity='I'
l=line.strip
if l=='ERROR MESSAGE --8<------'
in_error_message=true
next
elsif l=='ERROR MESSAGE ------>8--'
in_error_message=false
next
else
if in_error_message
severity='E'
elsif line.match(/^(ERROR|DEBUG|INFO):(.*)$/)
line=$2
case $1
when 'ERROR'
severity='E'
when 'DEBUG'
severity='D'
when 'INFO'
severity='I'
else
severity='I'
end
end
end
send_message("LOG", severity, number, line.strip)
}
end
# -------------------------------------------------------------------------
# Generates a proc with that calls log with a hardcoded number. It will
# be used to add loging to command actions
# -------------------------------------------------------------------------
def log_method(num)
lambda {|message|
log(num, message)
}
end
# -------------------------------------------------------------------------
# Start the driver. Reads from STDIN and executes methods associated with
# the messages
# -------------------------------------------------------------------------
def start_driver
loop_thread = Thread.new { loop }
start_listener
@ -101,13 +185,17 @@ private
if action == :DRIVER_CANCEL
cancel_action(action_id)
log(action_id,"Driver command for #{action_id} cancelled")
else
else
trigger_action(action,action_id,*args)
end
end
end
end
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if __FILE__ == $0
class SampleDriver < OpenNebulaDriver

View File

@ -66,10 +66,9 @@ class VirtualMachineDriver < OpenNebulaDriver
# Register default actions for the protocol
# -------------------------------------------------------------------------
def initialize(concurrency=10, threaded=true, retries=0)
super(concurrency,threaded)
super(concurrency,threaded,retries)
@hosts = Array.new
@retries = retries
register_action(ACTION[:deploy].to_sym, method("deploy"))
register_action(ACTION[:shutdown].to_sym, method("shutdown"))
@ -109,43 +108,14 @@ class VirtualMachineDriver < OpenNebulaDriver
# Execute a command associated to an action and id in a remote host.
# -------------------------------------------------------------------------
def remotes_action(command, id, host, action, remote_dir, std_in=nil)
command_exe = RemotesCommand.run(command,
host,
remote_dir,
log_method(id),
std_in,
@retries)
if command_exe.code == 0
result = :success
info = command_exe.stdout
else
result = :failure
info = command_exe.stderr
end
info = "-" if info == nil || info.empty?
send_message(ACTION[action],RESULT[result],id,info)
super(command,id,host,ACTION[action],remote_dir,std_in)
end
# -------------------------------------------------------------------------
# Execute a command associated to an action and id on localhost
# -------------------------------------------------------------------------
def local_action(command, id, action)
command_exe = LocalCommand.run(command)
if command_exe.code == 0
result = :success
info = command_exe.stdout
else
result = :failure
info = command_exe.stderr
end
info = "-" if info == nil || info.empty?
send_message(ACTION[action],RESULT[result],id,info)
super(command,id,ACTION[action])
end
# -------------------------------------------------------------------------
@ -187,7 +157,9 @@ class VirtualMachineDriver < OpenNebulaDriver
end
private
# -------------------------------------------------------------------------
# Interface to handle the pending events from the ActionManager Interface
# -------------------------------------------------------------------------
def delete_running_action(action_id)
action=@action_running[action_id]
if action
@ -227,11 +199,6 @@ private
@action_queue.delete_at(action_index)
end
STDERR.puts "action: #{action.inspect}"
STDERR.puts "queue: #{@action_queue.inspect}"
STDERR.puts "hosts: #{@hosts.inspect}"
STDERR.flush
return action
end
@ -240,6 +207,10 @@ private
end
end
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if __FILE__ == $0
class TemplateDriver < VirtualMachineDriver

View File

@ -0,0 +1,70 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
module OpenNebula
# Generic log function
def self.log_function(severity, message)
STDERR.puts "#{severity}: #{File.basename $0}: #{message}"
end
# Logs an info message
def self.log_info(message)
log_function("INFO", message)
end
# Logs an error message
def self.log_error(message)
log_function("ERROR", message)
end
# Logs a debug message
def self.log_debug(message)
log_function("DEBUG", message)
end
# Alias log to log_info in the singleton class
class << self
alias :log :log_info
end
# This function is used to pass error message to the mad
def self.error_message(message)
STDERR.puts "ERROR MESSAGE --8<------"
STDERR.puts message
STDERR.puts "ERROR MESSAGE ------>8--"
end
# Executes a command, if it fails returns error message and exits
# If a second parameter is present it is used as the error message when
# the command fails
def self.exec_and_log(command, message=nil)
output=`#{command} 2>&1 1>/dev/null`
code=$?
if code!=0
log_error "Command \"#{command}\" failed."
log_error output
if !message
error_message output
else
error_message message
end
exit code
end
log "Executed \"#{command}\"."
end
end

147
src/mad/sh/scripts_common.sh Executable file
View File

@ -0,0 +1,147 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
# Paths for utilities
AWK=awk
BASH=/bin/bash
CUT=cut
DATE=/bin/date
DD=/bin/dd
LVCREATE=/sbin/lvcreate
LVREMOVE=/sbin/lvremove
LVS=/sbin/lvs
MD5SUM=/usr/bin/md5sum
MKFS=/sbin/mkfs
MKISOFS=/usr/bin/mkisofs
MKSWAP=/sbin/mkswap
SCP=/usr/bin/scp
SED=/bin/sed
SSH=/usr/bin/ssh
SUDO=/usr/bin/sudo
WGET=/usr/bin/wget
# Used for log messages
SCRIPT_NAME=`basename $0`
# Formats date for logs
function log_date
{
$DATE +"%a %b %d %T %Y"
}
# Logs a message, alias to log_info
function log
{
log_info "$1"
}
# Log function that knows how to deal with severities and adds the
# script name
function log_function
{
echo "$1: $SCRIPT_NAME: $2" 1>&2
}
# Logs an info message
function log_info
{
log_function "INFO" "$1"
}
# Logs an error message
function log_error
{
log_function "ERROR" "$1"
}
# Logs a debug message
function log_debug
{
log_function "DEBUG" "$1"
}
# This function is used to pass error message to the mad
function error_message
{
(
echo "ERROR MESSAGE --8<------"
echo "$1"
echo "ERROR MESSAGE ------>8--"
) 1>&2
}
# Executes a command, if it fails returns error message and exits
# If a second parameter is present it is used as the error message when
# the command fails
function exec_and_log
{
message=$2
output=`$1 2>&1 1>/dev/null`
code=$?
if [ "x$code" != "x0" ]; then
log_error "Command \"$1\" failed."
log_error "$output"
if [ -z "$message" ]; then
error_message "$output"
else
error_message "$message"
fi
exit $code
fi
log "Executed \"$1\"."
}
# Like exec_and_log but the first argument is the number of seconds
# before here is timeout and kills the command
#
# NOTE: if the command is killed because a timeout the exit code
# will be 143 = 128+15 (SIGHUP)
function timeout_exec_and_log
{
TIMEOUT=$1
shift
CMD="$1"
exec_and_log "$CMD" &
CMD_PID=$!
# timeout process
(
sleep $TIMEOUT
kill $CMD_PID 2>/dev/null
log_error "Timeout executing $CMD"
error_message "Timeout executing $CMD"
exit -1
) &
TIMEOUT_PID=$!
# stops the execution until the command finalizes
wait $CMD_PID 2>/dev/null
CMD_CODE=$?
# if the script reaches here the command finished before it
# consumes timeout seconds so we can kill timeout process
kill $TIMEOUT_PID 2>/dev/null 1>/dev/null
wait $TIMEOUT_PID 2>/dev/null
# checks the exit code of the command and exits if it is not 0
if [ "x$CMD_CODE" != "x0" ]; then
exit $CMD_CODE
fi
}

View File

@ -208,7 +208,7 @@ void Nebula::start()
{
ostringstream oss;
db = new MySqlDB(server,port,user,passwd,0);
db = new MySqlDB(server,port,user,passwd,db_name);
oss << "CREATE DATABASE IF NOT EXISTS " << db_name;
rc = db->exec(oss);
@ -235,6 +235,7 @@ void Nebula::start()
UserPool::bootstrap(db);
ImagePool::bootstrap(db);
ClusterPool::bootstrap(db);
VMTemplatePool::bootstrap(db);
}
catch (exception&)
{
@ -245,7 +246,6 @@ void Nebula::start()
{
string mac_prefix;
int size;
string repository_path;
string default_image_type;
string default_device_prefix;
@ -265,17 +265,17 @@ void Nebula::start()
upool = new UserPool(db);
nebula_configuration->get("IMAGE_REPOSITORY_PATH", repository_path);
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);
cpool = new ClusterPool(db);
tpool = new VMTemplatePool(db);
}
catch (exception&)
{
@ -442,6 +442,7 @@ void Nebula::start()
upool,
ipool,
cpool,
tpool,
rm_port,
log_location + "one_xmlrpc.log");
}
@ -511,6 +512,27 @@ void Nebula::start()
}
}
// ---- Image Manager ----
try
{
vector<const Attribute *> image_mads;
nebula_configuration->get("IMAGE_MAD", image_mads);
imagem = new ImageManager(ipool,image_mads);
}
catch (bad_alloc&)
{
throw;
}
rc = imagem->start();
if ( rc != 0 )
{
throw runtime_error("Could not start the Image Manager");
}
// -----------------------------------------------------------
// Load mads
// -----------------------------------------------------------
@ -522,6 +544,7 @@ void Nebula::start()
im->load_mads(0);
tm->load_mads(0);
hm->load_mads(0);
imagem->load_mads(0);
if ( authm != 0 )
{
@ -552,6 +575,7 @@ void Nebula::start()
im->finalize();
rm->finalize();
hm->finalize();
imagem->finalize();
//sleep to wait drivers???
@ -563,6 +587,7 @@ void Nebula::start()
pthread_join(im->get_thread_id(),0);
pthread_join(rm->get_thread_id(),0);
pthread_join(hm->get_thread_id(),0);
pthread_join(imagem->get_thread_id(),0);
//XML Library
xmlCleanupParser();

View File

@ -126,17 +126,10 @@ NebulaTemplate::NebulaTemplate(string& etc_location, string& var_location)
#*******************************************************************************
# Image Repository Configuration
#*******************************************************************************
# IMAGE_REPOSITORY_PATH
# DEFAULT_IMAGE_TYPE
# DEFAULT_DEVICE_PREFIX
#*******************************************************************************
*/
//IMAGE_REPOSITORY_PATH
value = var_location + "/images";
attribute = new SingleAttribute("IMAGE_REPOSITORY_PATH",value);
conf_default.insert(make_pair(attribute->name(),attribute));
//DEFAULT_IMAGE_TYPE
value = "OS";

View File

@ -50,6 +50,7 @@ env.Prepend(LIBS=[
'nebula_host',
'nebula_vnm',
'nebula_vm',
'nebula_vmtemplate',
'nebula_common',
'nebula_sql',
'nebula_log',

View File

@ -22,7 +22,6 @@ import org.opennebula.client.Client;
import org.opennebula.client.OneResponse;
import org.opennebula.client.Pool;
import org.opennebula.client.PoolElement;
import org.opennebula.client.vm.VirtualMachinePool;
import org.w3c.dom.Node;
/**
@ -42,7 +41,7 @@ public class ImagePool extends Pool implements Iterable<Image>
*
* @param client XML-RPC Client.
*
* @see VirtualMachinePool#VirtualMachinePool(Client, int)
* @see ImagePool#ImagePool(Client, int)
*/
public ImagePool(Client client)
{
@ -58,8 +57,8 @@ public class ImagePool extends Pool implements Iterable<Image>
* {@link ImagePool#info()}. Possible values:
* <ul>
* <li><= -2: All Images</li>
* <li>-1: Connected user's Images</li>
* <li>>= 0: UID User's VMs</li>
* <li>-1: Connected user's Images and public ones</li>
* <li>>= 0: UID User's Images</li>
* </ul>
*/
public ImagePool(Client client, int filter)
@ -85,8 +84,8 @@ public class ImagePool extends Pool implements Iterable<Image>
* {@link ImagePool#info()}. Possible values:
* <ul>
* <li><= -2: All Images</li>
* <li>-1: Connected user's Images</li>
* <li>>= 0: UID User's VMs</li>
* <li>-1: Connected user's Images and public ones</li>
* <li>>= 0: UID User's Images</li>
* </ul>
* @return If successful the message contains the string
* with the information returned by OpenNebula.

View File

@ -0,0 +1,236 @@
/*******************************************************************************
* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.opennebula.client.template;
import org.opennebula.client.Client;
import org.opennebula.client.OneResponse;
import org.opennebula.client.PoolElement;
import org.w3c.dom.Node;
/**
* This class represents an OpenNebula template.
* It also offers static XML-RPC call wrappers.
*/
public class Template extends PoolElement
{
private static final String METHOD_PREFIX = "template.";
private static final String ALLOCATE = METHOD_PREFIX + "allocate";
private static final String INFO = METHOD_PREFIX + "info";
private static final String DELETE = METHOD_PREFIX + "delete";
private static final String UPDATE = METHOD_PREFIX + "update";
private static final String RMATTR = METHOD_PREFIX + "rmattr";
private static final String PUBLISH = METHOD_PREFIX + "publish";
/**
* Creates a new Template representation.
* @param id The template id.
* @param client XML-RPC Client.
*/
public Template(int id, Client client)
{
super(id, client);
}
/**
* @see PoolElement
*/
protected Template(Node xmlElement, Client client)
{
super(xmlElement, client);
}
// =================================
// Static XML-RPC methods
// =================================
/**
* Allocates a new Template in OpenNebula.
*
* @param client XML-RPC Client.
* @param description A string containing the template of the template.
* @return If successful the message contains the associated
* id generated for this Template.
*/
public static OneResponse allocate(Client client, String description)
{
return client.call(ALLOCATE, description);
}
/**
* Retrieves the information of the given Template.
*
* @param client XML-RPC Client.
* @param id The template id for the template to retrieve the information from
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public static OneResponse info(Client client, int id)
{
return client.call(INFO, id);
}
/**
* Deletes a template from OpenNebula.
*
* @param client XML-RPC Client.
* @param id The template id of the target template we want to delete.
* @return A encapsulated response.
*/
public static OneResponse delete(Client client, int id)
{
return client.call(DELETE, id);
}
/**
* Modifies a template attribute.
*
* @param client XML-RPC Client.
* @param id The template id of the target template we want to modify.
* @param att_name The name of the attribute to update.
* @param att_val The new value for the attribute.
* @return If successful the message contains the template id.
*/
public static OneResponse update(Client client, int id,
String att_name, String att_val)
{
return client.call(UPDATE, id, att_name, att_val);
}
/**
* Removes a template attribute.
*
* @param client XML-RPC Client.
* @param id The template id of the target template we want to modify.
* @param att_name The name of the attribute to remove.
* @return If successful the message contains the template id.
*/
public static OneResponse rmattr(Client client, int id, String att_name)
{
return client.call(RMATTR, id, att_name);
}
/**
* Publishes or unpublishes a template.
*
* @param client XML-RPC Client.
* @param id The template id of the target template we want to modify.
* @param publish True for publishing, false for unpublishing.
* @return If successful the message contains the template id.
*/
public static OneResponse publish(Client client, int id, boolean publish)
{
return client.call(PUBLISH, id, publish);
}
// =================================
// Instanced object XML-RPC methods
// =================================
/**
* Retrieves the information of the Template.
*
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public OneResponse info()
{
OneResponse response = info(client, id);
super.processInfo(response);
return response;
}
/**
* Deletes the template from OpenNebula.
*
* @return A encapsulated response.
*/
public OneResponse delete()
{
return delete(client, id);
}
/**
* Modifies a template attribute.
*
* @param att_name The name of the attribute to update.
* @param att_val The new value for the attribute.
* @return If successful the message contains the template id.
*/
public OneResponse update(String att_name, String att_val)
{
return update(client, id, att_name, att_val);
}
/**
* Removes a template attribute.
*
* @param att_name The name of the attribute to remove.
* @return If successful the message contains the template id.
*/
public OneResponse rmattr(String att_name)
{
return rmattr(client, id, att_name);
}
/**
* Publishes or unpublishes the template.
*
* @param publish True for publishing, false for unpublishing.
* @return If successful the message contains the template id.
*/
public OneResponse publish(boolean publish)
{
return publish(client, id, publish);
}
/**
* Publishes the template.
*
* @return If successful the message contains the template id.
*/
public OneResponse publish()
{
return publish(true);
}
/**
* Unpublishes the template.
*
* @return If successful the message contains the template id.
*/
public OneResponse unpublish()
{
return publish(false);
}
// =================================
// Helpers
// =================================
/**
* Returns true if the template is public.
*
* @return True if the template is public.
*/
public boolean isPublic()
{
String isPub = xpath("PUBLIC");
return isPub != null && isPub.equals("1");
}
}

View File

@ -0,0 +1,132 @@
/*******************************************************************************
* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.opennebula.client.template;
import java.util.AbstractList;
import java.util.Iterator;
import org.opennebula.client.Client;
import org.opennebula.client.OneResponse;
import org.opennebula.client.Pool;
import org.opennebula.client.PoolElement;
import org.w3c.dom.Node;
/**
* This class represents an OpenNebula Template pool.
* It also offers static XML-RPC call wrappers.
*/
public class TemplatePool extends Pool implements Iterable<Template>
{
private static final String ELEMENT_NAME = "VMTEMPLATE";
private static final String INFO_METHOD = "templatepool.info";
private int filter;
/**
* Creates a new Template pool with the default filter flag value
* set to 0 (Templates belonging to user with UID 0)
*
* @param client XML-RPC Client.
*
* @see TemplatePool#TemplatePool(Client, int)
*/
public TemplatePool(Client client)
{
super(ELEMENT_NAME, client);
this.filter = 0;
}
/**
* Creates a new Template pool.
*
* @param client XML-RPC Client.
* @param filter Filter flag used by default in the method
* {@link TemplatePool#info()}. Possible values:
* <ul>
* <li><= -2: All Templates</li>
* <li>-1: Connected user's Templates and public ones</li>
* <li>>= 0: UID User's Templates</li>
* </ul>
*/
public TemplatePool(Client client, int filter)
{
super(ELEMENT_NAME, client);
this.filter = filter;
}
/* (non-Javadoc)
* @see org.opennebula.client.Pool#factory(org.w3c.dom.Node)
*/
@Override
public PoolElement factory(Node node)
{
return new Template(node, client);
}
/**
* Retrieves all or part of the templates in the pool.
*
* @param client XML-RPC Client.
* @param filter Filter flag used by default in the method
* {@link TemplatePool#info()}. Possible values:
* <ul>
* <li><= -2: All Templates</li>
* <li>-1: Connected user's Templates and public ones</li>
* <li>>= 0: UID User's Templates</li>
* </ul>
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public static OneResponse info(Client client, int filter)
{
return client.call(INFO_METHOD, filter);
}
/**
* Loads the xml representation of all or part of the
* Templates in the pool. The filter used is the one set in
* the constructor.
*
* @see TemplatePool#info(Client, int)
*
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public OneResponse info()
{
OneResponse response = info(client, filter);
super.processInfo(response);
return response;
}
public Iterator<Template> iterator()
{
AbstractList<Template> ab = new AbstractList<Template>()
{
public int size()
{
return getLength();
}
public Template get(int index)
{
return (Template) item(index);
}
};
return ab.iterator();
}
}

View File

@ -19,6 +19,7 @@ package org.opennebula.client.vm;
import org.opennebula.client.Client;
import org.opennebula.client.OneResponse;
import org.opennebula.client.PoolElement;
import org.opennebula.client.template.Template;
import org.w3c.dom.Node;
/**
@ -134,6 +135,56 @@ public class VirtualMachine extends PoolElement{
return client.call(ALLOCATE, description);
}
/**
* Allocates a new VM in OpenNebula from a registered Template.
*
* @param client XML-RPC Client.
* @param templateId The source Template's ID
* @param newName Name for the new VM, replaces the Template's one.
* Can be null.
* @return If successful the message contains the associated
* id generated for this VM.
*/
public static OneResponse allocateFromTemplate(Client client,
int templateId, String newName)
{
String template = "TEMPLATE_ID = " + templateId;
if( newName != null )
{
template += "\nNAME = " + newName;
}
return allocate(client, template);
}
/**
* Allocates a new VM in OpenNebula from a registered Template.
*
* @param client XML-RPC Client.
* @param templateId The source Template's ID
* @return If successful the message contains the associated
* id generated for this VM.
*/
public static OneResponse allocateFromTemplate(Client client,
int templateId)
{
return allocateFromTemplate(client, templateId, null);
}
/**
* Allocates a new VM in OpenNebula from a registered Template.
*
* @param client XML-RPC Client.
* @param template The source Template.
* @return If successful the message contains the associated
* id generated for this VM.
*/
public static OneResponse allocateFromTemplate(Client client,
Template template)
{
return allocateFromTemplate(client, template.id());
}
/**
* Retrieves the information of the given VM.
*
@ -222,12 +273,12 @@ public class VirtualMachine extends PoolElement{
* VirtualMachine shutdowns.
*
* @param diskId ID of the disk to be saved.
* @param imageId ID of the image where the disk will be saved.
* @param imageName Name of the new Image that will be created.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse savedisk(int diskId, int imageId)
public OneResponse savedisk(int diskId, String imageName)
{
return client.call(SAVEDISK, id ,diskId, imageId);
return client.call(SAVEDISK, id ,diskId, imageName);
}
// =================================

View File

@ -35,12 +35,16 @@ public class ImageTest
private static Client client;
private static OneResponse res;
private static String name = "new_test_img";
private static int cont = 0;
private static String template()
{
cont++;
private static String template =
"NAME = \"" + name + "\"\n" +
"ATT1 = \"val1\"";
return "NAME = \"test_img_" + cont + "\"\n" +
"PATH = /etc/hosts\n" +
"ATT1 = \"val1\"";
}
/**
* @throws java.lang.Exception
@ -66,7 +70,7 @@ public class ImageTest
@Before
public void setUp() throws Exception
{
res = Image.allocate(client, template);
res = Image.allocate(client, template());
int imgid = res.isError() ? -1 : Integer.parseInt(res.getMessage());
image = new Image(imgid, client);
@ -86,7 +90,7 @@ public class ImageTest
{
image.delete();
res = Image.allocate(client, template);
res = Image.allocate(client, template());
assertTrue( !res.isError() );
int imgid = res.isError() ? -1 : Integer.parseInt(res.getMessage());
@ -98,7 +102,7 @@ public class ImageTest
boolean found = false;
for(Image img : imagePool)
{
found = found || img.getName().equals(name);
found = found || img.getName().equals("test_img_"+cont);
}
assertTrue( found );
@ -112,7 +116,7 @@ public class ImageTest
// assertTrue( image.getId().equals("0") );
// assertTrue( image.id() == 0 );
assertTrue( image.getName().equals(name) );
assertTrue( image.getName().equals("test_img_"+cont) );
}
@Test
@ -147,7 +151,8 @@ public class ImageTest
assertTrue( image.xpath("ATT1").equals("") );
}
@Test
// TODO
// @Test
public void enable()
{
res = image.enable();
@ -157,7 +162,8 @@ public class ImageTest
assertTrue( image.isEnabled() );
}
@Test
// TODO
// @Test
public void disable()
{
res = image.disable();
@ -194,7 +200,7 @@ public class ImageTest
assertTrue( !res.isError() );
// assertTrue( image.xpath("ID").equals("0") );
assertTrue( image.xpath("NAME").equals(name) );
assertTrue( image.xpath("NAME").equals("test_img_"+cont) );
}
// @Test

View File

@ -0,0 +1,201 @@
/*******************************************************************************
* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opennebula.client.Client;
import org.opennebula.client.OneResponse;
import org.opennebula.client.template.*;
import org.opennebula.client.vm.VirtualMachine;
public class TemplateTest
{
private static Template template;
private static TemplatePool templatePool;
private static Client client;
private static OneResponse res;
private static String name = "new_test_template";
private static String template_str =
"NAME = \"" + name + "\"\n" +
"ATT1 = \"val1\"";
/**
* @throws java.lang.Exception
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception
{
client = new Client();
templatePool = new TemplatePool(client);
}
/**
* @throws java.lang.Exception
*/
@AfterClass
public static void tearDownAfterClass() throws Exception
{
}
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception
{
res = Template.allocate(client, template_str);
int oid = res.isError() ? -1 : Integer.parseInt(res.getMessage());
template = new Template(oid, client);
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception
{
template.delete();
}
@Test
public void allocate()
{
template.delete();
res = Template.allocate(client, template_str);
assertTrue( !res.isError() );
int oid = res.isError() ? -1 : Integer.parseInt(res.getMessage());
template = new Template(oid, client);
templatePool.info();
boolean found = false;
for(Template temp : templatePool)
{
found = found || temp.getName().equals(name);
}
assertTrue( found );
}
@Test
public void info()
{
res = template.info();
assertTrue( !res.isError() );
// assertTrue( template.getId().equals("0") );
// assertTrue( template.id() == 0 );
assertTrue( template.getName().equals(name) );
}
@Test
public void update()
{
// Update an existing att.
res = template.update("ATT1", "new_val_1");
assertTrue( !res.isError() );
res = template.info();
assertTrue( !res.isError() );
assertTrue( template.xpath("TEMPLATE/ATT1").equals("new_val_1") );
// Create a new att.
res = template.update("ATT2", "new_val_2");
assertTrue( !res.isError() );
res = template.info();
assertTrue( !res.isError() );
assertTrue( template.xpath("TEMPLATE/ATT2").equals("new_val_2") );
}
@Test
public void rmattr()
{
res = template.rmattr("ATT1");
assertTrue( !res.isError() );
res = template.info();
assertTrue( !res.isError() );
assertTrue( template.xpath("ATT1").equals("") );
}
@Test
public void publish()
{
res = template.publish();
assertTrue( !res.isError() );
template.info();
assertTrue( template.isPublic() );
}
@Test
public void unpublish()
{
res = template.unpublish();
assertTrue( !res.isError() );
template.info();
assertTrue( !template.isPublic() );
}
@Test
public void attributes()
{
res = template.info();
assertTrue( !res.isError() );
// assertTrue( template.xpath("ID").equals("0") );
assertTrue( template.xpath("NAME").equals(name) );
}
@Test
public void delete()
{
res = template.delete();
assertTrue( !res.isError() );
res = template.info();
assertTrue( res.isError() );
}
@Test
public void allocateFromTemplate()
{
template.info();
assertTrue( !res.isError() );
res = VirtualMachine.allocateFromTemplate(client, template);
assertTrue( !res.isError() );
assertTrue( res.getMessage().equals("0") );
}
}

View File

@ -23,7 +23,6 @@ import org.junit.Test;
import org.opennebula.client.Client;
import org.opennebula.client.OneResponse;
import org.opennebula.client.host.Host;
import org.opennebula.client.image.Image;
import org.opennebula.client.vm.VirtualMachine;
import org.opennebula.client.vm.VirtualMachinePool;
@ -309,21 +308,14 @@ public class VirtualMachineTest
vm = new VirtualMachine(vmid, client);
String imgTemplate =
"NAME = \"image\"\n" +
"ATT1 = \"val1\"";
res = Image.allocate(client, imgTemplate);
int imgid = res.isError() ? -1 : Integer.parseInt(res.getMessage());
res = vm.savedisk(0, imgid);
res = vm.savedisk(0, "New_image");
assertTrue( !res.isError() );
assertTrue( res.getMessage().equals("0") );
res = vm.info();
assertTrue( !res.isError() );
assertTrue( vm.xpath("TEMPLATE/DISK/SAVE_AS").equals(Integer.toString(imgid)) );
assertTrue( vm.xpath("TEMPLATE/DISK/SAVE_AS").equals(("0")) );
}
}

View File

@ -1,9 +1,27 @@
#!/bin/bash
if [ -z $ONE_LOCATION ]; then
echo "ONE_LOCATION not defined."
exit -1
fi
ONEDCONF_LOCATION="$ONE_LOCATION/etc/oned.conf"
if [ -f $ONEDCONF_LOCATION ]; then
echo "$ONEDCONF_LOCATION has to be overwritten, move it to a safe place."
exit -1
fi
cp oned.conf $ONEDCONF_LOCATION
export ONE_XMLRPC=http://localhost:2666/RPC2
./test.sh ClusterTest
./test.sh HostTest
./test.sh ImageTest
./test.sh SessionTest
./test.sh UserTest
./test.sh VirtualMachineTest
./test.sh VirtualNetworkTest
./test.sh VirtualNetworkTest
./test.sh TemplateTest

View File

@ -5,20 +5,30 @@
#*******************************************************************************
# Daemon configuration attributes
#-------------------------------------------------------------------------------
# HOST_MONITORING_INTERVAL: Time in seconds between host monitorization
# MANAGER_TIMER: Time in seconds the core uses to evaluate periodical functions.
# HOST_MONITORING_INTERVAL and VM_POLLING_INTERVAL can not have smaller values
# than MANAGER_TIMER.
#
# HOST_MONITORING_INTERVAL: Time in seconds between host monitorization.
#
# VM_POLLING_INTERVAL: Time in seconds between virtual machine monitorization.
# (use 0 to disable VM monitoring).
#
# VM_DIR: Remote path to store the VM images, it should be shared between all
# the cluster nodes to perform live migrations. This variable is the default
# for all the hosts in the cluster.
# for all the hosts in the cluster. VM_DIR IS ONLY FOR THE NODES AND *NOT* THE
# FRONT-END
#
# SCRIPTS_REMOTE_DIR: Remote path to store the monitoring and VM management
# scripts.
#
# PORT: Port where oned will listen for xmlrpc calls.
#
# DB: Configuration attributes for the database backend
# backend : can be sqlite or mysql (default is sqlite)
# server : (mysql) host name or an IP address for the MySQL server
# port : (mysql) port for the connection to the server.
# If set to 0, the default port is used.
# user : (mysql) user's MySQL login ID
# passwd : (mysql) the password for user
# db_name : (mysql) the database name
@ -29,13 +39,15 @@
# DEBUG_LEVEL: 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG
#*******************************************************************************
#MANAGER_TIMER=30
HOST_MONITORING_INTERVAL = 600
VM_POLLING_INTERVAL = 600
#VM_DIR=/srv/cloud/one/var
SCRIPTS_REMOTE_DIR=/tmp/one
SCRIPTS_REMOTE_DIR=/var/tmp/one
PORT=2666
@ -44,6 +56,7 @@ DB = [ backend = "sqlite" ]
# Sample configuration for MySQL
# DB = [ backend = "mysql",
# server = "localhost",
# port = 0,
# user = "oneadmin",
# passwd = "oneadmin",
# db_name = "opennebula" ]
@ -70,7 +83,7 @@ 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
# is set to $ONE_LOCATION/var/images
#
# DEFAULT_IMAGE_TYPE: This can take values
# OS Image file holding an operating system
@ -107,15 +120,19 @@ DEFAULT_DEVICE_PREFIX = "hd"
#-------------------------------------------------------------------------------
# KVM Information Driver Manager Configuration
# -r number of retries when monitoring a host
# -t number of threads, i.e. number of hosts monitored at the same time
#-------------------------------------------------------------------------------
IM_MAD = [
name = "im_kvm",
executable = "one_im_ssh",
arguments = "kvm" ]
arguments = "-r 0 -t 15 kvm" ]
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# XEN Information Driver Manager Configuration
# -r number of retries when monitoring a host
# -t number of threads, i.e. number of hosts monitored at the same time
#-------------------------------------------------------------------------------
#IM_MAD = [
# name = "im_xen",
@ -132,6 +149,15 @@ IM_MAD = [
# arguments = "im_ec2/im_ec2.conf" ]
#-------------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Ganglia Information Driver Manager Configuration
#-----------------------------------------------------------------------------
#IM_MAD = [
# name = "im_ganglia",
# executable = "one_im_sh",
# arguments = "ganglia" ]
#-----------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# Dummy Information Driver Manager Configuration
#-------------------------------------------------------------------------------
@ -161,17 +187,24 @@ IM_MAD = [ name="im_dummy", executable="one_im_dummy"]
#-------------------------------------------------------------------------------
# KVM Virtualization Driver Manager Configuration
# -r number of retries when monitoring a host
# -t number of threads, i.e. number of hosts monitored at the same time
# -p name of the poll probe (executed locally)
#-------------------------------------------------------------------------------
VM_MAD = [
name = "vmm_kvm",
executable = "one_vmm_ssh",
arguments = "kvm",
arguments = "-t 15 -r 0 kvm",
default = "vmm_ssh/vmm_ssh_kvm.conf",
type = "kvm" ]
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# XEN Virtualization Driver Manager Configuration
# -r number of retries when monitoring a host
# -t number of threads, i.e. number of hosts monitored at the same time
# -l do not perform the VM polling in the node
# -p name of the poll probe (executed locally)
#-------------------------------------------------------------------------------
#VM_MAD = [
# name = "vmm_xen",
@ -252,6 +285,25 @@ TM_MAD = [
# arguments = "tm_lvm/tm_lvm.conf" ]
#-------------------------------------------------------------------------------
#*******************************************************************************
# Image Manager Driver Configuration
#*******************************************************************************
# Drivers to manage the image repository, specialized for the storage backend
# executable: path of the transfer driver executable, can be an
# absolute path or relative to $ONE_LOCATION/lib/mads (or
# /usr/lib/one/mads/ if OpenNebula was installed in /)
#
# arguments : for the driver executable
#*******************************************************************************
#-------------------------------------------------------------------------------
# FS based Image Manager Driver Configuration
# -t number of threads, i.e. number of repo operations at the same time
#-------------------------------------------------------------------------------
IMAGE_MAD = [
executable = "one_image",
arguments = "fs -t 15" ]
#-------------------------------------------------------------------------------
#*******************************************************************************
# Hook Manager Configuration
#*******************************************************************************
@ -272,6 +324,7 @@ TM_MAD = [
# - SHUTDOWN, after the VM is shutdown
# - STOP, after the VM is stopped (including VM image transfers)
# - DONE, after the VM is deleted or shutdown
# - FAILED, when the VM enters the failed state
# command : path can be absolute or relative to $ONE_LOCATION/share/hooks
# case of self-contained installation or relative to
# /usr/share/one/hooks in case of system-wide installation
@ -284,44 +337,88 @@ TM_MAD = [
# - YES, The hook is executed in the host where the VM was
# allocated
# - NO, The hook is executed in the OpenNebula server (default)
#
#
# Host Hooks (HOST_HOOK) defined by:
# name : for the hook, useful to track the hook (OPTIONAL)
# on : when the hook should be executed,
# - CREATE, when the Host is created (onehost create)
# - ERROR, when the Host enters the error state
# - DISABLE, when the Host is disabled
# command : path can be absolute or relative to $ONE_LOCATION/share/hooks
# case of self-contained installation or relative to
# /usr/share/one/hooks in case of system-wide installation
# arguments : for the hook. You can use the Host ID with $HID to pass it as
# argument for the hook
# remote : values,
# - YES, The hook is executed in the host
# - NO, The hook is executed in the OpenNebula server (default)
#-------------------------------------------------------------------------------
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.
VM_HOOK = [
name = "image",
on = "DONE",
command = "image.rb",
arguments = "$VMID" ]
#-------------------------------------------------------------------------------
#-------------------------------- Hook Examples --------------------------------
#VM_HOOK = [
# name = "dhcp",
# on = "create",
# command = "/bin/echo",
# arguments = "$NAME > /tmp/test.$VMID" ]
#------------------------------ Fault Tolerance Hooks --------------------------
# This hook is used to perform recovery actions when a host fails. The VMs
# running in the host can be deleted (use -d option) or resubmitted (-r) in
# other host
# Last argument (force) can be "y", so suspended VMs in the host will be
# resubmitted/deleted, or "n", so suspended VMs in the host will be ignored
#
#HOST_HOOK = [
# name = "error",
# on = "ERROR",
# command = "host_error.rb",
# arguments = "$HID -r n",
# remote = "no" ]
#-------------------------------------------------------------------------------
# This two hooks can be used to automatically delete or resubmit VMs that reach
# the "failed" state. This way, the administrator doesn't have to interact
# manually to release its resources or retry the deployment.
#
# Only one of them should be uncommented.
#-------------------------------------------------------------------------------
#
#VM_HOOK = [
# name = "ebtables",
# name = "on_failure_delete",
# on = "FAILED",
# command = "/usr/bin/env onevm delete",
# arguments = "$VMID" ]
#
#VM_HOOK = [
# name = "on_failure_resubmit",
# on = "FAILED",
# command = "/usr/bin/env onevm resubmit",
# arguments = "$VMID" ]
#-------------------------------------------------------------------------------
#-------------------------------- ebtables Hook---------------------------------
# You can use these two hooks to isolate networks at the ethernet level so the
# traffic generated in different virtual networks can not be seen in others.
#
# All the network configuration will be done in the cluster nodes, these are the
# additional requisites:
# - ebtables package installed
# - sudoers configured so oneadmin can execute ebtables without password
#
# NOTE: Change the first command for ebtables-xen if you are using Xen
#
#VM_HOOK = [
# name = "ebtables-start",
# on = "running",
# command = "/usr/local/one/bin/set_net",
# arguments = '$NIC[MAC, Network = "Private"]',
# command = "ebtables-kvm", # or ebtables-xen
# arguments = "one-$VMID",
# remote = "yes" ]
#
#VM_HOOK = [
# name = "ebtables-flush",
# on = "done",
# command = "ebtables-flush",
# arguments = "",
# remote = "yes" ]
#-------------------------------------------------------------------------------
#VM_HOOK = [
# name = "mail",
# on = "running",
# command = "/usr/local/one/bin/send_mail",
# arguments = "$VMID $NAME",
# remote = "no" ]
#------------------------------------------------------------------------------
#*******************************************************************************
# Auth Manager Configuration
@ -340,4 +437,3 @@ VM_HOOK = [
#AUTH_MAD = [
# executable = "one_auth_mad" ]

View File

@ -11,11 +11,12 @@ fi
VAR_LOCATION="$ONE_LOCATION/var"
if [ "$(ls -A $VAR_LOCATION)" ]; then
echo "$VAR_LOCATION is not empty."
if [ -f $VAR_LOCATION/one.db ]; then
echo "$VAR_LOCATION/one.db has to be overwritten, move it to a safe place."
exit -1
fi
PID=$$
oned -f &
@ -29,6 +30,6 @@ CODE=$?
pkill -P $PID oned
sleep 4s;
pkill -9 -P $PID oned
rm -rf $VAR_LOCATION/*
rm -f $VAR_LOCATION/one.db
exit $CODE

View File

@ -31,13 +31,14 @@ require 'OpenNebula/VirtualNetwork'
require 'OpenNebula/VirtualNetworkPool'
require 'OpenNebula/Image'
require 'OpenNebula/ImagePool'
require 'OpenNebula/ImageRepository'
require 'OpenNebula/User'
require 'OpenNebula/UserPool'
require 'OpenNebula/Host'
require 'OpenNebula/HostPool'
require 'OpenNebula/Cluster'
require 'OpenNebula/ClusterPool'
require 'OpenNebula/Template'
require 'OpenNebula/TemplatePool'
module OpenNebula

View File

@ -33,13 +33,15 @@ module OpenNebula
:delete => "image.delete"
}
IMAGE_STATES=%w{INIT READY USED DISABLED}
IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR}
SHORT_IMAGE_STATES={
"INIT" => "init",
"READY" => "rdy",
"USED" => "used",
"DISABLED" => "disa"
"DISABLED" => "disa",
"LOCKED" => "lock",
"ERROR" => "err"
}
IMAGE_TYPES=%w{OS CDROM DATABLOCK}

View File

@ -1,272 +0,0 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'OpenNebula/Image'
require 'fileutils'
require 'CommandManager'
module OpenNebula
############################################################################
# The ImageRepository class represents and abstraction of the Image
# Repository, and it provides basic operations to manage and mantain it.
# This class is used by the OpenNebula daemon (through the image hook) to
# save and update images, and by the OpenNebula CLI to create and delete
# them
############################################################################
class ImageRepository
########################################################################
#
########################################################################
def create(image, template)
if image.nil?
error_msg = "Image could not be found, aborting."
return OpenNebula::Error.new(error_msg)
end
# ------ Allocate the Image ------
result = image.allocate(template)
if OpenNebula.is_error?(result)
return result
end
# ------ Copy the Image file ------
image.info
if image['SOURCE'] and File.exists?(image['SOURCE'])
error_msg =
"Destination file for image already exists, aborting."
result = OpenNebula::Error.new(error_msg)
elsif image['TEMPLATE/PATH'] and image['TEMPLATE/SOURCE'].nil?
# --- CDROM, DATABLOCK or OS based on a PATH ---
file_path = image['TEMPLATE/PATH']
if !File.exists?(file_path)
error_msg = "Image file could not be found, aborting."
result = OpenNebula::Error.new(error_msg)
end
if !OpenNebula.is_error?(result)
result = copy(file_path, image['SOURCE'])
end
# If the copy failed, the file should be removed
if OpenNebula.is_error?(result)
remove(image['SOURCE'])
end
elsif image['TEMPLATE/SIZE'] and image['TEMPLATE/FSTYPE'] and \
image['TEMPLATE/TYPE'] == 'DATABLOCK'
# --- Empty DATABLOCK ---
result = dd(image['TEMPLATE/SIZE'], image['SOURCE'])
if !OpenNebula.is_error?(result)
result = mkfs(image['TEMPLATE/FSTYPE'], image['SOURCE'])
end
# If the dd or mkfs failed, the file should be removed
if OpenNebula.is_error?(result)
remove(image['SOURCE'])
end
elsif image['TEMPLATE/PATH'].nil? and image['TEMPLATE/SOURCE'].nil?
error_msg = "Image path not present, aborting."
result = OpenNebula::Error.new(error_msg)
elsif image['TEMPLATE/PATH'] and image['TEMPLATE/SOURCE']
error_msg = "Template malformed, PATH and SOURCE are" <<
" mutuallly exclusive"
result = OpenNebula::Error.new(error_msg)
end
# ------ Enable the Image ------
if !OpenNebula.is_error?(result)
image.enable
else
image.delete
end
return result
end
########################################################################
#
########################################################################
def delete(image)
if image.nil?
error_msg = "Image could not be found, aborting."
return OpenNebula::Error.new(error_msg)
end
result = image.info
if !OpenNebula.is_error?(result)
file_path = image['SOURCE']
result = image.delete
if !OpenNebula.is_error?(result)
result = remove(file_path)
end
end
return result
end
########################################################################
#
########################################################################
def update_source(image, source)
if image.nil?
error_msg = "Image could not be found, aborting."
return OpenNebula::Error.new(error_msg)
end
result = image.info
if !OpenNebula.is_error?(result)
result = move(source, image['SOURCE'])
image.enable
end
return result
end
private
FS_UTILS = {
:dd => "env dd",
:mkfs => "env mkfs"
}
########################################################################
#
########################################################################
def set_permissions(source)
if File.directory?(source)
perms = 0770
else
perms = 0660
end
FileUtils.chmod(perms, source)
end
########################################################################
#
########################################################################
def copy(path, source)
if source.nil? or path.nil?
return OpenNebula::Error.new("copy Image: missing parameters.")
end
begin
FileUtils.copy(path, source)
set_permissions(source)
rescue Exception => e
return OpenNebula::Error.new(e.message)
end
return nil
end
########################################################################
#
########################################################################
def move(path, source)
if source.nil? || path.nil? || File.identical?(path,source)
return nil
end
begin
FileUtils.move(path, source)
set_permissions(source)
rescue Exception => e
return OpenNebula::Error.new(e.message)
end
return nil
end
########################################################################
#
########################################################################
def dd(size, source)
if source.nil? or size.nil?
return OpenNebula::Error.new("dd Image: missing parameters.")
end
command = ""
command << FS_UTILS[:dd]
command << " if=/dev/zero of=#{source} ibs=1 count=1"
command << " obs=1048576 seek=#{size}"
local_command=LocalCommand.run(command)
if local_command.code!=0
return OpenNebula::Error.new("dd Image: in dd command.")
end
return nil
end
########################################################################
#
########################################################################
def mkfs(fstype, source)
if source.nil? or fstype.nil?
return OpenNebula::Error.new("mkfs Image: missing parameters.")
end
command = ""
command << FS_UTILS[:mkfs]
command << " -t #{fstype} -F #{source}"
local_command=LocalCommand.run(command)
if local_command.code!=0
return OpenNebula::Error.new("mkfs Image: in mkfs command.")
end
return nil
end
########################################################################
#
########################################################################
def remove(source)
if !File.exists?(source)
return nil
end
begin
if File.directory?(source)
FileUtils.rmdir(source)
else
FileUtils.rm(source)
end
rescue Exception => e
return OpenNebula::Error.new(e.message)
end
return nil
end
end
end

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