deltacloud-core 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (242) hide show
  1. data/LICENSE +145 -0
  2. data/NOTICE +10 -1
  3. data/Rakefile +50 -2
  4. data/bin/deltacloudd +111 -14
  5. data/config/addresses.xml +14 -0
  6. data/config/condor.yaml +30 -0
  7. data/config/drivers/azure.yaml +3 -0
  8. data/config/drivers/condor.yaml +3 -0
  9. data/config/{drivers.yaml → drivers/ec2.yaml} +5 -34
  10. data/config/drivers/eucalyptus.yaml +8 -0
  11. data/config/drivers/gogrid.yaml +3 -0
  12. data/config/drivers/mock.yaml +3 -0
  13. data/config/drivers/opennebula.yaml +4 -0
  14. data/config/drivers/rackspace.yaml +3 -0
  15. data/config/drivers/rhevm.yaml +3 -0
  16. data/config/drivers/rimuhosting.yaml +3 -0
  17. data/config/drivers/sbc.yaml +2 -0
  18. data/config/drivers/terremark.yaml +3 -0
  19. data/config/drivers/vsphere.yaml +8 -0
  20. data/deltacloud-core.gemspec +13 -5
  21. data/deltacloud.rb +4 -2
  22. data/lib/deltacloud/backend_capability.rb +2 -2
  23. data/lib/deltacloud/base_driver/base_driver.rb +23 -52
  24. data/lib/deltacloud/base_driver/exceptions.rb +168 -0
  25. data/lib/deltacloud/base_driver/features.rb +31 -12
  26. data/lib/deltacloud/base_driver/mock_driver.rb +2 -1
  27. data/lib/deltacloud/core_ext/string.rb +2 -0
  28. data/lib/deltacloud/drivers/azure/azure_driver.rb +5 -5
  29. data/lib/deltacloud/drivers/condor/condor_client.rb +273 -0
  30. data/lib/deltacloud/drivers/condor/condor_driver.rb +236 -0
  31. data/lib/deltacloud/drivers/condor/ip_agents/confserver.rb +75 -0
  32. data/lib/deltacloud/drivers/condor/ip_agents/default.rb +84 -0
  33. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +326 -95
  34. data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +3 -3
  35. data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +40 -8
  36. data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +7 -7
  37. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +42 -25
  38. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob1.yml +6 -4
  39. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob2.yml +7 -5
  40. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob3.yml +6 -4
  41. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob4.yml +6 -4
  42. data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob5.yml +6 -4
  43. data/lib/deltacloud/drivers/mock/data/buckets/bucket1.yml +7 -1
  44. data/lib/deltacloud/drivers/mock/data/buckets/bucket2.yml +6 -1
  45. data/lib/deltacloud/drivers/mock/data/images/img1.yml +6 -2
  46. data/lib/deltacloud/drivers/mock/data/images/img2.yml +6 -2
  47. data/lib/deltacloud/drivers/mock/data/images/img3.yml +6 -2
  48. data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +11 -10
  49. data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +14 -7
  50. data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +14 -7
  51. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +3 -2
  52. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +3 -2
  53. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +3 -2
  54. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +4 -3
  55. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +4 -3
  56. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +4 -3
  57. data/lib/deltacloud/drivers/mock/mock_client.rb +101 -0
  58. data/lib/deltacloud/drivers/mock/mock_driver.rb +367 -429
  59. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +6 -0
  60. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +59 -9
  61. data/lib/deltacloud/drivers/rhevm/rhevm_client.rb +62 -8
  62. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +100 -45
  63. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +3 -2
  64. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +8 -11
  65. data/lib/deltacloud/drivers/sbc/sbc_client.rb +6 -6
  66. data/lib/deltacloud/drivers/sbc/sbc_driver.rb +16 -0
  67. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +17 -12
  68. data/lib/deltacloud/drivers/vsphere/vsphere_client.rb +140 -0
  69. data/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +405 -0
  70. data/lib/deltacloud/drivers/vsphere/vsphere_filemanager.rb +182 -0
  71. data/lib/deltacloud/hardware_profile.rb +1 -1
  72. data/lib/deltacloud/helpers.rb +2 -1
  73. data/lib/deltacloud/helpers/application_helper.rb +92 -20
  74. data/lib/deltacloud/helpers/blob_stream.rb +160 -12
  75. data/lib/deltacloud/helpers/conversion_helper.rb +6 -2
  76. data/lib/deltacloud/helpers/json_helper.rb +31 -0
  77. data/lib/deltacloud/models/address.rb +28 -0
  78. data/lib/deltacloud/models/base_model.rb +5 -1
  79. data/lib/deltacloud/models/blob.rb +1 -1
  80. data/lib/deltacloud/models/bucket.rb +10 -0
  81. data/lib/deltacloud/models/firewall.rb +22 -0
  82. data/lib/deltacloud/models/firewall_rule.rb +23 -0
  83. data/lib/deltacloud/models/image.rb +12 -0
  84. data/lib/deltacloud/models/instance.rb +20 -2
  85. data/lib/deltacloud/models/key.rb +1 -1
  86. data/lib/deltacloud/runner.rb +3 -3
  87. data/lib/deltacloud/validation.rb +3 -7
  88. data/lib/drivers.rb +7 -1
  89. data/lib/sinatra/body_proxy.rb +34 -0
  90. data/lib/sinatra/lazy_auth.rb +5 -0
  91. data/lib/sinatra/rabbit.rb +54 -31
  92. data/lib/sinatra/rack_accept.rb +157 -0
  93. data/lib/sinatra/rack_date.rb +38 -0
  94. data/lib/sinatra/rack_etag.rb +2 -3
  95. data/lib/sinatra/rack_matrix_params.rb +51 -29
  96. data/lib/sinatra/rack_runtime.rb +1 -1
  97. data/lib/sinatra/rack_syslog.rb +86 -0
  98. data/lib/sinatra/url_for.rb +14 -1
  99. data/public/images/address.png +0 -0
  100. data/public/images/balancer.png +0 -0
  101. data/public/images/blob.png +0 -0
  102. data/public/images/bucket.png +0 -0
  103. data/public/images/cloud.png +0 -0
  104. data/public/images/firewall.png +0 -0
  105. data/public/images/image.png +0 -0
  106. data/public/images/key.png +0 -0
  107. data/public/images/machine.png +0 -0
  108. data/public/images/profile.png +0 -0
  109. data/public/images/realm.png +0 -0
  110. data/public/images/snapshot.png +0 -0
  111. data/public/images/volume.png +0 -0
  112. data/public/javascripts/application.js +119 -16
  113. data/public/javascripts/jquery.min.js +18 -0
  114. data/public/javascripts/jquery.mobile-1.0b1.min.js +146 -0
  115. data/public/stylesheets/compiled/application.css +8 -0
  116. data/public/stylesheets/images/ajax-loader.png +0 -0
  117. data/public/{images → stylesheets/images}/bread-bg.png +0 -0
  118. data/public/{images → stylesheets/images}/error.png +0 -0
  119. data/public/{images → stylesheets/images}/grid.png +0 -0
  120. data/public/stylesheets/images/icon-search-black.png +0 -0
  121. data/public/stylesheets/images/icons-18-black.png +0 -0
  122. data/public/stylesheets/images/icons-18-white.png +0 -0
  123. data/public/stylesheets/images/icons-36-black.png +0 -0
  124. data/public/stylesheets/images/icons-36-white.png +0 -0
  125. data/public/{images → stylesheets/images}/logo-wide.png +0 -0
  126. data/public/{images → stylesheets/images}/pending.png +0 -0
  127. data/public/{images → stylesheets/images}/rails.png +0 -0
  128. data/public/{images → stylesheets/images}/running.png +0 -0
  129. data/public/{images → stylesheets/images}/stopped.png +0 -0
  130. data/public/{images → stylesheets/images}/topbar-bg.png +0 -0
  131. data/public/stylesheets/jquery.mobile-1.0b1.min.css +8 -0
  132. data/public/stylesheets/new.css +53 -0
  133. data/server.rb +487 -175
  134. data/support/condor/bash/cached_images.sh +8 -0
  135. data/support/condor/bash/cloud_exit_hook.sh +17 -0
  136. data/support/condor/bash/cloud_functions +175 -0
  137. data/support/condor/bash/cloud_prepare_hook.sh +20 -0
  138. data/support/condor/bash/libvirt_cloud_script.sh +13 -0
  139. data/support/condor/config/50condor_cloud.config +37 -0
  140. data/support/condor/config/50condor_cloud_node.config +37 -0
  141. data/support/condor/config/condor-cloud +2 -0
  142. data/support/condor/config/condor_config.local +44 -0
  143. data/support/fedora/deltacloud-core +48 -26
  144. data/support/fedora/deltacloud-core-config +26 -0
  145. data/support/fedora/deltacloud-core.spec +314 -68
  146. data/support/fedora/deltacloudd-fedora +5 -0
  147. data/tests/common.rb +34 -4
  148. data/tests/drivers/mock/api_test.rb +3 -3
  149. data/tests/drivers/mock/images_test.rb +12 -0
  150. data/tests/drivers/mock/instances_test.rb +2 -0
  151. data/tests/rabbit_test.rb +2 -2
  152. data/views/addresses/_address.html.haml +6 -0
  153. data/views/addresses/associate.html.haml +12 -0
  154. data/views/addresses/index.html.haml +9 -0
  155. data/views/addresses/index.xml.haml +4 -0
  156. data/views/addresses/show.html.haml +21 -0
  157. data/views/addresses/show.xml.haml +14 -0
  158. data/views/api/show.html.haml +6 -11
  159. data/views/api/show.xml.haml +2 -0
  160. data/views/blobs/new.html.haml +24 -23
  161. data/views/blobs/show.html.haml +30 -31
  162. data/views/buckets/index.html.haml +9 -21
  163. data/views/buckets/index.xml.haml +3 -7
  164. data/views/buckets/new.html.haml +13 -12
  165. data/views/buckets/show.html.haml +22 -22
  166. data/views/buckets/show.xml.haml +5 -3
  167. data/views/docs/collection.html.haml +23 -34
  168. data/views/docs/collection.xml.haml +2 -2
  169. data/views/docs/index.html.haml +9 -13
  170. data/views/docs/index.xml.haml +1 -1
  171. data/views/docs/operation.html.haml +28 -38
  172. data/views/docs/operation.xml.haml +1 -1
  173. data/views/drivers/index.html.haml +8 -13
  174. data/views/drivers/show.html.haml +18 -18
  175. data/views/error.html.haml +32 -27
  176. data/views/errors/400.html.haml +41 -0
  177. data/views/errors/{validation_failure.xml.haml → 400.xml.haml} +0 -4
  178. data/views/errors/401.html.haml +41 -0
  179. data/views/errors/{auth_exception.xml.haml → 401.xml.haml} +0 -0
  180. data/views/errors/403.html.haml +42 -0
  181. data/views/errors/{not_allowed.xml.haml → 403.xml.haml} +0 -0
  182. data/views/errors/404.html.haml +29 -0
  183. data/views/errors/{not_found.xml.haml → 404.xml.haml} +1 -1
  184. data/views/errors/405.html.haml +29 -0
  185. data/views/errors/405.xml.haml +5 -0
  186. data/views/errors/500.html.haml +43 -0
  187. data/views/errors/500.xml.haml +5 -0
  188. data/views/errors/502.html.haml +43 -0
  189. data/views/errors/{backend_error.xml.haml → 502.xml.haml} +1 -2
  190. data/views/errors/backend_capability_failure.html.haml +27 -9
  191. data/views/firewalls/index.html.haml +15 -0
  192. data/views/firewalls/index.xml.haml +28 -0
  193. data/views/firewalls/new.html.haml +11 -0
  194. data/views/firewalls/new_rule.html.haml +20 -0
  195. data/views/firewalls/show.html.haml +42 -0
  196. data/views/firewalls/show.xml.haml +26 -0
  197. data/views/hardware_profiles/index.html.haml +15 -23
  198. data/views/hardware_profiles/show.html.haml +22 -18
  199. data/views/images/index.html.haml +11 -23
  200. data/views/images/index.xml.haml +4 -13
  201. data/views/images/new.html.haml +12 -13
  202. data/views/images/show.html.haml +26 -20
  203. data/views/images/show.xml.haml +2 -1
  204. data/views/instance_states/show.html.haml +21 -25
  205. data/views/instances/index.html.haml +13 -30
  206. data/views/instances/index.xml.haml +2 -23
  207. data/views/instances/new.html.haml +83 -88
  208. data/views/instances/show.html.haml +53 -55
  209. data/views/instances/show.xml.haml +12 -10
  210. data/views/keys/index.html.haml +13 -24
  211. data/views/keys/new.html.haml +7 -7
  212. data/views/keys/show.html.haml +26 -21
  213. data/views/layout.html.haml +28 -27
  214. data/views/load_balancers/index.html.haml +11 -31
  215. data/views/load_balancers/index.xml.haml +0 -1
  216. data/views/load_balancers/new.html.haml +1 -1
  217. data/views/load_balancers/show.html.haml +33 -34
  218. data/views/load_balancers/show.xml.haml +2 -2
  219. data/views/realms/index.html.haml +11 -24
  220. data/views/realms/index.xml.haml +2 -8
  221. data/views/realms/show.html.haml +17 -15
  222. data/views/realms/show.xml.haml +2 -1
  223. data/views/storage_snapshots/index.html.haml +11 -21
  224. data/views/storage_snapshots/index.xml.haml +2 -5
  225. data/views/storage_snapshots/new.html.haml +1 -1
  226. data/views/storage_snapshots/show.html.haml +21 -13
  227. data/views/storage_snapshots/show.xml.haml +2 -1
  228. data/views/storage_volumes/index.html.haml +11 -34
  229. data/views/storage_volumes/new.html.haml +1 -1
  230. data/views/storage_volumes/show.html.haml +33 -27
  231. data/views/storage_volumes/show.xml.haml +2 -1
  232. metadata +266 -178
  233. data/lib/sinatra/respond_to.rb +0 -248
  234. data/support/fedora/deltacloudd +0 -128
  235. data/support/fedora/rubygem-deltacloud-core.spec +0 -127
  236. data/views/accounts/index.html.haml +0 -11
  237. data/views/accounts/show.html.haml +0 -30
  238. data/views/errors/auth_exception.html.haml +0 -8
  239. data/views/errors/backend_error.html.haml +0 -22
  240. data/views/errors/not_allowed.html.haml +0 -6
  241. data/views/errors/not_found.html.haml +0 -6
  242. data/views/errors/validation_failure.html.haml +0 -11
