From: Jan Provaznik jprovazn@redhat.com
import of single image: rake dc:import[ec2,uid,password,ami-20b65349]
import of multiple images by passing yaml file: rake dc:bulk_import[ec2,uid,password,/tmp/list.yml]
yaml file looks like (currently only ID, do we want other attrs?): - id: ari-faf01293 - id: ari-fcfd1095 --- src/app/models/image.rb | 76 +++++++++++++++++++++++++++++++++++++++++ src/app/models/template.rb | 8 ++++ src/lib/tasks/dc_tasks.rake | 30 ++++++++++++++++ src/spec/models/image_spec.rb | 18 ++++++++++ 4 files changed, 132 insertions(+), 0 deletions(-)
diff --git a/src/app/models/image.rb b/src/app/models/image.rb index 5ca3fd4..f6b10ac 100644 --- a/src/app/models/image.rb +++ b/src/app/models/image.rb @@ -85,4 +85,80 @@ class Image < ActiveRecord::Base end return img end + + def self.single_import(providername, username, password, image_id) + account = Image.get_account(providername, username, password) + Image.import(account, image_id) + end + + def self.bulk_import(providername, username, password, images) + account = Image.get_account(providername, username, password) + images.each do |image| + begin + Image.import(account, image['id']) + $stderr.puts "imported image with id '#{image['id']}'" + rescue + $stderr.puts "failed to import image with id '#{image['id']}'" + end + end + end + + def self.import(account, image_id) + unless raw_image = account.connect.image(image_id) + raise "There is no image with '#{image_id}' id" + end + + if ReplicatedImage.find_by_provider_id_and_provider_image_key(account.provider.id, image_id) + raise "Image '#{image_id}' is already imported" + end + + image = nil + ActiveRecord::Base.transaction do + template = Template.new( + :name => raw_image.name + '_template', + :summary => raw_image.description, + :platform_hash => {:platform => 'unknown', + :version => 'unknown', + :architecture => raw_image.architecture}, + :complete => true, + :uploaded => true, + :imported => true + ) + template.save! + + image = Image.new( + :name => raw_image.name, + :status => 'complete', + :target => account.provider.cloud_type, + :template_id => template.id + ) + image.save! + + rep = ReplicatedImage.new( + :image_id => image.id, + :provider_id => account.provider.id, + :provider_image_key => image_id, + :uploaded => true, + :registered => true + ) + rep.save! + end + image + end + + private + + def self.get_account(providername, username, password) + unless provider = Provider.find_by_name(providername) + raise "There is not provider with name '#{providername}'" + end + + account = CloudAccount.new(:provider => provider, :username => username, :password => password) + + unless account.valid_credentials? + raise "Invalid credentials for provider '#{providername}'" + end + + return account + end end diff --git a/src/app/models/template.rb b/src/app/models/template.rb index 74bf208..0a83773 100644 --- a/src/app/models/template.rb +++ b/src/app/models/template.rb @@ -89,12 +89,20 @@ class Template < ActiveRecord::Base add_groups(groups) end
+ # sets platform info from predefined platform list def platform=(plat) write_attribute(:platform, plat) self.platform_version = platforms[plat]['version'].to_s self.architecture = platforms[plat]['architecture'] end
+ # sets platform info from hash (used when importing images) + def platform_hash=(plat) + write_attribute(:platform, plat[:platform]) + self.platform_version = plat[:version] + self.architecture = plat[:architecture] + end + # packages and groups are virtual attributes def packages xml.packages diff --git a/src/lib/tasks/dc_tasks.rake b/src/lib/tasks/dc_tasks.rake index 3ae6022..495f3aa 100644 --- a/src/lib/tasks/dc_tasks.rake +++ b/src/lib/tasks/dc_tasks.rake @@ -79,4 +79,34 @@ namespace :dc do Rake::Task[:'dc:create_admin_user'].invoke end
+ desc 'Import images' + task :import, [:provider, :username, :password, :image] => :environment do |t, args| + unless args.provider and args.username and args.password and args.image + puts "Usage: rake 'dc:import[provider,username,password,imageid]'" + exit(1) + end + #account = get_account(args.provider, args.account) + img = Image.single_import(args.provider, args.username, args.password, args.image) + puts "Imported image with id '#{args.image}'" + end + + desc 'Bulk import images' + task :bulk_import, [:provider, :username, :password, :yml_file] => :environment do |t, args| + unless args.provider and args.username and args.password and args.yml_file + puts "Usage: rake 'dc:import[provider,username,password,yml_file]'" + exit(1) + end + list = YAML.load_file(args.yml_file) + Image.bulk_import(args.provider, args.username, args.password, list) + end + + def get_account(provider_name, account_name) + unless provider = Provider.find_by_name(provider_name) + raise "There is no provider with '#{provider_name}' name" + end + unless account = provider.cloud_accounts.find_by_label(account_name) + raise "There is no account with '#{account_name}' label" + end + account + end end diff --git a/src/spec/models/image_spec.rb b/src/spec/models/image_spec.rb index 04c8171..58cbc10 100644 --- a/src/spec/models/image_spec.rb +++ b/src/spec/models/image_spec.rb @@ -43,6 +43,7 @@ describe Image do
it "should build image if there is provider and cloud account for specified target" do acc = Factory.build(:mock_cloud_account) + acc.stub!(:valid_credentials?).and_return(true) acc.save! tpl = Factory.build(:template) tpl.save! @@ -50,4 +51,21 @@ describe Image do Image.find(img).should == img ReplicatedImage.find_by_image_id(img.id).should_not be_nil end + + it "should import image" do + image = OpenStruct.new(:id => 'mock', :name => 'mock', :description => 'imported mock', :architecture => 'i386') + client = mock('DeltaCloud', :null_object => true, :image => image) + account = Factory.build(:ec2_cloud_account) + account.stub!(:connect).and_return(client) + account.stub!(:valid_credentials?).and_return(true) + account.save! + + lambda do + lambda do + lambda do + Image.import(account, 'mock').should_not be_nil + end.should change(Image, :count).by(1) + end.should change(Template, :count).by(1) + end.should change(ReplicatedImage, :count).by(1) + end end