deltacloud-core 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (294) hide show
  1. data/NOTICE +1 -1
  2. data/Rakefile +63 -21
  3. data/bin/deltacloudd +10 -6
  4. data/config.ru +62 -6
  5. data/config/drivers/ec2.yaml +8 -0
  6. data/config/drivers/fgcp.yaml +13 -0
  7. data/deltacloud-core.gemspec +10 -2
  8. data/lib/cimi/collections.rb +58 -0
  9. data/lib/cimi/collections/address_templates.rb +49 -0
  10. data/lib/cimi/collections/addresses.rb +74 -0
  11. data/lib/cimi/collections/cloud_entry_point.rb +37 -0
  12. data/lib/{deltacloud/helpers/conversion_helper.rb → cimi/collections/entity_metadata.rb} +24 -16
  13. data/lib/cimi/collections/machine_admins.rb +74 -0
  14. data/lib/cimi/collections/machine_configurations.rb +49 -0
  15. data/lib/cimi/collections/machine_images.rb +50 -0
  16. data/lib/cimi/collections/machines.rb +157 -0
  17. data/lib/cimi/collections/network_configurations.rb +47 -0
  18. data/lib/cimi/collections/network_templates.rb +48 -0
  19. data/lib/cimi/collections/networks.rb +125 -0
  20. data/lib/cimi/collections/routing_group_templates.rb +47 -0
  21. data/lib/cimi/collections/routing_groups.rb +48 -0
  22. data/lib/cimi/collections/volume_configurations.rb +48 -0
  23. data/lib/cimi/collections/volume_images.rb +50 -0
  24. data/lib/cimi/collections/volumes.rb +80 -0
  25. data/lib/cimi/collections/vsp_configurations.rb +48 -0
  26. data/lib/cimi/collections/vsp_templates.rb +50 -0
  27. data/lib/cimi/collections/vsps.rb +108 -0
  28. data/lib/cimi/dependencies.rb +1 -0
  29. data/lib/cimi/helpers.rb +116 -0
  30. data/lib/cimi/helpers/cimi_helper.rb +6 -2
  31. data/lib/cimi/models.rb +72 -0
  32. data/lib/cimi/{model → models}/action.rb +1 -1
  33. data/lib/cimi/models/address.rb +72 -0
  34. data/lib/cimi/models/address_collection.rb +34 -0
  35. data/lib/cimi/models/address_template.rb +54 -0
  36. data/lib/cimi/models/address_template_collection.rb +34 -0
  37. data/lib/cimi/{model → models}/base.rb +2 -2
  38. data/lib/cimi/{model → models}/cloud_entry_point.rb +3 -5
  39. data/lib/cimi/{model → models}/entity_metadata.rb +7 -6
  40. data/lib/cimi/{model → models}/entity_metadata_collection.rb +2 -2
  41. data/lib/cimi/{model → models}/errors.rb +8 -0
  42. data/lib/cimi/{model → models}/machine.rb +10 -10
  43. data/lib/cimi/{model → models}/machine_admin.rb +1 -1
  44. data/lib/cimi/{model → models}/machine_admin_collection.rb +2 -2
  45. data/lib/cimi/{model → models}/machine_collection.rb +2 -2
  46. data/lib/cimi/{model → models}/machine_configuration.rb +9 -6
  47. data/lib/cimi/{model → models}/machine_configuration_collection.rb +2 -2
  48. data/lib/cimi/{model → models}/machine_image.rb +1 -1
  49. data/lib/cimi/{model → models}/machine_image_collection.rb +2 -2
  50. data/lib/cimi/{model → models}/machine_template.rb +0 -0
  51. data/lib/cimi/{model → models}/machine_template_collection.rb +2 -2
  52. data/lib/cimi/models/network.rb +109 -0
  53. data/lib/cimi/{model → models}/network_collection.rb +2 -2
  54. data/lib/cimi/{model → models}/network_configuration.rb +3 -4
  55. data/lib/cimi/{model → models}/network_configuration_collection.rb +2 -2
  56. data/lib/cimi/models/network_template.rb +36 -0
  57. data/lib/cimi/models/network_template_collection.rb +35 -0
  58. data/lib/cimi/models/routing_group.rb +34 -0
  59. data/lib/cimi/models/routing_group_collection.rb +34 -0
  60. data/lib/cimi/models/routing_group_template.rb +34 -0
  61. data/lib/cimi/models/routing_group_template_collection.rb +35 -0
  62. data/lib/cimi/{model → models}/schema.rb +0 -0
  63. data/lib/cimi/{model → models}/volume.rb +4 -4
  64. data/lib/cimi/{model → models}/volume_collection.rb +2 -2
  65. data/lib/cimi/{model → models}/volume_configuration.rb +1 -1
  66. data/lib/cimi/{model → models}/volume_configuration_collection.rb +2 -2
  67. data/lib/cimi/{model → models}/volume_image.rb +1 -1
  68. data/lib/cimi/{model → models}/volume_image_collection.rb +2 -2
  69. data/lib/cimi/{model → models}/volume_template.rb +0 -0
  70. data/lib/cimi/{model → models}/volume_template_collection.rb +2 -2
  71. data/lib/cimi/models/vsp.rb +102 -0
  72. data/lib/cimi/models/vsp_collection.rb +34 -0
  73. data/lib/cimi/models/vsp_configuration.rb +40 -0
  74. data/lib/cimi/models/vsp_configuration_collection.rb +34 -0
  75. data/lib/cimi/models/vsp_template.rb +34 -0
  76. data/lib/cimi/models/vsp_template_collection.rb +34 -0
  77. data/lib/cimi/server.rb +27 -549
  78. data/lib/deltacloud/api.rb +79 -0
  79. data/lib/deltacloud/collections.rb +54 -0
  80. data/lib/deltacloud/collections/addresses.rb +91 -0
  81. data/lib/deltacloud/collections/buckets.rb +273 -0
  82. data/lib/deltacloud/collections/drivers.rb +51 -0
  83. data/lib/deltacloud/collections/firewalls.rb +116 -0
  84. data/lib/deltacloud/collections/hardware_profiles.rb +29 -0
  85. data/lib/deltacloud/collections/images.rb +73 -0
  86. data/lib/deltacloud/collections/instance_states.rb +59 -0
  87. data/lib/deltacloud/collections/instances.rb +113 -0
  88. data/lib/deltacloud/collections/keys.rb +61 -0
  89. data/lib/deltacloud/collections/load_balancers.rb +102 -0
  90. data/lib/deltacloud/collections/metrics.rb +28 -0
  91. data/lib/deltacloud/collections/realms.rb +28 -0
  92. data/lib/deltacloud/collections/storage_snapshots.rb +51 -0
  93. data/lib/deltacloud/collections/storage_volumes.rb +99 -0
  94. data/lib/deltacloud/core_ext.rb +14 -6
  95. data/lib/deltacloud/core_ext/string.rb +17 -5
  96. data/lib/deltacloud/drivers.rb +6 -42
  97. data/lib/deltacloud/drivers/azure/azure_driver.rb +0 -4
  98. data/lib/deltacloud/{base_driver → drivers}/base_driver.rb +56 -18
  99. data/lib/deltacloud/drivers/condor/condor_driver.rb +1 -8
  100. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +142 -33
  101. data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +2 -6
  102. data/lib/deltacloud/{base_driver → drivers}/exceptions.rb +25 -2
  103. data/lib/deltacloud/drivers/features.rb +154 -0
  104. data/lib/deltacloud/drivers/fgcp/fgcp_client.rb +387 -0
  105. data/lib/deltacloud/drivers/fgcp/fgcp_driver.rb +1435 -0
  106. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +8 -11
  107. data/lib/deltacloud/drivers/google/google_driver.rb +2 -5
  108. data/lib/deltacloud/drivers/mock/data/keys/test-key.yml +28 -0
  109. data/lib/deltacloud/drivers/mock/mock_client.rb +2 -2
  110. data/lib/deltacloud/drivers/mock/mock_driver.rb +58 -40
  111. data/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb +145 -0
  112. data/lib/deltacloud/drivers/opennebula/cloud_client.rb +107 -73
  113. data/lib/deltacloud/drivers/opennebula/occi_client.rb +285 -145
  114. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +189 -126
  115. data/lib/deltacloud/drivers/openstack/openstack_driver.rb +427 -8
  116. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +7 -9
  117. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +48 -66
  118. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +44 -51
  119. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +7 -8
  120. data/lib/deltacloud/drivers/sbc/sbc_client.rb +1 -1
  121. data/lib/deltacloud/drivers/sbc/sbc_driver.rb +3 -3
  122. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +8 -8
  123. data/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +39 -13
  124. data/lib/deltacloud/drivers/vsphere/vsphere_filemanager.rb +1 -0
  125. data/lib/deltacloud/helpers.rb +79 -7
  126. data/lib/{sinatra/lazy_auth.rb → deltacloud/helpers/auth_helper.rb} +5 -9
  127. data/lib/deltacloud/helpers/{blob_stream.rb → blob_stream_helper.rb} +7 -7
  128. data/lib/deltacloud/helpers/deltacloud_helper.rb +286 -0
  129. data/lib/deltacloud/helpers/driver_helper.rb +58 -0
  130. data/lib/deltacloud/helpers/rabbit_helper.rb +34 -0
  131. data/lib/{sinatra/url_for.rb → deltacloud/helpers/url_helper.rb} +31 -9
  132. data/lib/deltacloud/models.rb +19 -17
  133. data/lib/deltacloud/models/bucket.rb +4 -0
  134. data/lib/deltacloud/{hardware_profile.rb → models/hardware_profile.rb} +4 -2
  135. data/lib/deltacloud/models/image.rb +1 -0
  136. data/lib/deltacloud/models/instance.rb +4 -2
  137. data/lib/deltacloud/models/instance_address.rb +4 -0
  138. data/lib/deltacloud/models/key.rb +4 -0
  139. data/lib/deltacloud/models/metric.rb +40 -0
  140. data/lib/deltacloud/{state_machine.rb → models/state_machine.rb} +18 -1
  141. data/lib/deltacloud/server.rb +41 -1222
  142. data/lib/deltacloud_rack.rb +79 -0
  143. data/lib/{cimi/model/network_template.rb → ec2/helpers.rb} +7 -10
  144. data/lib/{deltacloud/backend_capability.rb → ec2/helpers/errors.rb} +24 -29
  145. data/lib/ec2/helpers/result.rb +31 -0
  146. data/lib/ec2/query_parser.rb +152 -0
  147. data/lib/ec2/server.rb +70 -0
  148. data/lib/{deltacloud.rb → sinatra.rb} +7 -12
  149. data/lib/sinatra/rack_accept.rb +13 -7
  150. data/lib/sinatra/rack_driver_select.rb +1 -1
  151. data/lib/sinatra/rack_matrix_params.rb +1 -3
  152. data/public/images/metric.png +0 -0
  153. data/public/javascripts/jquery.mobile-1.0.1.min.js +177 -0
  154. data/public/stylesheets/jquery.mobile-1.0.1.min.css +2 -0
  155. data/public/stylesheets/new.css +10 -0
  156. data/support/fedora/deltacloud-core.spec +1 -1
  157. data/tests/api/common.rb +1 -0
  158. data/tests/api/driver_test.rb +79 -0
  159. data/tests/api/library_test.rb +48 -0
  160. data/tests/cimi/features/step_definitions/common_steps.rb +2 -2
  161. data/tests/cimi/features/step_definitions/machines_steps.rb +5 -4
  162. data/tests/cimi/features/step_definitions/volumes_steps.rb +8 -8
  163. data/tests/cimi/features/support/env.rb +33 -11
  164. data/tests/common.rb +7 -8
  165. data/tests/drivers/ec2/api_test.rb +19 -0
  166. data/tests/drivers/ec2/common.rb +23 -0
  167. data/tests/drivers/ec2/drivers_test.rb +120 -0
  168. data/tests/drivers/ec2/hardware_profiles_test.rb +224 -0
  169. data/tests/drivers/ec2/images_test.rb +230 -0
  170. data/tests/drivers/ec2/instances_test.rb +356 -0
  171. data/tests/drivers/ec2/keys_test.rb +181 -0
  172. data/tests/drivers/ec2/realms_test.rb +146 -0
  173. data/tests/drivers/fgcp/api_test.rb +47 -0
  174. data/tests/drivers/fgcp/hardware_profiles_test.rb +54 -0
  175. data/tests/drivers/fgcp/realms_test.rb +42 -0
  176. data/tests/drivers/{rackspace → fgcp}/setup.rb +5 -6
  177. data/tests/drivers/google/api_test.rb +10 -26
  178. data/tests/drivers/google/buckets_test.rb +79 -95
  179. data/tests/drivers/google/common.rb +54 -0
  180. data/tests/drivers/mock/api_test.rb +4 -127
  181. data/tests/drivers/mock/buckets_test.rb +195 -0
  182. data/tests/drivers/mock/common.rb +7 -0
  183. data/tests/drivers/mock/drivers_test.rb +123 -0
  184. data/tests/drivers/mock/hardware_profiles_test.rb +190 -100
  185. data/tests/drivers/mock/images_test.rb +162 -103
  186. data/tests/drivers/mock/instances_test.rb +310 -220
  187. data/tests/drivers/mock/keys_test.rb +161 -0
  188. data/tests/drivers/mock/realms_test.rb +109 -70
  189. data/tests/drivers/mock/storage_snapshots_test.rb +114 -0
  190. data/tests/drivers/mock/storage_volumes_test.rb +122 -0
  191. data/tests/drivers/openstack/api_test.rb +8 -3
  192. data/tests/drivers/openstack/common.rb +21 -0
  193. data/tests/drivers/openstack/hardware_profiles_test.rb +20 -9
  194. data/tests/drivers/openstack/images_test.rb +11 -5
  195. data/tests/drivers/openstack/instances_test.rb +61 -16
  196. data/tests/drivers/openstack/realms_test.rb +11 -7
  197. data/tests/drivers/rackspace/api_test.rb +7 -2
  198. data/tests/drivers/rackspace/buckets_test.rb +7 -2
  199. data/tests/drivers/rackspace/common.rb +16 -0
  200. data/tests/drivers/rackspace/hardware_profiles_test.rb +7 -2
  201. data/tests/drivers/rackspace/images_test.rb +7 -2
  202. data/tests/drivers/rackspace/instances_test.rb +10 -5
  203. data/tests/drivers/rackspace/realms_test.rb +7 -2
  204. data/tests/drivers/rhevm/api_test.rb +12 -6
  205. data/tests/drivers/rhevm/{setup.rb → common.rb} +8 -1
  206. data/tests/drivers/rhevm/hardware_profiles_test.rb +7 -2
  207. data/tests/drivers/rhevm/images_test.rb +8 -2
  208. data/tests/drivers/rhevm/instances_test.rb +7 -2
  209. data/tests/drivers/rhevm/realms_test.rb +7 -2
  210. data/tests/minitest_common.rb +58 -0
  211. data/tests/minitest_common_api_test.rb +115 -0
  212. data/views/addresses/associate.html.haml +1 -1
  213. data/views/addresses/index.html.haml +1 -1
  214. data/views/addresses/show.html.haml +2 -3
  215. data/views/api/show.html.haml +22 -9
  216. data/views/api/show.xml.haml +8 -7
  217. data/views/blobs/show.xml.haml +7 -4
  218. data/views/buckets/new.html.haml +2 -2
  219. data/views/cimi/errors/401.xml.haml +1 -1
  220. data/views/error.html.haml +3 -3
  221. data/views/errors/400.html.haml +1 -1
  222. data/views/errors/400.xml.haml +1 -2
  223. data/views/errors/401.html.haml +8 -7
  224. data/views/errors/401.xml.haml +1 -1
  225. data/views/errors/404.xml.haml +1 -0
  226. data/views/errors/500.xml.haml +4 -2
  227. data/views/{cimi/errors/403.html.haml → errors/501.html.haml} +4 -2
  228. data/views/errors/501.xml.haml +1 -0
  229. data/views/errors/502.xml.haml +1 -7
  230. data/views/{cimi/errors/500.html.haml → errors/504.html.haml} +0 -0
  231. data/views/errors/504.xml.haml +1 -0
  232. data/views/firewalls/new.html.haml +2 -2
  233. data/views/firewalls/new_rule.html.haml +1 -1
  234. data/views/firewalls/show.html.haml +1 -1
  235. data/views/hardware_profiles/index.html.haml +3 -1
  236. data/views/hardware_profiles/index.xml.haml +2 -2
  237. data/views/hardware_profiles/show.html.haml +3 -3
  238. data/views/hardware_profiles/show.xml.haml +3 -3
  239. data/views/images/show.html.haml +5 -0
  240. data/views/images/show.xml.haml +6 -1
  241. data/views/instance_states/show.html.haml +1 -1
  242. data/views/instances/index.html.haml +1 -1
  243. data/views/instances/new.html.haml +54 -39
  244. data/views/instances/run_command.html.haml +24 -15
  245. data/views/instances/show.html.haml +7 -3
  246. data/views/instances/show.xml.haml +2 -2
  247. data/views/keys/show.xml.haml +1 -0
  248. data/views/layout.html.haml +5 -9
  249. data/views/load_balancers/show.html.haml +12 -6
  250. data/views/metrics/index.html.haml +13 -0
  251. data/views/metrics/index.xml.haml +5 -0
  252. data/views/metrics/show.html.haml +23 -0
  253. data/views/metrics/show.xml.haml +9 -0
  254. data/views/realms/show.xml.haml +2 -1
  255. data/views/root/index.html.haml +1 -1
  256. data/views/storage_snapshots/show.html.haml +1 -1
  257. data/views/storage_snapshots/show.xml.haml +1 -0
  258. data/views/storage_volumes/attach.html.haml +1 -2
  259. data/views/storage_volumes/index.html.haml +1 -1
  260. data/views/storage_volumes/new.html.haml +22 -16
  261. data/views/storage_volumes/show.html.haml +10 -4
  262. data/views/storage_volumes/show.xml.haml +3 -4
  263. metadata +547 -519
  264. data/DISCLAIMER +0 -8
  265. data/lib/cimi/model.rb +0 -52
  266. data/lib/cimi/model/network.rb +0 -69
  267. data/lib/deltacloud/base_driver.rb +0 -18
  268. data/lib/deltacloud/base_driver/features.rb +0 -262
  269. data/lib/deltacloud/base_driver/mock_driver.rb +0 -78
  270. data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +0 -186
  271. data/lib/deltacloud/drivers/rhevm/rhevm_client.rb +0 -521
  272. data/lib/deltacloud/helpers/application_helper.rb +0 -267
  273. data/lib/deltacloud/helpers/hardware_profiles_helper.rb +0 -50
  274. data/lib/deltacloud/helpers/json_helper.rb +0 -31
  275. data/lib/deltacloud/method_serializer.rb +0 -83
  276. data/lib/deltacloud/validation.rb +0 -107
  277. data/lib/sinatra/rabbit.rb +0 -441
  278. data/lib/sinatra/rack_runtime.rb +0 -47
  279. data/lib/sinatra/rack_syslog.rb +0 -86
  280. data/lib/sinatra/sinatra_verbose.rb +0 -73
  281. data/lib/sinatra/static_assets.rb +0 -99
  282. data/public/javascripts/jquery.mobile-1.0rc1.min.js +0 -170
  283. data/public/stylesheets/jquery.mobile-1.0rc1.min.css +0 -12
  284. data/tests/drivers/google/setup.rb +0 -38
  285. data/tests/drivers/mock/instance_states_test.rb +0 -71
  286. data/tests/drivers/mock/setup.rb +0 -3
  287. data/tests/drivers/mock/url_for_test.rb +0 -67
  288. data/tests/drivers/openstack/setup.rb +0 -20
  289. data/views/cimi/errors/400.html.haml +0 -41
  290. data/views/cimi/errors/401.html.haml +0 -41
  291. data/views/cimi/errors/404.html.haml +0 -29
  292. data/views/cimi/errors/405.html.haml +0 -29
  293. data/views/cimi/errors/502.html.haml +0 -43
  294. data/views/cimi/errors/backend_capability_failure.html.haml +0 -29