@@ -1,10 +1,17 @@
1
- :name: MockUserInstance
2
- :state: RUNNING
3
- :image_id: img3
4
- :owner_id: mockuser
5
- :public_addresses: [ img3.inst1.public.com ]
6
- :private_addresses: [ img3.inst1.private.com ]
7
- :realm_id: us
1
+ ---
8
2
  :instance_profile: !ruby/object:InstanceProfile
9
3
  id: m1-small
4
+ :realm_id: us
5
+ :owner_id: mockuser
6
+ :public_addresses:
7
+ - img3.inst1.public.com
8
+ :private_addresses:
9
+ - img3.inst1.private.com
10
10
  :create_image: true
11
+ :image_id: img3
12
+ :name: MockUserInstance
13
+ :id: inst1
14
+ :state: RUNNING
15
+ :actions:
16
+ - :reboot
17
+ - :stop
@@ -1,10 +1,17 @@
1
- :name: AnotherInstance
2
- :state: RUNNING
3
- :image_id: img1
4
- :owner_id: anotheruser
5
- :public_addresses: [ img1.inst2.public.com ]
6
- :private_addresses: [ img1.inst2.private.com ]
7
- :realm_id: us
1
+ ---
8
2
  :instance_profile: !ruby/object:InstanceProfile
9
3
  id: m1-large
