From: Jan Provaznik <jprovazn(a)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
--
1.7.2.3