@@ -0,0 +1,58 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+
16
+ module Deltacloud::Helpers
17
+
18
+ module Drivers
19
+
20
+ def driver_symbol
21
+ driver_name.to_sym
22
+ end
23
+
24
+ def driver_name
25
+ Thread.current[:driver] ||= ENV['API_DRIVER']
26
+ end
27
+
28
+ def driver_class_name
29
+ driver_name.camelize
30
+ end
31
+
32
+ def driver_source_name
33
+ File.join('..', 'drivers', driver_name, driver_name + '_driver.rb')
34
+ end
35
+
36
+ def driver_class
37
+ begin
38
+ m = Deltacloud::Drivers.const_get(driver_class_name)
39
+ m.const_get(driver_class_name + "Driver").new
40
+ rescue NameError
41
+ raise "[ERROR] The driver class name is not defined as #{driver_class_name}Driver"
42
+ end
43
+ end
44
+
45
+ def driver
46
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..')
47
+ begin
48
+ require_relative driver_source_name
49
+ driver_class
50
+ rescue LoadError => e
51
+ raise "[ERROR] The driver '#{driver_name}' is unknown or not installed (#{driver_source_name})\n" +
52
+ "\n#{e.message}\n"
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,34 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+
16
+
17
+ Sinatra::Rabbit::Collection.class_eval do
18
+
19
+ def self.standard_index_operation(opts={})
20
+ collection_name = @collection_name
21
+ operation :index, :with_capability => opts[:capability] || collection_name do
22
+ control { filter_all collection_name }
23
+ end
24
+ end
25
+
26
+ def self.standard_show_operation(opts={})
27
+ collection_name = @collection_name
28
+ operation :show, :with_capability => opts[:capability] || collection_name do
29
+ control { show collection_name.to_s.singularize.intern }
30
+ end
31
+ end
32
+
33
+ end
34
+
@@ -24,11 +24,31 @@
24
24
  # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25