4
+ :realm_id: us
5
+ :owner_id: anotheruser
6
+ :public_addresses:
7
+ - img1.inst2.public.com
8
+ :private_addresses:
9
+ - img1.inst2.private.com
10
10
  :create_image: true
11
+ :image_id: img1
12
+ :name: AnotherInstance
13
+ :id: inst2
14
+ :state: RUNNING
15
+ :actions:
16
+ - :reboot
17
+ - :stop
@@ -1,4 +1,5 @@
1
- :owner_id: fedoraproject
1
+ ---
2
2
  :created: Wed Jul 29 18:15:24 UTC 2009
3
- :state: COMPLETED
4
3
  :storage_volume_id: vol1
4
+ :id: snap1
5
+ :state: COMPLETED
@@ -1,4 +1,5 @@
1
- :owner_id: mockuser
1
+ ---
2
2
  :created: Wed Jul 29 18:15:24 UTC 2009
3
- :state: COMPLETED
4
3
  :storage_volume_id: vol2
4
+ :id: snap2
5
+ :state: COMPLETED
@@ -1,4 +1,5 @@
1
- :owner_id: mockuser
1
+ ---
2
2
  :created: Wed Jul 29 18:15:24 UTC 2009
3
- :state: COMPLETED
4
3
  :storage_volume_id: vol2
4
+ :id: snap3
5
+ :state: COMPLETED
@@ -1,7 +1,8 @@
1
- :owner_id: fedoraproject
1
+ ---
2
2
  :realm_id: us
3
- :created: Thu Jul 30 14:35:11 UTC 2009
4
- :state: AVAILABLE
5
3
  :capacity: 1
6
4
  :device:
5
+ :created: Thu Jul 30 14:35:11 UTC 2009
7
6
  :instance_id:
7
+ :id: vol1
8
+ :state: AVAILABLE
@@ -1,7 +1,8 @@
1
- :owner_id: mockuser
1
+ ---
2
2
  :realm_id: us
3
- :created: Thu Jul 30 14:35:11 UTC 2009
4
- :state: AVAILABLE
5
3
  :capacity: 1
6
4
  :device:
5
+ :created: Thu Jul 30 14:35:11 UTC 2009
7
6
  :instance_id:
7
+ :id: vol2
8
+ :state: AVAILABLE
@@ -1,7 +1,8 @@
1
- :owner_id: mockuser
1
+ ---
2
2
  :realm_id: us
3
- :created: Thu Jul 30 14:35:11 UTC 2009
4
- :state: IN-USE
5
3
  :capacity: 1
6
4
  :device: /dev/sda1
5
+ :created: Thu Jul 30 14:35:11 UTC 2009
7
6
  :instance_id: inst1
7
+ :id: vol3
8
+ :state: IN-USE
@@ -0,0 +1,101 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one or more
3
+ # contributor license agreements. See the NOTICE file distributed with
4
+ # this work for additional information regarding copyright ownership. The
5
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance with the
7
+ # License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations
15
+ # under the License.
16
+
17
+ # The mock client does a bunch of filesystem judo. It's mostly there to
18
+ # keep the driver from looking too ugly with all the File I/O
19
+
20
+ module Deltacloud::Drivers::Mock
21
+
22
+ class Client
23
+ def initialize(storage_root)
24
+ @storage_root = storage_root
25
+ @collections = []
26
+
27
+ if ! File::directory?(@storage_root)
28
+ FileUtils::rm_rf(@storage_root)
29
+ FileUtils::mkdir_p(@storage_root)
30
+ data = Dir[File::join(File::dirname(__FILE__), "data", "*")]
31
+ FileUtils::cp_r(data, @storage_root)
32
+ end
33
+ end
34
+
35
+ def dir(collection)
36
+ result = File::join(@storage_root, collection.to_s)
37
+ unless @collections.include?(collection)
38
+ FileUtils::mkdir_p(result) unless File::directory?(result)
39
+ @collections << collection
40
+ end
41
+ result
42
+ end
43
+
44
+ def file(collection, id)
45
+ File::join(dir(collection), "#{id}.yml")
46
+ end
47
+
48
+ def files(collection)
49
+ Dir[File::join(dir(collection), "*.yml")]
50
+ end
51
+
52
+ # Return the ID's of all members of +collection+
53
+ def members(collection)
54
+ files(collection).map { |f| File::basename(f, ".yml") }
55
+ end
56
+
57
+ def load(collection, id)
58
+ fname = file(collection, id)
59
+ begin
60
+ YAML.load(File.read(fname))
61
+ rescue Errno::ENOENT
62
+ nil
63
+ end
64
+ end
65
+
66
+ def store(collection, obj)
67
+ raise "Why no obj[:id] ?" unless obj[:id]
68
+ File::open(file(collection, obj[:id]), "w") { |f| YAML.dump(obj, f) }
69
+ end
70
+
71
+ # Return the object with id +id+ of class +klass+ from the collection
72
+ # derived from the classes name
73
+ def build(klass, id)
74
+ klass.new(load(collection_name(klass), id))
75
+ end
76
+
77
+ # Return an array of hashes of all the resources in the collection
78
+ def load_all(collection)
79
+ members(collection).map { |id| load(collection, id) }
80
+ end
81
+
82
+ # Return an array of model objects of the resources in the collection
83
+ # corresponding to class. The name of the collection is derived from
84
+ # the name of the class
85
+ def build_all(klass)
86
+ load_all(collection_name(klass)).map { |hash| klass.new(hash) }
87
+ end
88
+
89
+ def destroy(collection, id)
90
+ fname = file(collection, id)
91
+ FileUtils.rm(fname) if File::exists?(fname)
92
+ end
93
+
94
+ private
95
+
96
+ def collection_name(klass)
97
+ klass.name.underscore.pluralize
98
+ end
99
+ end
100
+
101
+ end
@@ -17,502 +17,440 @@
17
17
 
