1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-11 04:58:16 +03:00

Merge branch 'feature-523' into feature-575

This commit is contained in:
Ruben S. Montero 2011-04-13 00:03:19 +02:00
commit abe4ff6894
62 changed files with 2432 additions and 1139 deletions

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,65 @@ public:
return (persistent_img == 1);
};
/**
* Returns the source path of the image
* @return source of image
*/
const string& get_source()
{
return 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 +181,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,92 +250,13 @@ 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
* Generates the source path for the repository.
* @param uid of the image owner
* @param name of the image
* @return source for the image
*/
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;
}
static string generate_source(int uid, const string& name);
private:
@ -369,16 +310,6 @@ private:
*/
int running_vms;
// -------------------------------------------------------------------------
// Image Attributes
// -------------------------------------------------------------------------
/**
* The Image template, holds the Image attributes.
*/
ImageTemplate * image_template;
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************
@ -401,13 +332,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,106 @@
/* -------------------------------------------------------------------------- */
/* 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 string& destination) const;
/**
* Sends a move request to the MAD: "MV IMAGE_ID SRC_PATH DST_PATH"
* @param oid the image id.
* @param destination is the path to the image to be created
* @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 destination is the path to the image to be created
* @param fs type
* @param size_mb of the image to be created
*/
void mkfs(int oid,
const string& destination,
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

@ -34,6 +34,7 @@
#include "RequestManager.h"
#include "HookManager.h"
#include "AuthManager.h"
#include "ImageManager.h"
class Nebula
{
@ -114,12 +115,16 @@ public:
return hm;
};
AuthManager * get_authm()
{
return authm;
};
ImageManager * get_imagem()
{
return imagem;
};
// --------------------------------------------------------------
// Environment & Configuration
// --------------------------------------------------------------
@ -229,7 +234,8 @@ private:
// -----------------------------------------------------------------------
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)
ipool(0),cpool(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");
@ -334,6 +340,11 @@ private:
delete authm;
}
if ( imagem != 0)
{
delete imagem;
}
if ( nebula_configuration != 0)
{
delete nebula_configuration;
@ -394,6 +405,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,104 @@ 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;
obj_template->erase(name);
sattr = new SingleAttribute(name,value);
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);
}
protected:
/**
@ -198,6 +296,11 @@ protected:
*/
bool valid;
/**
* Template for this object, will be allocated if needed
*/
Template * obj_template;
private:
/**

View File

@ -459,8 +459,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(){};

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,8 +539,8 @@ 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
// ------------------------------------------------------------------------
@ -743,7 +656,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 +688,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.
*/

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