25
  # USE OR OTHER DEALINGS IN THE SOFTWARE.
26
26
 
27
- require 'uri'
28
-
29
27
  module Sinatra
30
28
  module UrlForHelper
31
29
 
30
+ require 'uri'
31
+
32
+ def method_missing(name, *args)
33
+ if name.to_s =~ /^([\w\_]+)_url$/
34
+ if args.size > 0
35
+ t = $1
36
+ if t.match(/^(stop|reboot|start|attach|detach)_/)
37
+ action = $1
38
+ api_url_for(t.pluralize.split('_').last + '/' + args.first + '/' + action, :full)
39
+ elsif t.match(/^(destroy|update)_/)
40
+ api_url_for(t.pluralize.split('_').last + '/' + args.first, :full)
41
+ else
42
+ api_url_for(t.pluralize, :full) + '/' + "#{args.first}"
43
+ end
44
+ else
45
+ api_url_for($1, :full)
46
+ end
47
+ else
48
+ super
49
+ end
50
+ end
51
+
32
52
  def api_url_for(url_fragment, mode=:path_only)
33
53
  matrix_params = ''
34
54
  if request.params['api']
@@ -36,7 +56,11 @@ module Sinatra
36
56
  matrix_params += ";driver=%s" % request.params['api']['driver'] if request.params['api']['driver']
37
57
  end
38
58
  url_fragment = "/#{url_fragment}" unless url_fragment =~ /^\// # There is no need to prefix URI with '/'
39
- url_for "#{settings.root_url}#{matrix_params}#{url_fragment}", mode
59
+ if mode == :path_only
60
+ url_for "#{settings.root_url}#{matrix_params}#{url_fragment}", mode
61
+ else
62
+ url_for "#{matrix_params}#{url_fragment}", :full
63
+ end
40
64
  end
41
65
 
42
66
  # Construct a link to +url_fragment+, which should be given relative to
@@ -55,7 +79,7 @@ module Sinatra
55
79
  def url_for url_fragment, mode=:path_only
56
80
  case mode
57
81
  when :path_only
58
- base = request.script_name
82
+ base = request.script_name.empty? ? Deltacloud[ENV['API_FRONTEND'] || :deltacloud].root_url : request.script_name
59
83
  when :full
60
84
  scheme = request.scheme
61
85
  port = request.port
@@ -72,11 +96,12 @@ module Sinatra
72
96
  else
73
97
  port = ":#{port}"
74
98
  end
75
- base = "#{scheme}://#{request_host}#{port}#{request.script_name}"
99
+ base = "#{scheme}://#{request_host}#{port}#{request.script_name.empty? ? Deltacloud[ENV['API_FRONTEND'] || :deltacloud].root_url : request.script_name}"
76
100
  else
77
101
  raise TypeError, "Unknown url_for mode #{mode}"
78
102
  end
79
- url_escape = URI.escape(url_fragment)
103
+ uri_parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
104
+ url_escape = uri_parser.escape(url_fragment)
80
105
  # Don't add the base fragment if url_for gets called more than once
81
106
  # per url or the url_fragment passed in is an absolute url
82
107
  if url_escape.match(/^#{base}/) or url_escape.match(/^http/)
@@ -87,7 +112,4 @@ module Sinatra
87
112
  end
88
113
  end
89
114
 
90
-
91
-
92
- helpers UrlForHelper
93
115
  end
@@ -1,4 +1,3 @@
1
- #
2
1
  # Licensed to the Apache Software Foundation (ASF) under one or more
3
2
  # contributor license agreements. See the NOTICE file distributed with
4
3
  # this work for additional information regarding copyright ownership. The
@@ -14,19 +13,22 @@
14
13
  # License for the specific language governing permissions and limitations
15
14
  # under the License.
16
15
 
17
- require 'deltacloud/models/base_model'
18
- require 'deltacloud/models/realm'
19
- require 'deltacloud/models/image'
20
- require 'deltacloud/models/instance'
21
- require 'deltacloud/models/key'
22
- require 'deltacloud/models/address'
23
- require 'deltacloud/models/instance_address'
24
- require 'deltacloud/models/instance_profile'
25
- require 'deltacloud/models/storage_snapshot'
26
- require 'deltacloud/models/storage_volume'
27
- require 'deltacloud/models/bucket'
28
- require 'deltacloud/models/blob'
29
- require 'deltacloud/models/load_balancer'
30
- require 'deltacloud/models/firewall'
31
- require 'deltacloud/models/firewall_rule'
32
- require 'deltacloud/models/provider'
16
+ require_relative 'models/base_model'
17
+ require_relative 'models/address'
18
+ require_relative 'models/blob'
19
+ require_relative 'models/bucket'
20
+ require_relative 'models/firewall'
21
+ require_relative 'models/firewall_rule'
22
+ require_relative 'models/hardware_profile'
23
+ require_relative 'models/image'
24
+ require_relative 'models/instance'
25
+ require_relative 'models/instance_address'
26
+ require_relative 'models/instance_profile'
27
+ require_relative 'models/key'
28
+ require_relative 'models/load_balancer'
29
+ require_relative 'models/metric'
30
+ require_relative 'models/provider'
31
+ require_relative 'models/realm'
32
+ require_relative 'models/state_machine'
33
+ require_relative 'models/storage_snapshot'
34
+ require_relative 'models/storage_volume'
@@ -22,6 +22,10 @@ class Bucket < BaseModel
22
22
 
23
23
  alias :to_hash_original :to_hash
24
24
 
25
+ def blob_list
26
+ @blob_list || []
27
+ end
28
+
25
29
  def to_hash
26
30
  h = self.to_hash_original
27
31
  unless blob_list.nil?
@@ -22,7 +22,7 @@ module Deltacloud
22
22
  :storage => "GB",
23
23
  :architecture => "label",
24
24
  :cpu => "count"
25
- }
25
+ } unless defined?(UNITS)
26
26
 