18
18
  require 'deltacloud/base_driver'
19
19
  require 'yaml'
20
+ require 'deltacloud/drivers/mock/mock_client'
20
21
 
21
- module Deltacloud
22
- module Drivers
23
- module Mock
24
- class MockDriver < Deltacloud::BaseDriver
22
+ module Deltacloud::Drivers::Mock
25
23
 
26
- # If the provider is set to storage, pretend to be a storage-only
27
- # driver
28
- def supported_collections
29
- endpoint = Thread.current[:provider] || ENV['API_PROVIDER']
30
- if endpoint == 'storage'
31
- [:buckets]
32
- else
33
- DEFAULT_COLLECTIONS + [:buckets, :keys]
24
+ class MockDriver < Deltacloud::BaseDriver
25
+
26
+ # If the provider is set to storage, pretend to be a storage-only
27
+ # driver
28
+ def supported_collections
29
+ if api_provider == 'storage'
30
+ [:buckets]
31
+ else
32
+ DEFAULT_COLLECTIONS + [:buckets, :keys]
33
+ end
34
34
  end
35
- end
36
35
 
37
- ( REALMS = [
38
- Realm.new({
39
- :id=>'us',
40
- :name=>'United States',
41
- :limit=>:unlimited,
42
- :state=>'AVAILABLE',
43
- }),
44
- Realm.new({
45
- :id=>'eu',
46
- :name=>'Europe',
47
- :limit=>:unlimited,
48
- :state=>'AVAILABLE',
49
- }),
50
- ] ) unless defined?( REALMS )
51
-
52
- define_hardware_profile('m1-small') do
53
- cpu 1
54
- memory 1.7 * 1024
55
- storage 160
56
- architecture 'i386'
57
- end
36
+ ( REALMS = [
37
+ Realm.new({
38
+ :id=>'us',
39
+ :name=>'United States',
40
+ :limit=>:unlimited,
41
+ :state=>'AVAILABLE'}),
42
+ Realm.new({
43
+ :id=>'eu',
44
+ :name=>'Europe',
45
+ :limit=>:unlimited,
46
+ :state=>'AVAILABLE'}),
47
+ ] ) unless defined?( REALMS )
48
+
49
+ define_hardware_profile('m1-small') do
50
+ cpu 1
51
+ memory 1.7 * 1024
52
+ storage 160
53
+ architecture 'i386'
54
+ end
58
55
 
59
- define_hardware_profile('m1-large') do
60
- cpu 2
61
- memory (7.5*1024 .. 15*1024), :default => 10 * 1024
62
- storage [ 850, 1024 ]
63
- architecture 'x86_64'
64
- end
56
+ define_hardware_profile('m1-large') do
57
+ cpu 2
58
+ memory (7.5*1024 .. 15*1024), :default => 10 * 1024
59
+ storage [ 850, 1024 ]
60
+ architecture 'x86_64'
61
+ end
65
62
 
66
- define_hardware_profile('m1-xlarge') do
67
- cpu 4
68
- memory (12*1024 .. 32*1024)
69
- storage [ 1024, 2048, 4096 ]
70
- architecture 'x86_64'
71
- end
63
+ define_hardware_profile('m1-xlarge') do
64
+ cpu 4
65
+ memory (12*1024 .. 32*1024)
66
+ storage [ 1024, 2048, 4096 ]
67
+ architecture 'x86_64'
68
+ end
72
69
 
73
- # Some clouds tell us nothing about hardware profiles (e.g., OpenNebula)
74
- define_hardware_profile 'opaque'
70
+ # Some clouds tell us nothing about hardware profiles (e.g., OpenNebula)
71
+ define_hardware_profile 'opaque'
75
72
 
76
- define_instance_states do
77
- start.to( :pending ) .on( :create )
73
+ define_instance_states do
74
+ start.to( :pending ) .on( :create )
78
75
 
79
- pending.to( :running ) .automatically
76
+ pending.to( :running ) .automatically
80
77
 
81
- running.to( :running ) .on( :reboot )
82
- running.to( :stopped ) .on( :stop )
78
+ running.to( :running ) .on( :reboot )
79
+ running.to( :stopped ) .on( :stop )
83
80
 
84
- stopped.to( :running ) .on( :start )
85
- stopped.to( :finish ) .on( :destroy )
86
- end
81
+ stopped.to( :running ) .on( :start )
82
+ stopped.to( :finish ) .on( :destroy )
83
+ end
87
84
 
88
- feature :instances, :user_name
89
- feature :instances, :authentication_key
85
+ feature :instances, :user_name
86
+ feature :instances, :user_data
87
+ feature :instances, :authentication_key
90
88
 
91
- def initialize
92
- if ENV["DELTACLOUD_MOCK_STORAGE"]
93
- @storage_root = ENV["DELTACLOUD_MOCK_STORAGE"]
94
- elsif ENV["USER"]
95
- @storage_root = File::join("/var/tmp", "deltacloud-mock-#{ENV["USER"]}")
96
- else
97
- raise "Please set either the DELTACLOUD_MOCK_STORAGE or USER environment variable"
98
- end
99
- if ! File::directory?(@storage_root)
100
- FileUtils::rm_rf(@storage_root)
101
- FileUtils::mkdir_p(@storage_root)
102
- data = Dir::glob(File::join(File::dirname(__FILE__), "data", "*"))
103
- FileUtils::cp_r(data, @storage_root)
89
+ def initialize
90
+ if ENV["DELTACLOUD_MOCK_STORAGE"]
91
+ storage_root = ENV["DELTACLOUD_MOCK_STORAGE"]
92
+ elsif ENV["USER"]
93
+ storage_root = File::join("/var/tmp", "deltacloud-mock-#{ENV["USER"]}")
94
+ else
95
+ raise "Please set either the DELTACLOUD_MOCK_STORAGE or USER environment variable"
96
+ end
97
+ @client = Client.new(storage_root)
104
98
  end
