From 4e70f46b58e60ba859ea65a53a75267afec99f1d Mon Sep 17 00:00:00 2001 From: Jaime Melis <j.melis@fdi.ucm.es> Date: Wed, 30 Jun 2010 12:17:47 +0200 Subject: [PATCH 1/4] Added image hook --- share/hooks/image.rb | 83 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100755 share/hooks/image.rb diff --git a/share/hooks/image.rb b/share/hooks/image.rb new file mode 100755 index 0000000000..e0688fa4cf --- /dev/null +++ b/share/hooks/image.rb @@ -0,0 +1,83 @@ +#!/usr/bin/env ruby + +# -------------------------------------------------------------------------- # +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +ONE_LOCATION=ENV["ONE_LOCATION"] + +if !ONE_LOCATION + RUBY_LIB_LOCATION="/usr/lib/one/ruby" + VMDIR="/var/lib/one" +else + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" + VMDIR=ONE_LOCATION+"/var" +end + +$: << RUBY_LIB_LOCATION + + +require 'OpenNebula' +require 'client_utilities' +require 'pp' + +if !(vm_id=ARGV[0]) + exit -1 +end + +vm=OpenNebula::VirtualMachine.new_with_id(vm_id, get_one_client) +vm.info +template=vm.to_hash +template=template['VM']['TEMPLATE'] +disks=[template['DISK']].flatten if template['DISK'] +disks.each_with_index do |disk,i| + source_path=VMDIR+"/#{vm_id}/disk.#{i}" + if disk["NAME"]# and File.exists?(source_path) + if nil#disk["SAVE_AS"] + # Perform the allocate if all goes well + image=OpenNebula::Image.new( + OpenNebula::Image.build_xml, get_one_client) + begin + template="NAME=#{disk['SAVE_AS']}\n" + template+="TYPE=#{disk['TYPE'].upcase}\n" if DISK["TYPE"] + result=image.allocate(template) + rescue + result=OpenNebula::Error.new("Error in template") + end + + # Get the allocated image + image=OpenNebula::Image.new_with_id(image.id, get_one_client) + image.info + template=image.to_hash + template=template['IMAGE']['TEMPLATE'] + + if !is_successful?(result) + exit -1 + end + elsif disk["OVERWRITE"] + # Get the allocated image + image=OpenNebula::Image.new_with_id(disk['IID'], get_one_client) + image.info + image.disable + end + # Perform the copy to the image repo if needed + if File.copy(source_path, image['SOURCE']) + result=image.enable + else + result=OpenNebula::Error.new( + "Cannot copy image, please update before enabling it.") + end + end +end \ No newline at end of file From f8df7cb595c252316f36f3b2c422cabd35ecdeb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= <cmartins@fdi.ucm.es> Date: Wed, 30 Jun 2010 13:10:07 +0200 Subject: [PATCH 2/4] feature #200: Image initialization code refactor --- include/Image.h | 9 +++ include/ImagePool.h | 27 ++++++--- src/image/Image.cc | 108 +++++++++++++++++++++++++++++++++++ src/image/ImagePool.cc | 127 +++++------------------------------------ 4 files changed, 148 insertions(+), 123 deletions(-) diff --git a/include/Image.h b/include/Image.h index 3998263b4f..5d6258a151 100644 --- a/include/Image.h +++ b/include/Image.h @@ -19,6 +19,7 @@ #include "PoolSQL.h" #include "ImageTemplate.h" +#include "NebulaLog.h" using namespace std; @@ -367,6 +368,14 @@ private: db->exec(oss_templ); }; + + /** + * "Encrypts" the password with SHA1 digest + * @param password + * @return sha1 encrypted password + */ + string sha1_digest(const string& pass); + protected: // ************************************************************************* diff --git a/include/ImagePool.h b/include/ImagePool.h index 196400705b..8aa7c523e7 100644 --- a/include/ImagePool.h +++ b/include/ImagePool.h @@ -194,6 +194,21 @@ public: return rc; } + static string get_source_prefix() + { + return source_prefix; + }; + + static string get_default_type() + { + return default_type; + }; + + static string get_default_dev_prefix() + { + return default_dev_prefix; + }; + private: /** * This map stores the association between IIDs and Image names @@ -203,17 +218,17 @@ private: /** * Path to the image repository **/ - string source_prefix; + static string source_prefix; /** * Default image type **/ - string default_type; + static string default_type; /** * Default device prefix **/ - string default_dev_prefix; + static string default_dev_prefix; /** * Factory method to produce Image objects @@ -243,12 +258,6 @@ private: */ int init_cb(void *nil, int num, char **values, char **names); - /** - * "Encrypts" the password with SHA1 digest - * @param password - * @return sha1 encrypted password - */ - string sha1_digest(const string& pass); }; #endif /*IMAGE_POOL_H_*/ diff --git a/src/image/Image.cc b/src/image/Image.cc index 9ffdf39b8c..6a805230d9 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -19,6 +19,8 @@ #include <iostream> #include <sstream> +#include <openssl/evp.h> +#include <iomanip> #include "Image.h" #include "ImagePool.h" @@ -137,6 +139,76 @@ int Image::insert(SqlDB *db) { int rc; + string source_att; + string type_att; + string public_attr; + string dev_prefix; + + ostringstream tmp_hashstream; + ostringstream tmp_sourcestream; + + + // --------------------------------------------------------------------- + // Check default image attributes + // --------------------------------------------------------------------- + + // ------------ NAME -------------------- + + get_template_attribute("NAME", name); + + if ( name.empty() == true ) + { + goto error_name; + } + + // ------------ TYPE -------------------- + + get_template_attribute("TYPE", type_att); + + transform (type_att.begin(), type_att.end(), type_att.begin(), + (int(*)(int))toupper); + + if ( type_att.empty() == true ) + { + type_att = ImagePool::get_default_type(); + } + + if (set_type(type_att) != 0) + { + goto error_type; + } + + // ------------ PUBLIC -------------------- + + get_template_attribute("PUBLIC", public_attr); + + transform (public_attr.begin(), public_attr.end(), public_attr.begin(), + (int(*)(int))toupper); + + public_img = (public_attr == "YES"); + + // ------------ PREFIX -------------------- + + get_template_attribute("DEV_PREFIX", dev_prefix); + + if( dev_prefix.empty() ) + { + SingleAttribute * dev_att = new SingleAttribute("DEV_PREFIX", + ImagePool::get_default_dev_prefix()); + + image_template.set(dev_att); + } + + // ------------ SOURCE (path to store the image)-------------------- + + tmp_hashstream << uid << ":" << name; + + tmp_sourcestream << ImagePool::get_source_prefix() << "/"; + tmp_sourcestream << sha1_digest(tmp_hashstream.str()); + + source = tmp_sourcestream.str(); + + // Set up the template ID, to insert it if ( image_template.id == -1 ) { @@ -164,6 +236,15 @@ int Image::insert(SqlDB *db) } return 0; + +error_name: + NebulaLog::log("IMG", Log::ERROR, "NAME not present in image template"); + goto error_common; +error_type: + NebulaLog::log("IMG", Log::ERROR, "Incorrect TYPE in image template"); + goto error_common; +error_common: + return -1; } /* ------------------------------------------------------------------------ */ @@ -591,6 +672,33 @@ int Image::disk_attribute(VectorAttribute * disk, int * index) return 0; } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +string Image::sha1_digest(const string& pass) +{ + EVP_MD_CTX mdctx; + unsigned char md_value[EVP_MAX_MD_SIZE]; + unsigned int md_len; + ostringstream oss; + + EVP_MD_CTX_init(&mdctx); + EVP_DigestInit_ex(&mdctx, EVP_sha1(), NULL); + + EVP_DigestUpdate(&mdctx, pass.c_str(), pass.length()); + + EVP_DigestFinal_ex(&mdctx,md_value,&md_len); + EVP_MD_CTX_cleanup(&mdctx); + + for(unsigned int i = 0; i<md_len; i++) + { + oss << setfill('0') << setw(2) << hex << nouppercase + << (unsigned short) md_value[i]; + } + + return oss.str(); +} + /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc index ca384af46b..cfbeefa58b 100644 --- a/src/image/ImagePool.cc +++ b/src/image/ImagePool.cc @@ -19,11 +19,12 @@ /* ************************************************************************** */ #include "ImagePool.h" -#include <openssl/evp.h> -#include <iomanip> /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +string ImagePool::source_prefix; +string ImagePool::default_type; +string ImagePool::default_dev_prefix; int ImagePool::init_cb(void *nil, int num, char **values, char **names) { @@ -40,19 +41,22 @@ int ImagePool::init_cb(void *nil, int num, char **values, char **names) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + ImagePool::ImagePool( SqlDB * db, const string& _source_prefix, const string& _default_type, const string& _default_dev_prefix): - PoolSQL(db,Image::table), - source_prefix(_source_prefix), - default_type(_default_type), - default_dev_prefix(_default_dev_prefix) + PoolSQL(db,Image::table) { ostringstream sql; int rc; + // Init static defaults + source_prefix = _source_prefix; + default_type = _default_type; + default_dev_prefix = _default_dev_prefix; + // Set default type if (_default_type != "OS" && _default_type != "CDROM" && @@ -87,18 +91,11 @@ int ImagePool::allocate ( const string& stemplate, int * oid) { - Image * img; - string name; - string source; - string type; - string public_attr; - string dev_prefix; - - char * error_msg; int rc; + Image * img; - ostringstream tmp_hashstream; - ostringstream tmp_sourcestream; + string name; + char * error_msg; // --------------------------------------------------------------------- // Build a new Image object @@ -115,68 +112,8 @@ int ImagePool::allocate ( goto error_parse; } - // --------------------------------------------------------------------- - // Check default image attributes - // --------------------------------------------------------------------- - - // ------------ NAME -------------------- - img->get_template_attribute("NAME", name); - if ( name.empty() == true ) - { - goto error_name; - } - - img->name = name; - - // ------------ TYPE -------------------- - - img->get_template_attribute("TYPE", type); - - transform (type.begin(), type.end(), type.begin(), - (int(*)(int))toupper); - - if ( type.empty() == true ) - { - type = default_type; - } - - if (img->set_type(type) != 0) - { - goto error_type; - } - - // ------------ PUBLIC -------------------- - - img->get_template_attribute("PUBLIC", public_attr); - - transform (public_attr.begin(), public_attr.end(), public_attr.begin(), - (int(*)(int))toupper); - - img->public_img = (public_attr == "YES"); - - // ------------ PREFIX -------------------- - - img->get_template_attribute("DEV_PREFIX", dev_prefix); - - if( dev_prefix.empty() ) - { - SingleAttribute * dev_att = - new SingleAttribute("DEV_PREFIX", default_dev_prefix); - - img->image_template.set(dev_att); - } - - // ------------ SOURCE (path to store the image)-------------------- - - tmp_hashstream << uid << ":" << name; - - tmp_sourcestream << source_prefix << "/"; - tmp_sourcestream << sha1_digest(tmp_hashstream.str()); - - img->source = tmp_sourcestream.str(); - // --------------------------------------------------------------------- // Insert the Object in the pool // --------------------------------------------------------------------- @@ -196,17 +133,6 @@ int ImagePool::allocate ( return *oid; -error_name: - NebulaLog::log("IMG", Log::ERROR, "NAME not present in image template"); - goto error_common; -error_type: - NebulaLog::log("IMG", Log::ERROR, "Incorrect TYPE in image template"); - goto error_common; -error_common: - delete img; - *oid = -1; - return -1; - error_parse: ostringstream oss; oss << "ImagePool template parse error: " << error_msg; @@ -263,30 +189,3 @@ int ImagePool::dump(ostringstream& oss, const string& where) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ - -string ImagePool::sha1_digest(const string& pass) -{ - EVP_MD_CTX mdctx; - unsigned char md_value[EVP_MAX_MD_SIZE]; - unsigned int md_len; - ostringstream oss; - - EVP_MD_CTX_init(&mdctx); - EVP_DigestInit_ex(&mdctx, EVP_sha1(), NULL); - - EVP_DigestUpdate(&mdctx, pass.c_str(), pass.length()); - - EVP_DigestFinal_ex(&mdctx,md_value,&md_len); - EVP_MD_CTX_cleanup(&mdctx); - - for(unsigned int i = 0; i<md_len; i++) - { - oss << setfill('0') << setw(2) << hex << nouppercase - << (unsigned short) md_value[i]; - } - - return oss.str(); -} - -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ From 5955da4dbe38cd451223e6e89d06d1c1b57fcff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= <cmartins@fdi.ucm.es> Date: Wed, 30 Jun 2010 14:54:29 +0200 Subject: [PATCH 3/4] feature #192 & #200 : New test for Image::disk_attribute --- src/image/test/ImagePoolTest.cc | 134 ++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/src/image/test/ImagePoolTest.cc b/src/image/test/ImagePoolTest.cc index 7e41cb17bc..8c516e4dd8 100644 --- a/src/image/test/ImagePoolTest.cc +++ b/src/image/test/ImagePoolTest.cc @@ -85,6 +85,7 @@ class ImagePoolTest : public PoolTest CPPUNIT_TEST ( target_generation ); CPPUNIT_TEST ( bus_source_assignment ); CPPUNIT_TEST ( public_attribute ); + CPPUNIT_TEST ( disk_overwrite ); CPPUNIT_TEST ( dump ); CPPUNIT_TEST ( dump_where ); @@ -156,6 +157,7 @@ protected: delete user_pool; }; + public: ImagePoolTest(){}; @@ -292,6 +294,8 @@ public: check(1, obj); }; +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ void wrong_get_name() { @@ -548,6 +552,136 @@ public: delete disk; } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + + void disk_overwrite() + { + ImagePool * imp = static_cast<ImagePool *>(pool); + Image * img; + + VectorAttribute * disk; + int oid, rc; + string value; + int index = 0; + + // --------------------------------------------------------------------- + // Allocate an OS type image + oid = allocate(0); + CPPUNIT_ASSERT( oid > -1 ); + img = imp->get(oid, false); + + // Disk with overwrite=yes, save_as empty + disk = new VectorAttribute("DISK"); + + disk->replace("OVERWRITE", "yes"); + + img->enable(true); + rc = img->disk_attribute(disk, &index); + CPPUNIT_ASSERT( rc == 0 ); + + + value = disk->vector_value("OVERWRITE"); + CPPUNIT_ASSERT( value == "YES" ); + + value = ""; + value = disk->vector_value("SAVE_AS"); + CPPUNIT_ASSERT( value == "" ); + + value = ""; + value = disk->vector_value("CLONE"); + CPPUNIT_ASSERT( value == "NO" ); + + value = ""; + value = disk->vector_value("SAVE"); + CPPUNIT_ASSERT( value == "YES" ); + + value = ""; + value = disk->vector_value("READONLY"); + CPPUNIT_ASSERT( value == "NO" ); + + // clean up + delete disk; + + + // --------------------------------------------------------------------- + // Allocate an OS type image + oid = allocate(1); + CPPUNIT_ASSERT( oid > -1 ); + img = imp->get(oid, false); + + // Disk with overwrite=no, save_as not empty + disk = new VectorAttribute("DISK"); + + disk->replace("OVERWRITE", "NO"); + disk->replace("SAVE_AS", "path_to_save"); + + img->enable(true); + rc = img->disk_attribute(disk, &index); + CPPUNIT_ASSERT( rc == 0 ); + + value = ""; + value = disk->vector_value("OVERWRITE"); + CPPUNIT_ASSERT( value == "NO" ); + + value = ""; + value = disk->vector_value("SAVE_AS"); + CPPUNIT_ASSERT( value == "path_to_save" ); + + value = ""; + value = disk->vector_value("CLONE"); + CPPUNIT_ASSERT( value == "YES" ); + + value = ""; + value = disk->vector_value("SAVE"); + CPPUNIT_ASSERT( value == "YES" ); + + value = ""; + value = disk->vector_value("READONLY"); + CPPUNIT_ASSERT( value == "NO" ); + + // clean up + delete disk; + + // --------------------------------------------------------------------- + // Allocate an OS type image + oid = allocate(2); + CPPUNIT_ASSERT( oid > -1 ); + img = imp->get(oid, false); + + // Disk with overwrite=no, save_as not present + disk = new VectorAttribute("DISK"); + + disk->replace("OVERWRITE", "NO"); + + img->enable(true); + rc = img->disk_attribute(disk, &index); + CPPUNIT_ASSERT( rc == 0 ); + + value = ""; + value = disk->vector_value("OVERWRITE"); + CPPUNIT_ASSERT( value == "NO" ); + + value = ""; + value = disk->vector_value("SAVE_AS"); + CPPUNIT_ASSERT( value == "" ); + + value = ""; + value = disk->vector_value("CLONE"); + CPPUNIT_ASSERT( value == "YES" ); + + value = ""; + value = disk->vector_value("SAVE"); + CPPUNIT_ASSERT( value == "NO" ); + + value = ""; + value = disk->vector_value("READONLY"); + CPPUNIT_ASSERT( value == "NO" ); + + // clean up + delete disk; + } + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ From 85fd79c02979de2411f5670789fbc3cf5ea3c6c1 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" <rubensm@dacya.ucm.es> Date: Wed, 30 Jun 2010 17:08:11 +0200 Subject: [PATCH 4/4] feature #200: Slight modification of configuration attributes for the pool --- include/ImagePool.h | 34 ++++++++++++++++++++-------------- src/image/Image.cc | 6 +++--- src/image/ImagePool.cc | 20 ++++++++++---------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/include/ImagePool.h b/include/ImagePool.h index 8aa7c523e7..d46c09c4ae 100644 --- a/include/ImagePool.h +++ b/include/ImagePool.h @@ -194,41 +194,47 @@ public: return rc; } - static string get_source_prefix() + static const string& source_prefix() { - return source_prefix; + return _source_prefix; }; - static string get_default_type() + static const string& default_type() { - return default_type; + return _default_type; }; - static string get_default_dev_prefix() + static const string& default_dev_prefix() { - return default_dev_prefix; + return _default_dev_prefix; }; private: - /** - * This map stores the association between IIDs and Image names - */ - map<string, int> image_names; - + //-------------------------------------------------------------------------- + // Configuration Attributes for Images + // ------------------------------------------------------------------------- /** * Path to the image repository **/ - static string source_prefix; + static string _source_prefix; /** * Default image type **/ - static string default_type; + static string _default_type; /** * Default device prefix **/ - static string default_dev_prefix; + static string _default_dev_prefix; + + //-------------------------------------------------------------------------- + // Pool Attributes + // ------------------------------------------------------------------------- + /** + * This map stores the association between IIDs and Image names + */ + map<string, int> image_names; /** * Factory method to produce Image objects diff --git a/src/image/Image.cc b/src/image/Image.cc index 6a805230d9..042228e718 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -170,7 +170,7 @@ int Image::insert(SqlDB *db) if ( type_att.empty() == true ) { - type_att = ImagePool::get_default_type(); + type_att = ImagePool::default_type(); } if (set_type(type_att) != 0) @@ -194,7 +194,7 @@ int Image::insert(SqlDB *db) if( dev_prefix.empty() ) { SingleAttribute * dev_att = new SingleAttribute("DEV_PREFIX", - ImagePool::get_default_dev_prefix()); + ImagePool::default_dev_prefix()); image_template.set(dev_att); } @@ -203,7 +203,7 @@ int Image::insert(SqlDB *db) tmp_hashstream << uid << ":" << name; - tmp_sourcestream << ImagePool::get_source_prefix() << "/"; + tmp_sourcestream << ImagePool::source_prefix() << "/"; tmp_sourcestream << sha1_digest(tmp_hashstream.str()); source = tmp_sourcestream.str(); diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc index cfbeefa58b..38e2b566e8 100644 --- a/src/image/ImagePool.cc +++ b/src/image/ImagePool.cc @@ -22,9 +22,9 @@ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -string ImagePool::source_prefix; -string ImagePool::default_type; -string ImagePool::default_dev_prefix; +string ImagePool::_source_prefix; +string ImagePool::_default_type; +string ImagePool::_default_dev_prefix; int ImagePool::init_cb(void *nil, int num, char **values, char **names) { @@ -43,9 +43,9 @@ int ImagePool::init_cb(void *nil, int num, char **values, char **names) ImagePool::ImagePool( SqlDB * db, - const string& _source_prefix, - const string& _default_type, - const string& _default_dev_prefix): + const string& __source_prefix, + const string& __default_type, + const string& __default_dev_prefix): PoolSQL(db,Image::table) { @@ -53,9 +53,9 @@ ImagePool::ImagePool( SqlDB * db, int rc; // Init static defaults - source_prefix = _source_prefix; - default_type = _default_type; - default_dev_prefix = _default_dev_prefix; + _source_prefix = __source_prefix; + _default_type = __default_type; + _default_dev_prefix = __default_dev_prefix; // Set default type if (_default_type != "OS" && @@ -64,7 +64,7 @@ ImagePool::ImagePool( SqlDB * db, { NebulaLog::log("IMG", Log::ERROR, "Bad default for image type, setting OS"); - default_type = "OS"; + _default_type = "OS"; } // Read from the DB the existing images, and build the ID:Name map