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..d46c09c4ae 100644 --- a/include/ImagePool.h +++ b/include/ImagePool.h @@ -194,26 +194,47 @@ public: return rc; } -private: - /** - * This map stores the association between IIDs and Image names - */ - map image_names; + static const string& source_prefix() + { + return _source_prefix; + }; + static const string& default_type() + { + return _default_type; + }; + + static const string& default_dev_prefix() + { + return _default_dev_prefix; + }; + +private: + //-------------------------------------------------------------------------- + // Configuration Attributes for Images + // ------------------------------------------------------------------------- /** * Path to the image repository **/ - 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; + + //-------------------------------------------------------------------------- + // Pool Attributes + // ------------------------------------------------------------------------- + /** + * This map stores the association between IIDs and Image names + */ + map image_names; /** * Factory method to produce Image objects @@ -243,12 +264,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/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 diff --git a/src/image/Image.cc b/src/image/Image.cc index ed01074da2..3c1cf4c1ef 100644 --- a/src/image/Image.cc +++ b/src/image/Image.cc @@ -19,6 +19,8 @@ #include #include +#include +#include #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::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::default_dev_prefix()); + + image_template.set(dev_att); + } + + // ------------ SOURCE (path to store the image)-------------------- + + tmp_hashstream << uid << ":" << name; + + tmp_sourcestream << ImagePool::source_prefix() << "/"; + tmp_sourcestream << sha1_digest(tmp_hashstream.str()); + + source = tmp_sourcestream.str(); + + // Set up the template ID, to insert it if ( image_template.id == -1 ) { @@ -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; } /* ------------------------------------------------------------------------ */ @@ -583,6 +664,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 -#include /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +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) +ImagePool::ImagePool( SqlDB * db, + const string& __source_prefix, + const string& __default_type, + const string& __default_dev_prefix): + + PoolSQL(db,Image::table) { ostringstream sql; int rc; + // Init static defaults + _source_prefix = __source_prefix; + _default_type = __default_type; + _default_dev_prefix = __default_dev_prefix; + // Set default type if (_default_type != "OS" && _default_type != "CDROM" && @@ -60,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 @@ -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(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; + } + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */