openstack 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING ADDED
@@ -0,0 +1,7 @@
1
+ Unless otherwise noted, all files are released under the MIT license, exceptions contain licensing information in them.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,189 @@
1
+ = Ruby OpenStack
2
+
3
+ == Description
4
+
5
+ Ruby Openstack Compute and Object-Store bindings for the v1.0 OSAPI.
6
+
7
+ Currently supports both v1.0 and v2.0 (keystone) auth.
8
+
9
+ Use OpenStack::Connection.create to get a handle to an OpenStack service - set the :service_type parameter to either 'compute' or 'object-store' (defaults to 'compute')
10
+
11
+ == Examples
12
+
13
+ == For Compute:
14
+
15
+ See the class definitions for documentation on specific methods and operations.
16
+
17
+ require 'openstack'
18
+
19
+ os = OpenStack::Connection.create(:username => USERNAME, :api_key => API_KEY, :authtenant => TENANT, :auth_url => API_URL, :service_type => "compute")
20
+
21
+ # Get a listing of all current servers
22
+ >> os.servers
23
+ => [{:name=>"Server1", :id=>110917}]
24
+
25
+ # Access a specific server
26
+ >> server = os.server(110917)
27
+ >> server.name
28
+ => "Server1"
29
+
30
+ # See what type of server this is
31
+ >> server.flavor.name
32
+ => "256 server"
33
+ >> server.image.name
34
+ => "Ubuntu 8.04.2 LTS (hardy)"
35
+
36
+ # Soft-reboot the server
37
+ >> server.reboot
38
+ => true
39
+
40
+ # Create a new 512MB CentOS 5.2 server. The root password is returned in the adminPass method.
41
+ >> image = os.get_image(8)
42
+ => #<OpenStack::Compute::Image:0x1014a8060 ...>, status"ACTIVE"
43
+ >> image.name
44
+ => "CentOS 5.2"
45
+ >> flavor = os.get_flavor(2)
46
+ => #<OpenStack::Compute::Flavor:0x101469130 @disk=20, @name="512 server", @id=2, @ram=512>
47
+ >> flavor.name
48
+ => "512 server"
49
+ >> newserver = os.create_server(:name => "New Server", :imageRef => image.id, :flavorRef => flavor.id)
50
+ => #<OpenStack::Compute::Server:0x101433f08 ....
51
+ >> newserver.status
52
+ => "BUILD"
53
+ >> newserver.progress
54
+ => 0
55
+ >> newserver.adminPass
56
+ => "NewServerMbhzUnO"
57
+ >> newserver.refresh
58
+ => true
59
+ >> newserver.progress
60
+ => 12
61
+
62
+ # Delete the new server
63
+ >> newserver.delete!
64
+ => true
65
+
66
+ == Examples for Object-Store:
67
+
68
+
69
+ os = OpenStack::Connection.create(:username => USERNAME, :api_key => API_KEY, :authtenant => TENANT, :auth_url => API_URL, :service_type => "object-store")
70
+
71
+ # Get info on container count and bytes:
72
+ >> os.get_info
73
+ => {:count=>2, :bytes=>495041}
74
+
75
+ # Get list of containers under this account:
76
+ >> os.containers
77
+ => ["another_containerfoo", "marios_test_container"]
78
+
79
+ # Get details of containers under this account:
80
+ >> os.containers_detail
81
+ =>=> {"another_containerfoo"=>{:count=>"3", :bytes=>"1994"}, "marios_test_container"=>{:count=>"2", :bytes=>"493047"}}
82
+
83
+ # Check if a container exists
84
+ >> os.container_exists?("no_such_thing")
85
+ => false
86
+
87
+ # Create new container
88
+ >> os.create_container("foo")
89
+ => => #<OpenStack::Swift::Container:0xb7275c38 ...... (rest of OpenStack::Swift::Container object)
90
+
91
+ # Delete container
92
+ >> os.delete_container("foo")
93
+ => true
94
+
95
+ # Get a container (OpenStack::Swift::Container object):
96
+ >> cont = os.container("foo")
97
+ => #<OpenStack::Swift::Container:0xb7262124 ...... (rest of OpenStack::Swift::Container object)
98
+
99
+ # Retrieve container metadata:
100
+ >> cont.container_metadata
101
+ =>{:count=>"2", :bytes=>"493047", :metadata=>{"foo"=>"bar", "author"=>"foobar", "jj"=>"foobar", "date"=>"today", "owner"=>"foo"}}
102
+
103
+ # Retrieve user defined metadata:
104
+ >> cont.metadata
105
+ => {"foo"=>"bar", "author"=>"foobar", "jj"=>"foobar", "date"=>"today", "owner"=>"foo"}
106
+
107
+ # Set user defined metadata:
108
+ >> cont.set_metadata({"X-Container-Meta-Author"=> "msa", "version"=>"1.2", :date=>"today"})
109
+ => true
110
+
111
+ # Get list of objects:
112
+ >> cont.objects
113
+ => ["fosdem2012.pdf", "moved_object"]
114
+
115
+ # Get list of objects with details:
116
+ >> cont.objects_detail
117
+ => {"fosdem2012.pdf"=>{:bytes=>"493009", :content_type=>"application/json", :hash=>"494e444f92a8082dabac80a74cdf2c3b", :last_modified=>"2012-04-26T09:22:51.611230"}, "moved_object"=>{:bytes=>"38", :content_type=>"application/json", :hash=>"a7942f97fe6bd34920a4f61fe5e604a5", :last_modified=>"2012-04-26T09:35:33.839920"}}
118
+
119
+ # Check if container is empty:
120
+ >> cont.empty?
121
+ => false
122
+
123
+ # Check if object exists:
124
+ >> cont.object_exists?("foo")
125
+ => false
126
+
127
+ # Create new object
128
+ >> new_obj = cont.create_object("foo", {:metadata=>{"herpy"=>"derp"}, :content_type=>"text/plain"}, "this is the data") [can also supply File.open(/path/to/file) and the data]
129
+ => #<OpenStack::Swift::StorageObject:0xb72fdac0 ... etc
130
+
131
+ # Delete object
132
+ >> cont.delete_object("foo")
133
+ => true
134
+
135
+ # Get handle to an OpenStack::Swift::StorageObject Object
136
+ >> obj = cont.object("foo")
137
+ => #<OpenStack::Swift::StorageObject:0xb72fdac0 ... etc
138
+
139
+ # Get object metadata
140
+ >> obj.object_metadata
141
+ =>
142
+
143
+ # Get user defined metadata pairs
144
+ >> obj.metadata
145
+ =>
146
+
147
+ # Get data (non streaming - returned as a String)
148
+ >> obj.data
149
+ => "This is the text stored in the file"
150
+
151
+ # Get data (streaming - requires a block)
152
+ >> data = ""; object.data_stream do |chunk| data += chunk end
153
+ => #<Net::HTTPOK 200 OK readbody=true>
154
+ >> data
155
+ => "This is the text stored in the file"
156
+
157
+ # Set user defined metadata
158
+ >> obj.set_metadata({:foo=>"bar", "X-Object-Meta-herpa"=>"derp", "author"=>"me"})
159
+ => true
160
+
161
+ # (Over)Write object data
162
+ >> object.write("This is new data")
163
+ => true
164
+ >> object.data
165
+ => "This is new data"
166
+
167
+ # Copy object:
168
+ >>copied = obj.copy('copied_object', "destination_container", {:content_type=>"text/plain", :metadata=>{:herp=>"derp", "X-Object-Meta-foo"=>"bar} } )
169
+ => #<OpenStack::Swift::StorageObject:0xb728974c ..... etc
170
+
171
+ # Move object: (copy and then delete original):
172
+ >> moved = obj.move('moved_object', "destination_container", {:content_type=>"text/plain", :metadata=>{:herp=>"derp", "X-Object-Meta-foo"=>"bar"} } )
173
+ => #<OpenStack::Swift::StorageObject:0xb7266bd4 ...
174
+ >> moved.metadata
175
+ => {"foo"=>"bar", "herp"=>"derp", "herpy"=>"derp"}
176
+ >> obj.metadata
177
+ => OpenStack::Exception::ItemNotFound: The resource could not be found
178
+
179
+
180
+ == Authors
181
+
182
+ By Dan Prince <dprince@redhat.com>, Naveed Massjouni <naveedm9@gmail.com>, Marios Andreou <marios@redhat.com>
183
+
184
+ Initial code checkin on May 23rd 2012 - code refactored from and based on the Rackspace Cloud Servers gem
185
+ (https://github.com/rackspace/ruby-openstack-compute) and Rackspace Cloud Files gem (https://github.com/rackspace/ruby-cloudfiles).
186
+
187
+ == License
188
+
189
+ See COPYING for license information.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/lib/openstack.rb ADDED
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # == Ruby OpenStack API
4
+ #
5
+ # See COPYING for license information.
6
+ # ----
7
+ #
8
+ # === Documentation & Examples
9
+ # To begin reviewing the available methods and examples, view the README.rdoc file
10
+ #
11
+ # Example:
12
+ # os = OpenStack::Connection.create({:username => "herp@derp.com", :api_key=>"password",
13
+ # :auth_url => "https://region-a.geo-1.identity.cloudsvc.com:35357/v2.0/",
14
+ # :authtenant=>"herp@derp.com-default-tenant", :service_type=>"object-store")
15
+ #
16
+ # will return a handle to the object-storage service swift. Alternatively, passing
17
+ # :service_type=>"compute" will return a handle to the compute service nova.
18
+
19
+ module OpenStack
20
+
21
+ VERSION = IO.read(File.dirname(__FILE__) + '/../VERSION')
22
+ require 'net/http'
23
+ require 'net/https'
24
+ require 'uri'
25
+ require 'rubygems'
26
+ require 'json'
27
+ require 'date'
28
+
29
+ unless "".respond_to? :each_char
30
+ require "jcode"
31
+ $KCODE = 'u'
32
+ end
33
+
34
+ $:.unshift(File.dirname(__FILE__))
35
+ require 'openstack/connection'
36
+ require 'openstack/compute/connection'
37
+ require 'openstack/compute/server'
38
+ require 'openstack/compute/image'
39
+ require 'openstack/compute/flavor'
40
+ require 'openstack/compute/address'
41
+ require 'openstack/compute/personalities'
42
+ require 'openstack/swift/connection'
43
+ require 'openstack/swift/container'
44
+ require 'openstack/swift/storage_object'
45
+
46
+ # Constants that set limits on server creation
47
+ MAX_PERSONALITY_ITEMS = 5
48
+ MAX_PERSONALITY_FILE_SIZE = 10240
49
+ MAX_SERVER_PATH_LENGTH = 255
50
+
51
+ # Helper method to recursively symbolize hash keys.
52
+ def self.symbolize_keys(obj)
53
+ case obj
54
+ when Array
55
+ obj.inject([]){|res, val|
56
+ res << case val
57
+ when Hash, Array
58
+ symbolize_keys(val)
59
+ else
60
+ val
61
+ end
62
+ res
63
+ }
64
+ when Hash
65
+ obj.inject({}){|res, (key, val)|
66
+ nkey = case key
67
+ when String
68
+ key.to_sym
69
+ else
70
+ key
71
+ end
72
+ nval = case val
73
+ when Hash, Array
74
+ symbolize_keys(val)
75
+ else
76
+ val
77
+ end
78
+ res[nkey] = nval
79
+ res
80
+ }
81
+ else
82
+ obj
83
+ end
84
+ end
85
+
86
+ def self.paginate(options = {})
87
+ path_args = []
88
+ path_args.push(URI.encode("limit=#{options[:limit]}")) if options[:limit]
89
+ path_args.push(URI.encode("offset=#{options[:offset]}")) if options[:offset]
90
+ path_args.join("&")
91
+ end
92
+
93
+ # e.g. keys = [:limit, :marker]
94
+ # params = {:limit=>2, :marker="marios", :prefix=>"/"}
95
+ # you want url = /container_name?limit=2&marker=marios
96
+ def self.get_query_params(params, keys, url="")
97
+ set_keys = params.inject([]){|res, (k,v)| res << k if keys.include?(k) and not v.nil?; res }
98
+ return url if set_keys.empty?
99
+ url = "#{url}?#{set_keys[0]}=#{params[set_keys[0]]}"
100
+ set_keys.slice!(0)
101
+ set_keys.each do |k|
102
+ url = "#{url}&#{k}=#{params[set_keys[0]]}"
103
+ end
104
+ url
105
+ end
106
+
107
+ end
@@ -0,0 +1,39 @@
1
+ module OpenStack
2
+ module Compute
3
+
4
+ class AddressList < Array
5
+ def [](index)
6
+ addresses = Array.new
7
+ if index.class == Symbol then
8
+ self.each do |address|
9
+ if address.label == index.to_s then
10
+ addresses << address
11
+ end
12
+ end
13
+ addresses
14
+ else
15
+ super
16
+ end
17
+ end
18
+ end
19
+
20
+ class Address
21
+
22
+ attr_reader :address
23
+ attr_reader :label
24
+ attr_reader :version
25
+
26
+ def initialize(label, address, version = 4)
27
+ @label = label
28
+ if address.class == Hash then
29
+ @address = address["addr"]
30
+ @version = address["version"]
31
+ else
32
+ @address = address
33
+ @version = version
34
+ end
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,207 @@
1
+ module OpenStack
2
+ module Compute
3
+
4
+ class Connection
5
+
6
+ attr_accessor :connection
7
+
8
+ def initialize(connection)
9
+ @connection = connection
10
+ OpenStack::Authentication.init(@connection)
11
+ end
12
+
13
+ # Returns true if the authentication was successful and returns false otherwise.
14
+ #
15
+ # cs.authok?
16
+ # => true
17
+ def authok?
18
+ @connection.authok
19
+ end
20
+
21
+ # Returns the OpenStack::Compute::Server object identified by the given id.
22
+ #
23
+ # >> server = cs.get_server(110917)
24
+ # => #<OpenStack::Compute::Server:0x101407ae8 ...>
25
+ # >> server.name
26
+ # => "MyServer"
27
+ def get_server(id)
28
+ OpenStack::Compute::Server.new(self,id)
29
+ end
30
+ alias :server :get_server
31
+
32
+ # Returns an array of hashes, one for each server that exists under this account. The hash keys are :name and :id.
33
+ #
34
+ # You can also provide :limit and :offset parameters to handle pagination.
35
+ #
36
+ # >> cs.list_servers
37
+ # => [{:name=>"MyServer", :id=>110917}]
38
+ #
39
+ # >> cs.list_servers(:limit => 2, :offset => 3)
40
+ # => [{:name=>"demo-standingcloud-lts", :id=>168867},
41
+ # {:name=>"demo-aicache1", :id=>187853}]
42
+ def list_servers(options = {})
43
+ anti_cache_param="cacheid=#{Time.now.to_i}"
44
+ path = OpenStack.paginate(options).empty? ? "#{@connection.service_path}/servers?#{anti_cache_param}" : "#{@connection.service_path}/servers?#{OpenStack.paginate(options)}&#{anti_cache_param}"
45
+ response = @connection.csreq("GET",@connection.service_host,path,@connection.service_port,@connection.service_scheme)
46
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
47
+ OpenStack.symbolize_keys(JSON.parse(response.body)["servers"])
48
+ end
49
+ alias :servers :list_servers
50
+
51
+ # Returns an array of hashes with more details about each server that exists under this account. Additional information
52
+ # includes public and private IP addresses, status, hostID, and more. All hash keys are symbols except for the metadata
53
+ # hash, which are verbatim strings.
54
+ #
55
+ # You can also provide :limit and :offset parameters to handle pagination.
56
+ # >> cs.list_servers_detail
57
+ # => [{:name=>"MyServer", :addresses=>{:public=>["67.23.42.37"], :private=>["10.176.241.237"]}, :metadata=>{"MyData" => "Valid"}, :imageRef=>10, :progress=>100, :hostId=>"36143b12e9e48998c2aef79b50e144d2", :flavorRef=>1, :id=>110917, :status=>"ACTIVE"}]
58
+ #
59
+ # >> cs.list_servers_detail(:limit => 2, :offset => 3)
60
+ # => [{:status=>"ACTIVE", :imageRef=>10, :progress=>100, :metadata=>{}, :addresses=>{:public=>["x.x.x.x"], :private=>["x.x.x.x"]}, :name=>"demo-standingcloud-lts", :id=>168867, :flavorRef=>1, :hostId=>"xxxxxx"},
61
+ # {:status=>"ACTIVE", :imageRef=>8, :progress=>100, :metadata=>{}, :addresses=>{:public=>["x.x.x.x"], :private=>["x.x.x.x"]}, :name=>"demo-aicache1", :id=>187853, :flavorRef=>3, :hostId=>"xxxxxx"}]
62
+ def list_servers_detail(options = {})
63
+ path = OpenStack.paginate(options).empty? ? "#{@connection.service_path}/servers/detail" : "#{@connection.service_path}/servers/detail?#{OpenStack.paginate(options)}"
64
+ response = @connection.csreq("GET",@connection.service_host,path,@connection.service_port,@connection.service_scheme)
65
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
66
+ OpenStack.symbolize_keys(JSON.parse(response.body)["servers"])
67
+ end
68
+ alias :servers_detail :list_servers_detail
69
+
70
+ # Creates a new server instance on OpenStack Compute
71
+ #
72
+ # The argument is a hash of options. The keys :name, :flavorRef,
73
+ # and :imageRef are required; :metadata and :personality are optional.
74
+ #
75
+ # :flavorRef and :imageRef are href strings identifying a particular
76
+ # server flavor and image to use when building the server. The :imageRef
77
+ # can either be a stock image, or one of your own created with the
78
+ # server.create_image method.
79
+ #
80
+ # The :metadata argument should be a hash of key/value pairs. This
81
+ # metadata will be applied to the server at the OpenStack Compute API level.
82
+ #
83
+ # The "Personality" option allows you to include up to five files, # of
84
+ # 10Kb or less in size, that will be placed on the created server.
85
+ # For :personality, pass a hash of the form {'local_path' => 'server_path'}.
86
+ # The file located at local_path will be base64-encoded and placed at the
87
+ # location identified by server_path on the new server.
88
+ #
89
+ # Returns a OpenStack::Compute::Server object. The root password is
90
+ # available in the adminPass instance method.
91
+ #
92
+ # >> server = cs.create_server(
93
+ # :name => 'NewServer',
94
+ # :imageRef => '3',
95
+ # :flavorRef => '1',
96
+ # :metadata => {'Racker' => 'Fanatical'},
97
+ # :personality => {'/home/bob/wedding.jpg' => '/root/wedding.jpg'})
98
+ # => #<OpenStack::Compute::Server:0x101229eb0 ...>
99
+ # >> server.name
100
+ # => "NewServer"
101
+ # >> server.status
102
+ # => "BUILD"
103
+ # >> server.adminPass
104
+ # => "NewServerSHMGpvI"
105
+ def create_server(options)
106
+ raise OpenStack::Exception::MissingArgument, "Server name, flavorRef, and imageRef, must be supplied" unless (options[:name] && options[:flavorRef] && options[:imageRef])
107
+ options[:personality] = Personalities.get_personality(options[:personality])
108
+ data = JSON.generate(:server => options)
109
+ response = @connection.csreq("POST",@connection.service_host,"#{@connection.service_path}/servers",@connection.service_port,@connection.service_scheme,{'content-type' => 'application/json'},data)
110
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
111
+ server_info = JSON.parse(response.body)['server']
112
+ server = OpenStack::Compute::Server.new(self,server_info['id'])
113
+ server.adminPass = server_info['adminPass']
114
+ return server
115
+ end
116
+
117
+ # Returns an array of hashes listing available server images that you have access too,
118
+ # including stock OpenStack Compute images and any that you have created. The "id" key
119
+ # in the hash can be used where imageRef is required. You can also provide :limit and
120
+ # :offset parameters to handle pagination.
121
+ #
122
+ # >> cs.list_images
123
+ # => [{:name=>"CentOS 5.2", :id=>2, :updated=>"2009-07-20T09:16:57-05:00", :status=>"ACTIVE", :created=>"2009-07-20T09:16:57-05:00"},
124
+ # {:name=>"Gentoo 2008.0", :id=>3, :updated=>"2009-07-20T09:16:57-05:00", :status=>"ACTIVE", :created=>"2009-07-20T09:16:57-05:00"},...
125
+ #
126
+ # >> cs.list_images(:limit => 3, :offset => 2)
127
+ # => [{:status=>"ACTIVE", :name=>"Fedora 11 (Leonidas)", :updated=>"2009-12-08T13:50:45-06:00", :id=>13},
128
+ # {:status=>"ACTIVE", :name=>"CentOS 5.3", :updated=>"2009-08-26T14:59:52-05:00", :id=>7},
129
+ # {:status=>"ACTIVE", :name=>"CentOS 5.4", :updated=>"2009-12-16T01:02:17-06:00", :id=>187811}]
130
+ def list_images(options = {})
131
+ path = OpenStack.paginate(options).empty? ? "#{@connection.service_path}/images/detail" : "#{@connection.service_path}/images/detail?#{OpenStack.paginate(options)}"
132
+ response = @connection.csreq("GET",@connection.service_host,path,@connection.service_port,@connection.service_scheme)
133
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
134
+ OpenStack.symbolize_keys(JSON.parse(response.body)['images'])
135
+ end
136
+ alias :images :list_images
137
+
138
+ # Returns a OpenStack::Compute::Image object for the image identified by the provided id.
139
+ #
140
+ # >> image = cs.get_image(8)
141
+ # => #<OpenStack::Compute::Image:0x101659698 ...>
142
+ def get_image(id)
143
+ OpenStack::Compute::Image.new(self,id)
144
+ end
145
+ alias :image :get_image
146
+
147
+ # Returns an array of hashes listing all available server flavors. The :id key in the hash can be used when flavorRef is required.
148
+ #
149
+ # You can also provide :limit and :offset parameters to handle pagination.
150
+ #
151
+ # >> cs.list_flavors
152
+ # => [{:name=>"256 server", :id=>1, :ram=>256, :disk=>10},
153
+ # {:name=>"512 server", :id=>2, :ram=>512, :disk=>20},...
154
+ #
155
+ # >> cs.list_flavors(:limit => 3, :offset => 2)
156
+ # => [{:ram=>1024, :disk=>40, :name=>"1GB server", :id=>3},
157
+ # {:ram=>2048, :disk=>80, :name=>"2GB server", :id=>4},
158
+ # {:ram=>4096, :disk=>160, :name=>"4GB server", :id=>5}]
159
+ def list_flavors(options = {})
160
+ path = OpenStack.paginate(options).empty? ? "#{@connection.service_path}/flavors/detail" : "#{@connection.service_path}/flavors/detail?#{OpenStack.paginate(options)}"
161
+ response = @connection.csreq("GET",@connection.service_host,path,@connection.service_port,@connection.service_scheme)
162
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
163
+ OpenStack.symbolize_keys(JSON.parse(response.body)['flavors'])
164
+ end
165
+ alias :flavors :list_flavors
166
+
167
+ # Returns a OpenStack::Compute::Flavor object for the flavor identified by the provided ID.
168
+ #
169
+ # >> flavor = cs.flavor(1)
170
+ # => #<OpenStack::Compute::Flavor:0x10156dcc0 @name="256 server", @disk=10, @id=1, @ram=256>
171
+ def get_flavor(id)
172
+ OpenStack::Compute::Flavor.new(self,id)
173
+ end
174
+ alias :flavor :get_flavor
175
+
176
+ # Returns the current state of the programatic API limits. Each account has certain limits on the number of resources
177
+ # allowed in the account, and a rate of API operations.
178
+ #
179
+ # The operation returns a hash. The :absolute hash key reveals the account resource limits, including the maxmimum
180
+ # amount of total RAM that can be allocated (combined among all servers), the maximum members of an IP group, and the
181
+ # maximum number of IP groups that can be created.
182
+ #
183
+ # The :rate hash key returns an array of hashes indicating the limits on the number of operations that can be performed in a
184
+ # given amount of time. An entry in this array looks like:
185
+ #
186
+ # {:regex=>"^/servers", :value=>50, :verb=>"POST", :remaining=>50, :unit=>"DAY", :resetTime=>1272399820, :URI=>"/servers*"}
187
+ #
188
+ # This indicates that you can only run 50 POST operations against URLs in the /servers URI space per day, we have not run
189
+ # any operations today (50 remaining), and gives the Unix time that the limits reset.
190
+ #
191
+ # Another example is:
192
+ #
193
+ # {:regex=>".*", :value=>10, :verb=>"PUT", :remaining=>10, :unit=>"MINUTE", :resetTime=>1272399820, :URI=>"*"}
194
+ #
195
+ # This says that you can run 10 PUT operations on all possible URLs per minute, and also gives the number remaining and the
196
+ # time that the limit resets.
197
+ #
198
+ # Use this information as you're building your applications to put in relevant pauses if you approach your API limitations.
199
+ def limits
200
+ response = @connection.csreq("GET",@connection.service_host,"#{@connection.service_path}/limits",@connection.service_port,@connection.service_scheme)
201
+ OpenStack::Exception.raise_exception(response) unless response.code.match(/^20.$/)
202
+ OpenStack.symbolize_keys(JSON.parse(response.body)['limits'])
203
+ end
204
+
205
+ end
206
+ end
207
+ end