@ -35,6 +35,7 @@
#include "RequestManager.h"
#include "HookManager.h"
#include "AuthManager.h"
#include "ImageManager.h"
class NebulaTest
{
@ -71,6 +72,7 @@ public:
bool need_rm;
bool need_hm;
bool need_authm;
bool need_imagem;
static NebulaTest * instance()
{
@ -132,6 +134,8 @@ public:
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

@ -193,7 +193,9 @@ 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"
VAR_DIRS="$VAR_LOCATION/remotes \
$VAR_LOCATION/remotes/im \
@ -201,7 +203,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 \
@ -278,6 +282,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
@ -396,7 +402,6 @@ 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/XMLUtils.rb"
@ -428,7 +433,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 +521,15 @@ 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/rm"
#-------------------------------------------------------------------------------
# Configuration files for OpenNebula, to be installed under $ETC_LOCATION
#-------------------------------------------------------------------------------

View File

@ -285,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
#*******************************************************************************
@ -339,16 +358,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

@ -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

View File

@ -785,56 +785,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

@ -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

@ -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

@ -47,19 +47,19 @@ Image::Image(int _uid,
{
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;
}
}
@ -78,6 +78,22 @@ const char * Image::db_bootstrap = "CREATE TABLE IF NOT EXISTS image_pool ("
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
string Image::generate_source(int uid, const string& name)
{
ostringstream tmp_hashstream;
ostringstream tmp_sourcestream;
tmp_hashstream << uid << ":" << name;
tmp_sourcestream << ImagePool::source_prefix() << "/";
tmp_sourcestream << sha1_digest(tmp_hashstream.str());
return tmp_sourcestream.str();
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int Image::insert(SqlDB *db, string& error_str)
{
int rc;
@ -116,7 +132,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 +142,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);
@ -147,14 +163,12 @@ 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("PATH", path_attr);
get_template_attribute("SOURCE", source);
// The template should contain PATH or SOURCE
@ -163,14 +177,26 @@ int Image::insert(SqlDB *db, string& error_str)
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() )
{
@ -179,18 +205,10 @@ int Image::insert(SqlDB *db, string& error_str)
if (source.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 = Image::generate_source(uid,name);
}
state = DISABLED;
state = LOCKED; //LOCKED till the ImageManager copies it to the Repository
//--------------------------------------------------------------------------
// Insert the Image
@ -214,7 +232,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 +243,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 +359,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 +406,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 +419,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,15 +446,6 @@ int Image::disk_attribute( VectorAttribute * disk,
get_template_attribute("DEV_PREFIX", prefix);
//--------------------------------------------------------------------------
// Acquire the image
//--------------------------------------------------------------------------
if ( acquire_image() != 0 )
{
return -1;
}
//---------------------------------------------------------------------------
// NEW DISK ATTRIBUTES
//---------------------------------------------------------------------------
@ -533,8 +482,6 @@ int Image::disk_attribute( VectorAttribute * disk,
{
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
}
else
{

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,433 @@
/* -------------------------------------------------------------------------- */
/* 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() << " as " << img->get_source();
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(), img->get_source(), 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, img->get_source());
oss << "Copying image " << path
<< " to repository as " << img->get_source();
}
NebulaLog::log("ImM",Log::INFO,oss);
img->unlock();
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,268 @@
/* -------------------------------------------------------------------------- */
/* 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 string& destination) const
{
ostringstream os;
os << "CP " << oid << " " << source << " " << destination << 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& destination,
const string& fs,
const string& size_mb) const
{
ostringstream os;
os << "MKFS " << oid << " " << destination << " " <<
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 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::INFO, 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" )
{
image->set_state(Image::READY);
ipool->update(image);
image->unlock();
NebulaLog::log("ImM", Log::INFO, "Image copied and ready to use.");
}
else
{
goto error_cp;
}
}
else if ( action == "MV" )
{
if ( result == "SUCCESS" )
{
image->set_state(Image::READY);
ipool->update(image);
image->unlock();
NebulaLog::log("ImM", Log::INFO, "Image saved and ready to use.");
}
else
{
goto error_mv;
}
}
else if ( action == "MKFS" )
{
if ( result == "SUCCESS" )
{
image->set_state(Image::READY);
ipool->update(image);
image->unlock();
NebulaLog::log("ImM", Log::INFO, "Image created and ready to use");
}
else
{
goto error_mkfs;
}
}
else if ( action == "RM" )
{
int rc;
string source;
source = image->get_source();
rc = ipool->drop(image);
image->unlock();
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
{
ostringstream oss;
oss <<"Error removing image from repository. Remove file " << source
<<" to completely delete image.";
NebulaLog::log("ImM",Log::ERROR,oss);
}
}
else if (action == "LOG")
{
getline(is,info);
NebulaLog::log("ImM", Log::INFO, info.c_str());
}
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";
error_common:
getline(is,info);
if (!info.empty() && (info[0] != '-'))
{
os << ": " << info;
}
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,6 +20,7 @@
#include "ImagePool.h"
#include "AuthManager.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -68,9 +69,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 +94,6 @@ int ImagePool::allocate (
return *oid;
error_name:
oss << "NAME cannot be empty.";
goto error_common;
@ -128,6 +125,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 +144,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 +155,7 @@ int ImagePool::disk_attribute(VectorAttribute * disk,
}
else
{
img = get(source,uid,true);
img = imagem->acquire_image(source,uid);
if (img == 0)
{
@ -167,7 +167,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 +187,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_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Image one]]></NAME><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_prefix/c9d51800847467911c755e5e4c13dfe28c3a79f3</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a rather short description.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Second Image]]></NAME><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_prefix/e50b0c738be9d431475bf5859629e5580301a7d6</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><BUS><![CDATA[SCSI]]></BUS><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[The third image]]></NAME><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_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Image one]]></NAME><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>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_prefix/e50b0c738be9d431475bf5859629e5580301a7d6</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><BUS><![CDATA[SCSI]]></BUS><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[The third image]]></NAME><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_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198</SOURCE><STATE>4</STATE><RUNNING_VMS>0</RUNNING_VMS><TEMPLATE><DESCRIPTION><![CDATA[This is a very long description of an image, and to achieve the longness I will copy this over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over. This is a very long description of an image, and to achieve the longness I will copy this over. And over.This is a very long description of an image, and to achieve the longness I will copy this over.]]></DESCRIPTION><DEV_PREFIX><![CDATA[hd]]></DEV_PREFIX><NAME><![CDATA[Image one]]></NAME><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>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";
@ -128,7 +128,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 );
@ -241,7 +244,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 +256,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 +274,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 +401,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 +454,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 +469,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 +477,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 +491,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 +499,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 +513,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 +522,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 +555,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 );
@ -565,7 +569,7 @@ public:
"source_prefix/9ab4a4e021ee2883f57e3aeecc9e2aed7c3fa198" );
// clean up
img->release_image();
//img->release_image();
delete disk;
// ---------------------------------------------------------------------
@ -573,7 +577,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 );
@ -606,10 +610,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 +627,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 +681,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 +775,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,8 +874,8 @@ public:
string result = oss.str();
result.replace(157, 10, replacement);
result.replace(1147, 10, replacement);
result.replace(1677, 10, replacement);
result.replace(1129, 10, replacement);
result.replace(1641, 10, replacement);
/*
if( result != xml_dump )
@ -899,7 +909,7 @@ public:
string result = oss.str();
result.replace(157, 10, replacement);
result.replace(1147, 10, replacement);
result.replace(1129, 10, replacement);
/*
if( 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 $*

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

@ -0,0 +1,136 @@
#!/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 "CommandManager"
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)
@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
# -------------------------------------------------------------------------
# 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 = "-"
else
result = :failure
info = command_exe.stderr
end
info = "-" if info == nil || info.empty?
send_message(ACTION[action],RESULT[result],id,info)
end
# -------------------------------------------------------------------------
# Image Manager Protocol Actions (generic implementation
# -------------------------------------------------------------------------
def mv(id, src, dst)
local_action("#{@actions_path}/mv #{src} #{dst}",id,:mv)
end
def cp(id, src, dst)
local_action("#{@actions_path}/cp #{src} #{dst}",id,:cp)
end
def rm(id, dst)
local_action("#{@actions_path}/rm #{dst}",id,:rm)
end
def mkfs(id, dst, fs, size)
local_action("#{@actions_path}/mkfs #{dst} #{fs} #{size}",id,: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

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

@ -0,0 +1,53 @@
#!/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 ------------
if [ -z "${ONE_LOCATION}" ]; then
TMCOMMON=/usr/lib/one/mads/tm_common.sh
VAR_LOCATION=/var/lib/one/
else
TMCOMMON=$ONE_LOCATION/lib/mads/tm_common.sh
VAR_LOCATION=$ONE_LOCATION/var/
fi
. $TMCOMMON
# ------------ Copy the image to the repository ------------
SRC=$1
DST=$2
case $SRC in
http://*)
log "Downloading $SRC to the image repository"
exec_and_log "$WGET -O $DST $SRC"
;;
*)
log "Copying local image $SRC to the image repository"
exec_and_log "cp -f $SRC $DST"
;;
esac
exec_and_log "chmod 0660 $DST"

42
src/image_mad/remotes/fs/mkfs 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 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
TMCOMMON=/usr/lib/one/mads/tm_common.sh
else
TMCOMMON=$ONE_LOCATION/lib/mads/tm_common.sh
fi
. $TMCOMMON
# ------------ Create the image to the repository ------------
DST=$1
FSTYPE=$2
SIZE=$3
exec_and_log "$DD if=/dev/zero of=$DST bs=1 count=1 seek=${SIZE}M"
exec_and_log "$MKFS -t $FSTYPE -F $DST"
exec_and_log "chmod 0660 $DST"

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

@ -0,0 +1,53 @@
#!/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
TMCOMMON=/usr/lib/one/mads/tm_common.sh
VAR_LOCATION=/var/lib/one/
else
TMCOMMON=$ONE_LOCATION/lib/mads/tm_common.sh
VAR_LOCATION=$ONE_LOCATION/var/
fi
. $TMCOMMON
# ------------ Move the image to the repository ------------
SRC=$1
DST=$2
case $SRC in
http://*)
log "Downloading $SRC to the image repository"
exec_and_log "$WGET -O $DST $SRC"
;;
*)
log "Moving local image $SRC to the image repository"
exec_and_log "mv -f $SRC $DST"
;;
esac
exec_and_log "chmod 0660 $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
TMCOMMON=/usr/lib/one/mads/tm_common.sh
VAR_LOCATION=/var/lib/one/
else
TMCOMMON=$ONE_LOCATION/lib/mads/tm_common.sh
VAR_LOCATION=$ONE_LOCATION/var/
fi
. $TMCOMMON
# ------------ Remove the image to the repository ------------
SRC=$1
if [ -e $SRC ] ; then
log "Removing $SRC from the image repository"
exec_and_log "rm $SRC"
fi

View File

@ -511,6 +511,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 +543,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 +574,7 @@ void Nebula::start()
im->finalize();
rm->finalize();
hm->finalize();
imagem->finalize();
//sleep to wait drivers???
@ -563,6 +586,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

@ -222,12 +222,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

@ -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

@ -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,7 +31,6 @@ require 'OpenNebula/VirtualNetwork'
require 'OpenNebula/VirtualNetworkPool'
require 'OpenNebula/Image'
require 'OpenNebula/ImagePool'
require 'OpenNebula/ImageRepository'
require 'OpenNebula/User'
require 'OpenNebula/UserPool'
require 'OpenNebula/Host'

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

View File

@ -214,11 +214,11 @@ module OpenNebula
#
# +disk_id+ ID of the disk to be saved
#
# +image_id+ ID of the new image where the disk will be saved
def save_as(disk_id, image_id)
# +image_name+ Name for the new image where the disk will be saved
def save_as(disk_id, image_name)
return Error.new('ID not defined') if !@pe_id
rc = @client.call(VM_METHODS[:savedisk], @pe_id, disk_id, image_id)
rc = @client.call(VM_METHODS[:savedisk], @pe_id, disk_id, image_name)
rc = nil if !OpenNebula.is_error?(rc)
return rc

View File

@ -27,7 +27,6 @@ void RequestManager::ClusterInfo::execute(
xmlrpc_c::value * const retval)
{
string session;
string info;
Cluster * cluster;
ostringstream oss;
@ -70,7 +69,7 @@ void RequestManager::ClusterInfo::execute(
// All nice, return the cluster info to the client
arrayData.push_back(xmlrpc_c::value_boolean(true)); // SUCCESS
arrayData.push_back(xmlrpc_c::value_string(info));
arrayData.push_back(xmlrpc_c::value_string(oss.str()));
// Copy arrayresult into retval mem space
arrayresult = new xmlrpc_c::value_array(arrayData);

View File

@ -48,6 +48,9 @@ void RequestManager::ImageAllocate::execute(
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
Nebula& nd = Nebula::instance();
ImageManager * imagem = nd.get_imagem();
NebulaLog::log("ReM",Log::DEBUG,"ImageAllocate invoked");
session = xmlrpc_c::value_string(paramList.getString(0));
@ -55,7 +58,7 @@ void RequestManager::ImageAllocate::execute(
str_template += "\n";
//--------------------------------------------------------------------------
// Authorize this request
// Authenticate this request
//--------------------------------------------------------------------------
uid = ImageAllocate::upool->authenticate(session);
@ -98,7 +101,6 @@ void RequestManager::ImageAllocate::execute(
}
}
//--------------------------------------------------------------------------
// Get the User Name
//--------------------------------------------------------------------------
@ -124,7 +126,14 @@ void RequestManager::ImageAllocate::execute(
if ( rc < 0 )
{
goto error_allocate;
}
//--------------------------------------------------------------------------
// Register the Image in the repository
//--------------------------------------------------------------------------
if ( imagem->register_image(rc) == -1 )
{
goto error_register;
}
arrayData.push_back(xmlrpc_c::value_boolean(true));
@ -169,6 +178,11 @@ error_allocate:
oss << " " << error_str;
goto error_common;
error_register:
oss << action_error(method_name, "CREATE", "IMAGE", -2, 0);
oss << " Failed to copy image to repository. Image left in ERROR state.";
goto error_common;
error_common:
arrayData.push_back(xmlrpc_c::value_boolean(false)); // FAILURE
arrayData.push_back(xmlrpc_c::value_string(oss.str()));

View File

@ -46,6 +46,8 @@ void RequestManager::ImageDelete::execute(
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
Nebula& nd = Nebula::instance();
ImageManager * imagem = nd.get_imagem();
NebulaLog::log("ReM",Log::DEBUG,"ImageDelete invoked");
@ -91,17 +93,8 @@ void RequestManager::ImageDelete::execute(
}
}
// Get image from the ImagePool
image = ImageDelete::ipool->get(iid,true);
if ( image == 0 )
{
goto error_image_get;
}
rc = ImageDelete::ipool->drop(image);
image->unlock();
// Delete the Image from the repository
rc = imagem->delete_image(iid);
if ( rc < 0 )
{
@ -133,7 +126,7 @@ error_authorize:
error_delete:
oss << action_error(method_name, "DELETE", "IMAGE", iid, rc)
<< ". Reason: VMs might be running on it.";
<< ". Image is in use.";
image->unlock();
goto error_common;

View File

@ -48,6 +48,8 @@ void RequestManager::ImageEnable::execute(
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
Nebula& nd = Nebula::instance();
ImageManager * imagem = nd.get_imagem();
NebulaLog::log("ReM",Log::DEBUG,"ImageEnable invoked");
@ -93,26 +95,14 @@ void RequestManager::ImageEnable::execute(
}
}
// Get image from the ImagePool
image = ImageEnable::ipool->get(iid,true);
if ( image == 0 )
{
goto error_image_get;
}
rc = image->enable(enable_flag);
// Enable the Image
rc = imagem->enable_image(iid,enable_flag);
if ( rc < 0 )
{
goto error_enable;
}
ImageEnable::ipool->update(image);
image->unlock();
arrayData.push_back(xmlrpc_c::value_boolean(true));
arrayData.push_back(xmlrpc_c::value_int(iid));

View File

@ -137,8 +137,7 @@ error_authorize:
error_persistent:
image->unlock();
oss << action_error(method_name, "MANAGE", "IMAGE", iid, 0)
<< " Is the image public? An Image cannot be public and persistent.";
oss.str(action_error(method_name, "MANAGE", "IMAGE", iid, 0));
goto error_common;
error_common:

View File

@ -50,7 +50,7 @@ void RequestManager::VirtualMachinePoolInfo::execute(
state = -1;
break;
case 3:
state = xmlrpc_c::value_int (paramList.getInt(3));
state = xmlrpc_c::value_int (paramList.getInt(2));
break;
default:
paramList.verifyEnd(3);

View File

@ -26,63 +26,98 @@ void RequestManager::VirtualMachineSaveDisk::execute(
xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retval)
{
string session;
string session;
int vm_id;
int disk_id;
int img_id;
int vm_id;
int disk_id;
int iid;
string img_name;
int vm_owner;
int img_owner;
bool img_public;
int vm_owner;
string user_name;
int rc;
int rc;
int uid;
string estr;
char * error_char;
string error_str;
const string method_name = "VirtualMachineSaveDisk";
VirtualMachine * vm;
Image * image;
VirtualMachine * vm;
Image * image;
ImageTemplate * img_template;
User * user;
Image * source_img;
int source_img_id;
bool source_img_persistent = false;
vector<xmlrpc_c::value> arrayData;
xmlrpc_c::value_array * arrayresult;
ostringstream oss;
ostringstream oss;
Nebula& nd = Nebula::instance();
ImageManager * imagem = nd.get_imagem();
NebulaLog::log("ReM",Log::DEBUG,"VirtualMachineSaveDisk invoked");
//Parse Arguments
session = xmlrpc_c::value_string(paramList.getString(0));
vm_id = xmlrpc_c::value_int(paramList.getInt(1));
disk_id = xmlrpc_c::value_int(paramList.getInt(2));
img_name = xmlrpc_c::value_string(paramList.getString(3));
session = xmlrpc_c::value_string(paramList.getString(0));
vm_id = xmlrpc_c::value_int(paramList.getInt(1));
disk_id = xmlrpc_c::value_int(paramList.getInt(2));
img_id = xmlrpc_c::value_int(paramList.getInt(3));
//-------------------------------------------------------------------------
// Authenticate the user
//-------------------------------------------------------------------------
uid = VirtualMachineSaveDisk::upool->authenticate(session);
//Authenticate the user
rc = VirtualMachineSaveDisk::upool->authenticate(session);
if ( rc == -1 )
if ( uid == -1 )
{
goto error_authenticate;
}
// Check that the image exists
image = VirtualMachineSaveDisk::ipool->get(img_id,true);
user = VirtualMachineSaveDisk::upool->get(uid,true);
if ( image == 0 )
if ( user == 0 )
{
goto error_image_get;
goto error_user_get;
}
img_owner = image->get_uid();
img_public = image->isPublic();
user_name = user->get_name();
image->unlock();
user->unlock();
//Get the VM
//-------------------------------------------------------------------------
// Check that the image does not exist & prepare the template
//-------------------------------------------------------------------------
image = VirtualMachineSaveDisk::ipool->get(img_name,uid,false);
if ( image != 0 )
{
goto error_image_exists;
}
oss << "NAME= " << img_name << endl;
oss << "PUBLIC = NO " << endl;
oss << "SOURCE = " << Image::generate_source(uid,img_name);
img_template = new ImageTemplate;
img_template->parse(oss.str(),&error_char);
oss.str("");
//--------------------------------------------------------------------------
// Get the VM
//--------------------------------------------------------------------------
vm = VirtualMachineSaveDisk::vmpool->get(vm_id,true);
if ( vm == 0 )
{
delete img_template;
goto error_vm_get;
}
@ -90,14 +125,20 @@ void RequestManager::VirtualMachineSaveDisk::execute(
vm->unlock();
//Authorize the operation
if ( rc != 0 ) // rc == 0 means oneadmin
//--------------------------------------------------------------------------
// Authorize the operation
//--------------------------------------------------------------------------
if ( uid != 0 )
{
AuthRequest ar(rc);
AuthRequest ar(uid);
string t64;
ar.add_auth(AuthRequest::VM,vm_id,AuthRequest::MANAGE,vm_owner,false);
ar.add_auth(AuthRequest::IMAGE,img_id,
AuthRequest::MANAGE,img_owner,img_public);
ar.add_auth(AuthRequest::IMAGE,
img_template->to_xml(t64),
AuthRequest::CREATE,
uid,
false);
if (UserPool::authorize(ar) == -1)
{
@ -105,6 +146,25 @@ void RequestManager::VirtualMachineSaveDisk::execute(
}
}
//--------------------------------------------------------------------------
// Create the image
//--------------------------------------------------------------------------
rc = VirtualMachineSaveDisk::ipool->allocate(uid,user_name,img_template,
&iid,estr);
if ( rc < 0 )
{
goto error_allocate;
}
oss << "Image " << img_name << " created to store disk.";
NebulaLog::log("ReM",Log::INFO,oss);
oss.str("");
//--------------------------------------------------------------------------
// Get the VM
//--------------------------------------------------------------------------
vm = VirtualMachineSaveDisk::vmpool->get(vm_id,true);
if ( vm == 0 )
@ -112,11 +172,36 @@ void RequestManager::VirtualMachineSaveDisk::execute(
goto error_vm_get;
}
rc = vm->save_disk(disk_id, img_id);
//--------------------------------------------------------------------------
// Check if the disk has a persistent source image
//--------------------------------------------------------------------------
oss << "/VM/TEMPLATE/DISK[DISK_ID=" << disk_id << "]/IMAGE_ID";
rc = vm->xpath(source_img_id, oss.str().c_str(), -1);
oss.str("");
if( rc == 0 ) //The disk was created from an Image
{
source_img = VirtualMachineSaveDisk::ipool->get(source_img_id, true);
if( source_img != 0 ) //The Image still exists
{
source_img_persistent = source_img->isPersistent();
source_img->unlock();
if( source_img_persistent )
{
goto error_img_persistent;
}
}
}
//--------------------------------------------------------------------------
// Store image id to save the disk in the VM template
//--------------------------------------------------------------------------
rc = vm->save_disk(disk_id, iid, error_str);
if ( rc == -1 )
{
vm->unlock();
goto error_vm_get_disk_id;
}
@ -124,8 +209,11 @@ void RequestManager::VirtualMachineSaveDisk::execute(
vm->unlock();
//--------------------------------------------------------------------------
// Send results to client
//--------------------------------------------------------------------------
arrayData.push_back(xmlrpc_c::value_boolean(true));
arrayData.push_back(xmlrpc_c::value_int(iid));
arrayresult = new xmlrpc_c::value_array(arrayData);
@ -135,16 +223,31 @@ void RequestManager::VirtualMachineSaveDisk::execute(
return;
error_image_get:
oss.str(get_error(method_name, "IMAGE", img_id));
error_image_exists:
oss << action_error(method_name, "CREATE", "IMAGE", -2, 0);
oss << " Image " << img_name << " already exists in the repository.";
goto error_common;
error_vm_get:
oss.str(get_error(method_name, "VM", vm_id));
goto error_common;
error_img_persistent:
oss << action_error(method_name, "SAVEDISK", "DISK", disk_id, 0);
oss << " Source IMAGE " << source_img_id << " is persistent.";
vm->unlock();
goto error_common;
error_vm_get_disk_id:
oss.str(get_error(method_name, "DISK from VM", vm_id));
oss << " " << error_str;
oss << " Deleting Image " << img_name;
imagem->delete_image(iid);
vm->unlock();
goto error_common;
error_user_get:
oss.str(get_error(method_name, "USER", uid));
goto error_common;
error_authenticate:
@ -152,7 +255,13 @@ error_authenticate:
goto error_common;
error_authorize:
oss.str(authorization_error(method_name, "MANAGE", "VM/IMAGE", rc, vm_id));
oss.str(authorization_error(method_name, "MANAGE", "VM/IMAGE", uid, vm_id));
delete img_template;
goto error_common;
error_allocate:
oss << action_error(method_name, "CREATE", "IMAGE", -2, 0);
oss << " " << estr;
goto error_common;
error_common:

View File

@ -19,6 +19,7 @@
#include "NebulaLog.h"
#include "Nebula.h"
#include "VirtualNetworkTemplate.h"
#include "AuthManager.h"
/* -------------------------------------------------------------------------- */

View File

@ -16,6 +16,7 @@
#include "RequestManager.h"
#include "NebulaLog.h"
#include "VirtualNetworkTemplate.h"
#include "AuthManager.h"

View File

@ -15,6 +15,7 @@
/* -------------------------------------------------------------------------- */
#include "RequestManager.h"
#include "VirtualNetworkTemplate.h"
#include "NebulaLog.h"
#include "Nebula.h"

View File

@ -66,11 +66,10 @@ int VirtualMachinePoolXML::load_info(xmlrpc_c::value &result)
{
client->call(client->get_endpoint(), // serverUrl
"one.vmpool.info", // methodName
"sibi", // arguments format
"sii", // arguments format
&result, // resultP
client->get_oneauth().c_str(), // auth string
-2, // VM from all users
false, // not extended info
1); // in pending state
return 0;
}

View File

@ -424,6 +424,29 @@ void Nebula::start()
}
}
// ---- Auth Manager ----
if (tester->need_imagem)
{
try
{
imagem = tester->create_imagem(ipool);
}
catch (bad_alloc&)
{
throw;
}
if (imagem != 0)
{
rc = imagem->start();
if ( rc != 0 )
{
throw runtime_error("Could not start the Image Manager");
}
}
}
// -----------------------------------------------------------
// Load mads
// -----------------------------------------------------------

View File

@ -145,3 +145,18 @@ AuthManager* NebulaTest::create_authm(time_t timer_period)
{
return 0;
}
ImageManager* NebulaTest::create_imagem(ImagePool * ipool)
{
map<string,string> mad_value;
VectorAttribute * mad;
vector<const Attribute *> im_mads;
mad_value.insert(make_pair("executable","one_image"));
mad = new VectorAttribute("HM_MAD",mad_value);
im_mads.push_back(mad);
return new ImageManager(ipool,im_mads);
}

View File

@ -58,11 +58,11 @@ VirtualMachine::VirtualMachine(int id,
{
if (_vm_template != 0)
{
vm_template = _vm_template;
obj_template = _vm_template;
}
else
{
vm_template = new VirtualMachineTemplate;
obj_template = new VirtualMachineTemplate;
}
}
@ -83,9 +83,9 @@ VirtualMachine::~VirtualMachine()
delete _log;
}
if ( vm_template != 0 )
if ( obj_template != 0 )
{
delete vm_template;
delete obj_template;
}
}
@ -123,7 +123,7 @@ int VirtualMachine::select(SqlDB * db)
return rc;
}
//Get History Records. Current history is record is built in from_xml() (if any).
//Get History Records. Current history is built in from_xml() (if any).
if( hasHistory() )
{
last_seq = history->seq;
@ -191,7 +191,7 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
attr = new SingleAttribute("VMID",value);
vm_template->set(attr);
obj_template->set(attr);
get_template_attribute("NAME",name);
@ -202,7 +202,7 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
name = oss.str();
attr = new SingleAttribute("NAME",name);
vm_template->set(attr);
obj_template->set(attr);
}
this->name = name;
@ -301,7 +301,7 @@ int VirtualMachine::parse_context(string& error_str)
string * str;
string parsed;
num = vm_template->remove("CONTEXT", array_context);
num = obj_template->remove("CONTEXT", array_context);
if ( num == 0 )
{
@ -352,7 +352,7 @@ int VirtualMachine::parse_context(string& error_str)
context_parsed->replace("TARGET", dev_prefix);
}
vm_template->set(context_parsed);
obj_template->set(context_parsed);
}
/* --- Delete old context attributes --- */
@ -378,7 +378,7 @@ void VirtualMachine::parse_graphics()
vector<Attribute *> array_graphics;
VectorAttribute * graphics;
num = vm_template->get("GRAPHICS", array_graphics);
num = obj_template->get("GRAPHICS", array_graphics);
if ( num == 0 )
{
@ -425,7 +425,7 @@ int VirtualMachine::parse_requirements(string& error_str)
string parsed;
num = vm_template->remove("REQUIREMENTS", array_reqs);
num = obj_template->remove("REQUIREMENTS", array_reqs);
if ( num == 0 )
{
@ -452,7 +452,7 @@ int VirtualMachine::parse_requirements(string& error_str)
SingleAttribute * reqs_parsed;
reqs_parsed = new SingleAttribute("REQUIREMENTS",parsed);
vm_template->set(reqs_parsed);
obj_template->set(reqs_parsed);
}
/* --- Delete old requirements attributes --- */
@ -677,7 +677,7 @@ int VirtualMachine::get_disk_images(string& error_str)
Nebula& nd = Nebula::instance();
ipool = nd.get_ipool();
num_disks = vm_template->get("DISK",disks);
num_disks = obj_template->get("DISK",disks);
for(int i=0, index=0; i<num_disks; i++)
{
@ -760,14 +760,20 @@ void VirtualMachine::release_disk_images()
int num_disks;
vector<Attribute const * > disks;
Image * img;
ImagePool * ipool;
ImageManager * imagem;
string disk_base_path = "";
Nebula& nd = Nebula::instance();
ipool = nd.get_ipool();
imagem = nd.get_imagem();
num_disks = get_template_attribute("DISK",disks);
if (hasHistory() != 0)
{
disk_base_path = get_local_dir();
}
for(int i=0; i<num_disks; i++)
{
VectorAttribute const * disk =
@ -778,32 +784,20 @@ void VirtualMachine::release_disk_images()
continue;
}
iid = disk->vector_value("IMAGE_ID");
iid = disk->vector_value("IMAGE_ID");
saveas = disk->vector_value("SAVE_AS");
if ( iid.empty() )
{
continue;
if (!saveas.empty())
{
imagem->disk_to_image(disk_base_path,i,saveas);
}
}
img = ipool->get(atoi(iid.c_str()),true);
if ( img == 0 )
else
{
continue;
imagem->release_image(iid,disk_base_path,i,saveas);
}
img->release_image();
saveas = disk->vector_value("SAVE_AS");
if ( !saveas.empty() && saveas == iid )
{
img->enable(false);
}
ipool->update(img);
img->unlock();
}
}
@ -820,7 +814,7 @@ int VirtualMachine::get_network_leases()
Nebula& nd = Nebula::instance();
vnpool = nd.get_vnpool();
num_nics = vm_template->get("NIC",nics);
num_nics = obj_template->get("NIC",nics);
for(int i=0; i<num_nics; i++)
{
@ -957,7 +951,7 @@ int VirtualMachine::generate_context(string &files)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::save_disk(int disk_id, int img_id)
int VirtualMachine::save_disk(int disk_id, int img_id, string& error_str)
{
int num_disks;
vector<Attribute * > disks;
@ -970,7 +964,7 @@ int VirtualMachine::save_disk(int disk_id, int img_id)
istringstream iss;
num_disks = vm_template->get("DISK",disks);
num_disks = obj_template->get("DISK",disks);
for(int i=0; i<num_disks; i++, iss.clear())
{
@ -986,8 +980,13 @@ int VirtualMachine::save_disk(int disk_id, int img_id)
iss.str(disk_id_str);
iss >> tmp_disk_id;
if( tmp_disk_id == disk_id )
if ( tmp_disk_id == disk_id )
{
if(!((disk->vector_value("SAVE_AS")).empty()))
{
goto error_saved;
}
disk->replace("SAVE", "YES");
oss << (img_id);
@ -997,6 +996,19 @@ int VirtualMachine::save_disk(int disk_id, int img_id)
}
}
goto error_not_found;
error_saved:
oss << "The DISK " << disk_id << " is already suppossed to be saved.";
goto error_common;
error_not_found:
oss << "The DISK " << disk_id << " does not exist for VM " << oid << ".";
error_common:
NebulaLog::log("VM",Log::ERROR, oss);
error_str = oss.str();
return -1;
}
@ -1106,7 +1118,7 @@ string& VirtualMachine::to_xml(string& xml) const
<< "<CPU>" << cpu << "</CPU>"
<< "<NET_TX>" << net_tx << "</NET_TX>"
<< "<NET_RX>" << net_rx << "</NET_RX>"
<< vm_template->to_xml(template_xml);
<< obj_template->to_xml(template_xml);
if ( hasHistory() )
{
@ -1162,7 +1174,7 @@ int VirtualMachine::from_xml(const string &xml_str)
}
// Virtual Machine template
rc += vm_template->from_xml_node(content[0]);
rc += obj_template->from_xml_node(content[0]);
// Last history entry
content.clear();

View File

@ -17,6 +17,7 @@
#include "VirtualNetwork.h"
#include "VirtualNetworkPool.h"
#include "VirtualNetworkTemplate.h"
#include "NebulaLog.h"
#include "RangedLeases.h"
@ -40,11 +41,11 @@ VirtualNetwork::VirtualNetwork(int uid,
{
if (_vn_template != 0)
{
vn_template = _vn_template;
obj_template = _vn_template;
}
else
{
vn_template = new VirtualNetworkTemplate;
obj_template = new VirtualNetworkTemplate;
}
};
@ -58,9 +59,9 @@ VirtualNetwork::~VirtualNetwork()
delete leases;
}
if (vn_template != 0)
if (obj_template != 0)
{
delete vn_template;
delete obj_template;
}
}
@ -70,11 +71,11 @@ VirtualNetwork::~VirtualNetwork()
const char * VirtualNetwork::table = "network_pool";
const char * VirtualNetwork::db_names = "oid, name, body, uid";
const char * VirtualNetwork::db_names = "oid, name, body, uid, public";
const char * VirtualNetwork::db_bootstrap = "CREATE TABLE IF NOT EXISTS"
" network_pool (oid INTEGER PRIMARY KEY, name VARCHAR(256),"
" body TEXT, uid INTEGER, UNIQUE(name,uid))";
" body TEXT, uid INTEGER, public INTEGER, UNIQUE(name,uid))";
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -263,7 +264,7 @@ int VirtualNetwork::insert(SqlDB * db, string& error_str)
public_vnet = (pub == "YES");
vn_template->erase("PUBLIC");
obj_template->erase("PUBLIC");
//--------------------------------------------------------------------------
// Get the leases
@ -307,7 +308,7 @@ int VirtualNetwork::insert(SqlDB * db, string& error_str)
oss << default_size;
attribute = new SingleAttribute("NETWORK_SIZE",oss.str());
vn_template->set(attribute);
obj_template->set(attribute);
size = default_size;
}
@ -423,7 +424,8 @@ int VirtualNetwork::insert_replace(SqlDB *db, bool replace)
<< oid << ","
<< "'" << sql_name << "',"
<< "'" << sql_xml << "',"
<< uid << ")";
<< uid << ","
<< public_vnet << ")";
rc = db->exec(oss);
@ -505,7 +507,7 @@ string& VirtualNetwork::to_xml_extended(string& xml, bool extended) const
"<BRIDGE>" << bridge << "</BRIDGE>" <<
"<PUBLIC>" << public_vnet << "</PUBLIC>" <<
"<TOTAL_LEASES>"<< total_leases << "</TOTAL_LEASES>"<<
vn_template->to_xml(template_xml);
obj_template->to_xml(template_xml);
if (extended && leases != 0)
{
@ -552,7 +554,7 @@ int VirtualNetwork::from_xml(const string &xml_str)
}
// Virtual Network template
rc += vn_template->from_xml_node( content[0] );
rc += obj_template->from_xml_node( content[0] );
if (rc != 0)
{

View File

@ -19,6 +19,7 @@
#include <stdlib.h>
#include "VirtualNetworkPool.h"
#include "VirtualNetworkTemplate.h"
#include "PoolTest.h"
#include "ObjectXML.h"