27
27
  def self.unit(name)
28
28
  UNITS[name]
@@ -90,7 +90,9 @@ module Deltacloud
90
90
  end
91
91
 
92
92
  def to_param
93
- Validation::Param.new([param, :string, :optional, []])
93
+ if defined? Sinatra::Rabbit
94
+ Sinatra::Rabbit::Param.new([param, :string, :optional, []])
95
+ end
94
96
  end
95
97
 
96
98
  def include?(v)
@@ -22,6 +22,7 @@ class Image < BaseModel
22
22
  attr_accessor :description
23
23
  attr_accessor :architecture
24
24
  attr_accessor :state
25
+ attr_accessor :hardware_profiles
25
26
 
26
27
  alias :to_hash_original :to_hash
27
28
 
@@ -16,8 +16,6 @@
16
16
 
17
17
  class Instance < BaseModel
18
18
 
19
- include ApplicationHelper
20
-
21
19
  attr_accessor :owner_id
22
20
  attr_accessor :image_id
23
21
  attr_accessor :name
@@ -36,6 +34,10 @@ class Instance < BaseModel
36
34
  attr_accessor :firewalls
37
35
  attr_accessor :storage_volumes
38
36
 
37
+ def storage_volumes
38
+ @storage_volumes || []
39
+ end
40
+
39
41
  def can_create_image?
40
42
  self.create_image
41
43
  end
@@ -45,6 +45,10 @@ class InstanceAddress
45
45
  address_type == :ipv4
46
46
  end
47
47
 
48
+ def is_ipv6?
49
+ address_type == :ipv6
50
+ end
51
+
48
52
  def is_hostname?
49
53
  address_type == :hostname
50
54
  end
@@ -23,6 +23,10 @@ class Key < BaseModel
23
23
  attr_accessor :pem_rsa_key
24
24
  attr_accessor :state
25
25
 
26
+ def name
27
+ @name || @id
28
+ end
29
+
26
30
  def is_password?
27
31
  true if @credential_type.eql?(:password)
28
32
  end
@@ -0,0 +1,40 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+
16
+ class Metric < BaseModel
17
+
18
+ attr_accessor :entity
19
+ attr_accessor :properties
20
+
21
+ def unknown?
22
+ true if self.entity == :unknown
23
+ end
24
+
25
+ def add_property(name, values=nil)
26
+ self.properties ||= []
27
+ return self if self.properties.any? { |p| p.name == name }
28
+ self.properties << Property.new(name, values)
29
+ self
30
+ end
31
+
32
+ class Property
33
+ attr_accessor :name, :values
34
+
35
+ def initialize(name, values=nil)
36
+ @name, @values = name, values
37
+ end
38
+ end
39
+
40
+ end
@@ -18,7 +18,10 @@ module Deltacloud
18
18
  class StateMachine
19
19
 
20
20
  attr_reader :states
21
- def initialize(&block)
21
+
22
+ def initialize(opts={}, &block)
23
+ @all_states = opts[:all_states]
24
+ @all_actions = opts[:all_actions]
22
25
  @states = []
23
26
  instance_eval &block if block
24
27
  end
@@ -32,6 +35,9 @@ module Deltacloud
32
35
  end
33
36
 
34
37
  def state(name)
38
+ unless valid_state_name?(name)
39
+ raise "State '#{name}' not in list of allowed states"
40
+ end
35
41
  state = @states.find{|e| e.name == name.to_sym}
36
42
  if ( state.nil? )
37
43
  state = State.new( self, name.to_sym )
@@ -40,6 +46,14 @@ module Deltacloud
40
46
  state
41
47
  end
42
48
 
49
+ def valid_state_name?(name)
50
+ @all_states.nil? || @all_states.include?(name.to_sym)
51
+ end
52
+
53
+ def valid_action_name?(name)
54
+ @all_actions.nil? || @all_actions.include?(name.to_sym)
55
+ end
56
+
43
57
  def method_missing(sym,*args)
44
58
  return state( sym ) if ( args.empty? )
45
59
  super( sym, *args )
@@ -90,6 +104,9 @@ module Deltacloud
90
104
  end
91
105
 
92
106
  def on(action)
107
+ unless @machine.valid_action_name?(action)
108
+ raise "Action '#{action}' not in list of allowed actions"
109
+ end
93
110
  @action = action
94
111
  end
95
112
 
@@ -13,1246 +13,65 @@
13
13
  # License for the specific language governing permissions and limitations
14
14
  # under the License.
15
15
 
16
- require 'sinatra'
17
- require 'deltacloud'
16
+ require 'rubygems'
17
+ require 'crack'
18
18
  require 'json'
19
- require 'sinatra/rack_accept'
20
- require 'sinatra/static_assets'
21
- require 'sinatra/rabbit'
22
- require 'sinatra/lazy_auth'
23
- require 'erb'
19
+ require 'yaml'
24
20
  require 'haml'
