openstack 1.0.1 → 1.0.2

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.
@@ -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 (some provider support the Keys extension):
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
+ 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
- OpenStack.symbolize_keys(JSON.parse(response.body)["servers"])
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 and :personality are optional.
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
- response = @connection.req("GET", "/extensions")
232
- OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
233
- res = OpenStack.symbolize_keys(JSON.parse(response.body))
234
- res[:extensions].inject({}){|result, c| result[c[:alias].to_sym] = c ; result}
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["id"]
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
- hash: 21
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
- date: 2012-06-22 00:00:00 Z
20
- dependencies:
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
- prerelease: false
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
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
33
23
  type: :runtime
34
- version_requirements: *id001
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
- hash: 3
75
- segments:
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
- hash: 3
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.7.2
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: