dropmyemail-openstack 1.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +7 -0
- data/README.rdoc +371 -0
- data/VERSION +1 -0
- data/lib/openstack.rb +112 -0
- data/lib/openstack/compute/address.rb +68 -0
- data/lib/openstack/compute/connection.rb +412 -0
- data/lib/openstack/compute/flavor.rb +35 -0
- data/lib/openstack/compute/image.rb +73 -0
- data/lib/openstack/compute/metadata.rb +116 -0
- data/lib/openstack/compute/personalities.rb +23 -0
- data/lib/openstack/compute/server.rb +254 -0
- data/lib/openstack/connection.rb +494 -0
- data/lib/openstack/image/connection.rb +16 -0
- data/lib/openstack/swift/connection.rb +185 -0
- data/lib/openstack/swift/container.rb +214 -0
- data/lib/openstack/swift/storage_object.rb +311 -0
- data/lib/openstack/volume/connection.rb +123 -0
- data/lib/openstack/volume/snapshot.rb +25 -0
- data/lib/openstack/volume/volume.rb +31 -0
- data/test/authentication_test.rb +134 -0
- data/test/connection_test.rb +39 -0
- data/test/exception_test.rb +49 -0
- data/test/metadata_test.rb +210 -0
- data/test/servers_test.rb +210 -0
- data/test/test_helper.rb +22 -0
- metadata +123 -0
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,371 @@
|
|
1
|
+
= Ruby OpenStack
|
2
|
+
|
3
|
+
This fork assumes Swauth authentication for Swift object store.
|
4
|
+
|
5
|
+
== Description
|
6
|
+
|
7
|
+
Ruby Openstack Compute, Object-Store and Block Storage bindings for the OpenStack API.
|
8
|
+
|
9
|
+
http://api.openstack.org/api-reference.html
|
10
|
+
|
11
|
+
Currently supports both v1.0 and v2.0 (keystone) auth.
|
12
|
+
|
13
|
+
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'). If the requested service is not deployed the gem will throw a OpenStack::Exception::NotImplemented (501) - e.g. :service_type is 'object-store' but swift service isn't deployed.
|
14
|
+
|
15
|
+
The OpenStack::Connection.create class method is a factory constructor which will return the appropriate Connection object, depending on the ':service_type' parameter passed with the options hash: set to either 'compute', 'volume', or 'object-store' (defaults to 'compute') - see below for examples.
|
16
|
+
|
17
|
+
Other parameters for the create method:
|
18
|
+
|
19
|
+
* :auth_url - the OpenStack service provider specific authentication url endpoint.
|
20
|
+
* :auth_method - the type of authentication to be used with the above auth_url - either 'password' (username/password, 'key' (ec2 style key/private key) or 'rax-kskey'.
|
21
|
+
* :authtenant_name OR :authtenant_id - one of these MUST be specified when talking to a v2 authentication endpoint (keystone) - depending on whether you use tenant name (or tenant ID). Passing only :authtenant will result in that parameter being used as tenant name.
|
22
|
+
* :username - the username or public key (depending on auth_method)
|
23
|
+
* :api_key - the password or private key (denending on auth_method).
|
24
|
+
|
25
|
+
=== Try it out:
|
26
|
+
|
27
|
+
sudo gem install openstack
|
28
|
+
[sudo] password for herp:
|
29
|
+
Successfully installed openstack-1.0.0
|
30
|
+
|
31
|
+
[herp@name lib]$ irb -rubygems
|
32
|
+
irb(main):001:0> require 'openstack'
|
33
|
+
=> true
|
34
|
+
|
35
|
+
irb(main):002:0> os = OpenStack::Connection.create({:username => "herp@derp.net", :api_key=>"1234abcd", :auth_method=>"password", :auth_url => "https://regionerer-g.go-bar.identity.dacloudfoo.herpy:13327/v2.0/", :authtenant_name =>"herp@derp.net-default-tenant", :service_type=>"compute"})
|
36
|
+
|
37
|
+
=> #<OpenStack::Compute::Connection:0xb7339070 @connection=#<OpenStack::Connection:0xb73392dc @service_scheme="https", @auth_host="regionerer-g.go-bar.identity.dacloudfoo.herpy", @http={}, @service_name=nil, @authuser="herp@derp.net", @proxy_port=nil, @auth_path="/v2.0/", @authtenant={:type=>"tenantName", :value=>"herp@derp.net-default-tenant"}, @service_port=443, @authkey="1235abcd", @authok=true, @service_type="compute", @auth_method="password", @auth_scheme="https", @service_host="az-2.region-a.geo-1.dacloudfoo.herpy", @is_debug=nil, @proxy_host=nil, @service_path="/v1.1/482195756462871", @auth_port=35357, @auth_url="https://regionerer-g.go-bar.identity.dacloudfoo.herpy:13327/v2.0/", @region=nil, @authtoken="Auth_543254fdsasabd546543a3", @retry_auth=nil>>
|
38
|
+
|
39
|
+
irb(main):003:0> os.servers
|
40
|
+
=> []
|
41
|
+
|
42
|
+
irb(main):004:0> os = OpenStack::Connection.create({:username => "AWHFDADHJ32EL6V23GFK", :api_key=>"jd823jFDJEY2/82jfhYteG52AKJAUEY184JHRfeR", :auth_method=> "key", :auth_url => "https://regionerer-g.go-bar.identity.dacloudfoo.herpy:13327/v2.0/", :authtenant_id =>"482195756462871", :service_type=>"object-store"})
|
43
|
+
|
44
|
+
=> #<OpenStack::Swift::Connection:0xb72ff2a8 @connection=#<OpenStack::Connection:0xb72ff460 @service_scheme="https", @auth_host="regionerer-g.go-bar.identity.dacloudfoo.herpy", @http={}, @service_name=nil, @authuser="AWHFDADHJ32EL6V23GFK", @proxy_port=nil, @auth_path="/v2.0/", @authtenant={:type=>"tenantId", :value=>"482195756462871"}, @service_port=443, @authkey="jd823jFDJEY2/82jfhYteG52AKJAUEY184JHRfeR", @authok=true, @service_type="object-store", @auth_method="key", @auth_scheme="https", @service_host="region-a.geo-1.objects.dacloudfoo.herpy", @is_debug=nil, @proxy_host=nil, @service_path="/v1.0/482195756462871", @auth_port=35357, @auth_url="https://regionerer-g.go-bar.identity.dacloudfoo.herpy:13327/v2.0/", @region=nil, @authtoken="Auth_543254fdsasabd546543a3", @retry_auth=nil>>
|
45
|
+
|
46
|
+
irb(main):006:0> os.containers
|
47
|
+
=> ["herpy_Foo_container", "derpy_bar_bucket"]
|
48
|
+
|
49
|
+
== Examples
|
50
|
+
|
51
|
+
== For Compute:
|
52
|
+
|
53
|
+
See the class definitions for documentation on specific methods and operations.
|
54
|
+
|
55
|
+
require 'openstack'
|
56
|
+
|
57
|
+
os = OpenStack::Connection.create(:username => USERNAME, :api_key => API_KEY, :authtenant => TENANT, :auth_url => API_URL, :service_type => "compute")
|
58
|
+
|
59
|
+
# Get a listing of all current servers
|
60
|
+
>> os.servers
|
61
|
+
=> [{:name=>"Server1", :id=>110917}]
|
62
|
+
|
63
|
+
# Access a specific server
|
64
|
+
>> server = os.server(110917)
|
65
|
+
>> server.name
|
66
|
+
=> "Server1"
|
67
|
+
|
68
|
+
# See what type of server this is
|
69
|
+
>> server.flavor.name
|
70
|
+
=> "256 server"
|
71
|
+
>> server.image.name
|
72
|
+
=> "Ubuntu 8.04.2 LTS (hardy)"
|
73
|
+
|
74
|
+
# Soft-reboot the server
|
75
|
+
>> server.reboot
|
76
|
+
=> true
|
77
|
+
|
78
|
+
# Create a new 512MB CentOS 5.2 server. The root password is returned in the adminPass method.
|
79
|
+
>> image = os.get_image(8)
|
80
|
+
=> #<OpenStack::Compute::Image:0x1014a8060 ...>, status"ACTIVE"
|
81
|
+
>> image.name
|
82
|
+
=> "CentOS 5.2"
|
83
|
+
>> flavor = os.get_flavor(2)
|
84
|
+
=> #<OpenStack::Compute::Flavor:0x101469130 @disk=20, @name="512 server", @id=2, @ram=512>
|
85
|
+
>> flavor.name
|
86
|
+
=> "512 server"
|
87
|
+
>> newserver = os.create_server(:name => "New Server", :imageRef => image.id, :flavorRef => flavor.id)
|
88
|
+
=> #<OpenStack::Compute::Server:0x101433f08 ....
|
89
|
+
>> newserver.status
|
90
|
+
=> "BUILD"
|
91
|
+
>> newserver.progress
|
92
|
+
=> 0
|
93
|
+
>> newserver.adminPass
|
94
|
+
=> "NewServerMbhzUnO"
|
95
|
+
>> newserver.refresh
|
96
|
+
=> true
|
97
|
+
>> newserver.progress
|
98
|
+
=> 12
|
99
|
+
|
100
|
+
# Create a new server and specify the keyname and security_groups to be used (dependent on provider support for these API extensions):
|
101
|
+
>> server = os.create_server({:imageRef=>14075, :flavorRef=>100, :key_name=>"my_default_key", :security_groups=>["test", "default"], :name=>"marios_server"})
|
102
|
+
=> #<OpenStack::Compute::Server:0x101433f08 ....
|
103
|
+
>> server.key_name
|
104
|
+
=> "my_default_key"
|
105
|
+
>> server.security_groups
|
106
|
+
|
107
|
+
# Delete the new server
|
108
|
+
>> newserver.delete!
|
109
|
+
=> true
|
110
|
+
|
111
|
+
=== Compute API extensions.
|
112
|
+
|
113
|
+
# Get info on extensions offered by the given OpenStack provider:
|
114
|
+
>> os.api_extensions
|
115
|
+
=> { :os-keypairs => { :links=>[], :updated=>"2011-08-08T00:00:00+00:00", :description=>"Keypair Support",
|
116
|
+
:namespace=>"http://docs.openstack.org/ext/keypairs/api/v1.1", :name=>"Keypairs",
|
117
|
+
:alias=>"os-keypairs" },
|
118
|
+
:os-floating_ips => { :links=>[], :updated=>"2011-06-16T00:00:00+00:00", :description=>"Floating IPs support",
|
119
|
+
:namespace=>"http://docs.openstack.org/ext/floating_ips/api/v1.1", :name=>"Floating_ips", :alias=>"os-floating-ips"},
|
120
|
+
... }
|
121
|
+
|
122
|
+
# Get list of keypairs for current tenant/account:
|
123
|
+
>> os.keypairs
|
124
|
+
=> { :key_one => { :fingerprint => "3f:12:4d:d1:54:f1:f4:3f:fe:a8:12:ec:1a:fb:35:b2",
|
125
|
+
:public_key => "ssh-rsa AAAAB3Nza923kJ ...
|
126
|
+
:name => "key_one"},
|
127
|
+
:key_two => { ... },
|
128
|
+
... }
|
129
|
+
|
130
|
+
# Create new keypair:
|
131
|
+
>> os.create_keypair({:name=>"test_key"})
|
132
|
+
=> { :name => "test_key",
|
133
|
+
:fingerprint => "f1:f3:a2:d3:ca:75:da:f1:06:f4:f7:dc:cc:7d:e1:ca",
|
134
|
+
:user_id => "dev_41247879706381",$
|
135
|
+
:public_key => "ssh-rsa AAAAB3NzaC1y ...
|
136
|
+
:private_key => "-----BEGIN RSA PRIVATE KEY-----\nMIICXwIBA ... -----END RSA PRIVATE KEY-----\n"
|
137
|
+
}
|
138
|
+
|
139
|
+
# Import keypair:
|
140
|
+
>> os.create_keypair({:name=>"test_key_imported", :public_key=>"sh-rsa AAAAB3Nza923kJ ..."})
|
141
|
+
=> { :name => "test_key_imported",
|
142
|
+
:fingerprint => "f1:f3:a2:d3:ca:75:da:f1:06:f4:f7:dc:cc:7d:e1:ca",
|
143
|
+
:user_id => "dev_41247879706381",$
|
144
|
+
:public_key => "ssh-rsa AAAAB3Nza ...
|
145
|
+
}
|
146
|
+
|
147
|
+
# Delete Keypair:
|
148
|
+
>> os.delete_keypair("test_key_imported")
|
149
|
+
=> true
|
150
|
+
|
151
|
+
# List all security groups:
|
152
|
+
>> os.security_groups
|
153
|
+
=> { "1381" => { :tenant_id=>"12345678909876", :id=>1381, :name=>"default", :description=>"default",
|
154
|
+
:rules=> [
|
155
|
+
{:from_port=>22, :group=>{}, :ip_protocol=>"tcp", :to_port=>22,
|
156
|
+
:parent_group_id=>1381, :ip_range=>{:cidr=>"0.0.0.0/0"}, :id=>4902},
|
157
|
+
]
|
158
|
+
},
|
159
|
+
"1234" => { ... } }
|
160
|
+
|
161
|
+
# Get a specific security group:
|
162
|
+
>> os.security_group(1381)
|
163
|
+
=> { "1381" => { :tenant_id=>"12345678909876", :id=>1381, :name=>"default", :description=>"default",
|
164
|
+
:rules=> [
|
165
|
+
{:from_port=>22, :group=>{}, :ip_protocol=>"tcp", :to_port=>22,
|
166
|
+
:parent_group_id=>1381, :ip_range=>{:cidr=>"0.0.0.0/0"}, :id=>4902},
|
167
|
+
]
|
168
|
+
}}
|
169
|
+
|
170
|
+
#Create a new security group:
|
171
|
+
>> os.create_security_group("devel_group", "all development machines")
|
172
|
+
=> {"9573"=>{:rules=>[], :tenant_id=>"46871569847393", :id=>9573, :name=>"devel_group", :description=>"all development machines"}}
|
173
|
+
|
174
|
+
#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:
|
175
|
+
>> os.create_security_group_rule(9567, {:ip_protocol=>"tcp", :from_port=>"123", :to_port=>"123", :cidr=>"192.168.0.1/16" })
|
176
|
+
=> => {"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}}
|
177
|
+
|
178
|
+
#Delete a security group rule:
|
179
|
+
>> os.delete_security_group_rule(27375)
|
180
|
+
=> true
|
181
|
+
|
182
|
+
#Delete a security group:
|
183
|
+
>> os.delete_security_group(9571)
|
184
|
+
=> true
|
185
|
+
|
186
|
+
#Attach a volume to a server - params in order are: server_id, volume_id, attachment_point
|
187
|
+
|
188
|
+
>> os.attach_volume(704289, 90805, "/dev/sde")
|
189
|
+
=> true
|
190
|
+
|
191
|
+
#List attachments for a server:
|
192
|
+
|
193
|
+
>> os.list_attachments 704289
|
194
|
+
=> {:volumeAttachments=>[{:device=>"/dev/sde", :serverId=>704289, :id=>90805, :volumeId=>90805}]}
|
195
|
+
|
196
|
+
#Detach volume from server - params in order are server_id and attachment_id
|
197
|
+
>> os.detach_volume(704289, 90805)
|
198
|
+
=> true
|
199
|
+
|
200
|
+
== Examples for Volumes and Snaphots:
|
201
|
+
|
202
|
+
#NOTE - attach/detach operations are implemented for the compute service as the OS API defines these operations as extensions to Openstack Compute.
|
203
|
+
|
204
|
+
vs = OpenStack::Connection.create({:username => "username", :api_key=>"pass", :auth_url => "https://region-a.geo-1.identity.hpcloudsvc.com:35357/v2.0/", :authtenant=>"username-default-tenant", :service_type=>"volume"})
|
205
|
+
|
206
|
+
# Create a volume: - MUST specify display_name and size parameters... optional params are {:display_description, :metadata=>{:key=>val, ...}, :availability_zone, :volume_type }
|
207
|
+
|
208
|
+
>> volume = vs.create_volume({:display_name=>"marios volume", :size=>1, :display_description=>"some new volume bla"})
|
209
|
+
=> #<OpenStack::Volume::Volume:0x8a3c534 @id=90805, @display_name="marios volume", @display_description="some new volume bla", @size=1, @volume_type=nil, @metadata={}, @availability_zone="nova", @snapshot_id="", @attachments=[{}], @created_at="2012-11-15 13:51:23">
|
210
|
+
|
211
|
+
>> volume.size
|
212
|
+
=> 1
|
213
|
+
|
214
|
+
>> volume.attachments
|
215
|
+
=> [{}]
|
216
|
+
|
217
|
+
# List volumes:
|
218
|
+
|
219
|
+
>> vs.list_volumes #aliased as just 'volumes' ... vs.volumes
|
220
|
+
=> [#<OpenStack::Volume::Volume:0x8aad2e8 @id=90625, @display_name="marios volume", @display_description="attach test volume", @size=1, @volume_type=nil, @metadata={}, @availability_zone="nova", @snapshot_id="", @attachments=[{}], @created_at="2012-11-15 09:54:58">, #<OpenStack::Volume::Volume:0x8aad144 @id=90805, @display_name="marios volume", @display_description="some new volume bla", @size=1, @volume_type=nil, @metadata={}, @availability_zone="nova", @snapshot_id="", @attachments=[{}], @created_at="2012-11-15 13:51:23">]
|
221
|
+
|
222
|
+
# Get a particular volume - must specify ID:
|
223
|
+
|
224
|
+
>> vs.get_volume(90625) #aliased as 'volume'
|
225
|
+
=> #<OpenStack::Volume::Volume:0x8abd4a4 @id=90625, @display_name="marios volume", @display_description="attach test volume", @size=1, @volume_type=nil, @metadata={}, @availability_zone="nova", @snapshot_id="", @attachments=[{}], @created_at="2012-11-15 09:54:58">
|
226
|
+
|
227
|
+
# Delete a volume:
|
228
|
+
|
229
|
+
>> vs.delete_volume(90805)
|
230
|
+
=> true
|
231
|
+
|
232
|
+
# Create a snapshot: - must specify display_name and volume_id parameters... optionally also :display_description
|
233
|
+
>> vs.create_snapshot({:volume_id=>"3b38b570-a4ff-4444-984a-3566cbdc8ab2", :display_name=>"marios_snapshot"})
|
234
|
+
=> #<OpenStack::Volume::Snapshot:0xa0cfea4 @id=223, @display_name="marios_snapshot", @display_description=nil, @volume_id="3b38b570-a4ff-4444-984a-3566cbdc8ab2", @status="creating", @size=1, @created_at="2013-01-23 14:25:02.654217">
|
235
|
+
|
236
|
+
# List snapshots: - aliased as just 'snapshots' ... vs.snapshots
|
237
|
+
>> vs.list_snapshots
|
238
|
+
=> [#<OpenStack::Volume::Snapshot:0x9a6e4fc @id="0e76dacb-2fcf-4565-84a3-aa3d7bd16224", @display_name="marios_snapshot", @display_description=nil, @volume_id="3b38b570-a4ff-4444-984a-3566cbdc8ab2", @status="creating", @size=1, @created_at="2013-01-23T14:18:13.000000">]
|
239
|
+
|
240
|
+
# Get a specific snapshot: - aliased as 'snapshot'
|
241
|
+
>> vs.get_snapshot("0e76dacb-2fcf-4565-84a3-aa3d7bd16224")
|
242
|
+
=> #<OpenStack::Volume::Snapshot:0x9a890b8 @id="0e76dacb-2fcf-4565-84a3-aa3d7bd16224", @display_name="marios_snapshot", @display_description=nil, @volume_id="3b38b570-a4ff-4444-984a-3566cbdc8ab2", @status="creating", @size=1, @created_at="2013-01-23T14:18:13.000000">
|
243
|
+
|
244
|
+
# Delete a snapshot:
|
245
|
+
>> vs.delete_snapshot("0e76dacb-2fcf-4565-84a3-aa3d7bd16224")
|
246
|
+
=> true
|
247
|
+
|
248
|
+
== Examples for Object-Store:
|
249
|
+
|
250
|
+
|
251
|
+
os = OpenStack::Connection.create(:username => USERNAME, :api_key => API_KEY, :authtenant => TENANT, :auth_url => API_URL, :service_type => "object-store")
|
252
|
+
|
253
|
+
# Get info on container count and bytes:
|
254
|
+
>> os.get_info
|
255
|
+
=> {:count=>2, :bytes=>495041}
|
256
|
+
|
257
|
+
# Get list of containers under this account:
|
258
|
+
>> os.containers
|
259
|
+
=> ["another_containerfoo", "marios_test_container"]
|
260
|
+
|
261
|
+
# Get details of containers under this account:
|
262
|
+
>> os.containers_detail
|
263
|
+
=>=> {"another_containerfoo"=>{:count=>"3", :bytes=>"1994"}, "marios_test_container"=>{:count=>"2", :bytes=>"493047"}}
|
264
|
+
|
265
|
+
# Check if a container exists
|
266
|
+
>> os.container_exists?("no_such_thing")
|
267
|
+
=> false
|
268
|
+
|
269
|
+
# Create new container
|
270
|
+
>> os.create_container("foo")
|
271
|
+
=> => #<OpenStack::Swift::Container:0xb7275c38 ...... (rest of OpenStack::Swift::Container object)
|
272
|
+
|
273
|
+
# Delete container
|
274
|
+
>> os.delete_container("foo")
|
275
|
+
=> true
|
276
|
+
|
277
|
+
# Get a container (OpenStack::Swift::Container object):
|
278
|
+
>> cont = os.container("foo")
|
279
|
+
=> #<OpenStack::Swift::Container:0xb7262124 ...... (rest of OpenStack::Swift::Container object)
|
280
|
+
|
281
|
+
# Retrieve container metadata:
|
282
|
+
>> cont.container_metadata
|
283
|
+
=>{:count=>"2", :bytes=>"493047", :metadata=>{"foo"=>"bar", "author"=>"foobar", "jj"=>"foobar", "date"=>"today", "owner"=>"foo"}}
|
284
|
+
|
285
|
+
# Retrieve user defined metadata:
|
286
|
+
>> cont.metadata
|
287
|
+
=> {"foo"=>"bar", "author"=>"foobar", "jj"=>"foobar", "date"=>"today", "owner"=>"foo"}
|
288
|
+
|
289
|
+
# Set user defined metadata:
|
290
|
+
>> cont.set_metadata({"X-Container-Meta-Author"=> "msa", "version"=>"1.2", :date=>"today"})
|
291
|
+
=> true
|
292
|
+
|
293
|
+
# Get list of objects:
|
294
|
+
>> cont.objects
|
295
|
+
=> ["fosdem2012.pdf", "moved_object"]
|
296
|
+
|
297
|
+
# Get list of objects with details:
|
298
|
+
>> cont.objects_detail
|
299
|
+
=> {"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"}}
|
300
|
+
|
301
|
+
# Check if container is empty:
|
302
|
+
>> cont.empty?
|
303
|
+
=> false
|
304
|
+
|
305
|
+
# Check if object exists:
|
306
|
+
>> cont.object_exists?("foo")
|
307
|
+
=> false
|
308
|
+
|
309
|
+
# Create new object
|
310
|
+
>> 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]
|
311
|
+
=> #<OpenStack::Swift::StorageObject:0xb72fdac0 ... etc
|
312
|
+
|
313
|
+
# Delete object
|
314
|
+
>> cont.delete_object("foo")
|
315
|
+
=> true
|
316
|
+
|
317
|
+
# Get handle to an OpenStack::Swift::StorageObject Object
|
318
|
+
>> obj = cont.object("foo")
|
319
|
+
=> #<OpenStack::Swift::StorageObject:0xb72fdac0 ... etc
|
320
|
+
|
321
|
+
# Get object metadata
|
322
|
+
>> obj.object_metadata
|
323
|
+
=>
|
324
|
+
|
325
|
+
# Get user defined metadata pairs
|
326
|
+
>> obj.metadata
|
327
|
+
=>
|
328
|
+
|
329
|
+
# Get data (non streaming - returned as a String)
|
330
|
+
>> obj.data
|
331
|
+
=> "This is the text stored in the file"
|
332
|
+
|
333
|
+
# Get data (streaming - requires a block)
|
334
|
+
>> data = ""; object.data_stream do |chunk| data += chunk end
|
335
|
+
=> #<Net::HTTPOK 200 OK readbody=true>
|
336
|
+
>> data
|
337
|
+
=> "This is the text stored in the file"
|
338
|
+
|
339
|
+
# Set user defined metadata
|
340
|
+
>> obj.set_metadata({:foo=>"bar", "X-Object-Meta-herpa"=>"derp", "author"=>"me"})
|
341
|
+
=> true
|
342
|
+
|
343
|
+
# (Over)Write object data
|
344
|
+
>> object.write("This is new data")
|
345
|
+
=> true
|
346
|
+
>> object.data
|
347
|
+
=> "This is new data"
|
348
|
+
|
349
|
+
# Copy object:
|
350
|
+
>>copied = obj.copy('copied_object', "destination_container", {:content_type=>"text/plain", :metadata=>{:herp=>"derp", "X-Object-Meta-foo"=>"bar} } )
|
351
|
+
=> #<OpenStack::Swift::StorageObject:0xb728974c ..... etc
|
352
|
+
|
353
|
+
# Move object: (copy and then delete original):
|
354
|
+
>> moved = obj.move('moved_object', "destination_container", {:content_type=>"text/plain", :metadata=>{:herp=>"derp", "X-Object-Meta-foo"=>"bar"} } )
|
355
|
+
=> #<OpenStack::Swift::StorageObject:0xb7266bd4 ...
|
356
|
+
>> moved.metadata
|
357
|
+
=> {"foo"=>"bar", "herp"=>"derp", "herpy"=>"derp"}
|
358
|
+
>> obj.metadata
|
359
|
+
=> OpenStack::Exception::ItemNotFound: The resource could not be found
|
360
|
+
|
361
|
+
|
362
|
+
== Authors
|
363
|
+
|
364
|
+
By Dan Prince <dprince@redhat.com>, Naveed Massjouni <naveedm9@gmail.com>, Marios Andreou <marios@redhat.com>
|
365
|
+
|
366
|
+
Initial code checkin on May 23rd 2012 - code refactored from and based on the Rackspace Cloud Servers gem
|
367
|
+
(https://github.com/rackspace/ruby-openstack-compute) and Rackspace Cloud Files gem (https://github.com/rackspace/ruby-cloudfiles).
|
368
|
+
|
369
|
+
== License
|
370
|
+
|
371
|
+
See COPYING for license information.
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.8
|
data/lib/openstack.rb
ADDED
@@ -0,0 +1,112 @@
|
|
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
|
+
require 'openstack/volume/connection'
|
46
|
+
require 'openstack/volume/volume'
|
47
|
+
require 'openstack/volume/snapshot'
|
48
|
+
require 'openstack/image/connection'
|
49
|
+
|
50
|
+
|
51
|
+
# Constants that set limits on server creation
|
52
|
+
MAX_PERSONALITY_ITEMS = 5
|
53
|
+
MAX_PERSONALITY_FILE_SIZE = 10240
|
54
|
+
MAX_SERVER_PATH_LENGTH = 255
|
55
|
+
|
56
|
+
# Helper method to recursively symbolize hash keys.
|
57
|
+
def self.symbolize_keys(obj)
|
58
|
+
case obj
|
59
|
+
when Array
|
60
|
+
obj.inject([]){|res, val|
|
61
|
+
res << case val
|
62
|
+
when Hash, Array
|
63
|
+
symbolize_keys(val)
|
64
|
+
else
|
65
|
+
val
|
66
|
+
end
|
67
|
+
res
|
68
|
+
}
|
69
|
+
when Hash
|
70
|
+
obj.inject({}){|res, (key, val)|
|
71
|
+
nkey = case key
|
72
|
+
when String
|
73
|
+
key.to_sym
|
74
|
+
else
|
75
|
+
key
|
76
|
+
end
|
77
|
+
nval = case val
|
78
|
+
when Hash, Array
|
79
|
+
symbolize_keys(val)
|
80
|
+
else
|
81
|
+
val
|
82
|
+
end
|
83
|
+
res[nkey] = nval
|
84
|
+
res
|
85
|
+
}
|
86
|
+
else
|
87
|
+
obj
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.paginate(options = {})
|
92
|
+
path_args = []
|
93
|
+
path_args.push(URI.encode("limit=#{options[:limit]}")) if options[:limit]
|
94
|
+
path_args.push(URI.encode("offset=#{options[:offset]}")) if options[:offset]
|
95
|
+
path_args.join("&")
|
96
|
+
end
|
97
|
+
|
98
|
+
# e.g. keys = [:limit, :marker]
|
99
|
+
# params = {:limit=>2, :marker="marios", :prefix=>"/"}
|
100
|
+
# you want url = /container_name?limit=2&marker=marios
|
101
|
+
def self.get_query_params(params, keys, url="")
|
102
|
+
set_keys = params.inject([]){|res, (k,v)| res << k if keys.include?(k) and not v.nil?; res }
|
103
|
+
return url if set_keys.empty?
|
104
|
+
url = "#{url}?#{set_keys[0]}=#{params[set_keys[0]]}"
|
105
|
+
set_keys.slice!(0)
|
106
|
+
set_keys.each do |k|
|
107
|
+
url = "#{url}&#{k}=#{params[set_keys[0]]}"
|
108
|
+
end
|
109
|
+
url
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|