25
- require 'open3'
26
- require 'sinatra/sinatra_verbose'
27
- require 'sinatra/rack_driver_select'
28
- require 'sinatra/rack_runtime'
29
- require 'sinatra/rack_etag'
30
- require 'sinatra/rack_date'
31
- require 'sinatra/rack_matrix_params'
32
- require 'sinatra/rack_syslog'
33
-
34
- set :version, '0.5.0'
35
-
36
- include Deltacloud::Drivers
37
- set :drivers, Proc.new { driver_config }
38
-
39
- Sinatra::Application.register Rack::RespondTo
40
-
41
- use Rack::ETag
42
- use Rack::Runtime
43
- use Rack::MatrixParams
44
- use Rack::DriverSelect
45
- use Rack::MediaType
46
- use Rack::Date
47
-
48
- configure do
49
- set :root_url, "/api"
50
- set :views, File::join($top_srcdir, 'views')
51
- # NOTE: Change :public to :public_folder once we update sinatra to 1.3
52
- # set :public_folder, File::join($top_srcdir, 'public')
53
- if settings.respond_to? :public_folder
54
- set :public_folder, File::join($top_srcdir, 'public')
55
- else
56
- set :public, File::join($top_srcdir, 'public')
57
- end
58
- # Try to load the driver on startup to fail early if there are issues
59
- driver
60
- end
61
-
62
- configure :production do
63
- use Rack::SyslogLogger
64
- disable :logging
65
- enable :show_errors
66
- set :dump_errors, false
67
- $stdout = SyslogFile.new
68
- $stderr = $stdout
69
- end
70
-
71
- configure :development do
72
- # So we can just use puts for logging
73
- set :raise_errors => false
74
- set :show_exceptions, false
75
- $stdout.sync = true
76
- $stderr.sync = true
77
- end
78
-
79
- # You could use $API_HOST environment variable to change your hostname to
80
- # whatever you want (eg. if you running API behind NAT)
81
- HOSTNAME=ENV['API_HOST'] ? ENV['API_HOST'] : nil
82
-
83
- error do
84
- report_error
85
- end
86
-
87
- before do
88
- # Respond with 400, If we don't get a http Host header,
89
- halt 400, "Unable to find HTTP Host header" if @env['HTTP_HOST'] == nil
90
- end
91
-
92
- after do
93
- headers 'Server' => 'Apache-Deltacloud/' + settings.version
94
- end
95
-
96
- # Redirect to /api
97
- get '/' do redirect settings.root_url, 301; end
98
-
99
-
100
- # Generate a root route for API docs
101
- get "#{settings.root_url}/docs\/?" do
102
- respond_to do |format|
103
- format.html { haml :'docs/index' }
104
- format.xml { haml :'docs/index' }
105
- end
106
- end
107
-
108
- get "#{settings.root_url}\/?" do
109
- if params[:force_auth]
110
- return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
111
- end
112
- @collections = [:drivers] + driver.supported_collections
113
- @driver_name = driver.name unless driver.name.to_sym == DRIVER
114
- @providers = driver.configured_providers
115
- respond_to do |format|
116
- format.xml { haml :"api/show" }
117
- format.json do
118
- { :api => {
119
- :version => settings.version,
120
- :driver => driver_symbol,
121
- :links => entry_points.collect do |l|
122
- { :rel => l[0], :href => l[1] }.merge(json_features_for_entrypoint(l))
123
- end
124
- }
125
- }.to_json
126
- end
127
- format.html { haml :"api/show" }
128
- end
129
- end
130
-
131
- post "#{settings.root_url}\/?" do
132
- p = {}
133
- ["provider", "driver"].each { |k| p[k] = params[k] if params[k] }
134
- p.delete("provider") if p["provider"] == "default"
135
- q = p.map { |k,v| "#{k}=#{v}" }.join(";")
136
- q = ";" + q unless q.empty?
137
- redirect "#{settings.root_url}#{q}", 301
138
- end
139
-
140
- # Rabbit DSL
141
-
142
- collection :drivers do
143
- global!
144
-
145
- description <<EOS
146
- List all the drivers supported by this server.
147
- EOS
148
-
149
- operation :index do
150
- description "List all drivers"
151
- control do
152
- @drivers = settings.drivers
153
- respond_to do |format|
154
- format.xml { haml :"drivers/index" }
155
- format.json { @drivers.to_json }
156
- format.html { haml :"drivers/index" }
157
- end
158
- end
159
- end
160
-
161
- operation :show do
162
- description "Show details for a driver"
163
- param :id, :string
164
- control do
165
- @name = params[:id].to_sym
166
- if driver_symbol == @name
167
- @providers = driver.providers(credentials) if driver.respond_to? :providers
168
- end
169
- @driver = settings.drivers[@name]
170
- return [404, "Driver #{@name} not found"] unless @driver
171
- respond_to do |format|
172
- format.xml { haml :"drivers/show" }
173
- format.json { @driver.to_json }
174
- format.html { haml :"drivers/show" }
175
- end
176
- end
177
- end
178
- end
179
-
180
- collection :realms do
181
- description <<END
182
- Within a cloud provider a realm represents a boundary containing resources.
183
- The exact definition of a realm is left to the cloud provider.
184
- In some cases, a realm may represent different datacenters, different continents,
185
- or different pools of resources within a single datacenter.
186
- A cloud provider may insist that resources must all exist within a single realm in
187
- order to cooperate. For instance, storage volumes may only be allowed to be mounted to
188
- instances within the same realm.
189
- END
190
-
191
- operation :index do
192
- description <<END
193
- Operation will list all available realms. Realms can be filtered using
194
- the "architecture" parameter.
195
- END
196
- with_capability :realms
197
- param :id, :string
198
- param :architecture, :string, :optional, [ 'i386', 'x86_64' ]
199
- control { filter_all(:realms) }
200
- end
201
-
202
- #FIXME: It always shows whole list
203
- operation :show do
204
- description 'Show an realm identified by "id" parameter.'
205
- with_capability :realm
206
- param :id, :string, :required
207
- control { show(:realm) }
208
- end
209
-
210
- end
211
-
212
- collection :images do
213
- description <<END
214
- An image is a platonic form of a machine. Images are not directly executable,
215
- but are a template for creating actual instances of machines.
216
- END
217
-
218
- operation :new do
219
- description "Form to create a new image resource"
220
- param :instance_id, :string, "An instance from which the new image will be created from"
221
- control do
222
- @instance = Instance.new( :id => params[:instance_id] )
223
- respond_to do |format|
224
- format.html { haml :"images/new" }
225
- end
226
- end
227
- end
228
-
229
- operation :index do
230
- description <<END
231
- The images collection will return a set of all images
232
- available to the current use. Images can be filtered using the
233
- "owner_id" and "architecture" parameters.
234
- END
235
- with_capability :images
236
- param :id, :string
237
- param :architecture, :string, :optional
238
- control { filter_all(:images) }
239
- end
240
-
241
- operation :show do
242
- description 'Show an image identified by "id" parameter.'
243
- with_capability :image
244
- param :id, :string, :required
245
- control { show(:image) }
246
- end
247
-
248
- operation :create do
249
- description 'Create image from instance'
250
- with_capability :create_image
251
- param :instance_id, :string, :required
252
- param :name, :string, :optional
253
- param :description, :string, :optional
254
- control do
255
- @image = driver.create_image(credentials, {
256
- :id => params[:instance_id],
257
- :name => params[:name],
258
- :description => params[:description]
259
- })
260
- status 201 # Created
261
- response['Location'] = image_url(@image.id)
262
- respond_to do |format|
263
- format.xml { haml :"images/show" }
264
- format.json { convert_to_json(:image, @image) }
265
- format.html { haml :"images/show" }
266
- end
267
- end
268
- end
269
-
270
- operation :destroy do
271
- description "Remove specified image from collection"
272
- with_capability :destroy_image
273
- param :id, :string, :required
274
- control do
275
- driver.destroy_image(credentials, params[:id])
276
- status 204
277
- respond_to do |format|
278
- format.xml
279
- format.json
280
- format.html { redirect(images_url) }
281
- end
282
- end
283
- end
284
-
285
- end
286
-
287
- collection :instance_states do
288
- description "The possible states of an instance, and how to traverse between them "
289
-
290
- operation :index do
291
- control do
292
- @machine = driver.instance_state_machine
293
- respond_to do |format|
294
- format.xml { haml :'instance_states/show', :layout => false }
295
- format.json do
296
- out = []
297
- @machine.states.each do |state|
298
- transitions = state.transitions.collect do |t|
299
- t.automatically? ? {:to => t.destination, :auto => 'true'} : {:to => t.destination, :action => t.action}
300
- end
301
- out << { :name => state, :transitions => transitions }
302
- end
303
- out.to_json
304
- end
305
- format.html { haml :'instance_states/show'}
306
- format.gv { erb :"instance_states/show" }
307
- format.png do
308
- # Trick respond_to into looking up the right template for the
309
- # graphviz file
310
- gv = erb(:"instance_states/show")
311
- png = ''
312
- cmd = 'dot -Kdot -Gpad="0.2,0.2" -Gsize="5.0,8.0" -Gdpi="180" -Tpng'
313
- Open3.popen3( cmd ) do |stdin, stdout, stderr|
314
- stdin.write( gv )
315
- stdin.close()
316
- png = stdout.read
317
- end
318
- content_type 'image/png'
319
- png
320
- end
321
- end
322
- end
323
- end
324
- end
325
-
326
- get "#{settings.root_url}/instances/:id/run" do
327
- @instance = driver.instance(credentials, :id => params[:id])
328
- respond_to do |format|
329
- format.html { haml :"instances/run_command" }
330
- end
331
- end
332
-
333
- collection :load_balancers do
334
- description "Load balancers"
335
-
336
- operation :new do
337
- description "Form to create a new load balancer"
338
- control do
339
- @realms = driver.realms(credentials)
340
- @instances = driver.instances(credentials) if driver_has_feature?(:register_instance, :load_balancers)
341
- respond_to do |format|
342
- format.html { haml :"load_balancers/new" }
343
- end
344
- end
345
- end
346
-
347
- operation :index do
348
- description "List of all active load balancers"
349
- control do
350
- filter_all :load_balancers
351
- end
352
- end
353
-
354
- operation :show do
355
- description "Show details about given load balancer"
356
- param :id, :string, :required
357
- control { show :load_balancer }
358
- end
359
-
360
- operation :create do
361
- description "Create a new load balancer"
362
- param :name, :string, :required
363
- param :realm_id, :string, :required
364
- param :listener_protocol, :string, :required, ['HTTP', 'TCP']
365
- param :listener_balancer_port, :string, :required
366
- param :listener_instance_port, :string, :required
367
- control do
368
- @load_balancer = driver.create_load_balancer(credentials, params)
369
- status 201 # Created
370
- response['Location'] = load_balancer_url(@instance.id)
371
- respond_to do |format|
372
- format.xml { haml :"load_balancers/show" }
373
- format.json { convert_to_json(:load_balancer, @load_balancer) }
374
- format.html { haml :"load_balancers/show" }
375
- end
376
- end
377
- end
378
-
379
- operation :register, :method => :post, :member => true do
380
- description "Add instance to loadbalancer"
381
- param :id, :string, :required
382
- param :instance_id, :string, :required
383
- control do
384
- driver.lb_register_instance(credentials, params)
385
- status 204
386
- respond_to do |format|
387
- format.xml
388
- format.json
389
- format.html { redirect(load_balancer_url(params[:id])) }
390
- end
391
- end
392
- end
393
-
394
- operation :unregister, :method => :post, :member => true do
395
- description "Remove instance from loadbalancer"
396
- param :id, :string, :required
397
- param :instance_id, :string, :required
398
- control do
399
- driver.lb_unregister_instance(credentials, params)
400
- status 204
401
- respond_to do |format|
402
- format.xml
403
- format.json
404
- format.html { redirect(load_balancer_url(params[:id])) }
405
- end
406
- end
407
- end
408
-
409
- operation :destroy do
410
- description "Destroy given load balancer"
411
- param :id, :string, :required
412
- control do
413
- driver.destroy_load_balancer(credentials, params[:id])
414
- status 204
415
- respond_to do |format|
416
- format.xml
417
- format.json
418
- format.html { redirect(load_balancers_url) }
419
- end
420
- end
421
- end
422
-
423
- end
424
-
425
-
426
- collection :instances do
427
- description <<END
428
- An instance is a concrete machine realized from an image.
429
- The images collection may be obtained by following the link from the primary entry-point.
430
- END
431
-
432
- operation :new do
433
- description "Form for creating a new instance resource"
434
- param :image_id, :string, "Image from which will be the new instance created from"
435
- param :realm_id, :string, :optional
436
- if driver_has_feature? :authentication_key
437
- param :authentication_key, :string, :optional
438
- end
439
- if driver_has_feature? :firewalls
440
- param :firewalls, :string, :optional
441
- end
442
- control do
443
- @instance = Instance.new( { :id=>params[:id], :image_id=>params[:image_id] } )
444
- @image = Image.new( :id => params[:image_id] )
445
- @hardware_profiles = driver.hardware_profiles(credentials, :architecture => @image.architecture )
446
- @realms = [Realm.new(:id => params[:realm_id])] if params[:realm_id]
447
- @realms ||= driver.realms(credentials)
448
- @keys = driver.keys(credentials) if driver_has_feature?(:authentication_key)
449
- @firewalls = driver.firewalls(credentials) if driver_has_feature?(:firewalls)
450
- respond_to do |format|
451
- format.html do
452
- haml :'instances/new'
453
- end
454
- end
455
- end
456
- end
457
-
458
- operation :index do
459
- description "List all instances."
460
- with_capability :instances
461
- param :id, :string, :optional
462
- param :state, :string, :optional
463
- control { filter_all(:instances) }
464
- end
465
-
466
- operation :show do
467
- description 'Show an instance identified by "id" parameter.'
468
- with_capability :instance
469
- param :id, :string, :required
470
- control { show(:instance) }
471
- end
472
-
473
- operation :create do
474
- description "Create a new instance."
475
- with_capability :create_instance
476
- param :image_id, :string, :required
477
- param :realm_id, :string, :optional
478
- param :hwp_id, :string, :optional
479
- control do
480
- @instance = driver.create_instance(credentials, params[:image_id], params)
481
- if @instance.kind_of? Array
482
- @elements = @instance
483
- action_handler = "index"
484
- else
485
- response['Location'] = instance_url(@instance.id)
486
- action_handler = "show"
487
- end
488
- status 201 # Created
489
- respond_to do |format|
490
- format.xml { haml :"instances/#{action_handler}" }
491
- format.json do
492
- if @elements
493
- convert_to_json(:instances, @elements)
494
- else
495
- convert_to_json(:instance, @elements)
496
- end
497
- end
498
- format.html do
499
- if @elements
500
- haml :"instances/index"
501
- elsif @instance and @instance.id
502
- response['Location'] = instance_url(@instance.id)
503
- redirect instance_url(@instance.id)
504
- else
505
- redirect instances_url
506
- end
507
- end
508
- end
509
- end
510
- end
511
-
512
- operation :reboot, :method => :post, :member => true do
513
- description "Reboot a running instance."
514
- with_capability :reboot_instance
515
- param :id, :string, :required
516
- control { instance_action(:reboot) }
517
- end
518
-
519
- operation :start, :method => :post, :member => true do
520
- description "Start an instance."
521
- with_capability :start_instance
522
- param :id, :string, :required
523
- control { instance_action(:start) }
524
- end
525
-
526
- operation :stop, :method => :post, :member => true do
527
- description "Stop a running instance."
528
- with_capability :stop_instance
529
- param :id, :string, :required
530
- control { instance_action(:stop) }
531
- end
532
-
533
- operation :destroy do
534
- description "Destroy an instance."
535
- with_capability :destroy_instance
536
- param :id, :string, :required
537
- control { instance_action(:destroy) }
538
- end
539
-
540
- operation :run, :method => :post, :member => true do
541
- description <<END
542
- Run command on instance. Either password or private key must be send
543
- in order to execute command. Authetication method should be advertised
544
- in instance.
545
- END
546
- with_capability :run_on_instance
547
- param :id, :string, :required
548
- param :cmd, :string, :required, [], "Shell command to run on instance"
549
- param :private_key, :string, :optional, [], "Private key in PEM format for authentication"
550
- param :password, :string, :optional, [], "Password used for authentication"
551
- control do
552
- @output = driver.run_on_instance(credentials, params)
553
- respond_to do |format|
554
- format.xml { haml :"instances/run" }
555
- format.html { haml :"instances/run" }
556
- end
557
- end
558
- end
559
- end
560
-
561
- collection :hardware_profiles do
562
- description <<END
563
- A hardware profile represents a configuration of resources upon which a
564
- machine may be deployed. It defines aspects such as local disk storage,
565
- available RAM, and architecture. Each provider is free to define as many
566
- (or as few) hardware profiles as desired.
567
- END
568
-
569
- operation :index do
570
- description "List of available hardware profiles."
571
- with_capability :hardware_profiles
572
- param :id, :string
573
- param :architecture, :string, :optional, [ 'i386', 'x86_64' ]
574
- control do
575
- @profiles = driver.hardware_profiles(credentials, params)
576
- respond_to do |format|
577
- format.xml { haml :'hardware_profiles/index' }
578
- format.html { haml :'hardware_profiles/index' }
579
- format.json { convert_to_json(:hardware_profile, @profiles) }
580
- end
581
- end
582
- end
583
-
584
- operation :show do
585
- description "Show specific hardware profile."
586
- with_capability :hardware_profile
587
- param :id, :string, :required
588
- control do
589
- @profile = driver.hardware_profile(credentials, params[:id])
590
- if @profile
591
- respond_to do |format|
592
- format.xml { haml :'hardware_profiles/show', :layout => false }
593
- format.html { haml :'hardware_profiles/show' }
594
- format.json { convert_to_json(:hardware_profile, @profile) }
595
- end
596
- else
597
- report_error(404)
598
- end
599
- end
600
- end
601
-
602
- end
603
-
604
- collection :storage_snapshots do
605
- description "Storage snapshots description here"
606
-
607
- operation :new do
608
- description "A form to create a new storage snapshot"
609
- control do
610
- respond_to do |format|
611
- format.html { haml :"storage_snapshots/new" }
612
- end
613
- end
614
- end
615
-
616
- operation :index do
617
- description "List of storage snapshots."
618
- with_capability :storage_snapshots
619
- param :id, :string
620
- control { filter_all(:storage_snapshots) }
621
- end
622
-
623
- operation :show do
624
- description "Show storage snapshot."
625
- with_capability :storage_snapshot
626
- param :id, :string, :required
627
- control { show(:storage_snapshot) }
628
- end
629
-
630
- operation :create do
631
- description "Create a new snapshot from volume"
632
- with_capability :create_storage_snapshot
633
- param :volume_id, :string, :required
634
- control do
635
- @storage_snapshot = driver.create_storage_snapshot(credentials, params)
636
- status 201 # Created
637
- response['Location'] = storage_snapshot_url(@storage_snapshot.id)
638
- show(:storage_snapshot)
639
- end
640
- end
641
-
642
- operation :destroy do
643
- description "Delete storage snapshot"
644
- with_capability :destroy_storage_snapshot
645
- param :id, :string, :required
646
- control do
647
- driver.destroy_storage_snapshot(credentials, params)
648
- status 204
649
- respond_to do |format|
650
- format.xml
651
- format.json
652
- format.html { redirect(storage_snapshots_url) }
653
- end
654
- end
655
- end
656
- end
657
-
658
- collection :storage_volumes do
659
- description "Storage volumes description here"
660
-
661
- operation :new do
662
- description "A form to create a new storage volume"
663
- control do
664
- respond_to do |format|
665
- format.html { haml :"storage_volumes/new" }
666
- end
667
- end
668
- end
21
+ require 'sinatra/base'
22
+ require 'sinatra/rabbit'
669
23
 
