openstack-compute 1.0.2 → 1.1.0.pre0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +2 -4
- data/VERSION +1 -1
- data/lib/openstack/compute.rb +1 -2
- data/lib/openstack/compute/authentication.rb +13 -67
- data/lib/openstack/compute/connection.rb +65 -34
- data/lib/openstack/compute/image.rb +4 -0
- data/lib/openstack/compute/metadata.rb +52 -0
- data/lib/openstack/compute/server.rb +41 -14
- metadata +17 -22
- data/test/authentication_test.rb +0 -36
- data/test/connection_test.rb +0 -39
- data/test/exception_test.rb +0 -49
- data/test/servers_test.rb +0 -123
- data/test/test_helper.rb +0 -23
data/README.rdoc
CHANGED
@@ -2,9 +2,7 @@
|
|
2
2
|
|
3
3
|
== Description
|
4
4
|
|
5
|
-
Ruby Openstack Compute binding
|
6
|
-
|
7
|
-
Currently supports both v1.0 and v2.0 (keystone) auth.
|
5
|
+
Ruby Openstack Compute binding.
|
8
6
|
|
9
7
|
== Examples
|
10
8
|
|
@@ -12,7 +10,7 @@ See the class definitions for documentation on specific methods and operations.
|
|
12
10
|
|
13
11
|
require 'openstack/compute'
|
14
12
|
|
15
|
-
cs = OpenStack::Compute::Connection.new(:username => USERNAME, :api_key => API_KEY, :
|
13
|
+
cs = OpenStack::Compute::Connection.new(:username => USERNAME, :api_key => API_KEY, :api_url => API_URL)
|
16
14
|
|
17
15
|
# Get a listing of all current servers
|
18
16
|
>> cs.servers
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.1.0.pre0
|
data/lib/openstack/compute.rb
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
# To begin reviewing the available methods and examples, view the README.rdoc file, or begin by looking at documentation for the OpenStack::Compute::Connection class.
|
10
10
|
#
|
11
11
|
# Example:
|
12
|
-
# OpenStack::Compute::Connection.new(:username => USERNAME, :api_key => API_KEY, :
|
12
|
+
# OpenStack::Compute::Connection.new(:username => USERNAME, :api_key => API_KEY, :api_url => API_URL) method.
|
13
13
|
module OpenStack
|
14
14
|
module Compute
|
15
15
|
|
@@ -38,7 +38,6 @@ module Compute
|
|
38
38
|
MAX_PERSONALITY_ITEMS = 5
|
39
39
|
MAX_PERSONALITY_FILE_SIZE = 10240
|
40
40
|
MAX_SERVER_PATH_LENGTH = 255
|
41
|
-
MAX_PERSONALITY_METADATA_ITEMS = 5
|
42
41
|
|
43
42
|
# Helper method to recursively symbolize hash keys.
|
44
43
|
def self.symbolize_keys(obj)
|
@@ -1,70 +1,19 @@
|
|
1
1
|
module OpenStack
|
2
2
|
module Compute
|
3
|
-
|
4
3
|
class Authentication
|
5
|
-
|
6
|
-
# Performs an authentication to the OpenStack auth server.
|
7
|
-
# If it succeeds, it sets the svrmgmthost, svrmgtpath, svrmgmtport,
|
8
|
-
# svrmgmtscheme, authtoken, and authok variables on the connection.
|
9
|
-
# If it fails, it raises an exception.
|
10
|
-
def self.init(conn)
|
11
|
-
if conn.auth_path =~ /.*v2.0\/?$/
|
12
|
-
AuthV20.new(conn)
|
13
|
-
else
|
14
|
-
AuthV10.new(conn)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
class AuthV20
|
22
|
-
|
23
|
-
def initialize(connection)
|
24
|
-
begin
|
25
|
-
server = Net::HTTP::Proxy(connection.proxy_host, connection.proxy_port).new(connection.auth_host, connection.auth_port)
|
26
|
-
if connection.auth_scheme == "https"
|
27
|
-
server.use_ssl = true
|
28
|
-
server.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
29
|
-
end
|
30
|
-
server.start
|
31
|
-
rescue
|
32
|
-
raise OpenStack::Compute::Exception::Connection, "Unable to connect to #{server}"
|
33
|
-
end
|
34
|
-
|
35
|
-
auth_data = JSON.generate({ "passwordCredentials" => { "username" => connection.authuser, "password" => connection.authkey }})
|
36
|
-
response = server.post(connection.auth_path.chomp("/")+"/tokens", auth_data, {'Content-Type' => 'application/json'})
|
37
|
-
if (response.code =~ /^20./)
|
38
|
-
resp_data=JSON.parse(response.body)
|
39
|
-
connection.authtoken = resp_data['auth']['token']['id']
|
40
|
-
if resp_data['auth']['serviceCatalog'] and resp_data['auth']['serviceCatalog'][connection.service_name] and resp_data['auth']['serviceCatalog'][connection.service_name][0] then
|
41
|
-
uri = URI.parse(resp_data['auth']['serviceCatalog'][connection.service_name][0]['publicURL'])
|
42
|
-
connection.svrmgmthost = uri.host
|
43
|
-
connection.svrmgmtpath = uri.path
|
44
|
-
# Force the path into the v1.0 URL space
|
45
|
-
connection.svrmgmtpath.sub!(/\/.*\/?/, '/v1.0/')
|
46
|
-
connection.svrmgmtport = uri.port
|
47
|
-
connection.svrmgmtscheme = uri.scheme
|
48
|
-
connection.authok = true
|
49
|
-
else
|
50
|
-
connection.authok = false
|
51
|
-
end
|
52
|
-
else
|
53
|
-
connection.authtoken = false
|
54
|
-
raise OpenStack::Compute::Exception::Authentication, "Authentication failed with response code #{response.code}"
|
55
|
-
end
|
56
|
-
server.finish
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
class AuthV10
|
61
4
|
|
5
|
+
# Performs an authentication to the OpenStack authorization servers. Opens a new HTTP connection to the API server,
|
6
|
+
# sends the credentials, and looks for a successful authentication. If it succeeds, it sets the svrmgmthost,
|
7
|
+
# svrmgtpath, svrmgmtport, svrmgmtscheme, authtoken, and authok variables on the connection. If it fails, it raises
|
8
|
+
# an exception.
|
9
|
+
#
|
10
|
+
# Should probably never be called directly.
|
62
11
|
def initialize(connection)
|
63
|
-
path =
|
12
|
+
path = connection.api_path
|
64
13
|
hdrhash = { "X-Auth-User" => connection.authuser, "X-Auth-Key" => connection.authkey }
|
65
14
|
begin
|
66
|
-
server = Net::HTTP::Proxy(connection.proxy_host, connection.proxy_port).new(connection.
|
67
|
-
if connection.
|
15
|
+
server = Net::HTTP::Proxy(connection.proxy_host, connection.proxy_port).new(connection.api_host, connection.api_port)
|
16
|
+
if connection.api_scheme == "https"
|
68
17
|
server.use_ssl = true
|
69
18
|
server.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
70
19
|
end
|
@@ -75,13 +24,11 @@ module Compute
|
|
75
24
|
response = server.get(path,hdrhash)
|
76
25
|
if (response.code =~ /^20./)
|
77
26
|
connection.authtoken = response["x-auth-token"]
|
78
|
-
|
79
|
-
connection.
|
80
|
-
connection.svrmgmtpath = uri.path
|
27
|
+
connection.svrmgmthost = URI.parse(response["x-server-management-url"]).host
|
28
|
+
connection.svrmgmtpath = URI.parse(response["x-server-management-url"]).path
|
81
29
|
# Force the path into the v1.0 URL space
|
82
|
-
connection.
|
83
|
-
connection.
|
84
|
-
connection.svrmgmtscheme = uri.scheme
|
30
|
+
connection.svrmgmtport = URI.parse(response["x-server-management-url"]).port
|
31
|
+
connection.svrmgmtscheme = URI.parse(response["x-server-management-url"]).scheme
|
85
32
|
connection.authok = true
|
86
33
|
else
|
87
34
|
connection.authtoken = false
|
@@ -90,6 +37,5 @@ module Compute
|
|
90
37
|
server.finish
|
91
38
|
end
|
92
39
|
end
|
93
|
-
|
94
40
|
end
|
95
41
|
end
|
@@ -10,11 +10,10 @@ module Compute
|
|
10
10
|
attr_accessor :svrmgmtpath
|
11
11
|
attr_accessor :svrmgmtport
|
12
12
|
attr_accessor :svrmgmtscheme
|
13
|
-
attr_reader :
|
14
|
-
attr_reader :
|
15
|
-
attr_reader :
|
16
|
-
attr_reader :
|
17
|
-
attr_accessor :service_name
|
13
|
+
attr_reader :api_host
|
14
|
+
attr_reader :api_port
|
15
|
+
attr_reader :api_scheme
|
16
|
+
attr_reader :api_path
|
18
17
|
attr_reader :proxy_host
|
19
18
|
attr_reader :proxy_port
|
20
19
|
|
@@ -24,37 +23,36 @@ module Compute
|
|
24
23
|
#
|
25
24
|
# :username - Your Openstack username *required*
|
26
25
|
# :api_key - Your Openstack API key *required*
|
27
|
-
# :
|
28
|
-
# :service_name - (Optional for v2.0 auth only). The name of the compute service to use. Defaults to 'nova'.
|
26
|
+
# :api_url - The url of the Openstack Compute API server.
|
29
27
|
# :retry_auth - Whether to retry if your auth token expires (defaults to true)
|
30
28
|
# :proxy_host - If you need to connect through a proxy, supply the hostname here
|
31
29
|
# :proxy_port - If you need to connect through a proxy, supply the port here
|
32
30
|
#
|
33
|
-
# cf = OpenStack::Compute::Connection.new(:username => 'USERNAME', :api_key => 'API_KEY', :
|
31
|
+
# cf = OpenStack::Compute::Connection.new(:username => 'USERNAME', :api_key => 'API_KEY', :api_url => 'API_URL')
|
34
32
|
def initialize(options = {:retry_auth => true})
|
35
33
|
@authuser = options[:username] || (raise Exception::MissingArgument, "Must supply a :username")
|
36
34
|
@authkey = options[:api_key] || (raise Exception::MissingArgument, "Must supply an :api_key")
|
37
|
-
@
|
38
|
-
@
|
35
|
+
@api_url = options[:api_url] || (raise Exception::MissingArgument, "Must supply an :api_url")
|
36
|
+
@is_debug = options[:is_debug]
|
39
37
|
|
40
|
-
|
38
|
+
api_uri=nil
|
41
39
|
begin
|
42
|
-
|
40
|
+
api_uri=URI.parse(@api_url)
|
43
41
|
rescue Exception => e
|
44
|
-
raise Exception::InvalidArgument, "Invalid :
|
42
|
+
raise Exception::InvalidArgument, "Invalid :api_url parameter: #{e.message}"
|
45
43
|
end
|
46
|
-
raise Exception::InvalidArgument, "Invalid :
|
47
|
-
@
|
48
|
-
@
|
49
|
-
@
|
50
|
-
@
|
44
|
+
raise Exception::InvalidArgument, "Invalid :api_url parameter." if api_uri.nil? or api_uri.host.nil?
|
45
|
+
@api_host = api_uri.host
|
46
|
+
@api_port = api_uri.port
|
47
|
+
@api_scheme = api_uri.scheme
|
48
|
+
@api_path = api_uri.path.sub(/\/$/, '')
|
51
49
|
|
52
50
|
@retry_auth = options[:retry_auth]
|
53
51
|
@proxy_host = options[:proxy_host]
|
54
52
|
@proxy_port = options[:proxy_port]
|
55
53
|
@authok = false
|
56
54
|
@http = {}
|
57
|
-
OpenStack::Compute::Authentication.
|
55
|
+
OpenStack::Compute::Authentication.new(self)
|
58
56
|
end
|
59
57
|
|
60
58
|
# Returns true if the authentication was successful and returns false otherwise.
|
@@ -64,7 +62,7 @@ module Compute
|
|
64
62
|
def authok?
|
65
63
|
@authok
|
66
64
|
end
|
67
|
-
|
65
|
+
|
68
66
|
# This method actually makes the HTTP REST calls out to the server
|
69
67
|
def csreq(method,server,path,port,scheme,headers = {},data = nil,attempts = 0) # :nodoc:
|
70
68
|
start = Time.now
|
@@ -73,6 +71,12 @@ module Compute
|
|
73
71
|
request = Net::HTTP.const_get(method.to_s.capitalize).new(path,hdrhash)
|
74
72
|
request.body = data
|
75
73
|
response = @http[server].request(request)
|
74
|
+
if @is_debug
|
75
|
+
puts "REQUEST: #{method} => #{path}"
|
76
|
+
puts data if data
|
77
|
+
puts "RESPONSE: #{response.body}"
|
78
|
+
puts '----------------------------------------'
|
79
|
+
end
|
76
80
|
raise OpenStack::Compute::Exception::ExpiredAuthToken if response.code == "401"
|
77
81
|
response
|
78
82
|
rescue Errno::EPIPE, Timeout::Error, Errno::EINVAL, EOFError
|
@@ -84,10 +88,27 @@ module Compute
|
|
84
88
|
retry
|
85
89
|
rescue OpenStack::Compute::Exception::ExpiredAuthToken
|
86
90
|
raise OpenStack::Compute::Exception::Connection, "Authentication token expired and you have requested not to retry" if @retry_auth == false
|
87
|
-
OpenStack::Compute::Authentication.
|
91
|
+
OpenStack::Compute::Authentication.new(self)
|
88
92
|
retry
|
89
93
|
end
|
90
|
-
|
94
|
+
|
95
|
+
# This is a much more sane way to make a http request to the api.
|
96
|
+
# Example: res = conn.req('GET', "/servers/#{id}")
|
97
|
+
def req(method, path, options = {})
|
98
|
+
server = options[:server] || @svrmgmthost
|
99
|
+
port = options[:port] || @svrmgmtport
|
100
|
+
scheme = options[:scheme] || @svrmgmtscheme
|
101
|
+
headers = options[:headers] || {'content-type' => 'application/json'}
|
102
|
+
data = options[:data]
|
103
|
+
attempts = options[:attempts] || 0
|
104
|
+
path = @svrmgmtpath + path
|
105
|
+
res = csreq(method,server,path,port,scheme,headers,data,attempts)
|
106
|
+
if not res.code.match(/^20.$/)
|
107
|
+
OpenStack::Compute::Exception.raise_exception(res)
|
108
|
+
end
|
109
|
+
return res
|
110
|
+
end;
|
111
|
+
|
91
112
|
# Returns the OpenStack::Compute::Server object identified by the given id.
|
92
113
|
#
|
93
114
|
# >> server = cs.get_server(110917)
|
@@ -139,21 +160,32 @@ module Compute
|
|
139
160
|
|
140
161
|
# Creates a new server instance on OpenStack Compute
|
141
162
|
#
|
142
|
-
# The argument is a hash of options. The keys :name, :
|
163
|
+
# The argument is a hash of options. The keys :name, :flavorRef,
|
164
|
+
# and :imageRef are required; :metadata and :personality are optional.
|
143
165
|
#
|
144
|
-
# :
|
145
|
-
#
|
166
|
+
# :flavorRef and :imageRef are href strings identifying a particular
|
167
|
+
# server flavor and image to use when building the server. The :imageRef
|
168
|
+
# can either be a stock image, or one of your own created with the
|
169
|
+
# server.create_image method.
|
146
170
|
#
|
147
|
-
# The :metadata argument
|
148
|
-
# API level.
|
171
|
+
# The :metadata argument should be a hash of key/value pairs. This
|
172
|
+
# metadata will be applied to the server at the OpenStack Compute API level.
|
149
173
|
#
|
150
|
-
# The "Personality" option allows you to include up to five files, of
|
151
|
-
#
|
152
|
-
#
|
174
|
+
# The "Personality" option allows you to include up to five files, # of
|
175
|
+
# 10Kb or less in size, that will be placed on the created server.
|
176
|
+
# For :personality, pass a hash of the form {'local_path' => 'server_path'}.
|
177
|
+
# The file located at local_path will be base64-encoded and placed at the
|
178
|
+
# location identified by server_path on the new server.
|
153
179
|
#
|
154
|
-
# Returns a OpenStack::Compute::Server object. The root password is
|
180
|
+
# Returns a OpenStack::Compute::Server object. The root password is
|
181
|
+
# available in the adminPass instance method.
|
155
182
|
#
|
156
|
-
# >> server = cs.create_server(
|
183
|
+
# >> server = cs.create_server(
|
184
|
+
# :name => 'NewServer',
|
185
|
+
# :imageRef => 'http://172.19.0.3/v1.1/images/3',
|
186
|
+
# :flavorRef => 'http://172.19.0.3/v1.1/flavors/1',
|
187
|
+
# :metadata => {'Racker' => 'Fanatical'},
|
188
|
+
# :personality => {'/home/bob/wedding.jpg' => '/root/wedding.jpg'})
|
157
189
|
# => #<OpenStack::Compute::Server:0x101229eb0 ...>
|
158
190
|
# >> server.name
|
159
191
|
# => "NewServer"
|
@@ -162,9 +194,8 @@ module Compute
|
|
162
194
|
# >> server.adminPass
|
163
195
|
# => "NewServerSHMGpvI"
|
164
196
|
def create_server(options)
|
165
|
-
raise OpenStack::Compute::Exception::MissingArgument, "Server name,
|
197
|
+
raise OpenStack::Compute::Exception::MissingArgument, "Server name, flavorRef, and imageRef, must be supplied" unless (options[:name] && options[:flavorRef] && options[:imageRef])
|
166
198
|
options[:personality] = get_personality(options[:personality])
|
167
|
-
raise TooManyMetadataItems, "Metadata is limited to a total of #{MAX_PERSONALITY_METADATA_ITEMS} key/value pairs" if options[:metadata].is_a?(Hash) && options[:metadata].keys.size > MAX_PERSONALITY_METADATA_ITEMS
|
168
199
|
data = JSON.generate(:server => options)
|
169
200
|
response = csreq("POST",svrmgmthost,"#{svrmgmtpath}/servers",svrmgmtport,svrmgmtscheme,{'content-type' => 'application/json'},data)
|
170
201
|
OpenStack::Compute::Exception.raise_exception(response) unless response.code.match(/^20.$/)
|
@@ -2,6 +2,8 @@ module OpenStack
|
|
2
2
|
module Compute
|
3
3
|
class Image
|
4
4
|
|
5
|
+
require 'compute/metadata'
|
6
|
+
|
5
7
|
attr_reader :id
|
6
8
|
attr_reader :name
|
7
9
|
attr_reader :serverId
|
@@ -9,6 +11,7 @@ module Compute
|
|
9
11
|
attr_reader :created
|
10
12
|
attr_reader :status
|
11
13
|
attr_reader :progress
|
14
|
+
attr_reader :metadata
|
12
15
|
|
13
16
|
# This class provides an object for the "Image" of a server. The Image refers to the Operating System type and version.
|
14
17
|
#
|
@@ -23,6 +26,7 @@ module Compute
|
|
23
26
|
def initialize(connection,id)
|
24
27
|
@id = id
|
25
28
|
@connection = connection
|
29
|
+
@metadata = OpenStack::Compute::ImageMetadata.new(connection, id)
|
26
30
|
populate
|
27
31
|
end
|
28
32
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module OpenStack
|
2
|
+
module Compute
|
3
|
+
|
4
|
+
class AbstractMetadata
|
5
|
+
|
6
|
+
def initialize(connection, server_id)
|
7
|
+
@connection = connection
|
8
|
+
@server_id = server_id
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_item(key)
|
12
|
+
response = @connection.req('GET', "#{@base_url}/#{key}")
|
13
|
+
return JSON.parse(response.body)['meta'][key]
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_item(key, value)
|
17
|
+
json = JSON.generate(:meta => { key => value })
|
18
|
+
@connection.req('PUT', "#{@base_url}/#{key}", :data => json)
|
19
|
+
end
|
20
|
+
|
21
|
+
def delete_item(key)
|
22
|
+
@connection.req('DELETE', "#{@base_url}/#{key}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_data()
|
26
|
+
response = @connection.req('GET', @base_url)
|
27
|
+
return JSON.parse(response.body)['metadata']
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_data(data = {})
|
31
|
+
json = JSON.generate(:metadata => data)
|
32
|
+
@connection.req('POST', @base_url, :data => json)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
class ServerMetadata < AbstractMetadata
|
38
|
+
def initialize(connection, server_id)
|
39
|
+
super(connection, server_id)
|
40
|
+
@base_url = "/servers/#{@server_id}/metadata"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class ImageMetadata < AbstractMetadata
|
45
|
+
def initialize(connection, server_id)
|
46
|
+
super(connection, server_id)
|
47
|
+
@base_url = "/images/#{@server_id}/metadata"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -2,15 +2,17 @@ module OpenStack
|
|
2
2
|
module Compute
|
3
3
|
class Server
|
4
4
|
|
5
|
+
require 'compute/metadata'
|
6
|
+
|
5
7
|
attr_reader :id
|
6
8
|
attr_reader :name
|
7
9
|
attr_reader :status
|
8
10
|
attr_reader :progress
|
9
11
|
attr_reader :addresses
|
10
|
-
attr_reader :metadata
|
11
12
|
attr_reader :hostId
|
12
13
|
attr_reader :imageId
|
13
14
|
attr_reader :flavorId
|
15
|
+
attr_reader :metadata
|
14
16
|
attr_accessor :adminPass
|
15
17
|
|
16
18
|
# This class is the representation of a single Server object. The constructor finds the server identified by the specified
|
@@ -50,10 +52,10 @@ module Compute
|
|
50
52
|
@status = data["status"]
|
51
53
|
@progress = data["progress"]
|
52
54
|
@addresses = OpenStack::Compute.symbolize_keys(data["addresses"])
|
53
|
-
@metadata =
|
55
|
+
@metadata = OpenStack::Compute::ServerMetadata.new(@connection, @id)
|
54
56
|
@hostId = data["hostId"]
|
55
|
-
@imageId = data["
|
56
|
-
@flavorId = data["
|
57
|
+
@imageId = data["image"]["id"]
|
58
|
+
@flavorId = data["flavor"]["id"]
|
57
59
|
true
|
58
60
|
end
|
59
61
|
alias :refresh :populate
|
@@ -65,7 +67,7 @@ module Compute
|
|
65
67
|
# >> flavor.name
|
66
68
|
# => "256 server"
|
67
69
|
def flavor
|
68
|
-
OpenStack::Compute::Flavor.new(@connection,self.flavorId)
|
70
|
+
OpenStack::Compute::Flavor.new(@connection, self.flavorId)
|
69
71
|
end
|
70
72
|
|
71
73
|
# Returns a new OpenStack::Compute::Image object for the image assigned to this server.
|
@@ -75,7 +77,7 @@ module Compute
|
|
75
77
|
# >> image.name
|
76
78
|
# => "Ubuntu 8.04.2 LTS (hardy)"
|
77
79
|
def image
|
78
|
-
OpenStack::Compute::Image.new(@connection,self.imageId)
|
80
|
+
OpenStack::Compute::Image.new(@connection, self.imageId)
|
79
81
|
end
|
80
82
|
|
81
83
|
# Sends an API request to reboot this server. Takes an optional argument for the type of reboot, which can be "SOFT" (graceful shutdown)
|
@@ -133,19 +135,36 @@ module Compute
|
|
133
135
|
true
|
134
136
|
end
|
135
137
|
|
136
|
-
#
|
137
|
-
# will
|
138
|
-
#
|
139
|
-
#
|
138
|
+
# The rebuild function removes all data on the server and replaces it with
|
139
|
+
# the specified image. The serverRef and all IP addresses will remain the
|
140
|
+
# same. If name and metadata are specified, they will replace existing
|
141
|
+
# values, otherwise they will not change. A rebuild operation always
|
142
|
+
# removes data injected into the file system via server personality. You
|
143
|
+
# may reinsert data into the filesystem during the rebuild.
|
144
|
+
#
|
145
|
+
# This method expects a hash of the form:
|
146
|
+
# {
|
147
|
+
# :imageId => "https://foo.com/v1.1/images/2",
|
148
|
+
# :name => "newName",
|
149
|
+
# :metadata => { :values => { :foo : "bar" } },
|
150
|
+
# :personality => [
|
151
|
+
# {
|
152
|
+
# :path => "/etc/banner.txt",
|
153
|
+
# :contents => : "ICAgpY2hhcmQgQmFjaA=="
|
154
|
+
# }
|
155
|
+
# ]
|
156
|
+
# }
|
157
|
+
#
|
158
|
+
# This will wipe and rebuild the server, but keep the server ID number,
|
159
|
+
# name, and IP addresses the same.
|
140
160
|
#
|
141
161
|
# Returns true if the API call succeeds.
|
142
162
|
#
|
143
163
|
# >> server.rebuild!
|
144
164
|
# => true
|
145
|
-
def rebuild!(
|
146
|
-
|
147
|
-
|
148
|
-
OpenStack::Compute::Exception.raise_exception(response) unless response.code.match(/^20.$/)
|
165
|
+
def rebuild!(options)
|
166
|
+
json = JSON.generate(:rebuild => options)
|
167
|
+
@connection.req('POST', "/servers/#{@id}/action", :data => json)
|
149
168
|
self.populate
|
150
169
|
true
|
151
170
|
end
|
@@ -214,6 +233,14 @@ module Compute
|
|
214
233
|
true
|
215
234
|
end
|
216
235
|
|
236
|
+
# Changes the admin password.
|
237
|
+
# Returns the password if it succeeds.
|
238
|
+
def change_password!(password)
|
239
|
+
json = JSON.generate(:changePassword => { :adminPass => password })
|
240
|
+
@connection.req('POST', "/servers/#{@id}/action", :data => json)
|
241
|
+
@adminPass = password
|
242
|
+
end
|
243
|
+
|
217
244
|
end
|
218
245
|
end
|
219
246
|
end
|
metadata
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openstack-compute
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: -1876988165
|
5
|
+
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
10
|
+
- pre0
|
11
|
+
version: 1.1.0.pre0
|
11
12
|
platform: ruby
|
12
13
|
authors:
|
13
14
|
- Dan Prince
|
@@ -15,7 +16,7 @@ autorequire:
|
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date: 2011-
|
19
|
+
date: 2011-10-13 00:00:00 -04:00
|
19
20
|
default_executable:
|
20
21
|
dependencies:
|
21
22
|
- !ruby/object:Gem::Dependency
|
@@ -50,19 +51,15 @@ files:
|
|
50
51
|
- lib/openstack/compute/exception.rb
|
51
52
|
- lib/openstack/compute/flavor.rb
|
52
53
|
- lib/openstack/compute/image.rb
|
54
|
+
- lib/openstack/compute/metadata.rb
|
53
55
|
- lib/openstack/compute/server.rb
|
54
|
-
- test/authentication_test.rb
|
55
|
-
- test/exception_test.rb
|
56
|
-
- test/test_helper.rb
|
57
|
-
- test/connection_test.rb
|
58
|
-
- test/servers_test.rb
|
59
56
|
has_rdoc: true
|
60
57
|
homepage: https://launchpad.net/ruby-openstack-compute
|
61
58
|
licenses: []
|
62
59
|
|
63
60
|
post_install_message:
|
64
|
-
rdoc_options:
|
65
|
-
|
61
|
+
rdoc_options: []
|
62
|
+
|
66
63
|
require_paths:
|
67
64
|
- lib
|
68
65
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -77,12 +74,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
77
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
75
|
none: false
|
79
76
|
requirements:
|
80
|
-
- - "
|
77
|
+
- - ">"
|
81
78
|
- !ruby/object:Gem::Version
|
82
|
-
hash:
|
79
|
+
hash: 25
|
83
80
|
segments:
|
84
|
-
-
|
85
|
-
|
81
|
+
- 1
|
82
|
+
- 3
|
83
|
+
- 1
|
84
|
+
version: 1.3.1
|
86
85
|
requirements: []
|
87
86
|
|
88
87
|
rubyforge_project:
|
@@ -90,9 +89,5 @@ rubygems_version: 1.3.7
|
|
90
89
|
signing_key:
|
91
90
|
specification_version: 3
|
92
91
|
summary: OpenStack Compute Ruby API
|
93
|
-
test_files:
|
94
|
-
|
95
|
-
- test/exception_test.rb
|
96
|
-
- test/test_helper.rb
|
97
|
-
- test/connection_test.rb
|
98
|
-
- test/servers_test.rb
|
92
|
+
test_files: []
|
93
|
+
|
data/test/authentication_test.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/test_helper'
|
2
|
-
|
3
|
-
class AuthenticationTest < Test::Unit::TestCase
|
4
|
-
|
5
|
-
def test_good_authentication
|
6
|
-
response = {'x-server-management-url' => 'http://server-manage.example.com/path', 'x-auth-token' => 'dummy_token'}
|
7
|
-
response.stubs(:code).returns('204')
|
8
|
-
server = mock(:use_ssl= => true, :verify_mode= => true, :start => true, :finish => true)
|
9
|
-
server.stubs(:get).returns(response)
|
10
|
-
Net::HTTP.stubs(:new).returns(server)
|
11
|
-
connection = stub(:authuser => 'bad_user', :authkey => 'bad_key', :auth_host => "a.b.c", :auth_port => "443", :auth_scheme => "https", :auth_path => "/v1.0", :authok= => true, :authtoken= => true, :svrmgmthost= => "", :svrmgmtpath= => "", :svrmgmtpath => "", :svrmgmtport= => "", :svrmgmtscheme= => "", :proxy_host => nil, :proxy_port => nil)
|
12
|
-
result = OpenStack::Compute::Authentication.init(connection)
|
13
|
-
assert_equal result.class, OpenStack::Compute::AuthV10
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_bad_authentication
|
17
|
-
response = mock()
|
18
|
-
response.stubs(:code).returns('499')
|
19
|
-
server = mock(:use_ssl= => true, :verify_mode= => true, :start => true)
|
20
|
-
server.stubs(:get).returns(response)
|
21
|
-
Net::HTTP.stubs(:new).returns(server)
|
22
|
-
connection = stub(:authuser => 'bad_user', :authkey => 'bad_key', :auth_host => "a.b.c", :auth_port => "443", :auth_scheme => "https", :auth_path => "/v1.0", :authok= => true, :authtoken= => true, :proxy_host => nil, :proxy_port => nil)
|
23
|
-
assert_raises(OpenStack::Compute::Exception::Authentication) do
|
24
|
-
result = OpenStack::Compute::Authentication.init(connection)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_bad_hostname
|
29
|
-
Net::HTTP.stubs(:new).raises(OpenStack::Compute::Exception::Connection)
|
30
|
-
connection = stub(:authuser => 'bad_user', :authkey => 'bad_key', :auth_host => "a.b.c", :auth_port => "443", :auth_scheme => "https", :auth_path => "/v1.0", :authok= => true, :authtoken= => true, :proxy_host => nil, :proxy_port => nil)
|
31
|
-
assert_raises(OpenStack::Compute::Exception::Connection) do
|
32
|
-
result = OpenStack::Compute::Authentication.init(connection)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
data/test/connection_test.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/test_helper'
|
2
|
-
|
3
|
-
class ComputeConnectionTest < Test::Unit::TestCase
|
4
|
-
|
5
|
-
def setup
|
6
|
-
connection = stub()
|
7
|
-
OpenStack::Compute::Authentication.stubs(:init).returns(connection)
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_init_connection_no_credentials
|
11
|
-
assert_raises(OpenStack::Compute::Exception::MissingArgument) do
|
12
|
-
conn = OpenStack::Compute::Connection.new(:api_key => "AABBCCDD11", :auth_url => "a.b.c")
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_init_connection_no_password
|
17
|
-
assert_raises(OpenStack::Compute::Exception::MissingArgument) do
|
18
|
-
conn = OpenStack::Compute::Connection.new(:username => "test_account", :auth_url => "a.b.c")
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_init_connection_no_auth_url
|
23
|
-
assert_raises(OpenStack::Compute::Exception::MissingArgument) do
|
24
|
-
conn = OpenStack::Compute::Connection.new(:username => "test_account", :api_key => "AABBCCDD11")
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_init_connection_bad_auth_url
|
29
|
-
assert_raises(OpenStack::Compute::Exception::InvalidArgument) do
|
30
|
-
conn = OpenStack::Compute::Connection.new(:username => "test_account", :api_key => "AABBCCDD11", :auth_url => "***")
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_init_connection
|
35
|
-
conn = OpenStack::Compute::Connection.new(:username => "test_account", :api_key => "AABBCCDD11", :auth_url => "https://a.b.c")
|
36
|
-
assert_not_nil conn, "Connection.new returned nil."
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
data/test/exception_test.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/test_helper'
|
2
|
-
|
3
|
-
class ExceptionTest < Test::Unit::TestCase
|
4
|
-
|
5
|
-
def test_400_cloud_servers_fault
|
6
|
-
response = mock()
|
7
|
-
response.stubs(:code => "400", :body => "{\"ComputeFault\":{\"message\":\"422 Unprocessable Entity: We could not process your request at this time. We have been notified and are looking into the issue. [E03]\",\"details\":\"com.rackspace.cloud.service.servers.OpenStack::ComputeFault: Fault occured\",\"code\":400}}" )
|
8
|
-
exception=nil
|
9
|
-
begin
|
10
|
-
OpenStack::Compute::Exception.raise_exception(response)
|
11
|
-
rescue Exception => e
|
12
|
-
exception=e
|
13
|
-
end
|
14
|
-
assert_equal(OpenStack::Compute::Exception::ComputeFault, e.class)
|
15
|
-
assert_equal("400", e.response_code)
|
16
|
-
assert_not_nil(e.response_body)
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_413_over_limit
|
20
|
-
response = mock()
|
21
|
-
response.stubs(:code => "413", :body => "{\"overLimit\":{\"message\":\"Too many requests...\",\"code\":413,\"retryAfter\":\"2010-08-25T10:47:57.890-05:00\"}}")
|
22
|
-
exception=nil
|
23
|
-
begin
|
24
|
-
OpenStack::Compute::Exception.raise_exception(response)
|
25
|
-
rescue Exception => e
|
26
|
-
exception=e
|
27
|
-
end
|
28
|
-
assert_equal(OpenStack::Compute::Exception::OverLimit, e.class)
|
29
|
-
assert_equal("413", e.response_code)
|
30
|
-
assert_not_nil(e.response_body)
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_other
|
34
|
-
response = mock()
|
35
|
-
body="{\"blahblah\":{\"message\":\"Failed...\",\"code\":500}}"
|
36
|
-
response.stubs(:code => "500", :body => body)
|
37
|
-
exception=nil
|
38
|
-
begin
|
39
|
-
OpenStack::Compute::Exception.raise_exception(response)
|
40
|
-
rescue Exception => e
|
41
|
-
exception=e
|
42
|
-
end
|
43
|
-
assert_equal(OpenStack::Compute::Exception::Other, exception.class)
|
44
|
-
assert_equal("500", exception.response_code)
|
45
|
-
assert_not_nil(exception.response_body)
|
46
|
-
assert_equal(body, exception.response_body)
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
data/test/servers_test.rb
DELETED
@@ -1,123 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/test_helper'
|
2
|
-
|
3
|
-
class ServersTest < Test::Unit::TestCase
|
4
|
-
|
5
|
-
include TestConnection
|
6
|
-
|
7
|
-
def setup
|
8
|
-
@conn=get_test_connection
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_list_servers
|
12
|
-
|
13
|
-
json_response = %{{
|
14
|
-
"servers" : [
|
15
|
-
{
|
16
|
-
"id" : 1234,
|
17
|
-
"name" : "sample-server",
|
18
|
-
"imageId" : 2,
|
19
|
-
"flavorId" : 1,
|
20
|
-
"hostId" : "e4d909c290d0fb1ca068ffaddf22cbd0",
|
21
|
-
"status" : "BUILD",
|
22
|
-
"progress" : 60,
|
23
|
-
"addresses" : {
|
24
|
-
"public" : [
|
25
|
-
"67.23.10.132",
|
26
|
-
"67.23.10.131"
|
27
|
-
],
|
28
|
-
"private" : [
|
29
|
-
"10.176.42.16"
|
30
|
-
]
|
31
|
-
},
|
32
|
-
"metadata" : {
|
33
|
-
"Server Label" : "Web Head 1",
|
34
|
-
"Image Version" : "2.1"
|
35
|
-
}
|
36
|
-
},
|
37
|
-
{
|
38
|
-
"id" : 5678,
|
39
|
-
"name" : "sample-server2",
|
40
|
-
"imageId" : 2,
|
41
|
-
"flavorId" : 1,
|
42
|
-
"hostId" : "9e107d9d372bb6826bd81d3542a419d6",
|
43
|
-
"status" : "ACTIVE",
|
44
|
-
"addresses" : {
|
45
|
-
"public" : [
|
46
|
-
"67.23.10.133"
|
47
|
-
],
|
48
|
-
"private" : [
|
49
|
-
"10.176.42.17"
|
50
|
-
]
|
51
|
-
},
|
52
|
-
"metadata" : {
|
53
|
-
"Server Label" : "DB 1"
|
54
|
-
}
|
55
|
-
}
|
56
|
-
]
|
57
|
-
}}
|
58
|
-
response = mock()
|
59
|
-
response.stubs(:code => "200", :body => json_response)
|
60
|
-
|
61
|
-
@conn.stubs(:csreq).returns(response)
|
62
|
-
servers=@conn.list_servers
|
63
|
-
|
64
|
-
assert_equal 2, servers.size
|
65
|
-
assert_equal 1234, servers[0][:id]
|
66
|
-
assert_equal "sample-server", servers[0][:name]
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_get_server
|
71
|
-
|
72
|
-
server=get_test_server
|
73
|
-
assert "sample-server", server.name
|
74
|
-
assert "2", server.imageId
|
75
|
-
assert "1", server.flavorId
|
76
|
-
assert "e4d909c290d0fb1ca068ffaddf22cbd0", server.hostId
|
77
|
-
assert "BUILD", server.status
|
78
|
-
assert "60", server.progress
|
79
|
-
assert "67.23.10.132", server.addresses[:public][0]
|
80
|
-
assert "67.23.10.131", server.addresses[:public][1]
|
81
|
-
assert "10.176.42.16", server.addresses[:private][1]
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
private
|
86
|
-
def get_test_server
|
87
|
-
|
88
|
-
json_response = %{{
|
89
|
-
"server" : {
|
90
|
-
"id" : 1234,
|
91
|
-
"name" : "sample-server",
|
92
|
-
"imageId" : 2,
|
93
|
-
"flavorId" : 1,
|
94
|
-
"hostId" : "e4d909c290d0fb1ca068ffaddf22cbd0",
|
95
|
-
"status" : "BUILD",
|
96
|
-
"progress" : 60,
|
97
|
-
"addresses" : {
|
98
|
-
"public" : [
|
99
|
-
"67.23.10.132",
|
100
|
-
"67.23.10.131"
|
101
|
-
],
|
102
|
-
"private" : [
|
103
|
-
"10.176.42.16"
|
104
|
-
]
|
105
|
-
},
|
106
|
-
"metadata" : {
|
107
|
-
"Server Label" : "Web Head 1",
|
108
|
-
"Image Version" : "2.1"
|
109
|
-
}
|
110
|
-
}
|
111
|
-
}}
|
112
|
-
|
113
|
-
response = mock()
|
114
|
-
response.stubs(:code => "200", :body => json_response)
|
115
|
-
|
116
|
-
@conn=get_test_connection
|
117
|
-
|
118
|
-
@conn.stubs(:csreq).returns(response)
|
119
|
-
return @conn.server(1234)
|
120
|
-
|
121
|
-
end
|
122
|
-
|
123
|
-
end
|
data/test/test_helper.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
$:.unshift File.dirname(__FILE__) + '/../lib'
|
3
|
-
require 'openstack/compute'
|
4
|
-
require 'rubygems'
|
5
|
-
require 'mocha'
|
6
|
-
|
7
|
-
module TestConnection
|
8
|
-
|
9
|
-
def get_test_connection
|
10
|
-
|
11
|
-
conn_response = {'x-server-management-url' => 'http://server-manage.example.com/path', 'x-auth-token' => 'dummy_token'}
|
12
|
-
conn_response.stubs(:code).returns('204')
|
13
|
-
#server = mock(:use_ssl= => true, :verify_mode= => true, :start => true, :finish => true)
|
14
|
-
server = mock(:start => true, :finish => true)
|
15
|
-
server.stubs(:get => conn_response, :use_ssl= => true, :verify_mode= => true)
|
16
|
-
#server.stubs(:get).returns(conn_response)
|
17
|
-
Net::HTTP.stubs(:new).returns(server)
|
18
|
-
|
19
|
-
OpenStack::Compute::Connection.new(:username => "test_account", :api_key => "AABBCCDD11", :auth_url => "http://a.b.c")
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|