rightimage_tools 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Rakefile +5 -0
- data/VERSION +1 -1
- data/bin/image_mover +60 -0
- data/bin/mci_merge +117 -0
- data/bin/update_s3_index +12 -0
- data/lib/id_list.rb +71 -0
- data/lib/mci.rb +19 -5
- data/lib/rightimage_tools.rb +4 -0
- data/lib/s3_html_indexer.rb +251 -0
- data/lib/util.rb +50 -0
- metadata +15 -12
- data/.document +0 -5
- data/.rspec +0 -1
- data/Gemfile.lock +0 -50
- data/spec/mci_spec.rb +0 -97
- data/spec/spec_helper.rb +0 -13
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'bundler'
|
5
|
+
|
5
6
|
begin
|
6
7
|
Bundler.setup(:default, :development)
|
7
8
|
rescue Bundler::BundlerError => e
|
@@ -10,14 +11,18 @@ rescue Bundler::BundlerError => e
|
|
10
11
|
exit e.status_code
|
11
12
|
end
|
12
13
|
require 'rake'
|
14
|
+
require 'lib/rightimage_tools'
|
13
15
|
|
14
16
|
require 'jeweler'
|
15
17
|
Jeweler::Tasks.new do |gem|
|
16
18
|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
19
|
gem.name = "rightimage_tools"
|
20
|
+
gem.version = RightImageTools::VERSION
|
18
21
|
gem.homepage = "http://github.com/rightscale/rightimage_tools"
|
19
22
|
gem.license = "MIT"
|
20
23
|
gem.summary = %Q{A set of tools to support the building of RightImages}
|
24
|
+
gem.files = %w(LICENSE.txt VERSION README.rdoc Rakefile Gemfile) + FileList["{bin,lib}/**/*"].to_a
|
25
|
+
gem.executables = %w(image_mover mci_merge update_s3_index)
|
21
26
|
gem.description = gem.summary
|
22
27
|
gem.email = "peter.schroeter@rightscale.com"
|
23
28
|
gem.authors = ["Peter Schroeter"]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/image_mover
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'optparse'
|
5
|
+
require 'right_aws'
|
6
|
+
|
7
|
+
THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
|
8
|
+
require File.expand_path(File.join(File.dirname(THIS_FILE), '..', 'lib', 's3_html_indexer'))
|
9
|
+
|
10
|
+
options = {}
|
11
|
+
opts = OptionParser.new
|
12
|
+
opts.on('-k', '--key KEY', "S3 key path (Ex: kvm/centos/5.6/RightImage_CentOS_5.6_x64_v5.7.14.qcow2.bz2)") { |key| options[:key] = key }
|
13
|
+
opts.on('-s', '--source BUCKET', "Source S3 bucket (Ex: rightscale-cloudstack-dev)") { |bucket| options[:bucket_from] = bucket }
|
14
|
+
opts.on('-d', '--destination BUCKET', "Destination S3 bucket (Ex: rightscale-cloudstack)") { |bucket| options[:bucket_to] = bucket }
|
15
|
+
opts.on_tail('-h', '--help', "Show this message") do
|
16
|
+
puts "#{opts}\n"
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
|
20
|
+
begin
|
21
|
+
opts.parse!
|
22
|
+
mandatory = [:bucket_to, :bucket_from, :key]
|
23
|
+
missing = mandatory.select { |param| options[param].nil? }
|
24
|
+
if not missing.empty?
|
25
|
+
puts "Missing options: #{missing.join(", ")}"
|
26
|
+
puts opts
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
|
30
|
+
puts $!.to_s
|
31
|
+
puts opts
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
raise "ERROR: you must define AWS_ACCESS_KEY_ID in you environment. " unless ENV["AWS_ACCESS_KEY_ID"]
|
36
|
+
raise "ERROR: you must define AWS_SECRET_ACCESS_KEY in you environment. " unless ENV["AWS_SECRET_ACCESS_KEY"]
|
37
|
+
|
38
|
+
s3 = RightAws::S3.new(ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_SECRET_ACCESS_KEY"])
|
39
|
+
bucket_from = s3.bucket(options[:bucket_from])
|
40
|
+
bucket_to = s3.bucket(options[:bucket_to])
|
41
|
+
|
42
|
+
puts "Moving file #{options[:key]} from #{options[:bucket_from]} to #{options[:bucket_to]}"
|
43
|
+
key_from = RightAws::S3::Key.create(bucket_from, options[:key])
|
44
|
+
key_to = RightAws::S3::Key.create(bucket_to, options[:key])
|
45
|
+
key_from.move(key_to)
|
46
|
+
raise "File move failed" unless key_to.exists?
|
47
|
+
|
48
|
+
puts "Granting public read"
|
49
|
+
grant = RightAws::S3::Grantee.new(key_to, 'http://acs.amazonaws.com/groups/global/AllUsers', 'READ', :apply_and_refresh)
|
50
|
+
raise "Grant update failed" unless grant
|
51
|
+
|
52
|
+
puts "Reindexing source bucket #{bucket_from}"
|
53
|
+
indexer_from = RightImage::S3HtmlIndexer.new(options[:bucket_from], ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_SECRET_ACCESS_KEY"])
|
54
|
+
indexer_from.to_html("index-from.html")
|
55
|
+
indexer_from.upload_index("index-from.html")
|
56
|
+
|
57
|
+
puts "Reindexing destination bucket #{bucket_to}"
|
58
|
+
indexer_to = RightImage::S3HtmlIndexer.new(options[:bucket_to], ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_SECRET_ACCESS_KEY"])
|
59
|
+
indexer_to.to_html("index-to.html")
|
60
|
+
indexer_to.upload_index("index-to.html")
|
data/bin/mci_merge
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'optparse'
|
5
|
+
#require 'ruby-debug'
|
6
|
+
require 'rest_connection'
|
7
|
+
require 'tmpdir'
|
8
|
+
|
9
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'mci'))
|
10
|
+
|
11
|
+
def aws_id_from_href(href)
|
12
|
+
id = href.split("/").last
|
13
|
+
id.split("?").first
|
14
|
+
end
|
15
|
+
|
16
|
+
def ask(prompt)
|
17
|
+
puts prompt+" "
|
18
|
+
res = gets
|
19
|
+
unless res =~ /^[yY]/
|
20
|
+
puts "Aborting"
|
21
|
+
exit 0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse_options
|
26
|
+
opts = OptionParser.new
|
27
|
+
options = {}
|
28
|
+
opts.on('-s', '--source MCI_SUFFIX', "Suffix of MCI to copy from i.e. 'v5.8.0_Beta_Dev2'") { |name| options[:src] = name}
|
29
|
+
opts.on('-d', '--destination MCI_SUFFIX', "Suffix of MCI to copy to i.e. 'v5.8'") { |name| options[:dest] = name}
|
30
|
+
opts.on_tail('-h', '--help', "Show help") do
|
31
|
+
puts "#{opts}\n"
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
opts.parse!
|
37
|
+
mandatory = [:src, :dest]
|
38
|
+
missing = mandatory.select { |param| options[param].nil? }
|
39
|
+
if not missing.empty?
|
40
|
+
puts "Missing options: #{missing.join(", ")}"
|
41
|
+
puts opts
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
|
45
|
+
puts $!.to_s
|
46
|
+
puts opts
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
options
|
50
|
+
end
|
51
|
+
|
52
|
+
options = parse_options
|
53
|
+
ENV['REST_CONNECTION_LOG'] = Dir.tmpdir + "/mci_merge_rest.log"
|
54
|
+
|
55
|
+
mcis = MultiCloudImage.find_all
|
56
|
+
sources = []
|
57
|
+
dests = []
|
58
|
+
|
59
|
+
mcis.each do |mci|
|
60
|
+
if mci.name =~ /RightImage.*#{Regexp.escape(options[:src])}$/
|
61
|
+
sources << MultiCloudImageInternal.find(mci.rs_id.to_i)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
puts "Found #{sources.length} MCIs to move: "
|
66
|
+
|
67
|
+
sources.each_with_index do |mci, i|
|
68
|
+
# print out source mci
|
69
|
+
print i.to_s.ljust(2)+") "
|
70
|
+
puts mci.name
|
71
|
+
clouds = mci.multi_cloud_image_cloud_settings.map {|s| s.cloud}
|
72
|
+
puts " CLOUDS: "+clouds.join(", ")
|
73
|
+
print " -->"
|
74
|
+
|
75
|
+
# find a destination mci and print that if found
|
76
|
+
# else note we'll make a new mci for the destination
|
77
|
+
name_no_suffix = mci.name.sub(options[:src],"")
|
78
|
+
dest_mci_name = name_no_suffix + options[:dest]
|
79
|
+
found = mcis.find { |new_mci| new_mci.name == dest_mci_name }
|
80
|
+
if found
|
81
|
+
dest_mci = MultiCloudImageInternal.find(found.rs_id.to_i)
|
82
|
+
dests << dest_mci
|
83
|
+
print dest_mci.name
|
84
|
+
else
|
85
|
+
dests << dest_mci_name
|
86
|
+
print "NEW MCI: "
|
87
|
+
print dest_mci_name
|
88
|
+
end
|
89
|
+
puts ""
|
90
|
+
end
|
91
|
+
|
92
|
+
ask("Continue - Y/N?")
|
93
|
+
|
94
|
+
mci_tool = RightImageTools::MCI.new
|
95
|
+
sources.each_with_index do |src_mci, i|
|
96
|
+
dest_mci = dests[i]
|
97
|
+
if dest_mci.class == String
|
98
|
+
src_mci.multi_cloud_image_cloud_settings.each do |s|
|
99
|
+
image_id = aws_id_from_href(s.image_href)
|
100
|
+
puts "New MCI with image: cloud_id=#{s.cloud_id.to_i}, mci_name=#{dest_mci}, image_id=#{image_id}"
|
101
|
+
mci_tool.add_image_to_mci(
|
102
|
+
:cloud_id=>s.cloud_id.to_i,
|
103
|
+
:name=>dest_mci,
|
104
|
+
:image_id=>image_id)
|
105
|
+
end
|
106
|
+
else
|
107
|
+
src_mci.multi_cloud_image_cloud_settings.each do |s|
|
108
|
+
image_id = aws_id_from_href(s.image_href)
|
109
|
+
puts "Adding image to MCI #{dest_mci.rs_id}: cloud_id=#{s.cloud_id.to_i}, mci_id=#{dest_mci.rs_id}, image_id=#{image_id}"
|
110
|
+
mci_tool.add_image_to_mci(
|
111
|
+
:cloud_id=>s.cloud_id.to_i,
|
112
|
+
:mci_id=>dest_mci.rs_id,
|
113
|
+
:image_id=>image_id)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
data/bin/update_s3_index
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
|
4
|
+
require File.expand_path(File.join(File.dirname(THIS_FILE), '..', 'lib', 's3_html_indexer'))
|
5
|
+
|
6
|
+
raise "ERROR: you must define AWS_IMAGE_BUCKET in you environment. " unless ENV["AWS_IMAGE_BUCKET"]
|
7
|
+
raise "ERROR: you must define AWS_ACCESS_KEY_ID in you environment. " unless ENV["AWS_ACCESS_KEY_ID"]
|
8
|
+
raise "ERROR: you must define AWS_SECRET_ACCESS_KEY in you environment. " unless ENV["AWS_SECRET_ACCESS_KEY"]
|
9
|
+
|
10
|
+
indexer = RightImageTools::S3HtmlIndexer.new(ENV["AWS_IMAGE_BUCKET"], ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_SECRET_ACCESS_KEY"])
|
11
|
+
indexer.to_html("index.html")
|
12
|
+
indexer.upload_index("index.html")
|
data/lib/id_list.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
module RightImage
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
# Manages a global store of image ids for images that have been
|
5
|
+
# on a single rightimage creator instance.
|
6
|
+
# The image data is persisted on the local filesystem.
|
7
|
+
#
|
8
|
+
class IdList
|
9
|
+
|
10
|
+
def initialize(logger = nil)
|
11
|
+
@log = (logger) ? logger : Logger.new(STDOUT)
|
12
|
+
@file = ::File.join(ENV["HOME"], "rightimage_id_list")
|
13
|
+
end
|
14
|
+
|
15
|
+
# Pass in id that the cloud provider passes back upon registration
|
16
|
+
# NOTE: Be sure to set storage type for EC2 "EBS" images so we can
|
17
|
+
# properly know what kind of MCI to make later.
|
18
|
+
#
|
19
|
+
def add(id, storage_type = nil)
|
20
|
+
list_load
|
21
|
+
key = id.to_s
|
22
|
+
key.chomp!
|
23
|
+
@log.info("Adding #{key} to #{(@list) ? 'existing' : 'empty'} id list.")
|
24
|
+
entry = { key => { } }
|
25
|
+
entry[key]["storage_type"] = storage_type if storage_type
|
26
|
+
@list.merge!(entry)
|
27
|
+
list_save
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns a hash of image ids registered from this instance.
|
31
|
+
# The keys are image ids, the values contain metadata
|
32
|
+
# (like "storage_type")
|
33
|
+
# Intended to be used in a loop. For Example:
|
34
|
+
# images = RightImage::IdList.new(Chef::Log).to_hash
|
35
|
+
# images.each do |id, params|
|
36
|
+
# ...
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
def to_hash
|
40
|
+
list_load
|
41
|
+
@log.info("Loaded #{(@list)?"existing":"empty"} id list.")
|
42
|
+
@list
|
43
|
+
end
|
44
|
+
|
45
|
+
# Wipes out the list by deleting the file.
|
46
|
+
#
|
47
|
+
def clear
|
48
|
+
if ::File.exists?(@file)
|
49
|
+
@log.info("Deleted id list file.")
|
50
|
+
::File.delete(@file)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def list_save
|
57
|
+
::File.open(@file, "w") { |f| f.write(@list.to_json) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def list_load
|
61
|
+
@list = { }
|
62
|
+
if ::File.exists?(@file)
|
63
|
+
json = nil
|
64
|
+
::File.open(@file, "r") { |f| json = f.read() }
|
65
|
+
@list = JSON.parse(json) if json
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
data/lib/mci.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'logger'
|
3
|
-
require 'ruby-debug'
|
3
|
+
#require 'ruby-debug'
|
4
4
|
require 'rest_connection'
|
5
5
|
|
6
6
|
module RightImageTools
|
@@ -55,12 +55,14 @@ module RightImageTools
|
|
55
55
|
def add_image_to_mci(options)
|
56
56
|
cloud_id = options[:cloud_id].to_i
|
57
57
|
image_id = options[:image_id]
|
58
|
-
mci_name = options[:name]
|
58
|
+
mci_name = options[:name] || options[:mci_name]
|
59
|
+
mci_id = options[:mci_id] || options[:id]
|
59
60
|
description = options[:description]
|
60
61
|
|
61
62
|
raise ArgumentError, ":cloud_id not supplied" unless cloud_id > 0
|
62
63
|
raise ArgumentError, ":image_id not supplied" unless image_id =~ /./
|
63
|
-
raise ArgumentError, "MCI name (:name) not supplied" unless mci_name =~ /./
|
64
|
+
raise ArgumentError, "MCI name (:name) or id (:mci_id) not supplied" unless (mci_name =~ /./ || mci_id =~ /^\d+$/)
|
65
|
+
raise ArgumentError, "MCI (:mci_id) supplied but an integer" if mci_id and mci_id !~ /^\d+$/
|
64
66
|
|
65
67
|
image_id = image_id.split("/").last
|
66
68
|
|
@@ -69,8 +71,9 @@ module RightImageTools
|
|
69
71
|
raise ArgumentError, "image_id #{image_id} doesn't look like an amazon ami"
|
70
72
|
end
|
71
73
|
end
|
72
|
-
|
73
|
-
mci =
|
74
|
+
|
75
|
+
mci = find_mci_by_id(cloud_id, mci_id) if mci_id
|
76
|
+
mci = find_mci(cloud_id, mci_name) unless mci
|
74
77
|
#validate_mci_name(mci_name) unless mci
|
75
78
|
mci = create_mci(cloud_id, mci_name, description) unless mci
|
76
79
|
add_rightlink_tag(mci)
|
@@ -135,6 +138,17 @@ module RightImageTools
|
|
135
138
|
end
|
136
139
|
|
137
140
|
# return MultiCloudImageInternal, or nil
|
141
|
+
def find_mci_by_id(cloud_id,mci_id)
|
142
|
+
if api_version(cloud_id) == "1.0"
|
143
|
+
existing_mci = MultiCloudImageInternal.find(mci_id.to_i)
|
144
|
+
else
|
145
|
+
existing_mci = McMultiCloudImage.find(mci_id.to_i)
|
146
|
+
end
|
147
|
+
raise ArgumentError, "Could not find #{existing_mci.rs_id}" unless existing_mci
|
148
|
+
@logger.info("Using mci #{existing_mci.rs_id} named #{existing_mci.name}")
|
149
|
+
existing_mci
|
150
|
+
end
|
151
|
+
|
138
152
|
def find_mci(cloud_id, mci_name)
|
139
153
|
mcis = []
|
140
154
|
if api_version(cloud_id) == "1.0"
|
data/lib/rightimage_tools.rb
CHANGED
@@ -3,3 +3,7 @@ module RightImageTools
|
|
3
3
|
end
|
4
4
|
|
5
5
|
require File.join(File.dirname(__FILE__), 'mci')
|
6
|
+
require File.join(File.dirname(__FILE__), 'id_list')
|
7
|
+
require File.join(File.dirname(__FILE__), 'util')
|
8
|
+
# command line tool
|
9
|
+
#require File.join(File.dirname(__FILE__), 's3_html_indexer')
|
@@ -0,0 +1,251 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'right_aws'
|
3
|
+
|
4
|
+
module RightImageTools
|
5
|
+
|
6
|
+
class S3HtmlIndexer
|
7
|
+
|
8
|
+
def initialize(bucket, id=nil, key=nil)
|
9
|
+
@s3 = RightAws::S3.new(id, key)
|
10
|
+
@dev_bucket = bucket.downcase.include?("dev")
|
11
|
+
@bucket = @s3.bucket(bucket)
|
12
|
+
@keys = @bucket.keys
|
13
|
+
@auto_hash = Hash.new{ |h,k| h[k] = Hash.new &h.default_proc }
|
14
|
+
end
|
15
|
+
|
16
|
+
def ver(key)
|
17
|
+
key.match(/v[0-9]+\.[0-9]+\.[0-9]+/).to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_html(filename)
|
21
|
+
# Create hash hierarchy from bucket list
|
22
|
+
@keys.reject! { |path| path.full_name =~ /index.html/ }
|
23
|
+
#@keys.sort! {|x,y| ver(x.full_name) <=> ver(y.full_name) } #TODO: sort by rightlink version
|
24
|
+
@keys.each do |path|
|
25
|
+
|
26
|
+
next unless is_public?(path)
|
27
|
+
|
28
|
+
sub = @auto_hash
|
29
|
+
path.full_name.split( "/" ).each do |dir|
|
30
|
+
sub = sub[dir]
|
31
|
+
end
|
32
|
+
|
33
|
+
sub[:link] = fix_public_endpoint(path.public_link)
|
34
|
+
sub[:size] = path.size
|
35
|
+
sub[:date] = path.last_modified.strftime("%m/%d/%Y")
|
36
|
+
sub[:md5sum] = path.e_tag.gsub(/\"/, "")
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
# make a non-auto hash copy
|
41
|
+
dirs = Hash.new
|
42
|
+
dirs = dirs.merge(@auto_hash)
|
43
|
+
|
44
|
+
# visualize hierarchy
|
45
|
+
dirs.each do |k,v|
|
46
|
+
@file = File.open(filename, "w")
|
47
|
+
output("<html>")
|
48
|
+
add_style
|
49
|
+
display_dirs(k,v)
|
50
|
+
output("</html>")
|
51
|
+
@file.close
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def upload_index(filename)
|
56
|
+
@bucket.put("index.html", File.open(filename), {}, 'public-read')
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def is_public?(key)
|
62
|
+
key.refresh
|
63
|
+
puts "Key: #{key.name}"
|
64
|
+
key.grantees.each do |g|
|
65
|
+
puts "grantee:#{g.name} perms:#{g.perms}"
|
66
|
+
if g.name.to_s == "AllUsers" && g.perms.to_s == "READ"
|
67
|
+
puts "Is public!!!"
|
68
|
+
return true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
false
|
72
|
+
end
|
73
|
+
|
74
|
+
def display_dirs(k,v,level=0)
|
75
|
+
return unless v
|
76
|
+
unless v.keys.include?(:link)
|
77
|
+
add_header(k, level)
|
78
|
+
v.sort_by {|k2, v2| k2}.each do |k2, v2|
|
79
|
+
display_dirs(k2, v2, level+1)
|
80
|
+
end
|
81
|
+
add_footer(k, level)
|
82
|
+
else
|
83
|
+
output("<tr class='code'>")
|
84
|
+
output("<td><a href='#{v[:link]}'>#{k}</a></td>")
|
85
|
+
output("<td>#{v[:size].to_i/(1024*1024)}MB</td>")
|
86
|
+
output("<td>#{v[:date]}</td>")
|
87
|
+
output("<td>#{v[:md5sum]}</td>")
|
88
|
+
output("</tr>")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def disclaimer
|
93
|
+
if @dev_bucket
|
94
|
+
"The following RightImages are currently in RightScale development and testing. They are not supported by RightScale. For RightImages that RightScale supports, please see our <a href='http://rightscale-cloudstack.s3-website-us-west-1.amazonaws.com/index.html'>production images</a>"
|
95
|
+
else
|
96
|
+
"The following RightImages are tested and supported by RightScale for general use. For further information regarding use of these images with RightScale, please contact your RightScale account manager or sign up for an account at <a href='http://www.rightscale.com'>www.rightscale.com</a>."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def add_header(str, level)
|
101
|
+
case level
|
102
|
+
when 0
|
103
|
+
# bucket name
|
104
|
+
output("<div id='header'><img alt='Embedded Image' width='140' height='19' src='#{encoded_logo}' /></div>")
|
105
|
+
output("<div class='bucket common'>#{str.gsub(/rightscale-/,"").upcase}")
|
106
|
+
output("<br/><br/>")
|
107
|
+
output("<div class='disclaimer code common'>#{disclaimer}</div>")
|
108
|
+
output("<br/>")
|
109
|
+
output("</div>")
|
110
|
+
when 1
|
111
|
+
# Hypervisor
|
112
|
+
output("<div class='hypervisor common'>")
|
113
|
+
output("<h#{level-1}>#{str.upcase} Hypervisor</h#{level-1}>\n")
|
114
|
+
output("</div>")
|
115
|
+
output("<div class='platform common'>")
|
116
|
+
output("<table style='padding:none; size:90%'>")
|
117
|
+
output("<tr style='border: solid 1px black;'>")
|
118
|
+
output("<th style='text-align:left'>Image</th>")
|
119
|
+
output("<th>Size</th>")
|
120
|
+
output("<th>Date</th>")
|
121
|
+
output("<th>MD5</th>")
|
122
|
+
output("</tr>")
|
123
|
+
when 2
|
124
|
+
return
|
125
|
+
# OS
|
126
|
+
when 3
|
127
|
+
return
|
128
|
+
else
|
129
|
+
# image
|
130
|
+
# output("<div class='platform'>")
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def add_footer(str, level)
|
135
|
+
case level
|
136
|
+
when 0
|
137
|
+
when 1
|
138
|
+
output("</table>")
|
139
|
+
output("</div>")
|
140
|
+
output("<br/>")
|
141
|
+
output("</div>")
|
142
|
+
output("<br/><br/>")
|
143
|
+
when 2
|
144
|
+
return
|
145
|
+
when 3
|
146
|
+
return
|
147
|
+
else
|
148
|
+
# output("</div>")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# https://s3.amazonaws.com/rightscale-cloudstack/foo
|
153
|
+
# to
|
154
|
+
# https://rightscale-cloudstack.s3.amazonaws.com
|
155
|
+
def fix_public_endpoint(link)
|
156
|
+
link_ary = link.split("/")
|
157
|
+
bucket = link_ary[3]
|
158
|
+
host = link_ary[2]
|
159
|
+
link_ary[2] = "#{bucket}.#{host}"
|
160
|
+
link_ary.delete_at(3)
|
161
|
+
link_ary.join("/")
|
162
|
+
end
|
163
|
+
|
164
|
+
def output(str)
|
165
|
+
@file.write "#{str}\n" if @file
|
166
|
+
p str
|
167
|
+
end
|
168
|
+
|
169
|
+
def add_style
|
170
|
+
output "<style>"
|
171
|
+
output( "body {min-width: 600px; margin:0; padding:0; font-size:70.5%; /* font-family:'Lucida Sans', Verdana, Arial, sans-serif; */ font-family:'Lucida Grande','Lucida Sans Unicode','Lucida Sans',Verdana,lucida,sans-serif; background:#FFF; height:100%}
|
172
|
+
html {height:100%}
|
173
|
+
a img {border:none}
|
174
|
+
a {color:#1e4a7e}
|
175
|
+
table { width:90% }
|
176
|
+
th { text-align:center }
|
177
|
+
|
178
|
+
#header {
|
179
|
+
background:#235186;
|
180
|
+
padding:2px 20px;
|
181
|
+
position:relative;
|
182
|
+
height:25px;
|
183
|
+
}
|
184
|
+
|
185
|
+
#header #logo {
|
186
|
+
margin-top:3px;
|
187
|
+
}
|
188
|
+
|
189
|
+
.common {
|
190
|
+
font-size: 16px;
|
191
|
+
margin-left:auto;
|
192
|
+
margin-right:auto;
|
193
|
+
font-weight: bold;
|
194
|
+
padding:2px 20px;
|
195
|
+
position:relative;
|
196
|
+
}
|
197
|
+
|
198
|
+
.bucket {
|
199
|
+
font-size: 24px;
|
200
|
+
color: #F5F2A9;
|
201
|
+
background:#235186;
|
202
|
+
padding:10px 30px 20px;
|
203
|
+
}
|
204
|
+
|
205
|
+
.version {
|
206
|
+
color: #F5F2A9;
|
207
|
+
background:#235186;
|
208
|
+
}
|
209
|
+
|
210
|
+
.hypervisor {
|
211
|
+
color: #235186;
|
212
|
+
background:#F5F2A9;
|
213
|
+
}
|
214
|
+
|
215
|
+
.platform {
|
216
|
+
background: #FFFFFF;
|
217
|
+
width:90%;
|
218
|
+
margin-left: auto ;
|
219
|
+
margin-right: auto ;
|
220
|
+
position: relative;
|
221
|
+
}
|
222
|
+
|
223
|
+
.disclaimer {
|
224
|
+
background: #FFFFFF;
|
225
|
+
width:90%;
|
226
|
+
margin-left: auto ;
|
227
|
+
margin-right: auto ;
|
228
|
+
position: relative;
|
229
|
+
border: 2px solid black;
|
230
|
+
font-weight: normal;
|
231
|
+
}
|
232
|
+
|
233
|
+
.code {
|
234
|
+
font-family:'Courier New', monospace;
|
235
|
+
color: #000000;
|
236
|
+
position:relative;
|
237
|
+
left:10px;
|
238
|
+
}
|
239
|
+
")
|
240
|
+
output "</style>"
|
241
|
+
end
|
242
|
+
|
243
|
+
def encoded_logo
|
244
|
+
"data:image/png;base64,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%3D%3D"
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
|
251
|
+
|
data/lib/util.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module RightImage
|
2
|
+
|
3
|
+
RELEASE_LEVELS = ["Alpha", "Beta", "Ga"]
|
4
|
+
HIDDEN_RELEASE_LEVELS = [ "Ga" ]
|
5
|
+
|
6
|
+
class Util
|
7
|
+
|
8
|
+
def self.create_image_name(image_prefix, os_name, os_version, os_arch, os_modifier, right_image_version, right_image_build = nil, image_build_number = nil, storage_type = nil, release_level = nil, suffix = nil)
|
9
|
+
|
10
|
+
image_name = "#{image_prefix}_#{os_name}_#{os_version.to_s}_#{os_arch}"
|
11
|
+
|
12
|
+
unless os_modifier.nil? || os_modifier.empty?
|
13
|
+
image_name << "_#{os_modifier}"
|
14
|
+
end
|
15
|
+
|
16
|
+
package_version = rightimage_version(right_image_version, right_image_build, image_build_number)
|
17
|
+
image_name << "_v#{package_version}"
|
18
|
+
image_name << "_#{storage_type}" if storage_type && storage_type.downcase != "s3"
|
19
|
+
|
20
|
+
if release_level
|
21
|
+
level = release_level.capitalize
|
22
|
+
raise "ERROR: release_level must be set to 'Alpha', 'GA', or 'Beta'" unless RELEASE_LEVELS.include?(level)
|
23
|
+
image_name << "_#{level}" unless HIDDEN_RELEASE_LEVELS.include?(level)
|
24
|
+
end
|
25
|
+
|
26
|
+
image_name << "_#{suffix.capitalize}" if suffix
|
27
|
+
|
28
|
+
image_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.rightimage_package_version(version, build_number=nil)
|
32
|
+
raise "ERROR: version must be a 'N.N' format." unless version.to_s =~ /^[0-9]*\.[0-9]*$/
|
33
|
+
ver = "#{version.to_s}"
|
34
|
+
ver << ".#{build_number}" if build_number
|
35
|
+
ver
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.rightimage_version(package_version, package_build=nil, image_build = nil)
|
39
|
+
ver = rightimage_package_version(package_version, package_build)
|
40
|
+
ver << ".#{image_build}" unless image_build == 0 || image_build == nil
|
41
|
+
ver
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.create_mci_name(image_prefix, os_name, os_version, os_arch, os_modifier, right_image_version, storage_type = nil, release_level = nil, suffix = nil)
|
45
|
+
create_image_name(image_prefix, os_name, os_version, os_arch, os_modifier, right_image_version, nil, nil, storage_type, release_level, suffix)
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rightimage_tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Peter Schroeter
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-02-
|
18
|
+
date: 2012-02-27 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: "0"
|
44
44
|
requirement: *id002
|
45
45
|
prerelease: false
|
46
|
-
name:
|
46
|
+
name: right_aws
|
47
47
|
type: :runtime
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
version_requirements: &id003 !ruby/object:Gem::Requirement
|
@@ -123,26 +123,29 @@ dependencies:
|
|
123
123
|
type: :development
|
124
124
|
description: A set of tools to support the building of RightImages
|
125
125
|
email: peter.schroeter@rightscale.com
|
126
|
-
executables:
|
127
|
-
|
126
|
+
executables:
|
127
|
+
- image_mover
|
128
|
+
- mci_merge
|
129
|
+
- update_s3_index
|
128
130
|
extensions: []
|
129
131
|
|
130
132
|
extra_rdoc_files:
|
131
133
|
- LICENSE.txt
|
132
134
|
- README.rdoc
|
133
135
|
files:
|
134
|
-
- .document
|
135
|
-
- .rspec
|
136
136
|
- Gemfile
|
137
|
-
- Gemfile.lock
|
138
137
|
- LICENSE.txt
|
139
138
|
- README.rdoc
|
140
139
|
- Rakefile
|
141
140
|
- VERSION
|
141
|
+
- bin/image_mover
|
142
|
+
- bin/mci_merge
|
143
|
+
- bin/update_s3_index
|
144
|
+
- lib/id_list.rb
|
142
145
|
- lib/mci.rb
|
143
146
|
- lib/rightimage_tools.rb
|
144
|
-
-
|
145
|
-
-
|
147
|
+
- lib/s3_html_indexer.rb
|
148
|
+
- lib/util.rb
|
146
149
|
homepage: http://github.com/rightscale/rightimage_tools
|
147
150
|
licenses:
|
148
151
|
- MIT
|
data/.document
DELETED
data/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--color
|
data/Gemfile.lock
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: http://rubygems.org/
|
3
|
-
specs:
|
4
|
-
activesupport (2.3.10)
|
5
|
-
columnize (0.3.4)
|
6
|
-
diff-lcs (1.1.3)
|
7
|
-
flexmock (0.9.0)
|
8
|
-
git (1.2.5)
|
9
|
-
highline (1.6.2)
|
10
|
-
jeweler (1.6.4)
|
11
|
-
bundler (~> 1.0)
|
12
|
-
git (>= 1.2.5)
|
13
|
-
rake
|
14
|
-
json (1.6.1)
|
15
|
-
linecache (0.46)
|
16
|
-
rbx-require-relative (> 0.0.4)
|
17
|
-
net-ssh (2.1.4)
|
18
|
-
rake (0.9.2.2)
|
19
|
-
rbx-require-relative (0.0.5)
|
20
|
-
rcov (1.0.0)
|
21
|
-
rest_connection (0.1.2)
|
22
|
-
activesupport (= 2.3.10)
|
23
|
-
highline
|
24
|
-
json
|
25
|
-
net-ssh (= 2.1.4)
|
26
|
-
rspec (2.3.0)
|
27
|
-
rspec-core (~> 2.3.0)
|
28
|
-
rspec-expectations (~> 2.3.0)
|
29
|
-
rspec-mocks (~> 2.3.0)
|
30
|
-
rspec-core (2.3.1)
|
31
|
-
rspec-expectations (2.3.0)
|
32
|
-
diff-lcs (~> 1.1.2)
|
33
|
-
rspec-mocks (2.3.0)
|
34
|
-
ruby-debug (0.10.4)
|
35
|
-
columnize (>= 0.1)
|
36
|
-
ruby-debug-base (~> 0.10.4.0)
|
37
|
-
ruby-debug-base (0.10.4)
|
38
|
-
linecache (>= 0.3)
|
39
|
-
|
40
|
-
PLATFORMS
|
41
|
-
ruby
|
42
|
-
|
43
|
-
DEPENDENCIES
|
44
|
-
bundler (~> 1.0.0)
|
45
|
-
flexmock
|
46
|
-
jeweler (~> 1.6.4)
|
47
|
-
rcov
|
48
|
-
rest_connection
|
49
|
-
rspec (~> 2.3.0)
|
50
|
-
ruby-debug
|
data/spec/mci_spec.rb
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
require 'flexmock/rspec'
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
-
|
4
|
-
describe RightImageTools::MCI do
|
5
|
-
|
6
|
-
before :each do
|
7
|
-
@mci = RightImageTools::MCI.new
|
8
|
-
|
9
|
-
@mock_mci_name = "Mock_RightImage_Ubuntu_10.04_x64_v5.7"
|
10
|
-
@mock_ami = "ami-2ehahaha"
|
11
|
-
|
12
|
-
@mock_mci = flexmock(MultiCloudImage,
|
13
|
-
:is_head_version => true,
|
14
|
-
:name => @mock_mci_name,
|
15
|
-
:rs_id => "10000",
|
16
|
-
:version=>0,
|
17
|
-
:href=>"https://my.rightscale.com/api/acct/99999/multi_cloud_images/10000")
|
18
|
-
|
19
|
-
@mock_mci_setting1 = flexmock(MultiCloudImageCloudSettingInternal,
|
20
|
-
:href=>"https://my.rightscale.com/api/acct/99999/multi_cloud_image_cloud_settings/20000",
|
21
|
-
:aws_instance_type =>"m1.large",
|
22
|
-
:image_name => @mock_mci_name,
|
23
|
-
:image_href => "https://my.rightscale.com/api/acct/0/ec2_images/#{@mock_ami}?cloud_id=5",
|
24
|
-
:cloud_id=>5,
|
25
|
-
:cloud=>"AWS AP-Tokyo")
|
26
|
-
|
27
|
-
@mock_mci_i = flexmock(MultiCloudImageInternal,
|
28
|
-
:is_head_version => @mock_mci.is_head_version,
|
29
|
-
:name=>@mock_mci.name,
|
30
|
-
:rs_id => @mock_mci.rs_id,
|
31
|
-
:version=>@mock_mci.version,
|
32
|
-
:href=>@mock_mci.href,
|
33
|
-
:multi_cloud_image_cloud_settings=>[@mock_mci_setting1])
|
34
|
-
end
|
35
|
-
|
36
|
-
# it "finds a MCI for gateway cloud (cloudstack)" do
|
37
|
-
# pending "TODO"
|
38
|
-
# end
|
39
|
-
# it "creates a MCI for gateway cloud (cloudstack)" do
|
40
|
-
# pending "TODO"
|
41
|
-
# end
|
42
|
-
# it "associates an image for a gateway cloud (cloudstack)" do
|
43
|
-
# pending "TODO"
|
44
|
-
# end
|
45
|
-
# it "replaces an image association for a gateway cloud (cloudstack)" do
|
46
|
-
# pending "TODO"
|
47
|
-
# end
|
48
|
-
#
|
49
|
-
it "finds a MCI for EC2 cloud" do
|
50
|
-
flexmock(MultiCloudImage).should_receive(:find_all).and_return([@mock_mci])
|
51
|
-
flexmock(MultiCloudImageInternal).should_receive(:find).with(10000).and_return(@mock_mci_i)
|
52
|
-
|
53
|
-
@mci.find_mci(6, @mock_mci_name).rs_id.should == "10000"
|
54
|
-
end
|
55
|
-
it "creates a MCI for EC2 mock cloud" do
|
56
|
-
flexmock(MultiCloudImageInternal).should_receive(:create).with(
|
57
|
-
:name=>@mock_mci_name,
|
58
|
-
:description => "blah"
|
59
|
-
).and_return(flexmock(MultiCloudImageInternal))
|
60
|
-
@mci.create_mci(6, @mock_mci_name, "blah")
|
61
|
-
end
|
62
|
-
|
63
|
-
it "associates an image to an EC2 cloud" do
|
64
|
-
flexmock(MultiCloudImage).should_receive(:find_all).and_return([@mock_mci])
|
65
|
-
flexmock(MultiCloudImageInternal).should_receive(:find).with(10000).and_return(@mock_mci_i)
|
66
|
-
flexmock(Tag).should_receive(:set).and_return(flexmock(Tag, :code=>"204"))
|
67
|
-
flexmock(MultiCloudImageCloudSettingInternal).should_receive(:create)
|
68
|
-
|
69
|
-
@mci.add_image_to_mci(
|
70
|
-
:cloud_id=>6,
|
71
|
-
:name=>@mock_mci_name,
|
72
|
-
:image_id=>"ami-b1ahb1ah")
|
73
|
-
end
|
74
|
-
|
75
|
-
it "replaces an image association for an EC2 cloud" do
|
76
|
-
flexmock(MultiCloudImage).should_receive(:find_all).and_return([@mock_mci])
|
77
|
-
flexmock(MultiCloudImageInternal).should_receive(:find).with(10000).and_return(@mock_mci_i)
|
78
|
-
flexmock(Tag).should_receive(:set).and_return(flexmock(Tag, :code=>"204"))
|
79
|
-
flexmock(MultiCloudImageCloudSettingInternal).should_receive(:destroy).and_return(flexmock("Response",:code=>"200"))
|
80
|
-
flexmock(MultiCloudImageCloudSettingInternal).should_receive(:create)
|
81
|
-
|
82
|
-
@mci.add_image_to_mci(
|
83
|
-
:cloud_id=>5,
|
84
|
-
:name=>@mock_mci_name,
|
85
|
-
:image_id=>"ami-b1ahb1ah")
|
86
|
-
end
|
87
|
-
|
88
|
-
it "sets a default description correctly" do
|
89
|
-
flexmock(MultiCloudImageInternal).should_receive(:create).with(
|
90
|
-
:name=>@mock_mci_name,
|
91
|
-
:description => "Development build: Ubuntu 10.04 with 64-bit architecture (x64) and RightLink 5.7."
|
92
|
-
).and_return(@mock_mci)
|
93
|
-
|
94
|
-
@mci.create_mci(5, @mock_mci_name)
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
-
require 'rspec'
|
4
|
-
require 'rightimage_tools'
|
5
|
-
|
6
|
-
|
7
|
-
# Requires supporting files with custom matchers and macros, etc,
|
8
|
-
# in ./support/ and its subdirectories.
|
9
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
10
|
-
|
11
|
-
RSpec.configure do |config|
|
12
|
-
config.mock_with :flexmock
|
13
|
-
end
|