670
- operation :index do
671
- description "List of storage volumes."
672
- with_capability :storage_volumes
673
- param :id, :string
674
- control { filter_all(:storage_volumes) }
675
- end
24
+ require_relative '../sinatra'
25
+ require_relative './models'
26
+ require_relative './drivers'
27
+ require_relative './helpers'
28
+ require_relative './collections'
676
29
 
677
- operation :show do
678
- description "Show storage volume."
679
- with_capability :storage_volume
680
- param :id, :string, :required
681
- control { show(:storage_volume) }
682
- end
30
+ module Deltacloud
31
+ class API < Collections::Base
683
32
 
684
- operation :create do
685
- description "Create a new storage volume"
686
- with_capability :create_storage_volume
687
- param :snapshot_id, :string, :optional
688
- param :capacity, :string, :optional
689
- param :realm_id, :string, :optional
690
- control do
691
- @storage_volume = driver.create_storage_volume(credentials, params)
692
- status 201
693
- response['Location'] = storage_volume_url(@storage_volume.id)
694
- respond_to do |format|
695
- format.xml { haml :"storage_volumes/show" }
696
- format.html { haml :"storage_volumes/show" }
697
- format.json { convert_to_json(:storage_volume, @storage_volume) }
698
- end
699
- end
700
- end
701
-
702
- operation :attach_instance, :method=>:get, :member=>true do
703
- description "A form to attach a storage volume to an instance"
704
- control do
705
- @instances = driver.instances(credentials)
706
- respond_to do |format|
707
- format.html{ haml :"storage_volumes/attach"}
708
- end
709
- end
710
- end
33
+ # Enable logging
34
+ use Rack::CommonLogger
35
+ use Rack::Date
36
+ use Rack::ETag
37
+ use Rack::MatrixParams
38
+ use Rack::DriverSelect
39
+ use Rack::Accept
40
+ use Rack::MediaType
711
41
 
712
- operation :attach, :method => :post, :member => true do
713
- description "Attach storage volume to instance"
714
- with_capability :attach_storage_volume
715
- param :id, :string, :required
716
- param :instance_id,:string, :required
717
- param :device, :string, :required
718
- control do
719
- @storage_volume = driver.attach_storage_volume(credentials, params)
720
- status 202
721
- respond_to do |format|
722
- format.html { redirect(storage_volume_url(params[:id]))}
723
- format.xml { haml :"storage_volumes/show" }
724
- format.json { convert_to_json(:storage_volume, @storage_volume) }
725
- end
726
- end
727
- end
42
+ include Deltacloud::Helpers
43
+ include Deltacloud::Collections
728
44
 
