openstack-compute 1.0.2 → 1.1.0.pre0
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/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
|