openstack 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +38 -2
- data/VERSION +1 -1
- data/lib/openstack/compute/address.rb +29 -0
- data/lib/openstack/compute/connection.rb +81 -7
- data/lib/openstack/compute/server.rb +4 -1
- metadata +35 -51
data/README.rdoc
CHANGED
@@ -93,11 +93,12 @@ See the class definitions for documentation on specific methods and operations.
|
|
93
93
|
>> newserver.progress
|
94
94
|
=> 12
|
95
95
|
|
96
|
-
# Create a new server and specify the keyname to be used (
|
97
|
-
>> server = os.create_server({:imageRef=>14075, :flavorRef=>100, :key_name=>"my_default_key", :name=>"marios_server"})
|
96
|
+
# Create a new server and specify the keyname and security_groups to be used (dependent on provider support for these API extensions):
|
97
|
+
>> server = os.create_server({:imageRef=>14075, :flavorRef=>100, :key_name=>"my_default_key", :security_groups=>["test", "default"], :name=>"marios_server"})
|
98
98
|
=> #<OpenStack::Compute::Server:0x101433f08 ....
|
99
99
|
>> server.key_name
|
100
100
|
=> "my_default_key"
|
101
|
+
>> server.security_groups
|
101
102
|
|
102
103
|
# Delete the new server
|
103
104
|
>> newserver.delete!
|
@@ -143,6 +144,41 @@ See the class definitions for documentation on specific methods and operations.
|
|
143
144
|
>> os.delete_keypair("test_key_imported")
|
144
145
|
=> true
|
145
146
|
|
147
|
+
# List all security groups:
|
148
|
+
>> os.security_groups
|
149
|
+
=> { "1381" => { :tenant_id=>"12345678909876", :id=>1381, :name=>"default", :description=>"default",
|
150
|
+
:rules=> [
|
151
|
+
{:from_port=>22, :group=>{}, :ip_protocol=>"tcp", :to_port=>22,
|
152
|
+
:parent_group_id=>1381, :ip_range=>{:cidr=>"0.0.0.0/0"}, :id=>4902},
|
153
|
+
]
|
154
|
+
},
|
155
|
+
"1234" => { ... } }
|
156
|
+
|
157
|
+
# Get a specific security group:
|
158
|
+
>> os.security_group(1381)
|
159
|
+
=> { "1381" => { :tenant_id=>"12345678909876", :id=>1381, :name=>"default", :description=>"default",
|
160
|
+
:rules=> [
|
161
|
+
{:from_port=>22, :group=>{}, :ip_protocol=>"tcp", :to_port=>22,
|
162
|
+
:parent_group_id=>1381, :ip_range=>{:cidr=>"0.0.0.0/0"}, :id=>4902},
|
163
|
+
]
|
164
|
+
}}
|
165
|
+
|
166
|
+
#Create a new security group:
|
167
|
+
>> os.create_security_group("devel_group", "all development machines")
|
168
|
+
=> {"9573"=>{:rules=>[], :tenant_id=>"46871569847393", :id=>9573, :name=>"devel_group", :description=>"all development machines"}}
|
169
|
+
|
170
|
+
#Create a new security group rule - first param is id of the security group for this rule. Instead of :cidr you may specify :group_id to use another group as source:
|
171
|
+
>> os.create_security_group_rule(9567, {:ip_protocol=>"tcp", :from_port=>"123", :to_port=>"123", :cidr=>"192.168.0.1/16" })
|
172
|
+
=> => {"27375"=>{:from_port=>123, :group=>{}, :ip_protocol=>"tcp", :to_port=>123, :parent_group_id=>9573, :ip_range=>{:cidr=>"192.168.0.1/16"}, :id=>27375}}
|
173
|
+
|
174
|
+
#Delete a security group rule:
|
175
|
+
>> os.delete_security_group_rule(27375)
|
176
|
+
=> true
|
177
|
+
|
178
|
+
#Delete a security group:
|
179
|
+
>> os.delete_security_group(9571)
|
180
|
+
=> true
|
181
|
+
|
146
182
|
== Examples for Object-Store:
|
147
183
|
|
148
184
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'ipaddr'
|
1
2
|
module OpenStack
|
2
3
|
module Compute
|
3
4
|
|
@@ -33,6 +34,34 @@ module Compute
|
|
33
34
|
@version = version
|
34
35
|
end
|
35
36
|
end
|
37
|
+
|
38
|
+
NON_ROUTABLE_ADDRESSES = [IPAddr.new("10.0.0.0/8"), IPAddr.new("192.168.0.0/16"), IPAddr.new("172.16.0.0/12")]
|
39
|
+
|
40
|
+
def self.is_private?(address_string)
|
41
|
+
NON_ROUTABLE_ADDRESSES.each do |no_route|
|
42
|
+
return true if no_route.include?(address_string)
|
43
|
+
end
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
#IN: { "private"=> [{"addr"=>"10.7.206.171", "version"=>4}, {"addr"=>"15.185.160.208", "version"=>4}]}
|
48
|
+
#OUT: { "private"=> [{"addr"=>"10.7.206.171", "version"=>4}],
|
49
|
+
# "public"=> [{"addr"=>"15.185.160.208", "version"=>4}] }
|
50
|
+
def self.fix_labels(addresses_info)
|
51
|
+
addresses_info.inject({"public"=>[], "private"=>[]}) do |res, (label,address_struct_list)|
|
52
|
+
address_struct_list.each do |address_struct|
|
53
|
+
if(address_struct["version"==6])#v6 addresses are all routable...
|
54
|
+
res["public"] << address_struct
|
55
|
+
else
|
56
|
+
is_private?(address_struct["addr"])? res["private"] << address_struct : res["public"] << address_struct
|
57
|
+
end
|
58
|
+
end
|
59
|
+
res
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
|
36
65
|
end
|
37
66
|
|
38
67
|
end
|
@@ -4,8 +4,10 @@ module Compute
|
|
4
4
|
class Connection
|
5
5
|
|
6
6
|
attr_accessor :connection
|
7
|
+
attr_accessor :extensions
|
7
8
|
|
8
9
|
def initialize(connection)
|
10
|
+
@extensions = nil
|
9
11
|
@connection = connection
|
10
12
|
OpenStack::Authentication.init(@connection)
|
11
13
|
end
|
@@ -63,14 +65,19 @@ module Compute
|
|
63
65
|
path = OpenStack.paginate(options).empty? ? "#{@connection.service_path}/servers/detail" : "#{@connection.service_path}/servers/detail?#{OpenStack.paginate(options)}"
|
64
66
|
response = @connection.csreq("GET",@connection.service_host,path,@connection.service_port,@connection.service_scheme)
|
65
67
|
OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
|
66
|
-
|
68
|
+
json_server_list = JSON.parse(response.body)["servers"]
|
69
|
+
json_server_list.each do |server|
|
70
|
+
server["addresses"] = OpenStack::Compute::Address.fix_labels(server["addresses"])
|
71
|
+
end
|
72
|
+
OpenStack.symbolize_keys(json_server_list)
|
67
73
|
end
|
68
74
|
alias :servers_detail :list_servers_detail
|
69
75
|
|
70
76
|
# Creates a new server instance on OpenStack Compute
|
71
77
|
#
|
72
78
|
# The argument is a hash of options. The keys :name, :flavorRef,
|
73
|
-
# and :imageRef are required; :metadata
|
79
|
+
# and :imageRef are required; :metadata, :security_groups,
|
80
|
+
# :key_name and :personality are optional.
|
74
81
|
#
|
75
82
|
# :flavorRef and :imageRef are href strings identifying a particular
|
76
83
|
# server flavor and image to use when building the server. The :imageRef
|
@@ -94,7 +101,9 @@ module Compute
|
|
94
101
|
# :imageRef => '3',
|
95
102
|
# :flavorRef => '1',
|
96
103
|
# :metadata => {'Racker' => 'Fanatical'},
|
97
|
-
# :personality => {'/home/bob/wedding.jpg' => '/root/wedding.jpg'}
|
104
|
+
# :personality => {'/home/bob/wedding.jpg' => '/root/wedding.jpg'},
|
105
|
+
# :key_name => "mykey",
|
106
|
+
# :security_groups => [ "devel", "test"])
|
98
107
|
# => #<OpenStack::Compute::Server:0x101229eb0 ...>
|
99
108
|
# >> server.name
|
100
109
|
# => "NewServer"
|
@@ -105,6 +114,7 @@ module Compute
|
|
105
114
|
def create_server(options)
|
106
115
|
raise OpenStack::Exception::MissingArgument, "Server name, flavorRef, and imageRef, must be supplied" unless (options[:name] && options[:flavorRef] && options[:imageRef])
|
107
116
|
options[:personality] = Personalities.get_personality(options[:personality])
|
117
|
+
options[:security_groups] = (options[:security_groups] || []).inject([]){|res, c| res << {"name"=>c} ;res}
|
108
118
|
data = JSON.generate(:server => options)
|
109
119
|
response = @connection.csreq("POST",@connection.service_host,"#{@connection.service_path}/servers",@connection.service_port,@connection.service_scheme,{'content-type' => 'application/json'},data)
|
110
120
|
OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
|
@@ -228,10 +238,13 @@ module Compute
|
|
228
238
|
# }
|
229
239
|
#
|
230
240
|
def api_extensions
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
241
|
+
if @extensions.nil?
|
242
|
+
response = @connection.req("GET", "/extensions")
|
243
|
+
OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
|
244
|
+
res = OpenStack.symbolize_keys(JSON.parse(response.body))
|
245
|
+
@extensions = res[:extensions].inject({}){|result, c| result[c[:alias].to_sym] = c ; result}
|
246
|
+
end
|
247
|
+
@extensions
|
235
248
|
end
|
236
249
|
|
237
250
|
# Retrieve a list of key pairs associated with the current authenticated account
|
@@ -313,6 +326,67 @@ module Compute
|
|
313
326
|
true
|
314
327
|
end
|
315
328
|
|
329
|
+
#Security Groups:
|
330
|
+
#Returns a hash with the security group IDs as keys:
|
331
|
+
#=> { "1381" => { :tenant_id=>"12345678909876", :id=>1381, :name=>"default", :description=>"default",
|
332
|
+
# :rules=> [
|
333
|
+
# {:from_port=>22, :group=>{}, :ip_protocol=>"tcp", :to_port=>22,
|
334
|
+
# :parent_group_id=>1381, :ip_range=>{:cidr=>"0.0.0.0/0"}, :id=>4902},
|
335
|
+
# {:from_port=>80, :group=>{}, :ip_protocol=>"tcp", :to_port=>80,
|
336
|
+
# :parent_group_id=>1381, :ip_range=>{:cidr=>"0.0.0.0/0"}, :id=>4903},
|
337
|
+
# {:from_port=>443, :group=>{}, :ip_protocol=>"tcp", :to_port=>443,
|
338
|
+
# :parent_group_id=>1381, :ip_range=>{:cidr=>"0.0.0.0/0"}, :id=>4904},
|
339
|
+
# {:from_port=>-1, :group=>{}, :ip_protocol=>"icmp", :to_port=>-1,
|
340
|
+
# :parent_group_id=>1381, :ip_range=>{:cidr=>"0.0.0.0/0"}, :id=>4905}],
|
341
|
+
# ]
|
342
|
+
# },
|
343
|
+
# "1234" => { ... } }
|
344
|
+
#
|
345
|
+
def security_groups
|
346
|
+
raise OpenStack::Exception::NotImplemented.new("os-security-groups not implemented by #{@connection.http.keys.first}", 501, "NOT IMPLEMENTED") unless api_extensions[:"os-security-groups"] or api_extensions[:security_groups]
|
347
|
+
response = @connection.req("GET", "/os-security-groups")
|
348
|
+
res = OpenStack.symbolize_keys(JSON.parse(response.body))
|
349
|
+
res[:security_groups].inject({}){|result, c| result[c[:id].to_s] = c ; result }
|
350
|
+
end
|
351
|
+
|
352
|
+
def security_group(id)
|
353
|
+
raise OpenStack::Exception::NotImplemented.new("os-security-groups not implemented by #{@connection.http.keys.first}", 501, "NOT IMPLEMENTED") unless api_extensions[:"os-security-groups"] or api_extensions[:security_groups]
|
354
|
+
response = @connection.req("GET", "/os-security-groups/#{id}")
|
355
|
+
res = OpenStack.symbolize_keys(JSON.parse(response.body))
|
356
|
+
{res[:security_group][:id].to_s => res[:security_group]}
|
357
|
+
end
|
358
|
+
|
359
|
+
def create_security_group(name, description)
|
360
|
+
raise OpenStack::Exception::NotImplemented.new("os-security-groups not implemented by #{@connection.http.keys.first}", 501, "NOT IMPLEMENTED") unless api_extensions[:"os-security-groups"] or api_extensions[:security_groups]
|
361
|
+
data = JSON.generate(:security_group => { "name" => name, "description" => description})
|
362
|
+
response = @connection.req("POST", "/os-security-groups", {:data => data})
|
363
|
+
res = OpenStack.symbolize_keys(JSON.parse(response.body))
|
364
|
+
{res[:security_group][:id].to_s => res[:security_group]}
|
365
|
+
end
|
366
|
+
|
367
|
+
def delete_security_group(id)
|
368
|
+
raise OpenStack::Exception::NotImplemented.new("os-security-groups not implemented by #{@connection.http.keys.first}", 501, "NOT IMPLEMENTED") unless api_extensions[:"os-security-groups"] or api_extensions[:security_groups]
|
369
|
+
response = @connection.req("DELETE", "/os-security-groups/#{id}")
|
370
|
+
true
|
371
|
+
end
|
372
|
+
|
373
|
+
#params: { :ip_protocol=>"tcp", :from_port=>"123", :to_port=>"123", :cidr=>"192.168.0.1/16", :group_id:="123" }
|
374
|
+
#observed behaviour against Openstack@HP cloud - can specify either cidr OR group_id as source, but not both
|
375
|
+
#if both specified, the group is used and the cidr ignored.
|
376
|
+
def create_security_group_rule(security_group_id, params)
|
377
|
+
raise OpenStack::Exception::NotImplemented.new("os-security-groups not implemented by #{@connection.http.keys.first}", 501, "NOT IMPLEMENTED") unless api_extensions[:"os-security-groups"] or api_extensions[:security_groups]
|
378
|
+
params.merge!({:parent_group_id=>security_group_id.to_s})
|
379
|
+
data = JSON.generate(:security_group_rule => params)
|
380
|
+
response = @connection.req("POST", "/os-security-group-rules", {:data => data})
|
381
|
+
res = OpenStack.symbolize_keys(JSON.parse(response.body))
|
382
|
+
{res[:security_group_rule][:id].to_s => res[:security_group_rule]}
|
383
|
+
end
|
384
|
+
|
385
|
+
def delete_security_group_rule(id)
|
386
|
+
raise OpenStack::Exception::NotImplemented.new("os-security-groups not implemented by #{@connection.http.keys.first}", 501, "NOT IMPLEMENTED") unless api_extensions[:"os-security-groups"] or api_extensions[:security_groups]
|
387
|
+
response = @connection.req("DELETE", "/os-security-group-rules/#{id}")
|
388
|
+
true
|
389
|
+
end
|
316
390
|
end
|
317
391
|
end
|
318
392
|
end
|
@@ -17,6 +17,7 @@ module Compute
|
|
17
17
|
attr_reader :metadata
|
18
18
|
attr_accessor :adminPass
|
19
19
|
attr_reader :key_name
|
20
|
+
attr_reader :security_groups
|
20
21
|
|
21
22
|
# This class is the representation of a single Server object. The constructor finds the server identified by the specified
|
22
23
|
# ID number, accesses the API via the populate method to get information about that server, and returns the object.
|
@@ -53,7 +54,7 @@ module Compute
|
|
53
54
|
OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
|
54
55
|
data = JSON.parse(response.body)["server"]
|
55
56
|
end
|
56
|
-
@id = data["
|
57
|
+
@id = data["uuid"]
|
57
58
|
@name = data["name"]
|
58
59
|
@status = data["status"]
|
59
60
|
@progress = data["progress"]
|
@@ -63,6 +64,7 @@ module Compute
|
|
63
64
|
@image = data["image"]
|
64
65
|
@flavor = data["flavor"]
|
65
66
|
@key_name = data["key_name"] # if provider uses the keys API extension for accessing servers
|
67
|
+
@security_groups = data["security_groups"].inject([]){|res, c| res << c["id"] ; res}
|
66
68
|
true
|
67
69
|
end
|
68
70
|
alias :refresh :populate
|
@@ -234,6 +236,7 @@ module Compute
|
|
234
236
|
end
|
235
237
|
|
236
238
|
def get_addresses(address_info)
|
239
|
+
address_info = OpenStack::Compute::Address.fix_labels(address_info)
|
237
240
|
address_list = OpenStack::Compute::AddressList.new
|
238
241
|
address_info.each do |label, addr|
|
239
242
|
addr.each do |address|
|
metadata
CHANGED
@@ -1,48 +1,42 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: openstack
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.2
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
- 1
|
10
|
-
version: 1.0.1
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Dan Prince
|
14
9
|
- Marios Andreou
|
15
10
|
autorequire:
|
16
11
|
bindir: bin
|
17
12
|
cert_chain: []
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
- !ruby/object:Gem::Dependency
|
13
|
+
date: 2012-08-24 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
22
16
|
name: json
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
25
18
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
33
23
|
type: :runtime
|
34
|
-
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
35
31
|
description: API Binding for OpenStack
|
36
|
-
email:
|
32
|
+
email:
|
37
33
|
- dprince@redhat.com
|
38
34
|
- marios@redhat.com
|
39
35
|
executables: []
|
40
|
-
|
41
36
|
extensions: []
|
42
|
-
|
43
|
-
extra_rdoc_files:
|
37
|
+
extra_rdoc_files:
|
44
38
|
- README.rdoc
|
45
|
-
files:
|
39
|
+
files:
|
46
40
|
- COPYING
|
47
41
|
- README.rdoc
|
48
42
|
- VERSION
|
@@ -60,37 +54,27 @@ files:
|
|
60
54
|
- lib/openstack/swift/storage_object.rb
|
61
55
|
homepage: https://github.com/ruby-openstack/ruby-openstack
|
62
56
|
licenses: []
|
63
|
-
|
64
57
|
post_install_message:
|
65
58
|
rdoc_options: []
|
66
|
-
|
67
|
-
require_paths:
|
59
|
+
require_paths:
|
68
60
|
- lib
|
69
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
62
|
none: false
|
71
|
-
requirements:
|
72
|
-
- -
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
|
75
|
-
|
76
|
-
- 0
|
77
|
-
version: "0"
|
78
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
68
|
none: false
|
80
|
-
requirements:
|
81
|
-
- -
|
82
|
-
- !ruby/object:Gem::Version
|
83
|
-
|
84
|
-
segments:
|
85
|
-
- 0
|
86
|
-
version: "0"
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
87
73
|
requirements: []
|
88
|
-
|
89
74
|
rubyforge_project:
|
90
|
-
rubygems_version: 1.
|
75
|
+
rubygems_version: 1.8.24
|
91
76
|
signing_key:
|
92
77
|
specification_version: 3
|
93
78
|
summary: OpenStack Ruby API
|
94
79
|
test_files: []
|
95
|
-
|
96
|
-
has_rdoc: false
|
80
|
+
has_rdoc:
|