729
- operation :detach, :method => :post, :member => true do
730
- description "Detach storage volume to instance"
731
- with_capability :detach_storage_volume
732
- param :id, :string, :required
733
- control do
734
- volume = driver.storage_volume(credentials, :id => params[:id])
735
- @storage_volume = driver.detach_storage_volume(credentials, :id => volume.id, :instance_id => volume.instance_id, :device => volume.device)
736
- status 202
737
- respond_to do |format|
738
- format.html { redirect(storage_volume_url(params[:id]))}
739
- format.xml { haml :"storage_volumes/show" }
740
- format.json { convert_to_json(:storage_volume, @storage_volume) }
741
- end
742
- end
743
- end
45
+ set :config, Deltacloud[:deltacloud]
744
46
 
745
- operation :destroy do
746
- description "Destroy storage volume"
747
- with_capability :destroy_storage_volume
748
- param :id, :string, :optional
749
- control do
750
- driver.destroy_storage_volume(credentials, params)
751
- status 204
752
- respond_to do |format|
753
- format.xml
754
- format.json
755
- format.html { redirect(storage_volumes_url) }
47
+ get Deltacloud.config[:deltacloud].root_url + '/?' do
48
+ if params[:force_auth]
49
+ return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
756
50
  end
757
- end
758
- end
759
-
760
- end
761
-
762
- collection :keys do
763
- description "Instance authentication credentials."
764
-
765
- operation :new do
766
- description "A form to create a new key resource"
767
- control do
768
51
  respond_to do |format|
769
- format.html { haml :"keys/new" }
770
- end
771
- end
772
- end
773
-
774
- operation :index do
775
- description "List all available credentials which could be used for instance authentication."
776
- with_capability :keys
777
- control do
778
- filter_all :keys
779
- end
780
- end
781
-
782
- operation :show do
783
- description "Show details about given instance credential."
784
- with_capability :key
785
- param :id, :string, :required
786
- control { show :key }
787
- end
788
-
789
- operation :create do
790
- description "Create a new instance credential if backend supports this."
791
- with_capability :create_key
792
- param :name, :string, :required
793
- control do
794
- @key = driver.create_key(credentials, { :key_name => params[:name] })
795
- status 201
796
- response['Location'] = key_url(@key.id)
797
- respond_to do |format|
798
- format.xml { haml :"keys/show", :ugly => true }
799
- format.html { haml :"keys/show" }
800
- format.json { convert_to_json(:key, @key)}
801
- end
802
- end
803
- end
804
-
805
- operation :destroy do
806
- description "Destroy given instance credential if backend supports this."
807
- with_capability :destroy_key
808
- param :id, :string, :required
809
- control do
810
- driver.destroy_key(credentials, { :id => params[:id]})
811
- status 204
812
- respond_to do |format|
813
- format.xml
814
- format.json
815
- format.html { redirect(keys_url) }
816
- end
817
- end
818
- end
819
-
820
- end
821
-
822
- #get html form for creating a new blob
823
-
824
- # The URL for getting the new blob form for the HTML UI looks like the URL
825
- # for getting the details of an existing blob. To make collisions less
826
- # likely, we use a name for the form that will rarely be the name of an
827
- # existing blob
828
- NEW_BLOB_FORM_ID = "new_blob_form_d15cfd90"
829
-
830
- get "#{settings.root_url}/buckets/:bucket/#{NEW_BLOB_FORM_ID}" do
831
- @bucket_id = params[:bucket]
832
- respond_to do |format|
833
- format.html {haml :"blobs/new"}
834
- end
835
- end
836
-
837
- collection :buckets do
838
- description "Cloud Storage buckets - aka buckets|directories|folders"
839
-
840
- collection :blobs do
841
- description "Blobs associated with given bucket"
842
-
843
- operation :show do
844
- description "Display blob"
845
- control do
846
- @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
847
- if @blob
848
- respond_to do |format|
849
- format.xml { haml :"blobs/show" }
850
- format.html { haml :"blobs/show" }
851
- format.json { convert_to_json(:blob, @blob) }
852
- end
853
- else
854
- report_error(404)
855
- end
856
- end
857
-
858
- end
859
-
860
- operation :create do
861
- description "Create new blob"
862
- control do
863
- bucket_id = params[:bucket]
864
- blob_id = params['blob_id']
865
- blob_data = params['blob_data']
866
- user_meta = {}
867
- #metadata from params (i.e., passed by http form post, e.g. browser)
868
- max = params[:meta_params]
869
- if(max)
870
- (1..max.to_i).each do |i|
871
- key = params[:"meta_name#{i}"]
872
- key = "HTTP_X_Deltacloud_Blobmeta_#{key}"
873
- value = params[:"meta_value#{i}"]
874
- user_meta[key] = value
875
- end
876
- end
877
- @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
878
- respond_to do |format|
879
- format.xml { haml :"blobs/show" }
880
- format.html { haml :"blobs/show"}
881
- end
882
- end
883
- end
884
-
885
- operation :destroy do
886
- description "Destroy given blob"
887
- control do
888
- bucket_id = params[:bucket]
889
- blob_id = params[:blob]
890
- driver.delete_blob(credentials, bucket_id, blob_id)
891
- status 204
892
- respond_to do |format|
893
- format.xml
894
- format.json
895
- format.html { redirect(bucket_url(bucket_id)) }
896
- end
897
- end
898
- end
899
-
900
- operation :stream, :member => true, :standard => true, :method => :put do
901
- description "Stream new blob data into the blob"
902
- control do
903
- if(env["BLOB_SUCCESS"]) #ie got a 200ok after putting blob
904
- content_type = env["CONTENT_TYPE"]
905
- content_type ||= ""
906
- @blob = driver.blob(credentials, {:id => params[:blob],
907
- 'bucket' => params[:bucket]})
908
- respond_to do |format|
909
- format.xml { haml :"blobs/show" }
910
- format.html { haml :"blobs/show" }
911
- format.json { convert_to_json(:blob, @blob) }
912
- end
913
- elsif(env["BLOB_FAIL"])
914
- report_error(500) #OK?
915
- else # small blobs - < 112kb dont hit the streaming monkey patch - use 'normal' create_blob
916
- # also, if running under webrick don't hit the streaming patch (Thin specific)
917
- bucket_id = params[:bucket]
918
- blob_id = params[:blob]
919
- temp_file = Tempfile.new("temp_blob_file")
920
- temp_file.write(env['rack.input'].read)
921
- temp_file.flush
922
- content_type = env['CONTENT_TYPE'] || ""
923
- blob_data = {:tempfile => temp_file, :type => content_type}
924
- user_meta = BlobHelper::extract_blob_metadata_hash(request.env)
925
- @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
926
- temp_file.delete
927
- respond_to do |format|
928
- format.xml { haml :"blobs/show" }
929
- format.html { haml :"blobs/show"}
930
- end
931
- end
932
- end
933
- end
934
-
935
- operation :metadata, :member => true, :standard => true, :method => :head do
936
- description "Get blob metadata"
937
- control do
938
- @blob_id = params[:blob]
939
- @blob_metadata = driver.blob_metadata(credentials, {:id => params[:blob], 'bucket' => params[:bucket]})
940
- if @blob_metadata
941
- @blob_metadata.each do |k,v|
942
- headers["X-Deltacloud-Blobmeta-#{k}"] = v
943
- end
944
- status 204
945
- respond_to do |format|
946
- format.xml
947
- format.json
948
- end
949
- else
950
- report_error(404)
951
- end
952
- end
953
- end
954
-
955
- operation :update, :member => true, :method => :post do
956
- description "Update blob metadata"
957
- control do
958
- meta_hash = BlobHelper::extract_blob_metadata_hash(request.env)
959
- success = driver.update_blob_metadata(credentials, {'bucket'=>params[:bucket], :id =>params[:blob], 'meta_hash' => meta_hash})
960
- if(success)
961
- meta_hash.each do |k,v|
962
- headers["X-Deltacloud-Blobmeta-#{k}"] = v
963
- end
964
- status 204
965
- respond_to do |format|
966
- format.xml
967
- format.json
968
- end
969
- else
970
- report_error(404) #FIXME is this the right error code?
971
- end
52
+ format.xml { haml :"api/show" }
53
+ format.json { xml_to_json :"api/show" }
54
+ format.html { haml :"api/show" }
972
55
  end
973
56
  end
974
57
 
975
- operation :content, :member => true, :method => :get do
976
- description "Download blob content"
977
- control do
978
- @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
979
- if @blob
980
- params['content_length'] = @blob.content_length
981
- params['content_type'] = @blob.content_type
982
- params['content_disposition'] = "attachment; filename=#{@blob.id}"
983
- BlobStream.call(env, credentials, params)
58
+ post Deltacloud.config[:deltacloud].root_url + '/?' do
59
+ param_driver, param_provider = params["driver"], params["provider"]
60
+ if param_driver
61
+ redirect "#{Deltacloud.config[:deltacloud].root_url}\;driver=#{param_driver}", 301
62
+ elsif param_provider && param_provider != "default"
63
+ #FIXME NEEDS A BETTER WAY OF GRABBING CURRENT DRIVER FROM MATRIX PARAMS...
64
+ current_matrix_driver = env["HTTP_REFERER"].match(/\;(driver)=(\w*).*$/i)
65
+ if current_matrix_driver
66
+ redirect "#{Deltacloud.config[:deltacloud].root_url}\;driver=#{$2}\;provider=#{param_provider}", 301
984
67
  else