105
- end
106
99
 
107
- def realms(credentials, opts=nil)
108
- return REALMS if ( opts.nil? )
109
- results = REALMS
110
- results = filter_on( results, :id, opts )
111
- results
112
- end
100
+ def realms(credentials, opts=nil)
101
+ return REALMS if ( opts.nil? )
102
+ results = REALMS
103
+ results = filter_on( results, :id, opts )
104
+ results
105
+ end
113
106
 
114
- #
115
- # Images
116
- #
117
- def images(credentials, opts=nil )
118
- check_credentials( credentials )
119
- images = []
120
- Dir[ "#{@storage_root}/images/*.yml" ].each do |image_file|
121
- image = YAML.load( File.read( image_file ) )
122
- image[:id] = File.basename( image_file, ".yml" )
123
- image[:name] = image[:description]
124
- images << Image.new( image )
125
- end
126
- images = filter_on( images, :id, opts )
127
- images = filter_on( images, :architecture, opts )
128
- if ( opts && opts[:owner_id] == 'self' )
129
- images = images.select{|e| e.owner_id == credentials.user }
130
- else
131
- images = filter_on( images, :owner_id, opts )
132
- end
133
- images.sort_by{|e| [e.owner_id,e.description]}
134
- end
107
+ #
108
+ # Images
109
+ #
110
+ def images(credentials, opts=nil )
111
+ check_credentials( credentials )
112
+ images = []
113
+ images = @client.build_all(Image)
114
+ images = filter_on( images, :id, opts )
115
+ images = filter_on( images, :architecture, opts )
116
+ if ( opts && opts[:owner_id] == 'self' )
117
+ images = images.select{|e| e.owner_id == credentials.user }
118
+ else
119
+ images = filter_on( images, :owner_id, opts )
120
+ end
121
+ images.sort_by{|e| [e.owner_id,e.description]}
122
+ end
135
123
 
136
- def create_image(credentials, opts={})
137
- check_credentials(credentials)
138
- instance = instance(credentials, :id => opts[:instance_id])
139
- raise BackendError::new(500, 'CreateImageNotSupported', '', '') unless instance.can_create_image?
140
- ids = Dir[ "#{@storage_root}/images/*.yml" ].collect{|e| File.basename( e, ".yml" )}
141
- count = 0
142
- while true
143
- next_id = "img#{count}"
144
- break if not ids.include?(next_id)
145
- count += 1
146
- end
147
- safely do
148
- image = {
149
- :name => opts[:name],
150
- :owner_id => 'root',
151
- :description => opts[:description],
152
- :architecture => 'i386',
153
- :state => 'UP'
154
- }
155
- File.open( "#{@storage_root}/images/#{next_id}.yml", 'w' ) do |f|
156
- YAML.dump( image, f )
124
+ def create_image(credentials, opts={})
125
+ check_credentials(credentials)
126
+ instance = instance(credentials, :id => opts[:id])
127
+ safely do
128
+ raise 'CreateImageNotSupported' unless instance and instance.can_create_image?
129
+ image = {
130
+ :id => opts[:name],
131
+ :name => opts[:name],
132
+ :owner_id => 'root',
133
+ :state => "AVAILABLE",
134
+ :description => opts[:description],
135
+ :architecture => 'i386'
136
+ }
137
+ @client.store(:images, image)
138
+ Image.new(image)
157
139
  end
158
- image[:id] = next_id
159
- Image.new(image)
160
140
  end
161
- end
162
141
 
163
- #
164
- # Instances
165
- #
166
-
167
- def instance(credentials, opts={})
168
- check_credentials( credentials )
169
- instance_filename = File.join(@storage_root, 'instances', "#{opts[:id]}.yml")
170
- return nil unless File.exists?(instance_filename)
171
- instance = YAML::load_file(instance_filename)
172
- instance[:actions] = instance_actions_for( instance[:state] )
173
- instance[:id] = File::basename(instance_filename, ".yml")
174
- Instance.new(instance)
175
- end
142
+ def destroy_image(credentials, id)
143
+ check_credentials( credentials )
144
+ @client.destroy(:images, id)
145
+ end
146
+
147
+ #
148
+ # Instances
149
+ #
176
150
 
177
- def instances(credentials, opts=nil)
178
- check_credentials( credentials )
179
- instances = []
180
- Dir[ "#{@storage_root}/instances/*.yml" ].each do |instance_file|
181
- instance = YAML::load_file(instance_file)
182
- if ( instance[:owner_id] == credentials.user )
183
- instance[:id] = File.basename( instance_file, ".yml" )
184
- instance[:actions] = instance_actions_for( instance[:state] )
185
- instances << Instance.new( instance )
151
+ def instance(credentials, opts={})
152
+ check_credentials( credentials )
153
+ if instance = @client.load(:instances, opts[:id])
154
+ Instance.new(instance)
186
155
  end
187
156
  end
188
- instances = filter_on( instances, :id, opts )
189
- instances = filter_on( instances, :state, opts )
190
- instances
191
- end
192
157
 
193
- def create_instance(credentials, image_id, opts)
194
- check_credentials( credentials )
195
- ids = Dir[ "#{@storage_root}/instances/*.yml" ].collect{|e| File.basename( e, ".yml" )}
158
+ def instances(credentials, opts=nil)
159
+ check_credentials( credentials )
160
+ instances = @client.build_all(Instance)
161
+ instances = filter_on( instances, :owner_id, :owner_id => credentials.user )
162
+ instances = filter_on( instances, :id, opts )
163
+ instances = filter_on( instances, :state, opts )
164
+ instances
165
+ end
166
+
167
+ def create_instance(credentials, image_id, opts)
168
+ check_credentials( credentials )
169
+ ids = @client.members(:instances)
196
170
 
197
- count = 0
198
- while true
199
- next_id = "inst" + count.to_s
200
- if not ids.include?(next_id)
201
- break
171
+ count = 0
172
+ while true
173
+ next_id = "inst" + count.to_s
174
+ if not ids.include?(next_id)
175
+ break
176
+ end
177
+ count = count + 1
202
178
  end
