deltacloud-core 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. data/Rakefile +63 -7
  2. data/bin/deltacloudd +29 -17
  3. data/config.ru +5 -3
  4. data/config/drivers/ec2.yaml +9 -0
  5. data/config/drivers/google.yaml +3 -0
  6. data/config/drivers/openstack.yaml +3 -0
  7. data/deltacloud-core.gemspec +1 -1
  8. data/lib/cimi/dependencies.rb +62 -0
  9. data/lib/cimi/helpers/cimi_helper.rb +50 -0
  10. data/lib/cimi/model.rb +52 -0
  11. data/lib/cimi/model/action.rb +24 -0
  12. data/lib/cimi/model/base.rb +249 -0
  13. data/lib/cimi/model/cloud_entry_point.rb +48 -0
  14. data/lib/cimi/model/entity_metadata.rb +83 -0
  15. data/lib/cimi/model/entity_metadata_collection.rb +31 -0
  16. data/lib/cimi/model/errors.rb +40 -0
  17. data/lib/cimi/model/machine.rb +227 -0
  18. data/lib/cimi/model/machine_admin.rb +59 -0
  19. data/lib/cimi/model/machine_admin_collection.rb +34 -0
  20. data/lib/cimi/model/machine_collection.rb +34 -0
  21. data/lib/cimi/model/machine_configuration.rb +67 -0
  22. data/lib/cimi/model/machine_configuration_collection.rb +34 -0
  23. data/lib/cimi/model/machine_image.rb +46 -0
  24. data/lib/cimi/model/machine_image_collection.rb +34 -0
  25. data/lib/cimi/model/machine_template.rb +41 -0
  26. data/lib/cimi/model/machine_template_collection.rb +34 -0
  27. data/lib/cimi/model/network.rb +69 -0
  28. data/lib/cimi/model/network_collection.rb +34 -0
  29. data/lib/cimi/model/network_configuration.rb +50 -0
  30. data/lib/cimi/model/network_configuration_collection.rb +34 -0
  31. data/lib/cimi/model/network_template.rb +26 -0
  32. data/lib/cimi/model/schema.rb +277 -0
  33. data/lib/cimi/model/volume.rb +103 -0
  34. data/lib/cimi/model/volume_collection.rb +34 -0
  35. data/lib/cimi/model/volume_configuration.rb +60 -0
  36. data/lib/cimi/model/volume_configuration_collection.rb +34 -0
  37. data/lib/cimi/model/volume_image.rb +49 -0
  38. data/lib/cimi/model/volume_image_collection.rb +34 -0
  39. data/lib/cimi/model/volume_template.rb +23 -0
  40. data/lib/cimi/model/volume_template_collection.rb +34 -0
  41. data/lib/cimi/server.rb +575 -0
  42. data/lib/deltacloud/base_driver/base_driver.rb +11 -1
  43. data/lib/deltacloud/core_ext.rb +2 -0
  44. data/lib/deltacloud/core_ext/array.rb +25 -0
  45. data/lib/deltacloud/core_ext/hash.rb +7 -0
  46. data/lib/deltacloud/core_ext/proc.rb +31 -0
  47. data/lib/deltacloud/core_ext/string.rb +15 -0
  48. data/lib/deltacloud/drivers/condor/condor_driver.rb +2 -1
  49. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +32 -10
  50. data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +1 -1
  51. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +1 -1
  52. data/lib/deltacloud/drivers/google/google_driver.rb +233 -0
  53. data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +7 -2
  54. data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +7 -2
  55. data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +7 -2
  56. data/lib/deltacloud/drivers/mock/mock_client.rb +17 -0
  57. data/lib/deltacloud/drivers/mock/mock_driver.rb +82 -8
  58. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +1 -1
  59. data/lib/deltacloud/drivers/openstack/openstack_driver.rb +47 -0
  60. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +8 -8
  61. data/lib/deltacloud/drivers/rhevm/rhevm_client.rb +122 -49
  62. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +42 -22
  63. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +1 -1
  64. data/lib/deltacloud/drivers/sbc/sbc_driver.rb +3 -2
  65. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +2 -2
  66. data/lib/deltacloud/drivers/vsphere/vsphere_client.rb +25 -4
  67. data/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +35 -12
  68. data/lib/deltacloud/hardware_profile.rb +34 -10
  69. data/lib/deltacloud/helpers/application_helper.rb +3 -28
  70. data/lib/deltacloud/helpers/blob_stream.rb +2 -1
  71. data/lib/deltacloud/models.rb +2 -0
  72. data/lib/deltacloud/models/bucket.rb +1 -1
  73. data/lib/deltacloud/models/image.rb +1 -1
  74. data/lib/deltacloud/models/instance.rb +2 -1
  75. data/lib/deltacloud/models/instance_address.rb +56 -0
  76. data/lib/deltacloud/models/provider.rb +27 -0
  77. data/{server.rb → lib/deltacloud/server.rb} +72 -14
  78. data/lib/deltacloud/validation.rb +31 -10
  79. data/lib/sinatra/rabbit.rb +34 -26
  80. data/lib/sinatra/rack_accept.rb +5 -5
  81. data/lib/sinatra/rack_matrix_params.rb +6 -2
  82. data/lib/sinatra/rack_syslog.rb +3 -3
  83. data/lib/sinatra/static_assets.rb +1 -1
  84. data/lib/sinatra/url_for.rb +1 -7
  85. data/public/images/bread-bg.png +0 -0
  86. data/public/images/logo-wide.png +0 -0
  87. data/public/images/topbar-bg.png +0 -0
  88. data/public/javascripts/application.js +5 -0
  89. data/public/javascripts/cmwgapp.js +249 -0
  90. data/public/javascripts/jquery-1.4.2.min.js +154 -0
  91. data/public/javascripts/jquery.mobile-1.0rc1.min.js +170 -0
  92. data/public/stylesheets/images/icons-18-black.png +0 -0
  93. data/public/stylesheets/images/icons-18-white.png +0 -0
  94. data/public/stylesheets/images/icons-36-black.png +0 -0
  95. data/public/stylesheets/images/icons-36-white.png +0 -0
  96. data/public/stylesheets/jquery.mobile-1.0rc1.min.css +12 -0
  97. data/public/stylesheets/new.css +4 -0
  98. data/support/fedora/deltacloud-core.init +20 -13
  99. data/tests/cimi/features/step_definitions/common_steps.rb +59 -0
  100. data/tests/cimi/features/step_definitions/machine_images_steps.rb +0 -0
  101. data/tests/cimi/features/step_definitions/machines_steps.rb +99 -0
  102. data/tests/cimi/features/step_definitions/volumes_steps.rb +115 -0
  103. data/tests/cimi/features/support/env.rb +53 -0
  104. data/tests/common.rb +89 -11
  105. data/tests/core_ext/string.rb +31 -0
  106. data/tests/drivers/google/api_test.rb +35 -0
  107. data/tests/drivers/google/buckets_test.rb +116 -0
  108. data/tests/drivers/google/setup.rb +38 -0
  109. data/tests/drivers/mock/instances_test.rb +20 -5
  110. data/tests/drivers/openstack/api_test.rb +41 -0
  111. data/tests/drivers/openstack/hardware_profiles_test.rb +53 -0
  112. data/tests/drivers/openstack/images_test.rb +40 -0
  113. data/tests/drivers/openstack/instances_test.rb +163 -0
  114. data/tests/drivers/openstack/realms_test.rb +36 -0
  115. data/tests/drivers/openstack/setup.rb +20 -0
  116. data/tests/drivers/rackspace/buckets_test.rb +145 -0
  117. data/tests/drivers/rackspace/setup.rb +3 -3
  118. data/tests/drivers/rhevm/api_test.rb +1 -1
  119. data/tests/drivers/rhevm/images_test.rb +2 -2
  120. data/tests/drivers/rhevm/instances_test.rb +10 -12
  121. data/tests/drivers/rhevm/realms_test.rb +4 -4
  122. data/tests/drivers/rhevm/setup.rb +3 -3
  123. data/tests/rabbit_test.rb +1 -1
  124. data/views/api/show.html.haml +13 -0
  125. data/views/cimi/cloudEntryPoint/index.html.haml +5 -0
  126. data/views/cimi/cloudEntryPoint/index.xml.haml +9 -0
  127. data/views/cimi/collection/index.html.haml +45 -0
  128. data/views/cimi/collection/response.xml.haml +3 -0
  129. data/views/cimi/error.html.haml +31 -0
  130. data/views/cimi/errors/400.html.haml +41 -0
  131. data/views/cimi/errors/400.xml.haml +3 -0
  132. data/views/cimi/errors/401.html.haml +41 -0
  133. data/views/cimi/errors/401.xml.haml +2 -0
  134. data/views/cimi/errors/403.html.haml +42 -0
  135. data/views/cimi/errors/403.xml.haml +2 -0
  136. data/views/cimi/errors/404.html.haml +29 -0
  137. data/views/cimi/errors/404.xml.haml +2 -0
  138. data/views/cimi/errors/405.html.haml +29 -0
  139. data/views/cimi/errors/405.xml.haml +5 -0
  140. data/views/cimi/errors/500.html.haml +43 -0
  141. data/views/cimi/errors/500.xml.haml +6 -0
  142. data/views/cimi/errors/502.html.haml +43 -0
  143. data/views/cimi/errors/502.xml.haml +7 -0
  144. data/views/cimi/errors/backend_capability_failure.html.haml +29 -0
  145. data/views/cimi/layout.html.haml +32 -0
  146. data/views/cimi/machine_configurations/show.html.haml +159 -0
  147. data/views/cimi/machine_configurations/show.xml.haml +27 -0
  148. data/views/cimi/machine_images/show.html.haml +79 -0
  149. data/views/cimi/machine_images/show.xml.haml +17 -0
  150. data/views/cimi/machines/show.html.haml +177 -0
  151. data/views/cimi/machines/show.xml.haml +28 -0
  152. data/views/cimi/volumes/show.html.haml +68 -0
  153. data/views/cimi/volumes/show.xml.haml +17 -0
  154. data/views/drivers/show.html.haml +10 -5
  155. data/views/drivers/show.xml.haml +9 -4
  156. data/views/error.html.haml +2 -2
  157. data/views/errors/500.xml.haml +7 -1
  158. data/views/instances/index.html.haml +1 -1
  159. data/views/instances/new.html.haml +19 -16
  160. data/views/instances/show.html.haml +7 -2
  161. data/views/instances/show.xml.haml +8 -7
  162. data/views/layout.html.haml +2 -2
  163. data/views/storage_volumes/show.html.haml +1 -1
  164. metadata +296 -204
  165. data/public/javascripts/jquery.mobile-1.0b1.min.js +0 -146
  166. data/public/stylesheets/jquery.mobile-1.0b1.min.css +0 -8
