torpedo 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +16 -0
- data/LICENSE.txt +20 -0
- data/README.md +69 -0
- data/Rakefile +58 -0
- data/VERSION +1 -0
- data/bin/torpedo +11 -0
- data/lib/torpedo/compute/flavors.rb +34 -0
- data/lib/torpedo/compute/helper.rb +41 -0
- data/lib/torpedo/compute/images.rb +35 -0
- data/lib/torpedo/compute/limits.rb +19 -0
- data/lib/torpedo/compute/servers.rb +351 -0
- data/lib/torpedo/config.rb +39 -0
- data/lib/torpedo.rb +63 -0
- data/test/helper.rb +18 -0
- data/test/test_torpedo.rb +7 -0
- data/torpedo.gemspec +68 -0
- metadata +146 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "bundler", "~> 1.0.0"
|
10
|
+
gem "jeweler", "~> 1.6.4"
|
11
|
+
end
|
data/Gemfile.lock
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Dan Prince
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
Torpedo
|
2
|
+
=======
|
3
|
+
|
4
|
+
Description
|
5
|
+
-----------
|
6
|
+
|
7
|
+
Sink bad code! Ruby Smoke Tests for the OpenStack.
|
8
|
+
|
9
|
+
Installation
|
10
|
+
------------
|
11
|
+
|
12
|
+
gem install torpedo
|
13
|
+
|
14
|
+
#create the torpedo YAML config in your $HOME dir:
|
15
|
+
cat > ~/.torpedo.conf <<"EOF_CAT"
|
16
|
+
# YAML config file for torpedo
|
17
|
+
|
18
|
+
# SERVER test settings
|
19
|
+
test_create_image: false
|
20
|
+
test_rebuild_server: false
|
21
|
+
test_resize_server: false
|
22
|
+
|
23
|
+
# IMAGES (Set one of the following)
|
24
|
+
#image_name:
|
25
|
+
#image_ref:
|
26
|
+
|
27
|
+
# TIMEOUTS
|
28
|
+
#ping_timeout: 60
|
29
|
+
#ssh_timeout: 30
|
30
|
+
|
31
|
+
# SSH KEYS (used to verify images which use an agent)
|
32
|
+
#ssh_private_key:
|
33
|
+
#ssh_public_key:
|
34
|
+
|
35
|
+
# KEYPAIRS (used to verify AMI style images)
|
36
|
+
keypair: test.pem
|
37
|
+
keyname: test
|
38
|
+
EOF_CAT
|
39
|
+
|
40
|
+
|
41
|
+
Examples
|
42
|
+
--------
|
43
|
+
|
44
|
+
Available torpedo tasks:
|
45
|
+
|
46
|
+
Tasks:
|
47
|
+
torpedo all # Run all tests.
|
48
|
+
torpedo fire # Fire away! (alias for all)
|
49
|
+
torpedo flavors # Run flavors tests for the OSAPI.
|
50
|
+
torpedo help [TASK] # Describe available tasks or one specific task
|
51
|
+
torpedo images # Run images tests for the OSAPI.
|
52
|
+
torpedo limits # Run limits tests for the OSAPI.
|
53
|
+
torpedo servers # Run servers tests for the OSAPI.
|
54
|
+
|
55
|
+
Run all tests:
|
56
|
+
|
57
|
+
torpedo fire
|
58
|
+
|
59
|
+
Run all tests with debug HTTP request response output:
|
60
|
+
|
61
|
+
DEBUG=true torpedo fire
|
62
|
+
|
63
|
+
Run all tests and output an Xunit style XML report:
|
64
|
+
|
65
|
+
torpedo fire --xml-report=FILE
|
66
|
+
|
67
|
+
License
|
68
|
+
-------
|
69
|
+
Copyright (c) 2011 Dan Prince. See LICENSE.txt for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "torpedo"
|
18
|
+
gem.executables = "torpedo"
|
19
|
+
gem.homepage = "http://github.com/dprince/torpedo"
|
20
|
+
gem.license = "MIT"
|
21
|
+
gem.summary = %Q{Sink bad code! Ruby Smoke Tests for OpenStack.}
|
22
|
+
gem.description = %Q{CLI to run functional smoke tests for OpenStack.}
|
23
|
+
gem.email = "dan.prince@rackspace.com"
|
24
|
+
gem.authors = ["Dan Prince"]
|
25
|
+
# dependencies defined in Gemfile
|
26
|
+
gem.add_dependency 'thor'
|
27
|
+
gem.add_dependency 'openstack-compute', '>= 1.1.4'
|
28
|
+
end
|
29
|
+
Jeweler::RubygemsDotOrgTasks.new
|
30
|
+
|
31
|
+
require 'rake/testtask'
|
32
|
+
Rake::TestTask.new(:test) do |test|
|
33
|
+
#test.libs << 'lib' << 'test'
|
34
|
+
test.pattern = 'test/**/test_*.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
|
38
|
+
=begin
|
39
|
+
require 'rcov/rcovtask'
|
40
|
+
Rcov::RcovTask.new do |test|
|
41
|
+
test.libs << 'test'
|
42
|
+
test.pattern = 'test/**/test_*.rb'
|
43
|
+
test.verbose = true
|
44
|
+
test.rcov_opts << '--exclude "gems/*"'
|
45
|
+
end
|
46
|
+
=end
|
47
|
+
|
48
|
+
task :default => :test
|
49
|
+
|
50
|
+
require 'rake/rdoctask'
|
51
|
+
Rake::RDocTask.new do |rdoc|
|
52
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
53
|
+
|
54
|
+
rdoc.rdoc_dir = 'rdoc'
|
55
|
+
rdoc.title = "torpedo #{version}"
|
56
|
+
rdoc.rdoc_files.include('README*')
|
57
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
58
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/bin/torpedo
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
module Torpedo
|
4
|
+
module Compute
|
5
|
+
class Flavors < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@conn=Helper::get_connection
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_list
|
12
|
+
|
13
|
+
@conn.flavors.each do |flavor|
|
14
|
+
assert_not_nil(flavor[:id])
|
15
|
+
assert_not_nil(flavor[:name])
|
16
|
+
assert_not_nil(flavor[:ram])
|
17
|
+
assert_not_nil(flavor[:disk])
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_get
|
23
|
+
|
24
|
+
flavor = @conn.flavor(1)
|
25
|
+
assert_not_nil(flavor.id)
|
26
|
+
assert_not_nil(flavor.name)
|
27
|
+
assert_not_nil(flavor.ram)
|
28
|
+
assert_not_nil(flavor.disk)
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'test-unit-ext'
|
2
|
+
require 'test/unit'
|
3
|
+
gem 'openstack-compute', OPENSTACK_COMPUTE_VERSION
|
4
|
+
require 'openstack/compute'
|
5
|
+
|
6
|
+
module Torpedo
|
7
|
+
module Compute
|
8
|
+
module Helper
|
9
|
+
|
10
|
+
def self.get_connection
|
11
|
+
debug = false
|
12
|
+
if ENV['DEBUG'] and ENV['DEBUG'] == 'true' then
|
13
|
+
debug = true
|
14
|
+
end
|
15
|
+
OpenStack::Compute::Connection.new(:username => USERNAME, :api_key => API_KEY, :auth_url => API_URL, :is_debug => debug)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.get_image_ref(conn)
|
19
|
+
|
20
|
+
image_ref = ENV['IMAGE_REF']
|
21
|
+
image_name = ENV['IMAGE_NAME']
|
22
|
+
|
23
|
+
if image_name and not image_name.empty? then
|
24
|
+
images = conn.images.each do |image|
|
25
|
+
if image[:name] == image_name then
|
26
|
+
image_ref = image[:id]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
elsif image_ref.nil? or image_ref.empty? then
|
30
|
+
#take the last image if IMAGE_REF and or IMAGE_NAME aren't set
|
31
|
+
images = conn.images.sort{|x,y| x[:id] <=> y[:id]}
|
32
|
+
image_ref = images.last[:id].to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
image_ref
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
module Torpedo
|
4
|
+
module Compute
|
5
|
+
class Images < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@conn=Helper::get_connection
|
9
|
+
@image_id = Helper::get_image_ref(@conn)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_list
|
13
|
+
|
14
|
+
@conn.images.each do |image|
|
15
|
+
assert_not_nil(image[:id])
|
16
|
+
assert_not_nil(image[:name])
|
17
|
+
assert_equal("ACTIVE", image[:status])
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_get
|
23
|
+
|
24
|
+
image=@conn.image(@image_id)
|
25
|
+
assert_equal(@image_id, image.id.to_s)
|
26
|
+
assert_not_nil(image.name)
|
27
|
+
assert_not_nil(image.updated)
|
28
|
+
assert_not_nil(image.created)
|
29
|
+
assert_not_nil(image.status)
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
module Torpedo
|
4
|
+
module Compute
|
5
|
+
class Limits < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@conn=Helper::get_connection
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_list
|
12
|
+
|
13
|
+
assert_not_nil @conn.limits
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,351 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module Torpedo
|
5
|
+
module Compute
|
6
|
+
class Servers < Test::Unit::TestCase
|
7
|
+
|
8
|
+
@@servers = []
|
9
|
+
@@images = []
|
10
|
+
@@image_ref = Helper::get_image_ref(Helper::get_connection)
|
11
|
+
@@server = nil #ref to last created server
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@conn=Helper::get_connection
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_server(server_opts)
|
18
|
+
@@server = @conn.create_server(server_opts)
|
19
|
+
@@servers << @@server
|
20
|
+
@@server
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_image(server, image_opts)
|
24
|
+
image = server.create_image(image_opts)
|
25
|
+
@@images << image
|
26
|
+
@@image_ref = image.id
|
27
|
+
image
|
28
|
+
end
|
29
|
+
|
30
|
+
def ssh_test(ip_addr)
|
31
|
+
begin
|
32
|
+
Timeout::timeout(SSH_TIMEOUT) do
|
33
|
+
|
34
|
+
while(1) do
|
35
|
+
ssh_identity=SSH_PRIVATE_KEY
|
36
|
+
if KEYPAIR and not KEYPAIR.empty? then
|
37
|
+
ssh_identity=KEYPAIR
|
38
|
+
end
|
39
|
+
if system("ssh -o StrictHostKeyChecking=no -i #{ssh_identity} root@#{ip_addr} /bin/true > /dev/null 2>&1") then
|
40
|
+
return true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
rescue Timeout::Error => te
|
46
|
+
fail("Timeout trying to ssh to server: #{ip_addr}")
|
47
|
+
end
|
48
|
+
|
49
|
+
return false
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def ping_test(ip_addr)
|
54
|
+
begin
|
55
|
+
Timeout::timeout(PING_TIMEOUT) do
|
56
|
+
|
57
|
+
while(1) do
|
58
|
+
if system("ping -c 1 #{ip_addr} > /dev/null 2>&1") then
|
59
|
+
return true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
rescue Timeout::Error => te
|
65
|
+
fail("Timeout pinging server: #{ip_addr}")
|
66
|
+
end
|
67
|
+
|
68
|
+
return false
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
def check_server(server, image_ref, flavor_ref, check_status="ACTIVE")
|
73
|
+
|
74
|
+
assert_not_nil(server.hostId)
|
75
|
+
assert_equal(flavor_ref.to_s, server.flavor['id'])
|
76
|
+
assert_equal(image_ref.to_s, server.image['id'])
|
77
|
+
assert_equal('test1', server.name)
|
78
|
+
server = @conn.server(server.id)
|
79
|
+
|
80
|
+
begin
|
81
|
+
timeout(SERVER_BUILD_TIMEOUT) do
|
82
|
+
until server.status == check_status do
|
83
|
+
if server.status == "ERROR" then
|
84
|
+
fail('Server ERROR state detected when booting instance!')
|
85
|
+
end
|
86
|
+
server = @conn.server(server.id)
|
87
|
+
sleep 1
|
88
|
+
end
|
89
|
+
end
|
90
|
+
rescue Timeout::Error => te
|
91
|
+
fail('Timeout creating server.')
|
92
|
+
end
|
93
|
+
|
94
|
+
# lookup the first IPv4 address and use that for verification
|
95
|
+
v4_addresses = server.addresses[:public].reject {|addr| addr.version != 4}
|
96
|
+
ping_test(v4_addresses[0].address)
|
97
|
+
ssh_test(v4_addresses[0].address)
|
98
|
+
|
99
|
+
server
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_001_create_server
|
104
|
+
|
105
|
+
# NOTE: When using AMI style images we rely on keypairs for SSH access.
|
106
|
+
|
107
|
+
# NOTE: injecting two or more files doesn't work for now due to XenStore
|
108
|
+
# limitations
|
109
|
+
personalities={SSH_PUBLIC_KEY => "/root/.ssh/authorized_keys"}
|
110
|
+
metadata={ "key1" => "value1", "key2" => "value2" }
|
111
|
+
options = {:name => "test1", :imageRef => @@image_ref, :flavorRef => 2, :personality => personalities, :metadata => metadata}
|
112
|
+
if KEYNAME and not KEYNAME.empty? then
|
113
|
+
options[:key_name] = KEYNAME
|
114
|
+
end
|
115
|
+
server = create_server(options)
|
116
|
+
assert_not_nil(@@server.adminPass)
|
117
|
+
|
118
|
+
#boot an instance and check it
|
119
|
+
check_server(server, @@image_ref, 2)
|
120
|
+
|
121
|
+
assert_equal "value1", @@server.metadata['key1']
|
122
|
+
assert_equal "value2", @@server.metadata['key2']
|
123
|
+
assert_equal 2, @@server.metadata.size
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_002_delete_server_metadata_items
|
128
|
+
|
129
|
+
metadata = @@server.metadata
|
130
|
+
metadata.each_pair do |key, value|
|
131
|
+
assert metadata.delete!(key)
|
132
|
+
end
|
133
|
+
|
134
|
+
metadata.refresh
|
135
|
+
|
136
|
+
assert_equal 0, metadata.size
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_003_update_one_server_metadata_item
|
141
|
+
|
142
|
+
metadata = @@server.metadata
|
143
|
+
metadata['foo1'] = 'bar1'
|
144
|
+
assert metadata.update('foo1')
|
145
|
+
|
146
|
+
metadata.refresh
|
147
|
+
|
148
|
+
assert_equal 'bar1', metadata['foo1']
|
149
|
+
|
150
|
+
assert_equal 1, metadata.size
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_004_update_some_server_metadata_items
|
155
|
+
|
156
|
+
metadata = @@server.metadata
|
157
|
+
metadata['foo1'] = 'bar1'
|
158
|
+
metadata['foo2'] = 'bar2'
|
159
|
+
assert metadata.update(['foo1','foo2'])
|
160
|
+
|
161
|
+
metadata.refresh
|
162
|
+
|
163
|
+
assert_equal 'bar1', metadata['foo1']
|
164
|
+
assert_equal 'bar2', metadata['foo2']
|
165
|
+
|
166
|
+
assert_equal 2, metadata.size
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_005_set_server_metadata_items
|
171
|
+
|
172
|
+
metadata = @@server.metadata
|
173
|
+
metadata['foo1'] = 'better'
|
174
|
+
metadata['foo2'] = 'watch'
|
175
|
+
metadata['foo3'] = 'out!'
|
176
|
+
assert metadata.save
|
177
|
+
|
178
|
+
metadata.refresh
|
179
|
+
|
180
|
+
assert_equal 'better', metadata['foo1']
|
181
|
+
assert_equal 'watch', metadata['foo2']
|
182
|
+
assert_equal 'out!', metadata['foo3']
|
183
|
+
|
184
|
+
assert_equal 3, metadata.size
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_006_clear_server_metadata
|
189
|
+
|
190
|
+
metadata = @@server.metadata
|
191
|
+
assert metadata.clear!
|
192
|
+
|
193
|
+
metadata.refresh
|
194
|
+
|
195
|
+
assert_equal 0, metadata.size
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_020_create_image
|
200
|
+
|
201
|
+
#snapshot the image
|
202
|
+
image = create_image(@@server, :name => "My Backup", :metadata => {"key1" => "value1"})
|
203
|
+
assert_equal('SAVING', image.status)
|
204
|
+
assert_equal('My Backup', image.name)
|
205
|
+
assert_equal(25, image.progress)
|
206
|
+
#FIXME: server id should be a uuid string
|
207
|
+
assert_equal(@@server.id.to_s, image.server['id'])
|
208
|
+
assert_not_nil(image.created)
|
209
|
+
assert_not_nil(image.id)
|
210
|
+
assert_equal('value1', image.metadata['key1'])
|
211
|
+
|
212
|
+
begin
|
213
|
+
timeout(SERVER_BUILD_TIMEOUT) do
|
214
|
+
until image.status == 'ACTIVE' do
|
215
|
+
image = @conn.image(image.id)
|
216
|
+
sleep 1
|
217
|
+
end
|
218
|
+
end
|
219
|
+
rescue Timeout::Error => te
|
220
|
+
fail('Timeout creating image snapshot.')
|
221
|
+
end
|
222
|
+
|
223
|
+
# Overwrite image_ref to make all subsequent tests use this snapshot
|
224
|
+
@@image_ref = image.id.to_s
|
225
|
+
|
226
|
+
end if TEST_CREATE_IMAGE == "true"
|
227
|
+
|
228
|
+
def test_021_delete_image_metadata_items
|
229
|
+
|
230
|
+
metadata = @conn.image(@@image_ref).metadata
|
231
|
+
metadata.each_pair do |key, value|
|
232
|
+
assert metadata.delete!(key)
|
233
|
+
end
|
234
|
+
|
235
|
+
metadata.refresh
|
236
|
+
|
237
|
+
assert_equal 0, metadata.size
|
238
|
+
|
239
|
+
end if TEST_CREATE_IMAGE == "true"
|
240
|
+
|
241
|
+
def test_022_update_one_image_metadata_item
|
242
|
+
|
243
|
+
metadata = @conn.image(@@image_ref).metadata
|
244
|
+
metadata['foo1'] = 'bar1'
|
245
|
+
assert metadata.update('foo1')
|
246
|
+
|
247
|
+
metadata.refresh
|
248
|
+
|
249
|
+
assert_equal 'bar1', metadata['foo1']
|
250
|
+
|
251
|
+
assert_equal 1, metadata.size
|
252
|
+
|
253
|
+
end if TEST_CREATE_IMAGE == "true"
|
254
|
+
|
255
|
+
def test_023_update_some_image_metadata_items
|
256
|
+
|
257
|
+
metadata = @conn.image(@@image_ref).metadata
|
258
|
+
metadata['foo1'] = 'bar1'
|
259
|
+
metadata['foo2'] = 'bar2'
|
260
|
+
assert metadata.update(['foo1','foo2'])
|
261
|
+
|
262
|
+
metadata.refresh
|
263
|
+
|
264
|
+
assert_equal 'bar1', metadata['foo1']
|
265
|
+
assert_equal 'bar2', metadata['foo2']
|
266
|
+
|
267
|
+
assert_equal 2, metadata.size
|
268
|
+
|
269
|
+
end if TEST_CREATE_IMAGE == "true"
|
270
|
+
|
271
|
+
def test_024_set_image_metadata_items
|
272
|
+
|
273
|
+
metadata = @conn.image(@@image_ref).metadata
|
274
|
+
metadata['foo1'] = 'that'
|
275
|
+
metadata['foo2'] = 'silly'
|
276
|
+
metadata['foo3'] = 'rabbit'
|
277
|
+
assert metadata.save
|
278
|
+
|
279
|
+
metadata.refresh
|
280
|
+
|
281
|
+
assert_equal 'that', metadata['foo1']
|
282
|
+
assert_equal 'silly', metadata['foo2']
|
283
|
+
assert_equal 'rabbit', metadata['foo3']
|
284
|
+
|
285
|
+
assert_equal 3, metadata.size
|
286
|
+
|
287
|
+
end if TEST_CREATE_IMAGE == "true"
|
288
|
+
|
289
|
+
def test_025_clear_image_metadata
|
290
|
+
|
291
|
+
metadata = @conn.image(@@image_ref).metadata
|
292
|
+
assert metadata.clear!
|
293
|
+
|
294
|
+
metadata.refresh
|
295
|
+
|
296
|
+
assert_equal 0, metadata.size
|
297
|
+
|
298
|
+
end if TEST_CREATE_IMAGE == "true"
|
299
|
+
|
300
|
+
def test_030_rebuild_instance
|
301
|
+
# make sure our snapshot boots
|
302
|
+
personalities={SSH_PUBLIC_KEY => "/root/.ssh/authorized_keys"}
|
303
|
+
@@server.rebuild!(:imageRef => @@image_ref, :personality => personalities)
|
304
|
+
server = @conn.server(@@server.id)
|
305
|
+
sleep 15 # sleep a couple seconds until rebuild starts
|
306
|
+
check_server(server, @@image_ref, 2)
|
307
|
+
|
308
|
+
end if TEST_REBUILD_SERVER == "true"
|
309
|
+
|
310
|
+
def test_040_resize_instance
|
311
|
+
|
312
|
+
@@server.resize!(3)
|
313
|
+
server = @conn.server(@@server.id)
|
314
|
+
assert_equal('RESIZE', @@server.status)
|
315
|
+
|
316
|
+
begin
|
317
|
+
timeout(SERVER_BUILD_TIMEOUT) do
|
318
|
+
until server.status == 'VERIFY_RESIZE' do
|
319
|
+
if server.status == "ERROR" then
|
320
|
+
fail('Server ERROR state detected when resizing instance!')
|
321
|
+
end
|
322
|
+
server = @conn.server(@@server.id)
|
323
|
+
sleep 1
|
324
|
+
end
|
325
|
+
end
|
326
|
+
rescue Timeout::Error => te
|
327
|
+
fail('Timeout resizing server.')
|
328
|
+
end
|
329
|
+
|
330
|
+
check_server(server, @@image_ref, 3, 'VERIFY_RESIZE')
|
331
|
+
|
332
|
+
server.confirm_resize!
|
333
|
+
server = @conn.server(@@server.id)
|
334
|
+
assert_equal('ACTIVE', @@server.status)
|
335
|
+
|
336
|
+
check_server(server, @@image_ref, 3)
|
337
|
+
|
338
|
+
end if TEST_RESIZE_SERVER == "true"
|
339
|
+
|
340
|
+
def test_999_teardown
|
341
|
+
@@servers.each do |server|
|
342
|
+
assert_equal(true, server.delete!)
|
343
|
+
end
|
344
|
+
@@images.each do |image|
|
345
|
+
assert_equal(true, image.delete!)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Torpedo
|
4
|
+
module Config
|
5
|
+
|
6
|
+
@@configs=nil
|
7
|
+
|
8
|
+
def self.load_configs
|
9
|
+
return @@configs if not @@configs.nil?
|
10
|
+
|
11
|
+
config_file=ENV['TORPEDO_CONFIG_FILE']
|
12
|
+
if config_file.nil? then
|
13
|
+
|
14
|
+
config_file=ENV['HOME']+File::SEPARATOR+".torpedo.conf"
|
15
|
+
if not File.exists?(config_file) then
|
16
|
+
config_file="/etc/torpedo.conf"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
if File.exists?(config_file) then
|
22
|
+
configs = YAML.load_file(config_file) || {}
|
23
|
+
@@configs = configs
|
24
|
+
else
|
25
|
+
raise "Failed to load torpedo config file. Please configure /etc/torpedo.conf or create a .torpedo.conf config file in your HOME directory."
|
26
|
+
end
|
27
|
+
|
28
|
+
@@configs
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.raise_if_nil_or_empty(options, key)
|
33
|
+
if not options or options[key].nil? or options[key].empty? then
|
34
|
+
raise "Please specify a valid #{key.to_s} parameter."
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/torpedo.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'torpedo/config'
|
3
|
+
|
4
|
+
configs = Torpedo::Config.load_configs
|
5
|
+
|
6
|
+
SSH_TIMEOUT=(configs['ssh_timeout'] || 30).to_i
|
7
|
+
PING_TIMEOUT=(configs['ping_timeout'] || 60).to_i
|
8
|
+
SERVER_BUILD_TIMEOUT=(configs['server_build_timeout'] || 60).to_i
|
9
|
+
SSH_PRIVATE_KEY=configs['ssh_private_key'] || ENV['HOME'] + "/.ssh/id_rsa"
|
10
|
+
SSH_PUBLIC_KEY=configs['ssh_public_key'] || ENV['HOME'] + "/.ssh/id_rsa.pub"
|
11
|
+
TEST_CREATE_IMAGE=configs['test_create_image'] || "false"
|
12
|
+
TEST_REBUILD_SERVER=configs['test_rebuild_server'] || "false"
|
13
|
+
TEST_RESIZE_SERVER=configs['test_resize_server'] || "false"
|
14
|
+
KEYPAIR=configs['keypair']
|
15
|
+
KEYNAME=configs['keyname']
|
16
|
+
|
17
|
+
IMAGE_REF=configs['image_ref']
|
18
|
+
IMAGE_NAME=configs['image_name']
|
19
|
+
|
20
|
+
OPENSTACK_COMPUTE_VERSION=configs['openstack_compute_version'] || '1.1.4'
|
21
|
+
|
22
|
+
USERNAME=ENV['NOVA_USERNAME']
|
23
|
+
API_KEY=ENV['NOVA_API_KEY']
|
24
|
+
API_URL=ENV['NOVA_URL']
|
25
|
+
|
26
|
+
module Torpedo
|
27
|
+
class Tasks < Thor
|
28
|
+
|
29
|
+
desc "flavors", "Run flavors tests for the OSAPI."
|
30
|
+
def flavors
|
31
|
+
require 'torpedo/compute/flavors'
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "limits", "Run limits tests for the OSAPI."
|
35
|
+
def limits
|
36
|
+
require 'torpedo/compute/limits'
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "images", "Run images tests for the OSAPI."
|
40
|
+
def images
|
41
|
+
require 'torpedo/compute/images'
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "servers", "Run servers tests for the OSAPI."
|
45
|
+
def servers
|
46
|
+
require 'torpedo/compute/servers'
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "all", "Run all tests."
|
50
|
+
def all
|
51
|
+
require 'torpedo/compute/flavors'
|
52
|
+
require 'torpedo/compute/limits'
|
53
|
+
require 'torpedo/compute/images'
|
54
|
+
require 'torpedo/compute/servers'
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "fire", "Fire away! (alias for all)"
|
58
|
+
def fire
|
59
|
+
invoke :all
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'torpedo'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
data/torpedo.gemspec
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{torpedo}
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Dan Prince"]
|
12
|
+
s.date = %q{2011-10-28}
|
13
|
+
s.default_executable = %q{torpedo}
|
14
|
+
s.description = %q{CLI to run functional smoke tests for OpenStack.}
|
15
|
+
s.email = %q{dan.prince@rackspace.com}
|
16
|
+
s.executables = ["torpedo"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE.txt",
|
19
|
+
"README.md"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".document",
|
23
|
+
"Gemfile",
|
24
|
+
"LICENSE.txt",
|
25
|
+
"README.md",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"bin/torpedo",
|
29
|
+
"lib/torpedo.rb",
|
30
|
+
"lib/torpedo/compute/flavors.rb",
|
31
|
+
"lib/torpedo/compute/helper.rb",
|
32
|
+
"lib/torpedo/compute/images.rb",
|
33
|
+
"lib/torpedo/compute/limits.rb",
|
34
|
+
"lib/torpedo/compute/servers.rb",
|
35
|
+
"lib/torpedo/config.rb",
|
36
|
+
"test/helper.rb",
|
37
|
+
"test/test_torpedo.rb",
|
38
|
+
"torpedo.gemspec"
|
39
|
+
]
|
40
|
+
s.homepage = %q{http://github.com/dprince/torpedo}
|
41
|
+
s.licenses = ["MIT"]
|
42
|
+
s.require_paths = ["lib"]
|
43
|
+
s.rubygems_version = %q{1.3.7}
|
44
|
+
s.summary = %q{Sink bad code! Ruby Smoke Tests for OpenStack.}
|
45
|
+
|
46
|
+
if s.respond_to? :specification_version then
|
47
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
48
|
+
s.specification_version = 3
|
49
|
+
|
50
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
51
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
52
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
53
|
+
s.add_runtime_dependency(%q<thor>, [">= 0"])
|
54
|
+
s.add_runtime_dependency(%q<openstack-compute>, [">= 1.1.4"])
|
55
|
+
else
|
56
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
57
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
58
|
+
s.add_dependency(%q<thor>, [">= 0"])
|
59
|
+
s.add_dependency(%q<openstack-compute>, [">= 1.1.4"])
|
60
|
+
end
|
61
|
+
else
|
62
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
63
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
64
|
+
s.add_dependency(%q<thor>, [">= 0"])
|
65
|
+
s.add_dependency(%q<openstack-compute>, [">= 1.1.4"])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: torpedo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Dan Prince
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-10-28 00:00:00 -04:00
|
19
|
+
default_executable: torpedo
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
prerelease: false
|
23
|
+
name: bundler
|
24
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 23
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 0
|
33
|
+
- 0
|
34
|
+
version: 1.0.0
|
35
|
+
requirement: *id001
|
36
|
+
type: :development
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
prerelease: false
|
39
|
+
name: jeweler
|
40
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 7
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 6
|
49
|
+
- 4
|
50
|
+
version: 1.6.4
|
51
|
+
requirement: *id002
|
52
|
+
type: :development
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
prerelease: false
|
55
|
+
name: thor
|
56
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
requirement: *id003
|
66
|
+
type: :runtime
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
prerelease: false
|
69
|
+
name: openstack-compute
|
70
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 27
|
76
|
+
segments:
|
77
|
+
- 1
|
78
|
+
- 1
|
79
|
+
- 4
|
80
|
+
version: 1.1.4
|
81
|
+
requirement: *id004
|
82
|
+
type: :runtime
|
83
|
+
description: CLI to run functional smoke tests for OpenStack.
|
84
|
+
email: dan.prince@rackspace.com
|
85
|
+
executables:
|
86
|
+
- torpedo
|
87
|
+
extensions: []
|
88
|
+
|
89
|
+
extra_rdoc_files:
|
90
|
+
- LICENSE.txt
|
91
|
+
- README.md
|
92
|
+
files:
|
93
|
+
- .document
|
94
|
+
- Gemfile
|
95
|
+
- Gemfile.lock
|
96
|
+
- LICENSE.txt
|
97
|
+
- README.md
|
98
|
+
- Rakefile
|
99
|
+
- VERSION
|
100
|
+
- bin/torpedo
|
101
|
+
- lib/torpedo.rb
|
102
|
+
- lib/torpedo/compute/flavors.rb
|
103
|
+
- lib/torpedo/compute/helper.rb
|
104
|
+
- lib/torpedo/compute/images.rb
|
105
|
+
- lib/torpedo/compute/limits.rb
|
106
|
+
- lib/torpedo/compute/servers.rb
|
107
|
+
- lib/torpedo/config.rb
|
108
|
+
- test/helper.rb
|
109
|
+
- test/test_torpedo.rb
|
110
|
+
- torpedo.gemspec
|
111
|
+
has_rdoc: true
|
112
|
+
homepage: http://github.com/dprince/torpedo
|
113
|
+
licenses:
|
114
|
+
- MIT
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
|
118
|
+
require_paths:
|
119
|
+
- lib
|
120
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
hash: 3
|
126
|
+
segments:
|
127
|
+
- 0
|
128
|
+
version: "0"
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
hash: 3
|
135
|
+
segments:
|
136
|
+
- 0
|
137
|
+
version: "0"
|
138
|
+
requirements: []
|
139
|
+
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 1.3.7
|
142
|
+
signing_key:
|
143
|
+
specification_version: 3
|
144
|
+
summary: Sink bad code! Ruby Smoke Tests for OpenStack.
|
145
|
+
test_files: []
|
146
|
+
|