203
- count = count + 1
204
- end
205
-
206
- realm_id = opts[:realm_id]
207
- if ( realm_id.nil? )
208
- realm = realms(credentials).first
209
- ( realm_id = realm.id ) if realm
210
- end
211
-
212
- hwp = find_hardware_profile(credentials, opts[:hwp_id], image_id)
213
-
214
- name = opts[:name] || "i-#{Time.now.to_i}"
215
-
216
- instance = {
217
- :name=>name,
218
- :state=>'RUNNING',
219
- :image_id=>image_id,
220
- :owner_id=>credentials.user,
221
- :public_addresses=>["#{image_id}.#{next_id}.public.com"],
222
- :private_addresses=>["#{image_id}.#{next_id}.private.com"],
223
- :instance_profile => InstanceProfile.new(hwp.name, opts),
224
- :realm_id=>realm_id,
225
- :create_image=>true,
226
- :actions=>instance_actions_for( 'RUNNING' )
227
- }
228
- File.open( "#{@storage_root}/instances/#{next_id}.yml", 'w' ) {|f|
229
- YAML.dump( instance, f )
230
- }
231
- instance[:id] = next_id
232
- Instance.new( instance )
233
- end
234
179
 
235
- def update_instance_state(credentials, id, state)
236
- instance_file = "#{@storage_root}/instances/#{id}.yml"
237
- instance_yml = YAML.load( File.read( instance_file ) )
238
- instance_yml[:id] = id
239
- instance_yml[:state] = state
240
- instance_yml[:actions] = instance_actions_for( instance_yml[:state] )
241
- File.open( instance_file, 'w' ) do |f|
242
- f << YAML.dump( instance_yml )
180
+ realm_id = opts[:realm_id]
181
+ if ( realm_id.nil? )
182
+ realm = realms(credentials).first
183
+ ( realm_id = realm.id ) if realm
184
+ end
185
+
186
+ hwp = find_hardware_profile(credentials, opts[:hwp_id], image_id)
187
+
188
+ name = opts[:name] || "i-#{Time.now.to_i}"
189
+
190
+ instance = {
191
+ :id => next_id,
192
+ :name=>name,
193
+ :state=>'RUNNING',
194
+ :keyname => opts[:keyname],
195
+ :image_id=>image_id,
196
+ :owner_id=>credentials.user,
197
+ :public_addresses=>["#{image_id}.#{next_id}.public.com"],
198
+ :private_addresses=>["#{image_id}.#{next_id}.private.com"],
199
+ :instance_profile => InstanceProfile.new(hwp.name, opts),
200
+ :realm_id=>realm_id,
201
+ :create_image=>true,
202
+ :actions=>instance_actions_for( 'RUNNING' ),
203
+ :user_data => opts[:user_data]
204
+ }
205
+ @client.store(:instances, instance)
206
+ Instance.new( instance )
243
207
  end
244
- Instance.new( instance_yml )
245
- end
246
208
 
247
- def start_instance(credentials, id)
248
- update_instance_state(credentials, id, 'RUNNING')
249
- end
209
+ def update_instance_state(credentials, id, state)
210
+ instance = @client.load(:instances, id)
211
+ instance[:state] = state
212
+ instance[:actions] = instance_actions_for( instance[:state] )
213
+ @client.store(:instances, instance)
214
+ Instance.new( instance )
215
+ end
250
216
 
251
- def reboot_instance(credentials, id)
252
- update_instance_state(credentials, id, 'RUNNING')
253
- end
217
+ def start_instance(credentials, id)
218
+ update_instance_state(credentials, id, 'RUNNING')
219
+ end
254
220
 
255
- def stop_instance(credentials, id)
256
- update_instance_state(credentials, id, 'STOPPED')
257
- end
221
+ def reboot_instance(credentials, id)
222
+ update_instance_state(credentials, id, 'RUNNING')
223
+ end
258
224
 
225
+ def stop_instance(credentials, id)
226
+ update_instance_state(credentials, id, 'STOPPED')
227
+ end
259
228
 
260
- def destroy_instance(credentials, id)
261
- check_credentials( credentials )
262
- FileUtils.rm( "#{@storage_root}/instances/#{id}.yml" )
263
- end
264
229
 
265
- #
266
- # Storage Volumes
267
- #
268
-
269
- def storage_volumes(credentials, opts=nil)
270
- check_credentials( credentials )
271
- volumes = []
272
- Dir[ "#{@storage_root}/storage_volumes/*.yml" ].each do |storage_volume_file|
273
- storage_volume = YAML.load( File.read( storage_volume_file ) )
274
- if ( storage_volume[:owner_id] == credentials.user )
275
- storage_volume[:id] = File.basename( storage_volume_file, ".yml" )
276
- volumes << StorageVolume.new( storage_volume )
277
- end
230
+ def destroy_instance(credentials, id)
231
+ check_credentials( credentials )
232
+ @client.destroy(:instances, id)
278
233
  end
279
- volumes = filter_on( volumes, :id, opts )
280
- volumes
281
- end
282
234
 
283
- #
284
- # Storage Snapshots
285
- #
286
-
287
- def storage_snapshots(credentials, opts=nil)
288
- check_credentials( credentials )
289
- snapshots = []
290
- Dir[ "#{@storage_root}/storage_snapshots/*.yml" ].each do |storage_snapshot_file|
291
- storage_snapshot = YAML.load( File.read( storage_snapshot_file ) )
292
- if ( storage_snapshot[:owner_id] == credentials.user )
293
- storage_snapshot[:id] = File.basename( storage_snapshot_file, ".yml" )
294
- snapshots << StorageSnapshot.new( storage_snapshot )
295
- end
296
- end
297
- snapshots = filter_on( snapshots, :id, opts )
298
- snapshots
299
- end
235
+ #
236
+ # Storage Volumes
237
+ #
300
238
 
301
- def keys(credentials, opts={})
302
- check_credentials(credentials)
303
- result = []
304
- key_dir = File.join(@storage_root, 'keys')
305
- Dir[key_dir + '/*.yml'].each do |key_file|
306
- result << Key.new(YAML::load(File.read(key_file)))
239
+ def storage_volumes(credentials, opts=nil)
240
+ check_credentials( credentials )
241
+ volumes = @client.build_all(StorageVolume)
242
+ volumes = filter_on( volumes, :id, opts )
243
+ volumes
307
244
  end
308
- result = filter_on( result, :id, opts )
309
- result
310
- end
311
245
 
312
- def key(credentials, opts={})
313
- keys(credentials, opts).first
314
- end
246
+ #
247
+ # Storage Snapshots
248
+ #
315
249
 