@@ -0,0 +1,103 @@
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 CIMI::Model::Volume < CIMI::Model::Base
17
+
18
+ struct :capacity do
19
+ scalar :quantity
20
+ scalar :units
21
+ end
22
+ text :bootable
23
+ text :supports_snapshots
24
+ array :snapshots do
25
+ scalar :ref
26
+ end
27
+ text :guest_interface
28
+ array :meters do
29
+ scalar :ref
30
+ end
31
+ href :eventlog
32
+ array :operations do
33
+ scalar :rel, :href
34
+ end
35
+
36
+ def self.find(id, context)
37
+ volumes = []
38
+ opts = ( id == :all ) ? {} : { :id => id }
39
+ volumes = self.driver.storage_volumes(context.credentials, opts)
40
+ volumes.collect!{ |volume| from_storage_volume(volume, context) }
41
+ return volumes.first unless volumes.length > 1
42
+ return volumes
43
+ end
44
+
45
+ def self.all(context); find(:all, context); end
46
+
47
+ def self.create_from_json(json_in, context)
48
+ json = JSON.parse(json_in)
49
+ volume_config_id = json["volumeTemplate"]["volumeConfig"]["href"].split("/").last
50
+ volume_image_id = (json["volumeTemplate"].has_key?("volumeImage") ?
51
+ json["volumeTemplate"]["volumeImage"]["href"].split("/").last : nil)
52
+ create_volume({:volume_config_id=>volume_config_id, :volume_image_id=>volume_image_id}, context)
53
+ end
54
+
55
+ def self.create_from_xml(xml_in, context)
56
+ xml = XmlSimple.xml_in(xml_in)
57
+ volume_config_id = xml["volumeTemplate"][0]["volumeConfig"][0]["href"].split("/").last
58
+ volume_image_id = (xml["volumeTemplate"][0].has_key?("volumeImage") ?
59
+ xml["volumeTemplate"][0]["volumeImage"][0]["href"].split("/").last : nil)
60
+ create_volume({:volume_config_id=>volume_config_id, :volume_image_id=>volume_image_id}, context)
61
+ end
62
+
63
+ def self.delete!(id, context)
64
+ context.driver.destroy_storage_volume(context.credentials, {:id=>id} )
65
+ end
66
+
67
+ def self.find_to_attach_from_json(json_in, context)
68
+ json = JSON.parse(json_in)
69
+ volumes = json["volumes"].map{|v| {:volume=>self.find(v["volume"]["href"].split("/volumes/").last, context),
70
+ :attachment_point=>v["attachmentPoint"] }}
71
+ end
72
+
73
+ def self.find_to_attach_from_xml(xml_in, context)
74
+ xml = XmlSimple.xml_in(xml_in)
75
+ volumes = xml["volume"].map{|v| {:volume => self.find(v["href"].split("/volumes/").last, context),
76
+ :attachment_point=>v["attachmentPoint"] }}
77
+ end
78
+
79
+ private
80
+
81
+ def self.create_volume(params, context)
82
+ volume_config = VolumeConfiguration.find(params[:volume_config_id], context)
83
+ opts = {:capacity=>volume_config.capacity[:quantity], :snapshot_id=>params[:volume_image_id] }
84
+ storage_volume = self.driver.create_storage_volume(context.credentials, opts)
85
+ from_storage_volume(storage_volume, context)
86
+ end
87
+
88
+ def self.from_storage_volume(volume, context)
89
+ self.new( { :name => volume.id,
90
+ :description => volume.id,
91
+ :created => volume.created,
92
+ :uri => context.volume_url(volume.id),
93
+ :capacity => { :quantity=>volume.capacity, :units=>"gibibyte" }, #FIXME... units will vary
94
+ :bootable => "false", #fixme ... will vary... ec2 doesn't expose this
95
+ :supports_snapshots => "true", #fixme, will vary (true for ec2)
96
+ :snapshots => [], #fixme...
97
+ :guest_interface => "",
98
+ :eventlog => {:href=> "http://eventlogs"},#FIXME
99
+ :meters => []
100
+ } )
101
+ end
102
+
103
+ 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
+ class CIMI::Model::VolumeCollection < CIMI::Model::Base
17
+
18
+ act_as_root_entity :volume
19
+
20
+ array :volumes do
21
+ scalar :href
22
+ end
23
+
24
+ def self.default(context)
25
+ self.new(
26
+ :uri => context.volumes_url,
27
+ :name => 'default',
28
+ :created => Time.now,
29
+ :description => "#{context.driver.name.capitalize} VolumeCollection",
30
+ :volumes => Volume.all_uri(context)
31
+ )
32
+ end
33
+
34
+ end
@@ -0,0 +1,60 @@
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 CIMI::Model::VolumeConfiguration < CIMI::Model::Base
17
+
18
+ text :format
19
+ struct :capacity do
20
+ scalar :quantity
21
+ scalar :units
22
+ end
23
+ text :supports_snapshots
24
+ text :guest_interface
25
+ array :operations do
26
+ scalar :rel, :href
27
+ end
28
+
29
+ def self.find(id, context)
30
+ volume_configs = []
31
+ if id == :all
32
+ #ec2 ebs volumes can 1gb..1tb
33
+ (1..1000).each do |size|
34
+ volume_configs << create(size, context)
35
+ end
36
+ else
37
+ volume_configs << create(id, context)
38
+ return volume_configs.first
39
+ end
40
+ return volume_configs
41
+ end
42
+
43
+
44
+ def self.all(context); find(:all, context); end
45
+
46
+ private
47
+
48
+ def self.create(size, context)
49
+ self.new( {
50
+ :uri => context.volume_configuration_url(size),
51
+ :name => size,
52
+ :description => "volume configuration with #{size} GiB",
53
+ :created => Time.now.to_s,
54
+ :capacity => {:quantity=>size, :units=>"gibibytes"},
55
+ :supports_snapshots => "true"
56
+ # FIXME :guest_interface => "NFS"
57
+ } )
58
+ end
59
+
60
+ 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
+ class CIMI::Model::VolumeConfigurationCollection < CIMI::Model::Base
17
+
18
+ act_as_root_entity :volume_configuration
19
+
20
+ array :volume_configurations do
21
+ scalar :href
22
+ end
23
+
24
+ def self.default(context)
25
+ self.new(
26
+ :uri => context.volume_configurations_url,
27
+ :name => 'default',
28
+ :created => Time.now,
29
+ :description => "#{context.driver.name.capitalize} VolumeConfigurationCollection",
30
+ :volume_configurations => VolumeConfiguration.all_uri(context)
31
+ )
32
+ end
33
+
34
+ end
@@ -0,0 +1,49 @@
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 CIMI::Model::VolumeImage < CIMI::Model::Base
17
+
18
+ href :image_location
19
+ text :image_data
20
+ text :bootable
21
+ array :operations do
22
+ scalar :rel, :href
23
+ end
24
+
25
+ def self.find(id, context)
26
+ storage_snapshots = []
27
+ opts = ( id==:all ) ? {} : { :id=>id }
28
+ storage_snapshots = self.driver.storage_snapshots(context.credentials, opts)
29
+ storage_snapshots.collect!{ |snapshot| from_storage_snapshot(snapshot, context) }
30
+ return storage_snapshots.first unless storage_snapshots.length > 1
31
+ return storage_snapshots
32
+ end
33
+
34
+ def self.all(context); find(:all, context); end
35
+
36
+ private
37
+
38
+ def self.from_storage_snapshot(snapshot, context)
39
+ self.new( {
40
+ :name => snapshot.id,
41
+ :description => snapshot.id,
42
+ :created => snapshot.created,
43
+ :uri => context.volume_image_url(snapshot.id),
44
+ :image_location => {:href=>context.volume_url(snapshot.storage_volume_id)},
45
+ :bootable => "false" #FIXME
46
+ } )
47
+ end
48
+
49
+ 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
+ class CIMI::Model::VolumeImageCollection < CIMI::Model::Base
17
+
18
+ act_as_root_entity :volume_image
19
+
20
+ array :volume_images do
21
+ scalar :href
22
+ end
23
+
24
+ def self.default(context)
25
+ self.new(
26
+ :uri => context.volume_images_url,
27
+ :name => 'default',
28
+ :created => Time.now,
29
+ :description => "#{context.driver.name.capitalize} VolumeImageCollection",
30
+ :volume_images => VolumeImage.all_uri(context)
31
+ )
32
+ end
33
+
34
+ end
@@ -0,0 +1,23 @@
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 CIMI::Model::VolumeTemplate < CIMI::Model::Base
17
+
18
+ href :volume_config
19
+ href :volume_image
20
+ array :operations do
21
+ scalar :rel, :href
22
+ end
23
+ 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
+ class CIMI::Model::VolumeTemplateCollection < CIMI::Model::Base
17
+
18
+ act_as_root_entity :volume_template
19
+
20
+ array :volume_templates do
21
+ scalar :href
22
+ end
23
+
24
+ def self.default(context)
25
+ self.new(
26
+ :uri => context.volume_template_url,
27
+ :name => 'default',
28
+ :created => Time.now,
29
+ :description => "#{context.driver.name.capitalize} VolumeTemplateCollection",
30
+ :volume_templates => VolumeTemplate.all_uri(context)
31
+ )
32
+ end
33
+
34
+ end
@@ -0,0 +1,575 @@
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
+ require 'cimi/dependencies'
17
+ require 'cimi/helpers/cimi_helper'
18
+ require 'cimi/model'
19
+
20
+ set :version, '0.1.0'
21
+
22
+ include Deltacloud::Drivers
23
+ include CIMI::Model
24
+
25
+ set :drivers, Proc.new { driver_config }
26
+
27
+ Sinatra::Application.register Rack::RespondTo
28
+
29
+ use Rack::ETag
30
+ use Rack::Runtime
31
+ use Rack::MatrixParams
32
+ use Rack::DriverSelect
33
+ use Rack::MediaType
34
+ use Rack::Date
35
+
36
+ configure do
37
+ set :root_url, "/cimi"
38
+ set :views, File::join($top_srcdir, 'views', 'cimi')
39
+ set :public_folder, File::join($top_srcdir, 'public')
40
+ driver
41
+ end
42
+
43
+ configure :production do
44
+ use Rack::SyslogLogger
45
+ disable :logging
46
+ enable :show_errors
47
+ set :dump_errors, false
48
+ $stdout = SyslogFile.new
49
+ $stderr = $stdout
50
+ end
51
+
52
+ configure :development do
53
+ set :raise_errors => false
54
+ set :show_exceptions, false
55
+ $stdout.sync = true
56
+ $stderr.sync = true
57
+ end
58
+
59
+ # You could use $API_HOST environment variable to change your hostname to
60
+ # whatever you want (eg. if you running API behind NAT)
61
+ HOSTNAME=ENV['API_HOST'] ? ENV['API_HOST'] : nil
62
+
63
+ error do
64
+ report_error
65
+ end
66
+
67
+ get "/" do
68
+ redirect settings.root_url
69
+ end
70
+
71
+ get "#{settings.root_url}\/?" do
72
+ halt 401 if params[:force_auth] and not driver.valid_credentials?(credentials)
73
+ redirect cloudEntryPoint_url, 301
74
+ end
75
+
76
+ global_collection :cloudEntryPoint do
77
+ description 'Cloud entry point'
78
+ operation :index do
79
+ description "list all resources of the cloud"
80
+ control do
81
+ entry_point = CloudEntryPoint.create(self)
82
+ respond_to do |format|
83
+ format.xml { entry_point.to_xml }
84
+ format.json { entry_point.to_json }
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ global_collection :machine_configurations do
91
+ description 'List all machine configurations'
92
+
93
+ operation :index do
94
+ param :CIMISelect, :string, :optional
95
+ description "List all machine configurations"
96
+ control do
97
+ machine_configs = MachineConfigurationCollection.default(self).filter_by(params[:CIMISelect])
98
+ respond_to do |format|
99
+ format.xml { machine_configs.to_xml }
100
+ format.json { machine_configs.to_json }
101
+ end
102
+ end
103
+ end
104
+
105
+ operation :show do
106
+
107
+ description "The Machine Configuration entity represents the set of configuration values "+
108
+ "that define the (virtual) hardware resources of a to-be-realized Machine Instance.."
109
+
110
+ param :id, :string, :required
111
+
112
+ control do
113
+ machine_conf = MachineConfiguration.find(params[:id], self)
114
+ respond_to do |format|
115
+ format.xml { machine_conf.to_xml }
116
+ format.json { machine_conf.to_json }
117
+ end
118
+ end
119
+
120
+ end
121
+ end
122
+
123
+ global_collection :machine_images do
124
+ description 'List all machine images'
125
+
126
+ operation :index do
127
+ description "List all machine configurations"
128
+ param :CIMISelect, :string, :optional
129
+ control do
130
+ machine_images = MachineImageCollection.default(self).filter_by(params[:CIMISelect])
131
+ respond_to do |format|
132
+ format.xml { machine_images.to_xml }
133
+ format.json { machine_images.to_json }
134
+ end
135
+ end
136
+ end
137
+
138
+ operation :show do
139
+ description "Show specific machine image."
140
+ param :id, :string, :required
141
+ control do
142
+ machine_image = MachineImage.find(params[:id], self)
143
+ respond_to do |format|
144
+ format.xml { machine_image.to_xml }
145
+ format.json { machine_image.to_json }
146
+ end
147
+ end
148
+ end
149
+
150
+ end
151
+
152
+ global_collection :machine_admins do
153
+ description 'Machine Admin entity'
154
+
155
+ operation :index do
156
+ description "List all machine admins"
157
+ param :CIMISelect, :string, :optional
158
+ with_capability :keys
159
+ control do
160
+ machine_admins = MachineAdminCollection.default(self).filter_by(params[:CIMISelect])
161
+ respond_to do |format|
162
+ format.xml { machine_admins.to_xml }
163
+ format.json { machine_admins.to_json }
164
+ end
165
+ end
166
+ end
167
+
168
+ operation :show do
169
+ description "Show specific machine admin"
170
+ param :id, :string, :required
171
+ with_capability :key
172
+ control do
173
+ machine_admin = MachineAdmin.find(params[:id], self)
174
+ respond_to do |format|
175
+ format.xml { machine_admin.to_xml }
176
+ format.json { machine_admin.to_json }
177
+ end
178
+ end
179
+ end
180
+
181
+ operation :create do
182
+ description "Show specific machine admin"
183
+ with_capability :create_key
184
+ control do
185
+ if request.content_type.end_with?("+json")
186
+ new_admin = MachineAdmin.create_from_json(request.body.read, self)
187
+ else
188
+ new_admin = MachineAdmin.create_from_xml(request.body.read, self)
189
+ end
190
+ status 201 # Created
191
+ respond_to do |format|
192
+ format.json { new_admin.to_json }
193
+ format.xml { new_admin.to_xml }
194
+ end
195
+ end
196
+ end
197
+
198
+ operation :delete, :method => :delete, :member => true do
199
+ description "Delete specified MachineAdmin entity"
200
+ param :id, :string, :required
201
+ control do
202
+ MachineAdmin.delete!(params[:id], self)
203
+ no_content_with_status(200)
204
+ end
205
+ end
206
+
207
+ end
208
+
209
+ global_collection :machines do
210
+ description 'List all machine'
211
+
212
+ operation :index do
213
+ param :CIMISelect, :string, :optional
214
+ description "List all machines"
215
+ control do
216
+ machines = MachineCollection.default(self).filter_by(params[:CIMISelect])
217
+ respond_to do |format|
218
+ format.xml { machines.to_xml }
219
+ format.json { machines.to_json }
220
+ end
221
+ end
222
+ end
223
+
224
+ operation :show do
225
+ description "Show specific machine."
226
+ param :id, :string, :required
227
+ control do
228
+ machine = Machine.find(params[:id], self)
229
+ respond_to do |format|
230
+ format.xml { machine.to_xml }
231
+ format.json { machine.to_json }
232
+ end
233
+ end
234
+ end
235
+
236
+ operation :create do
237
+ description "Create a new Machine entity."
238
+ control do
239
+ if request.content_type.end_with?("+json")
240
+ new_machine = Machine.create_from_json(request.body.read, self)
241
+ else
242
+ new_machine = Machine.create_from_xml(request.body.read, self)
243
+ end
244
+ status 201 # Created
245
+ respond_to do |format|
246
+ format.json { new_machine.to_json }
247
+ format.xml { new_machine.to_xml }
248
+ end
249
+ end
250
+ end
251
+
252
+ operation :destroy do
253
+ description "Delete a specified machine."
254
+ param :id, :string, :required
255
+ control do
256
+ Machine.delete!(params[:id], self)
257
+ no_content_with_status(200)
258
+ end
259
+ end
260
+
261
+ operation :stop, :method => :post, :member => true do
262
+ description "Stop specific machine."
263
+ param :id, :string, :required
264
+ control do
265
+ machine = Machine.find(params[:id], self)
266
+ if request.content_type.end_with?("+json")
267
+ action = Action.from_json(request.body.read)
268
+ else
269
+ action = Action.from_xml(request.body.read)
270
+ end
271
+ machine.perform(action, self) do |operation|
272
+ no_content_with_status(202) if operation.success?
273
+ # Handle errors using operation.failure?
274
+ end
275
+ end
276
+ end
277
+
278
+ operation :restart, :method => :post, :member => true do
279
+ description "Start specific machine."
280
+ param :id, :string, :required
281
+ control do
282
+ machine = Machine.find(params[:id], self)
283
+ if request.content_type.end_with?("+json")
284
+ action = Action.from_json(request.body.read)
285
+ else
286
+ action = Action.from_xml(request.body.read)
287
+ end
288
+ machine.perform(action, self) do |operation|
289
+ no_content_with_status(202) if operation.success?
290
+ # Handle errors using operation.failure?
291
+ end
292
+ end
293
+ end
294
+
295
+ operation :start, :method => :post, :member => true do
296
+ description "Start specific machine."
297
+ param :id, :string, :required
298
+ control do
299
+ machine = Machine.find(params[:id], self)
300
+ if request.content_type.end_with?("+json")
301
+ action = Action.from_json(request.body.read)
302
+ else
303
+ action = Action.from_xml(request.body.read)
304
+ end
305
+ machine.perform(action, self) do |operation|
306
+ no_content_with_status(202) if operation.success?
307
+ # Handle errors using operation.failure?
308
+ end
309
+ end
310
+ end
311
+
312
+ #NOTE: The routes for attach/detach used here are NOT as specified by CIMI
313
+ #will likely move later. CIMI specifies PUT of the whole Machine description
314
+ #with inclusion/ommission of the volumes you want [att|det]ached
315
+ operation :attach_volume, :method => :put, :member => true do
316
+ description "Attach CIMI Volume(s) to a machine."
317
+ param :id, :string, :required
318
+ control do
319
+ if request.content_type.end_with?("+json")
320
+ volumes_to_attach = Volume.find_to_attach_from_json(request.body.read, self)
321
+ else
322
+ volumes_to_attach = Volume.find_to_attach_from_xml(request.body.read, self)
323
+ end
324
+ machine = Machine.attach_volumes(volumes_to_attach, self)
325
+ respond_to do |format|
326
+ format.json{ machine.to_json}
327
+ format.xml{machine.to_xml}
328
+ end
329
+ end
330
+ end
331
+
332
+ operation :detach_volume, :method => :put, :member => true do
333
+ description "Detach CIMI Volume(s) from a machine."
334
+ param :id, :string, :required
335
+ control do
336
+ if request.content_type.end_with?("+json")
337
+ volumes_to_detach = Volume.find_to_attach_from_json(request.body.read, self)
338
+ else
339
+ volumes_to_detach = Volume.find_to_attach_from_xml(request.body.read, self)
340
+ end
341
+ machine = Machine.detach_volumes(volumes_to_detach, self)
342
+ respond_to do |format|
343
+ format.json{ machine.to_json}
344
+ format.xml{machine.to_xml}
345
+ end
346
+ end
347
+ end
348
+ end
349
+
350
+ global_collection :volumes do
351
+ description "Volume represents storage at either the block or file-system level. Volumes can be attached to Machines. Once attached, Volumes can be accessed by processes on that Machine"
352
+
353
+ operation :index do
354
+ description "List all volumes"
355
+ param :CIMISelect, :string, :optional
356
+ control do
357
+ volumes = VolumeCollection.default(self).filter_by(params[:CIMISelect])
358
+ respond_to do |format|
359
+ format.xml { volumes.to_xml }
360
+ format.json { volumes.to_json }
361
+ end
362
+ end
363
+ end
364
+
365
+ operation :show do
366
+ description "Show specific Volume."
367
+ param :id, :string, :required
368
+ control do
369
+ volume = Volume.find(params[:id], self)
370
+ if volume
371
+ respond_to do |format|
372
+ format.xml { volume.to_xml }
373
+ format.json { volume.to_json }
374
+ end
375
+ else
376
+ report_error(404)
377
+ end
378
+ end
379
+ end
380
+
381
+ operation :create do
382
+ description "Create a new Volume."
383
+ control do
384
+ content_type = (request.content_type.end_with?("+json") ? :json : :xml)
385
+ #((request.content_type.end_with?("+xml")) ? :xml : report_error(415) ) FIXME
386
+ case content_type
387
+ when :json
388
+ new_volume = Volume.create_from_json(request.body.read, self)
389
+ when :xml
390
+ new_volume = Volume.create_from_xml(request.body.read, self)
391
+ end
392
+ respond_to do |format|
393
+ format.json { new_volume.to_json }
394
+ format.xml { new_volume.to_xml }
395
+ end
396
+ end
397
+ end
398
+
399
+ operation :destroy do
400
+ description "Delete a specified Volume"
401
+ param :id, :string, :required
402
+ control do
403
+ Volume.delete!(params[:id], self)
404
+ no_content_with_status(200)
405
+ end
406
+ end
407
+
408
+ end
409
+
410
+ global_collection :volume_configurations do
411
+ description "The Volume Configuration entity represents the set of configuration values needed to create a Volume with certain characteristics. Volume Configurations are created by Providers and MAY, at the Providers discretion, be created by Consumers"
412
+
413
+ operation :index do
414
+ description "Get list all VolumeConfigurations"
415
+ param :CIMISelect, :string, :optional
416
+ control do
417
+ volume_configuration = VolumeConfigurationCollection.default(self).filter_by(params[:CIMISelect])
418
+ respond_to do |format|
419
+ format.xml { volume_configuration.to_xml }
420
+ format.json { volume_configuration.to_json }
421
+ end
422
+ end
423
+ end
424
+
425
+ operation :show do
426
+ description "Get a specific VolumeConfiguration"
427
+ param :id, :required, :string
428
+ control do
429
+ volume_config = VolumeConfiguration.find(params[:id], self)
430
+ respond_to do |format|
431
+ format.xml { volume_config.to_xml }
432
+ format.json { volume_config.json }
433
+ end
434
+ end
435
+ end
436
+
437
+ global_collection :volume_images do
438
+ description 'This entity represents an image that could be place on a pre-loaded volume.'
439
+
440
+ operation :index do
441
+ description "List all volumes images"
442
+ param :CIMISelect, :string, :optional
443
+ control do
444
+ volume_images = VolumeImageCollection.default(self).filter_by(params[:CIMISelect])
445
+ respond_to do |format|
446
+ format.xml { volume_images.to_xml }
447
+ format.json { volume_images.to_json }
448
+ end
449
+ end
450
+ end
451
+
452
+ operation :show do
453
+ description "Show a specific volume image"
454
+ param :id, :string, :required
455
+ control do
456
+ volume_image = VolumeImage.find(params[:id], self)
457
+ respond_to do |format|
458
+ format.xml { volume_image.to_xml }
459
+ format.json { volume_image.to_json }
460
+ end
461
+ end
462
+ end
463
+
464
+ end
465
+
466
+
467
+ global_collection :entity_metadata do
468
+ description 'This allows for the discovery of Provider defined constraints on the CIMI defined attributes as well as discovery of any new extension attributes that the Provider may have defined.'
469
+
470
+ operation :index do
471
+ description "List all entity metadata defined for this provider"
472
+ control do
473
+ entity_metadata = EntityMetadataCollection.default(self)
474
+ respond_to do |format|
475
+ format.xml{entity_metadata.to_xml}
476
+ format.json{entity_metadata.to_json}
477
+ end
478
+ end
479
+ end
480
+
481
+ operation :show do
482
+ description "Get the entity metadata for a specific collection"
483
+ param :id, :required, :string
484
+ control do
485
+ entity_metadata = EntityMetadata.find(params[:id], self)
486
+ respond_to do |format|
487
+ format.xml{entity_metadata.to_xml}
488
+ format.json{entity_metadata.to_json}
489
+ end
490
+ end
491
+ end
492
+
493
+ end
494
+
495
+ global_collection :networks do
496
+ description 'A Network represents an abstraction of a layer 2 broadcast domain'
497
+
498
+ operation :index do
499
+ description "List all Networks"
500
+ param :CIMISelect, :string, :optional
501
+ control do
502
+ networks = NetworkCollection.default(self).filter_by(params[:CIMISelect])
503
+ respond_to do |format|
504
+ format.xml { networks.to_xml }
505
+ format.json { networks.to_json }
506
+ end
507
+ end
508
+ end
509
+
510
+ operation :show do
511
+ description "Show a specific Network"
512
+ param :id, :string, :required
513
+ control do
514
+ network = Network.find(params[:id], self)
515
+ respond_to do |format|
516
+ format.xml { network.to_xml }
517
+ format.json { network.to_json }
518
+ end
519
+ end
520
+ end
521
+
522
+ operation :create do
523
+ description "Create a new Network"
524
+ control do
525
+ if request.content_type.end_with("+json")
526
+ network = Network.create_from_json(request.body.read, self)
527
+ else
528
+ network = Network.create_from_xml(request.body.read, self)
529
+ end
530
+ respond_to do |format|
531
+ format.xml { network.to_xml}
532
+ format.json { network.to_json }
533
+ end
534
+ end
535
+ end
536
+
537
+ operation :destroy do
538
+ description "Delete a specified Network"
539
+ param :id, :string, :required
540
+ control do
541
+ Network.delete!(params[:id], self)
542
+ no_content_with_status(200)
543
+ end
544
+ end
545
+
546
+ end
547
+
548
+ global_collection :network_configurations do
549
+ description 'Network Configurations contain the set of configuration values representing the information needed to create a Network with certain characteristics'
550
+
551
+ operation :index do
552
+ description 'List all NetworkConfigurations'
553
+ param :CIMISelect, :string, :optional
554
+ control do
555
+ network_configurations = NetworkConfigurationCollection.default(self).filter_by(params[:CIMISelect])
556
+ respond_to do |format|
557
+ format.xml { network_configurations.to_xml }
558
+ format.json { network_configurations.to_json }
559
+ end
560
+ end
561
+ end
562
+
563
+ operation :show do
564
+ description 'Show a specific NetworkConfiguration'
565
+ param :id, :string, :required
566
+ control do
567
+ network_config = NetworkConfiguration.find(params[:id], self)
568
+ respond_to do
569
+ format.xml { network_config.to_xml }
570
+ format.json { network_config.to_json }
571
+ end
572
+ end
573
+ end
574
+ end
575
+ end