985
- report_error(404)
68
+ redirect "#{Deltacloud.config[:deltacloud].root_url}\;provider=#{param_provider}", 301
986
69
  end
70
+ else
71
+ redirect "#{Deltacloud.config[:deltacloud].root_url}", 301
987
72
  end
988
73
  end
989
74
 
990
75
  end
991
-
992
- operation :new do
993
- description "A form to create a new bucket resource"
994
- control do
995
- respond_to do |format|
996
- format.html { haml :"buckets/new" }
997
- end
998
- end
999
- end
1000
-
1001
- operation :index do
1002
- description "List buckets associated with this account"
1003
- with_capability :buckets
1004
- param :id, :string
1005
- param :name, :string
1006
- param :size, :string
1007
- control { filter_all(:buckets) }
1008
- end
1009
-
1010
- operation :show do
1011
- description "Show bucket"
1012
- with_capability :bucket
1013
- param :id, :string
1014
- control { show(:bucket) }
1015
- end
1016
-
1017
- operation :create do
1018
- description "Create a new bucket (POST /api/buckets)"
1019
- with_capability :create_bucket
1020
- param :name, :string, :required
1021
- control do
1022
- @bucket = driver.create_bucket(credentials, params[:name], params)
1023
- status 201
1024
- response['Location'] = bucket_url(@bucket.id)
1025
- respond_to do |format|
1026
- format.xml { haml :"buckets/show" }
1027
- format.json { convert_to_json(:bucket, @bucket) }
1028
- format.html do
1029
- redirect bucket_url(@bucket.id) if @bucket and @bucket.id
1030
- redirect buckets_url
1031
- end
1032
- end
1033
- end
1034
- end
1035
-
1036
- operation :destroy do
1037
- description "Delete a bucket by name - bucket must be empty"
1038
- with_capability :delete_bucket
1039
- param :id, :string, :required
1040
- control do
1041
- driver.delete_bucket(credentials, params[:id], params)
1042
- status 204
1043
- respond_to do |format|
1044
- format.xml
1045
- format.json
1046
- format.html { redirect(buckets_url) }
1047
- end
1048
- end
1049
- end
1050
-
1051
- end
1052
-
1053
- get "#{settings.root_url}/addresses/:id/associate" do
1054
- @instances = driver.instances(credentials)
1055
- @address = Address::new(:id => params[:id])
1056
- respond_to do |format|
1057
- format.html { haml :"addresses/associate" }
1058
- end
1059
- end
1060
-
1061
- collection :addresses do
1062
- description "Manage IP addresses"
1063
-
1064
- operation :index do
1065
- description "List IP addresses assigned to your account."
1066
- with_capability :addresses
1067
- control do
1068
- filter_all :addresses
1069
- end
1070
- end
1071
-
1072
- operation :show do
1073
- description "Show details about IP addresses specified by given ID"
1074
- with_capability :address
1075
- param :id, :string, :required
1076
- control { show :address }
1077
- end
1078
-
1079
- operation :create do
1080
- description "Acquire a new IP address for use with your account."
1081
- with_capability :create_address
1082
- control do
1083
- @address = driver.create_address(credentials, {})
1084
- status 201 # Created
1085
- response['Location'] = address_url(@address.id)
1086
- respond_to do |format|
1087
- format.xml { haml :"addresses/show", :ugly => true }
1088
- format.html { haml :"addresses/_address", :layout => false }
1089
- format.json { convert_to_json(:address, @address) }
1090
- end
1091
- end
1092
- end
1093
-
1094
- operation :destroy do
1095
- description "Release an IP address associated with your account"
1096
- with_capability :destroy_address
1097
- param :id, :string, :required
1098
- control do
1099
- driver.destroy_address(credentials, { :id => params[:id]})
1100
- status 204
1101
- respond_to do |format|
1102
- format.xml
1103
- format.json
1104
- format.html { redirect(addresses_url) }
1105
- end
1106
- end
1107
- end
1108
-
1109
- operation :associate, :method => :post, :member => true do
1110
- description "Associate an IP address to an instance"
1111
- with_capability :associate_address
1112
- param :id, :string, :required
1113
- param :instance_id, :string, :required
1114
- control do
1115
- driver.associate_address(credentials, { :id => params[:id], :instance_id => params[:instance_id]})
1116
- status 202 # Accepted
1117
- respond_to do |format|
1118
- format.xml
1119
- format.json
1120
- format.html { redirect(address_url(params[:id])) }
1121
- end
1122
- end
1123
- end
1124
-
1125
- operation :disassociate, :method => :post, :member => true do
1126
- description "Disassociate an IP address from an instance"
1127
- with_capability :associate_address
1128
- param :id, :string, :required
1129
- control do
1130
- driver.disassociate_address(credentials, { :id => params[:id] })
1131
- status 202 # Accepted
1132
- respond_to do |format|
1133
- format.xml
1134
- format.json
1135
- format.html { redirect(address_url(params[:id])) }
1136
- end
1137
- end
1138
- end
1139
-
1140
- end
1141
-
1142
- #delete a firewall rule
1143
- delete '/api/firewalls/:firewall/:rule' do
1144
- opts = {}
1145
- opts[:firewall] = params[:firewall]
1146
- opts[:rule_id] = params[:rule]
1147
- driver.delete_firewall_rule(credentials, opts)
1148
- status 204
1149
- respond_to do |format|
1150
- format.xml
1151
- format.json
1152
- format.html {redirect firewall_url(params[:firewall])}
1153
- end
1154
76
  end
1155
77
 
1156
- #FIREWALLS
1157
- collection :firewalls do
1158
- description "Allow user to define firewall rules for an instance (ec2 security groups) eg expose ssh access [port 22, tcp]."
1159
-
1160
- operation :new do
1161
- description "A form to create a new firewall resource"
1162
- control do
1163
- respond_to do |format|
1164
- format.html { haml :"firewalls/new" }
1165
- end
1166
- end
1167
- end
1168
-
1169
- operation :new_rule, :form => true, :member => true, :method => :get do
1170
- description "A form to create a new firewall rule"
1171
- param :id, :string, :required
1172
- control do
1173
- @firewall_name = params[:id]
1174
- respond_to do |format|
1175
- format.html {haml :"firewalls/new_rule" }
1176
- end
1177
- end
1178
- end
1179
-
1180
- operation :index do
1181
- description 'List all firewalls'
1182
- with_capability :firewalls
1183
- control { filter_all(:firewalls) }
1184
- end
1185
-
1186
- operation :show do
1187
- description 'Show details for a specific firewall - list all rules'
1188
- with_capability :firewall
1189
- param :id, :string, :required
1190
- control { show(:firewall) }
1191
- end
1192
-
1193
- operation :create do
1194
- description 'Create a new firewall'
1195
- with_capability :create_firewall
1196
- param :name, :string, :required
1197
- param :description, :string, :required
1198
- control do
1199
- @firewall = driver.create_firewall(credentials, params )
1200
- status 201 # Created
1201
- response['Location'] = firewall_url(@firewall.id)
1202
- respond_to do |format|
1203
- format.xml { haml :"firewalls/show" }
1204
- format.html { haml :"firewalls/show" }
1205
- format.json { convert_to_json(:firewall, @firewall) }
1206
- end
1207
- end
1208
- end
1209
-
1210
- operation :destroy do
1211
- description 'Delete a specified firewall - error if firewall has rules'
1212
- with_capability :delete_firewall
1213
- param :id, :string, :required
1214
- control do
1215
- driver.delete_firewall(credentials, params)
1216
- status 204
1217
- respond_to do |format|
1218
- format.xml
1219
- format.json
1220
- format.html { redirect(firewalls_url) }
1221
- end
1222
- end
1223
- end
1224
-
1225
- #create a new firewall rule - POST /api/firewalls/:firewall/rules
1226
- operation :rules, :method => :post, :member => true do
1227
- description 'Create a new firewall rule for the specified firewall'
1228
- param :id, :required, :string, [], "Name of firewall in which to apply this rule"
1229
- param :protocol, :required, :string, ['tcp','udp','icmp'], "Transport layer protocol for the rule"
1230
- param :port_from, :required, :string, [], "Start of port range for the rule"
1231
- param :port_to, :required, :string, [], "End of port range for the rule"
1232
- with_capability :create_firewall_rule
1233
- control do
1234
- #source IPs from params
1235
- addresses = params.inject([]){|result,current| result << current.last unless current.grep(/^ip[-_]address/i).empty?; result}
1236
- #source groups from params
1237
- groups = {}
1238
- max_groups = params.select{|k,v| k=~/^group/}.size/2
1239
- for i in (1..max_groups) do
1240
- groups.merge!({params["group#{i}"]=>params["group#{i}owner"]})
1241
- end
1242
- params['addresses'] = addresses
1243
- params['groups'] = groups
1244
- if addresses.empty? && groups.empty?
1245
- raise Deltacloud::Validation::Failure.new(nil, "No sources. Specify at least one source ip_address or group")
1246
- end
1247
- driver.create_firewall_rule(credentials, params)
1248
- @firewall = driver.firewall(credentials, {:id => params[:id]})
1249
- status 201
1250
- respond_to do |format|
1251
- format.xml { haml :"firewalls/show" }
1252
- format.html { haml :"firewalls/show" }
1253
- format.json { convert_to_json(:firewall, @firewall) }
1254
- end
1255
- end
1256
- end
1257
-
1258
- end