316
- def create_key(credentials, opts={})
317
- check_credentials(credentials)
318
- key_hash = {
319
- :id => opts[:key_name],
320
- :credential_type => :key,
321
- :fingerprint => Key::generate_mock_fingerprint,
322
- :pem_rsa_key => Key::generate_mock_pem
323
- }
324
- key_dir = File.join(@storage_root, 'keys')
325
- if File.exists?(key_dir + "/#{key_hash[:id]}.yml")
326
- raise Deltacloud::BackendError.new(403, self.class.to_s, "key-exists",
327
- ["Key with same name already exists"])
328
- end
329
- FileUtils.mkdir_p(key_dir) unless File.directory?(key_dir)
330
- File.open(key_dir + "/#{key_hash[:id]}.yml", 'w') do |f|
331
- f.puts(YAML::dump(key_hash))
332
- end
333
- return Key.new(key_hash)
334
- end
250
+ def storage_snapshots(credentials, opts=nil)
251
+ check_credentials( credentials )
252
+ snapshots = @client.build_all(StorageSnapshot)
253
+ snapshots = filter_on(snapshots, :id, opts )
254
+ snapshots
255
+ end
335
256
 
336
- def destroy_key(credentials, opts={})
337
- key = key(credentials, opts)
338
- safely do
339
- key_dir = File.join(@storage_root, 'keys')
340
- File.delete(key_dir + "/#{key.id}.yml")
257
+ def keys(credentials, opts={})
258
+ check_credentials(credentials)
259
+ result = @client.build_all(Key)
260
+ result = filter_on( result, :id, opts )
261
+ result
341
262
  end
342
- end
343
263
 
344
- #--
345
- # Buckets
346
- #--
347
- def buckets(credentials, opts={})
348
- check_credentials(credentials)
349
- buckets=[]
350
- safely do
351
- unless (opts[:id].nil?)
352
- bucket_file = File::join(@storage_root, 'buckets', "#{opts[:id]}.yml")
353
- bucket = YAML.load_file(bucket_file)
354
- bucket[:id] = opts[:id]
355
- bucket[:name] = bucket[:id]
356
- buckets << Bucket.new( bucket )
357
- else
358
- Dir[ File::join(@storage_root, 'buckets', '*.yml')].each do |bucket_file|
359
- bucket_id = File.basename( bucket_file, ".yml" )
360
- buckets << Bucket.new( {:id => bucket_id, :name => bucket_id } )
361
- end
362
- end
264
+ def key(credentials, opts={})
265
+ keys(credentials, opts).first
363
266
  end
364
- buckets = filter_on( buckets, :id, opts )
365
- end
366
267
 
367
- #--
368
- # Create bucket
369
- #--
370
- def create_bucket(credentials, name, opts={})
371
- check_credentials(credentials)
372
- bucket = {
373
- :id => name,
374
- :name=>name,
375
- :size=>'0',
376
- :blob_list=>[]
377
- }
378
- File.open( File::join(@storage_root, 'buckets', "#{name}.yml"), 'w') {|b| YAML.dump( bucket, b )}
379
- Bucket.new(bucket)
380
- end
268
+ def create_key(credentials, opts={})
269
+ check_credentials(credentials)
270
+ key_hash = {
271
+ :id => opts[:key_name],
272
+ :credential_type => :key,
273
+ :fingerprint => Key::generate_mock_fingerprint,
274
+ :pem_rsa_key => Key::generate_mock_pem
275
+ }
381
276
 
382
- #--
383
- # Delete bucket
384
- #--
385
- def delete_bucket(credentials, name, opts={})
386
- check_credentials(credentials)
387
- bucket = bucket(credentials, {:id => name})
388
- unless (bucket.size == "0")
389
- raise Deltacloud::BackendError.new(403, self.class.to_s, "bucket-not-empty", "delete operation not valid for non-empty bucket")
277
+ raise "KeyExist" if @client.load(:keys, key_hash[:id])
278
+ @client.store(:keys, key_hash)
279
+ return Key.new(key_hash)
390
280
  end
391
- safely do
392
- File.delete(File::join(@storage_root, 'buckets', "#{name}.yml"))
281
+
282
+ def destroy_key(credentials, opts={})
283
+ key = key(credentials, opts)
284
+ @client.destroy(:keys, key.id)
393
285
  end
394
- end
395
286
 
396
- #--
397
- # Blobs
398
- #--
399
- def blobs(credentials, opts = {})
400
- check_credentials(credentials)
401
- blobs=[]
402
- blobfile = File::join("#{@storage_root}", "buckets", "blobs", "#{opts[:id]}.yml")
403
- safely do
404
- blob = YAML.load_file(blobfile)
405
- return [] unless blob[:bucket] == opts['bucket'] #can't return nil since base_driver invokes .first on return
406
- blob[:id] = File.basename( blobfile, ".yml" )
407
- blob[:name] = blob[:id]
408
- blobs << Blob.new( blob )
409
- blobs = filter_on( blobs, :id, opts )
287
+ #--
288
+ # Buckets
289
+ #--
290
+ def buckets(credentials, opts={})
291
+ check_credentials(credentials)
292
+ buckets = @client.build_all(Bucket)
293
+ blob_map = @client.load_all(:blobs).inject({}) do |map, blob|
294
+ map[blob[:bucket]] ||= []
295
+ map[blob[:bucket]] << blob[:id]
296
+ map
297
+ end
298
+ buckets.each { |bucket| bucket.blob_list = blob_map[bucket.id] }
299
+ filter_on( buckets, :id, opts )
410
300
  end
411
- end
412
301
 
413
- #--
414
- # Blob content
415
- #--
416
- def blob_data(credentials, bucket_id, blob_id, opts = {})
417
- check_credentials(credentials)
418
- blob=nil
419
- safely do
420
- blobfile = File::join("#{@storage_root}", "buckets", "blobs", "#{opts['blob']}.yml")
421
- blob = YAML.load_file(blobfile)
422
- end
423
- blob[:content].each {|part| yield part}
424
- end
302
+ #--
303
+ # Create bucket
304
+ #--
305
+ def create_bucket(credentials, name, opts={})
306
+ check_credentials(credentials)
307
+ bucket = {
308
+ :id => name,
309
+ :name=>name,
310
+ :size=>'0',
311
+ :blob_list=>[]
312
+ }
313
+ @client.store(:buckets, bucket)
314
+ Bucket.new(bucket)
315
+ end
425
316
 
426
- #--
427
- # Create blob
428
- #--
429
- def create_blob(credentials, bucket_id, blob_id, blob_data, opts={})
430
- check_credentials(credentials)
431
- blob_meta = {}
432
- opts.inject({}){|result, (k,v)| blob_meta[k] = v if k.match(/X[_-]Deltacloud[_-]Blobmeta[_-]/i)} #select{|k,v| k.match(/X[_-]Deltacloud[_-]Blobmeta[_-]/i)}
433
- blob = {
434
- :id => blob_id,
435
- :bucket => bucket_id,
436
- :content_length => blob_data[:tempfile].length,
437
- :content_type => blob_data[:type],
438
- :last_modified => Time.now,
439
- :user_metadata => blob_meta.gsub_keys('X_Deltacloud_Blobmeta_', ''),
440
- :content => blob_data[:tempfile].read
441
- }
442
- File.open( File::join("#{@storage_root}", "buckets", "blobs", "#{blob_id}.yml"), 'w' ) {|b| YAML.dump( blob, b )}
443
- Blob.new(blob)
444
- end
317
+ #--
318
+ # Delete bucket
319
+ #--
320
+ def delete_bucket(credentials, name, opts={})
321
+ check_credentials(credentials)
322
+ bucket = bucket(credentials, {:id => name})
323
+ raise "BucketNotEmpty" unless (bucket.size == "0")
324
+ @client.destroy(:buckets, bucket.id)
325
+ end
445
326
 
