From 11fbfb56364eb2de2edfb03327d019f774d058cb Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 24 Jun 2010 18:35:18 +0200 Subject: [PATCH] feature #200: Generate Disk attributes with the ImagePool metadata --- include/Image.h | 4 +- include/ImagePool.h | 38 ++++++++++- src/image/Image.cc | 142 +++++++++++++++++++++++++++-------------- src/image/ImagePool.cc | 33 +++++----- 4 files changed, 146 insertions(+), 71 deletions(-) diff --git a/include/Image.h b/include/Image.h index 3ea89352d4..46d9a30cce 100644 --- a/include/Image.h +++ b/include/Image.h @@ -202,9 +202,9 @@ public: * - CDROM images will be at prefix + c: hdc, sdc. * - Several DATABLOCK images can be mounted, they will be set to * prefix + (d + index) : hdd, hde, hdf... - * returns: 0 on success, -1 in case of error. + * @param disk attribute for the VM template */ - int get_disk_attribute(VectorAttribute * disk, int index); + void disk_attribute(VectorAttribute ** disk, int index); // ------------------------------------------------------------------------ // Template diff --git a/include/ImagePool.h b/include/ImagePool.h index 3db0cf3d47..691aa97439 100644 --- a/include/ImagePool.h +++ b/include/ImagePool.h @@ -29,6 +29,9 @@ using namespace std; +#define IMAGE_TO_UPPER(S) transform (S.begin(),S.end(),S.begin(), \ +(int(*)(int))toupper) + /** * The Image Pool class. */ @@ -78,8 +81,8 @@ public: * @return a pointer to the Image, 0 if the User could not be loaded */ Image * get( - string name, - bool lock) + const string& name, + bool lock) { map::iterator index; @@ -163,6 +166,37 @@ public: */ int dump(ostringstream& oss, const string& where); + /** + * Generates a DISK attribute for VM templates using the Image metadata + * @param disk the disk to be generated + * @return 0 on success, -1 error, -2 not using the pool + */ + int disk_attribute(VectorAttribute * disk, int index) + { + string source; + Image * img; + + source = disk->vector_value("NAME"); + + if (source.empty()) + { + return -2; + } + + img = get(source,true); + + if (img == 0) + { + return -1; + } + + img->disk_attribute(&disk,index); + + img->unlock(); + + return 0; + } + private: /** * This map stores the association between IIDs and Image names diff --git a/src/image/Image.cc b/src/image/Image.cc index 648ac58c79..a50449c9c5 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -21,6 +21,8 @@ #include #include "Image.h" +#include "ImagePool.h" + /* ************************************************************************ */ /* Image :: Constructor/Destructor */ @@ -456,69 +458,111 @@ void Image::release_image() /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ -int Image::get_disk_attribute(VectorAttribute * disk, int index) +void Image::disk_attribute(VectorAttribute ** disk, int index) { - string target = ""; - string bus = ""; + string overwrite; + string saveas; + string name; + string bus; + name = (*disk)->vector_value("NAME"); + overwrite = (*disk)->vector_value("OVERWRITE"); + saveas = (*disk)->vector_value("SAVE_AS"); + bus = (*disk)->vector_value("BUS"); - // SOURCE attribute - disk->replace("SOURCE", source); + string template_bus; + string prefix; + get_template_attribute("BUS", template_bus); + get_template_attribute("DEV_PREFIX", prefix); - // The BUS attribute isn't mandatory. + //--------------------------------------------------------------------------- + // NEW DISK ATTRIBUTES + //--------------------------------------------------------------------------- + VectorAttribute * new_disk = new VectorAttribute("DISK"); - get_template_attribute("BUS", bus); + new_disk->replace("NAME",name); + new_disk->replace("OVERWRITE",overwrite); + new_disk->replace("SAVE_AS",saveas); - if( !bus.empty() ) // If the image has a BUS defined ... + new_disk->replace("SOURCE", source); + + if (bus.empty()) { - string disk_bus = disk->vector_value("BUS"); - - if( disk_bus.empty() ) // ... and the disk doesn't have already one + if (!template_bus.empty()) { - disk->replace("BUS", bus); + new_disk->replace("BUS",template_bus); } } - - - // If the disk has already a user-defined target, then it will be used. - // First, check if it exists. - target = disk->vector_value("TARGET"); - - - if ( target.empty() ) + else { - // Generate the target from the image's prefix and type - - get_template_attribute("DEV_PREFIX", target); - - switch( type ) - { - case OS: - target += "a"; - break; - case CDROM: - target += "c"; - break; - case DATABLOCK: - // Multiple datablocks can be defined, and they are mounted as - // sdd, sde, sdf... - - if( index < 0 ) - { - return -1; - } - - char letter = ('d' + index); - target += letter; - break; - }; - - // "Replace" inserts the name-value pair even if it doesn't exist. - disk->replace("TARGET", target); + new_disk->replace("BUS",bus); } - return 0; + //--------------------------------------------------------------------------- + // TYPE, READONLY, CLONE, and SAVE attributes + //--------------------------------------------------------------------------- + + IMAGE_TO_UPPER(overwrite); + IMAGE_TO_UPPER(saveas); + + switch(type) + { + case OS: + case DATABLOCK: + new_disk->replace("TYPE","DISK"); + new_disk->replace("READONLY","NO"); + + if (overwrite == "YES") + { + new_disk->replace("CLONE","NO"); + new_disk->replace("SAVE","YES"); + } + else if (saveas == "YES") + { + new_disk->replace("CLONE","YES"); + new_disk->replace("SAVE","YES"); + } + else + { + new_disk->replace("CLONE","YES"); + new_disk->replace("SAVE","NO"); + } + break; + + case CDROM: + new_disk->replace("TYPE","CDROM"); + new_disk->replace("READONLY","YES"); + + new_disk->replace("CLONE","YES"); + new_disk->replace("SAVE","NO"); + break; + } + + //--------------------------------------------------------------------------- + // TARGET attribute + //--------------------------------------------------------------------------- + + switch(type) + { + case OS: + prefix += "a"; + break; + + case CDROM: + prefix += "c"; // b is for context + break; + + case DATABLOCK: + prefix += static_cast(('d'+ index)); + break; + + } + + new_disk->replace("TARGET", prefix); + + delete (*disk); + (*disk) = new_disk; } /* ------------------------------------------------------------------------ */ diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc index c9a034ce23..d85ab414bd 100644 --- a/src/image/ImagePool.cc +++ b/src/image/ImagePool.cc @@ -22,9 +22,6 @@ #include #include -#define TO_UPPER(S) transform (S.begin(),S.end(),S.begin(), \ -(int(*)(int))toupper) - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -76,7 +73,7 @@ ImagePool::ImagePool( SqlDB * db, sql << "SELECT oid, name FROM " << Image::table; rc = db->exec(sql, this); - + unset_callback(); if ( rc != 0 ) @@ -115,7 +112,7 @@ int ImagePool::allocate ( img = new Image(uid); // --------------------------------------------------------------------- - // Parse template + // Parse template // --------------------------------------------------------------------- rc = img->image_template.parse(stemplate, &error_msg); @@ -123,10 +120,10 @@ int ImagePool::allocate ( { goto error_parse; } - + // --------------------------------------------------------------------- // Check default image attributes - // --------------------------------------------------------------------- + // --------------------------------------------------------------------- img->get_template_attribute("NAME", name); if ( name.empty() == true ) @@ -149,11 +146,11 @@ int ImagePool::allocate ( } img->get_template_attribute("PUBLIC", public_attr); - TO_UPPER( public_attr ); + IMAGE_TO_UPPER( public_attr ); img->image_template.erase("PUBLIC"); img->get_template_attribute("ORIGINAL_PATH", original_path); - + if ( (type == "OS" || type == "CDROM") && original_path.empty() == true ) { @@ -167,7 +164,7 @@ int ImagePool::allocate ( if( dev_prefix.empty() ) { - SingleAttribute * dev_att = + SingleAttribute * dev_att = new SingleAttribute("DEV_PREFIX", default_dev_prefix); img->image_template.set(dev_att); @@ -193,7 +190,7 @@ int ImagePool::allocate ( goto error_type; } - + // --------------------------------------------------------------------- // Insert the Object in the pool // --------------------------------------------------------------------- @@ -217,14 +214,14 @@ error_type: NebulaLog::log("IMG", Log::ERROR, "Incorrect TYPE in image template"); goto error_common; error_original_path: - NebulaLog::log("IMG", Log::ERROR, + NebulaLog::log("IMG", Log::ERROR, "ORIGINAL_PATH compulsory and not present in image template of this type."); goto error_common; error_common: delete img; *oid = -1; return -1; - + error_parse: ostringstream oss; oss << "ImagePool template parse error: " << error_msg; @@ -259,12 +256,12 @@ int ImagePool::dump(ostringstream& oss, const string& where) set_callback(static_cast(&ImagePool::dump_cb), static_cast(&oss)); - - cmd << "SELECT " << Image::table << ".*, user_pool.user_name FROM " - << Image::table << + + cmd << "SELECT " << Image::table << ".*, user_pool.user_name FROM " + << Image::table << " LEFT OUTER JOIN (SELECT oid, user_name FROM user_pool) " << "AS user_pool ON " << Image::table << ".uid = user_pool.oid"; - + if ( !where.empty() ) { cmd << " WHERE " << where; @@ -273,7 +270,7 @@ int ImagePool::dump(ostringstream& oss, const string& where) rc = db->exec(cmd, this); oss << ""; - + unset_callback(); return rc;