446
- #--
447
- # Delete blob
448
- #--
449
- def delete_blob(credentials, bucket_id, blob_id, opts={})
450
- check_credentials(credentials)
451
- blobfile = File::join("#{@storage_root}", "buckets", "blobs", "#{blob_id}.yml")
452
- safely do
453
- unless File.exists?(blobfile)
454
- raise Deltacloud::BackendError.new(500, self.class.to_s, "blob #{blob_id} doesn't exist", "cannot delete non existant blob")
327
+ #--
328
+ # Blobs
329
+ #--
330
+ def blobs(credentials, opts = {})
331
+ check_credentials(credentials)
332
+ blobs = @client.build_all(Blob)
333
+ filter_on( blobs, :bucket, :bucket => opts['bucket'] )
334
+ filter_on( blobs, :id, opts )
335
+ end
336
+
337
+ #--
338
+ # Blob content
339
+ #--
340
+ def blob_data(credentials, bucket_id, blob_id, opts = {})
341
+ check_credentials(credentials)
342
+ if blob = @client.load(:blobs, blob_id)
343
+ blob[:content].each {|part| yield part}
455
344
  end
456
- File.delete(blobfile)
457
345
  end
458
- end
459
346
 
460
- #--
461
- # Get metadata
462
- #--
463
- def blob_metadata(credentials, opts={})
464
- check_credentials(credentials)
465
- blobfile = File::join("#{@storage_root}", "buckets", "blobs", "#{opts[:id]}.yml")
466
- #safely do - mechanism not suitable here since head requests don't return a body response
467
- begin
468
- blob = YAML.load_file(blobfile)
469
- rescue Errno::ENOENT
470
- return nil #server.rb picks this up and gives 404
471
- end
472
- blob[:user_metadata]
473
- end
347
+ #--
348
+ # Create blob
349
+ #--
350
+ def create_blob(credentials, bucket_id, blob_id, blob_data, opts={})
351
+ check_credentials(credentials)
352
+ blob_meta = BlobHelper::extract_blob_metadata_hash(opts)
353
+ blob = {
354
+ :id => blob_id,
355
+ :name => blob_id,
356
+ :bucket => bucket_id,
357
+ :content_length => blob_data[:tempfile].length,
358
+ :content_type => blob_data[:type],
359
+ :last_modified => Time.now,
360
+ :user_metadata => BlobHelper::rename_metadata_headers(blob_meta, ''),
361
+ :content => blob_data[:tempfile].read
362
+ }
363
+ @client.store(:blobs, blob)
364
+ Blob.new(blob)
365
+ end
474
366
 
475
- #--
476
- # Update metadata
477
- #--
478
- def update_blob_metadata(credentials, opts={})
479
- check_credentials(credentials)
480
- blobfile = File::join("#{@storage_root}", "buckets", "blobs", "#{opts[:id]}.yml")
481
- safely do
482
- blob = YAML.load_file(blobfile)
483
- return false unless blob
484
- blob[:user_metadata] = opts['meta_hash'].gsub_keys('HTTP[-_]X[-_]Deltacloud[-_]Blobmeta[-_]', '')
485
- File.open(File::join("#{@storage_root}", "buckets", "blobs", "#{opts[:id]}.yml"), 'w' ) {|b| YAML.dump( blob, b )}
367
+ #--
368
+ # Delete blob
369
+ #--
370
+ def delete_blob(credentials, bucket_id, blob_id, opts={})
371
+ check_credentials(credentials)
372
+ safely do
373
+ raise "NotExistentBlob" unless @client.load(:blobs, blob_id)
374
+ @client.destroy(:blobs, blob_id)
375
+ end
486
376
  end
487
- end
488
377
 
489
- def valid_credentials?(credentials)
490
- begin
378
+ #--
379
+ # Get metadata
380
+ #--
381
+ def blob_metadata(credentials, opts={})
491
382
  check_credentials(credentials)
492
- return true
493
- rescue Deltacloud::AuthException
383
+ if blob = @client.load(:blobs, params[:id])
384
+ blob[:user_metadata]
385
+ else
386
+ nil
387
+ end
494
388
  end
495
- return false
496
- end
497
389
 
498
- private
390
+ #--
391
+ # Update metadata
392
+ #--
393
+ def update_blob_metadata(credentials, opts={})
394
+ check_credentials(credentials)
395
+ safely do
396
+ blob = @client.load(:blobs, params[:id])
397
+ return false unless blob
398
+ blob[:user_metadata] = BlobHelper::rename_metadata_headers(opts['meta_hash'], '')
399
+ @client.store(:blobs, blob)
400
+ end
401
+ end
499
402
 
500
- def check_credentials(credentials)
501
- if ( credentials.user != 'mockuser' ) or ( credentials.password != 'mockpassword' )
502
- raise Deltacloud::AuthException.new
403
+ def valid_credentials?(credentials)
404
+ begin
405
+ check_credentials(credentials)
406
+ return true
407
+ rescue
408
+ end
409
+ return false
503
410
  end
504
- end
505
411
 
506
- def catched_exceptions_list
507
- {
508
- :auth => [],
509
- :error => [ /Deltacloud::BackendError/, /Errno::ENOENT/ ],
510
- :glob => [ /Error/ ]
511
- }
512
- end
412
+ private
513
413
 
514
- end
414
+ def check_credentials(credentials)
415
+ safely do
416
+ if ( credentials.user != 'mockuser' ) or ( credentials.password != 'mockpassword' )
417
+ raise 'AuthFailure'
418
+ end
419
+ end
420
+ end
421
+
422
+ exceptions do
423
+
424
+ on /AuthFailure/ do
425
+ status 401
426
+ message "Authentication Failure"
427
+ end
428
+
429
+ on /BucketNotEmpty/ do
430
+ status 403
431
+ message "Delete operation not valid for non-empty bucket"
432
+ end
433
+
434
+ on /KeyExist/ do
435
+ status 403
436
+ message "Key with same name already exists"
437
+ end
438
+
439
+ on /CreateImageNotSupported/ do
440
+ status 500
441
+ end
442
+
443
+ on /NotExistentBlob/ do
444
+ status 500
445
+ message "Could not delete a non existent blob"
446
+ end
447
+
448
+ on /Err/ do
449
+ status 500
450
+ end
515
451
 
516
452
  end
453
+
517
454
  end
455
+
518
456
  end