deltacloud-core 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (220) hide show
  1. data/Rakefile +40 -28
  2. data/bin/deltacloud-db-upgrade +24 -0
  3. data/bin/deltacloudd +20 -9
  4. data/config.ru +12 -53
  5. data/db/migrations/1_add_realm_to_machine_template.rb +23 -0
  6. data/deltacloud-core.gemspec +11 -5
  7. data/lib/cimi/collections.rb +4 -31
  8. data/lib/cimi/collections/address_templates.rb +2 -5
  9. data/lib/cimi/collections/addresses.rb +2 -5
  10. data/lib/cimi/collections/base.rb +18 -6
  11. data/lib/cimi/collections/credentials.rb +2 -5
  12. data/lib/cimi/collections/machine_images.rb +2 -1
  13. data/lib/cimi/collections/machine_templates.rb +2 -5
  14. data/lib/cimi/collections/machines.rb +6 -9
  15. data/lib/cimi/collections/network_ports.rb +3 -3
  16. data/lib/cimi/collections/networks.rb +5 -8
  17. data/lib/cimi/collections/system_templates.rb +72 -0
  18. data/lib/cimi/collections/systems.rb +194 -0
  19. data/lib/cimi/collections/volume_configurations.rb +1 -1
  20. data/lib/cimi/collections/volume_images.rb +2 -1
  21. data/lib/cimi/collections/volume_templates.rb +3 -2
  22. data/lib/cimi/collections/volumes.rb +2 -2
  23. data/lib/cimi/dependencies.rb +0 -2
  24. data/lib/cimi/helpers/cimi_helper.rb +12 -57
  25. data/lib/cimi/helpers/database_helper.rb +0 -4
  26. data/lib/cimi/models.rb +25 -14
  27. data/lib/cimi/models/address.rb +4 -31
  28. data/lib/cimi/models/address_create.rb +51 -0
  29. data/lib/cimi/models/address_template.rb +8 -52
  30. data/lib/cimi/models/address_template_create.rb +44 -0
  31. data/lib/cimi/models/base.rb +44 -6
  32. data/lib/cimi/models/cloud_entry_point.rb +1 -1
  33. data/lib/cimi/models/credential.rb +1 -1
  34. data/lib/cimi/models/credential_create.rb +46 -0
  35. data/lib/cimi/models/credential_template.rb +24 -0
  36. data/lib/cimi/models/machine.rb +1 -71
  37. data/lib/cimi/models/machine_configuration.rb +3 -3
  38. data/lib/cimi/models/machine_create.rb +49 -0
  39. data/lib/cimi/models/machine_image.rb +2 -25
  40. data/lib/cimi/models/machine_image_create.rb +41 -0
  41. data/lib/cimi/models/machine_template.rb +14 -34
  42. data/lib/cimi/models/machine_template_create.rb +33 -0
  43. data/lib/cimi/models/network.rb +0 -38
  44. data/lib/cimi/models/network_create.rb +43 -0
  45. data/lib/cimi/models/network_port.rb +17 -17
  46. data/lib/cimi/models/network_template.rb +2 -3
  47. data/lib/cimi/models/resource.rb +22 -3
  48. data/lib/cimi/models/schema.rb +94 -8
  49. data/lib/cimi/models/system.rb +67 -0
  50. data/lib/cimi/models/system_template.rb +63 -0
  51. data/lib/cimi/models/volume.rb +2 -42
  52. data/lib/cimi/models/volume_configuration.rb +4 -4
  53. data/lib/cimi/models/volume_create.rb +58 -0
  54. data/lib/cimi/models/volume_image.rb +8 -17
  55. data/lib/cimi/models/volume_image_create.rb +47 -0
  56. data/lib/cimi/models/volume_template.rb +6 -19
  57. data/lib/cimi/models/volume_template_create.rb +33 -0
  58. data/lib/db.rb +14 -22
  59. data/lib/db/volume_template.rb +1 -1
  60. data/lib/deltacloud/api.rb +6 -5
  61. data/lib/deltacloud/collections.rb +4 -27
  62. data/lib/deltacloud/collections/base.rb +4 -0
  63. data/lib/deltacloud/collections/images.rb +1 -1
  64. data/lib/deltacloud/collections/instances.rb +2 -2
  65. data/lib/deltacloud/core_ext/array.rb +1 -0
  66. data/lib/deltacloud/core_ext/integer.rb +13 -9
  67. data/lib/deltacloud/core_ext/string.rb +45 -28
  68. data/lib/deltacloud/drivers/arubacloud/arubacloud_driver.rb +0 -9
  69. data/lib/deltacloud/drivers/base_driver.rb +45 -16
  70. data/lib/deltacloud/drivers/digitalocean/digitalocean_driver.rb +78 -8
  71. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +13 -9
  72. data/lib/deltacloud/drivers/fgcp/fgcp_client.rb +44 -0
  73. data/lib/deltacloud/drivers/fgcp/fgcp_driver.rb +164 -90
  74. data/lib/deltacloud/drivers/fgcp/fgcp_driver_cimi_methods.rb +74 -0
  75. data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +3 -3
  76. data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +3 -3
  77. data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +3 -3
  78. data/lib/deltacloud/drivers/mock/mock_client.rb +17 -1
  79. data/lib/deltacloud/drivers/mock/mock_driver.rb +161 -204
  80. data/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb +80 -0
  81. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +6 -1
  82. data/lib/deltacloud/drivers/openstack/openstack_driver.rb +61 -68
  83. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +0 -9
  84. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +11 -6
  85. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +0 -8
  86. data/lib/deltacloud/drivers/vsphere/vsphere_client.rb +11 -4
  87. data/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +0 -12
  88. data/lib/deltacloud/helpers/collection_helper.rb +106 -0
  89. data/lib/deltacloud/helpers/deltacloud_helper.rb +12 -8
  90. data/lib/deltacloud/models/address.rb +19 -17
  91. data/lib/deltacloud/models/base_model.rb +29 -26
  92. data/lib/deltacloud/models/blob.rb +22 -20
  93. data/lib/deltacloud/models/bucket.rb +21 -16
  94. data/lib/deltacloud/models/firewall.rb +18 -16
  95. data/lib/deltacloud/models/firewall_rule.rb +22 -20
  96. data/lib/deltacloud/models/image.rb +29 -28
  97. data/lib/deltacloud/models/instance.rb +92 -94
  98. data/lib/deltacloud/models/instance_address.rb +42 -40
  99. data/lib/deltacloud/models/instance_profile.rb +28 -26
  100. data/lib/deltacloud/models/key.rb +47 -45
  101. data/lib/deltacloud/models/load_balancer.rb +32 -31
  102. data/lib/deltacloud/models/metric.rb +76 -29
  103. data/lib/deltacloud/models/provider.rb +15 -13
  104. data/lib/deltacloud/models/realm.rb +15 -21
  105. data/lib/deltacloud/models/storage_snapshot.rb +23 -19
  106. data/lib/deltacloud/models/storage_volume.rb +35 -34
  107. data/lib/deltacloud/version.rb +1 -1
  108. data/lib/deltacloud_rack.rb +22 -0
  109. data/lib/initialize.rb +28 -0
  110. data/lib/initializers/database_initialize.rb +76 -0
  111. data/lib/initializers/frontend_initialize.rb +42 -0
  112. data/lib/initializers/mock_initialize.rb +33 -0
  113. data/lib/sinatra/rack_logger.rb +35 -24
  114. data/tests/cimi/collections/cloud_entry_point_test.rb +1 -7
  115. data/tests/cimi/collections/machine_images_test.rb +2 -2
  116. data/tests/cimi/collections/machine_templates_test.rb +75 -0
  117. data/tests/cimi/collections/machines_test.rb +2 -2
  118. data/tests/cimi/collections/system_templates_test.rb +41 -0
  119. data/tests/cimi/collections/systems_test.rb +50 -0
  120. data/tests/cimi/db/database_helper_test.rb +17 -25
  121. data/tests/cimi/db/db_helper.rb +1 -12
  122. data/tests/cimi/db/entity_test.rb +7 -8
  123. data/tests/cimi/model/machine_create_spec.rb +44 -0
  124. data/tests/cimi/model/machine_template_spec.rb +29 -0
  125. data/tests/cimi/model/resource_spec.rb +40 -0
  126. data/tests/cimi/model/schema_spec.rb +37 -0
  127. data/tests/cimi/spec_helper.rb +3 -0
  128. data/tests/deltacloud/collections/buckets_collection_test.rb +1 -1
  129. data/tests/deltacloud/collections/drivers_collection_test.rb +2 -2
  130. data/tests/deltacloud/collections/hardware_profiles_collection_test.rb +2 -2
  131. data/tests/deltacloud/collections/images_collection_test.rb +2 -2
  132. data/tests/deltacloud/collections/instance_states_collection_test.rb +1 -1
  133. data/tests/deltacloud/collections/instances_collection_test.rb +6 -3
  134. data/tests/deltacloud/collections/keys_collection_test.rb +2 -2
  135. data/tests/deltacloud/collections/realms_collection_test.rb +2 -2
  136. data/tests/deltacloud/collections/storage_snapshots_collection_test.rb +2 -2
  137. data/tests/deltacloud/collections/storage_volumes_collection_test.rb +2 -2
  138. data/tests/deltacloud/collections_test.rb +5 -5
  139. data/tests/deltacloud/common.rb +2 -13
  140. data/tests/deltacloud/launcher_test.rb +3 -3
  141. data/tests/deltacloud/rack_test.rb +2 -2
  142. data/tests/deltacloud/server_test.rb +1 -1
  143. data/tests/drivers/base/base_driver_test.rb +5 -5
  144. data/tests/drivers/base/common.rb +2 -12
  145. data/tests/drivers/ec2/buckets_test.rb +1 -1
  146. data/tests/drivers/ec2/images_test.rb +2 -2
  147. data/tests/drivers/ec2/instance_test.rb +6 -6
  148. data/tests/drivers/ec2/keys_test.rb +3 -3
  149. data/tests/drivers/ec2/realms_test.rb +2 -2
  150. data/tests/drivers/ec2/storage_snapshots_test.rb +1 -1
  151. data/tests/drivers/fgcp/common.rb +32 -0
  152. data/tests/drivers/fgcp/firewall_test.rb +70 -0
  153. data/tests/drivers/fgcp/hardware_profiles_test.rb +61 -0
  154. data/tests/drivers/fgcp/images_test.rb +46 -0
  155. data/tests/drivers/fgcp/provider_test.rb +27 -0
  156. data/tests/drivers/fgcp/realms_test.rb +53 -0
  157. data/tests/drivers/fgcp/storage_volumes_test.rb +58 -0
  158. data/tests/drivers/gogrid/images_test.rb +2 -2
  159. data/tests/drivers/gogrid/instances_test.rb +2 -2
  160. data/tests/drivers/gogrid/realms_test.rb +2 -2
  161. data/tests/drivers/mock/images_test.rb +4 -4
  162. data/tests/drivers/mock/instances_test.rb +9 -9
  163. data/tests/drivers/mock/keys_test.rb +3 -3
  164. data/tests/drivers/mock/realms_test.rb +2 -2
  165. data/tests/drivers/mock/storage_snapshots_test.rb +2 -2
  166. data/tests/drivers/mock/storage_volumes_test.rb +4 -4
  167. data/tests/drivers/models/instance_test.rb +2 -2
  168. data/tests/drivers/openstack/images_test.rb +2 -2
  169. data/tests/drivers/openstack/instances_test.rb +2 -3
  170. data/tests/drivers/openstack/keys_test.rb +1 -1
  171. data/tests/drivers/openstack/realms_test.rb +2 -11
  172. data/tests/drivers/rhevm/common.rb +33 -12
  173. data/tests/drivers/rhevm/images_test.rb +20 -12
  174. data/tests/drivers/rhevm/instance_test.rb +62 -46
  175. data/tests/drivers/rhevm/provider_test.rb +12 -6
  176. data/tests/drivers/rhevm/realms_test.rb +15 -9
  177. data/tests/ec2/query_parser_test.rb +1 -1
  178. data/tests/test_helper.rb +68 -12
  179. data/views/addresses/show.html.haml +1 -1
  180. data/views/buckets/show.html.haml +1 -1
  181. data/views/errors/{500.html.haml → common.html.haml} +0 -0
  182. data/views/errors/common.xml.haml +17 -0
  183. data/views/firewalls/index.xml.haml +2 -2
  184. data/views/firewalls/new.html.haml +2 -2
  185. data/views/images/show.html.haml +1 -1
  186. data/views/instances/run_command.html.haml +1 -1
  187. data/views/instances/show.html.haml +3 -3
  188. data/views/keys/index.html.haml +1 -0
  189. data/views/keys/show.html.haml +8 -4
  190. data/views/keys/show.xml.haml +3 -2
  191. data/views/load_balancers/new.html.haml +1 -1
  192. data/views/load_balancers/show.html.haml +2 -2
  193. data/views/metrics/show.html.haml +1 -1
  194. data/views/realms/index.html.haml +0 -2
  195. data/views/realms/show.html.haml +0 -4
  196. data/views/realms/show.xml.haml +0 -3
  197. data/views/storage_snapshots/index.html.haml +1 -1
  198. data/views/storage_snapshots/new.html.haml +1 -1
  199. data/views/storage_volumes/new.html.haml +2 -2
  200. data/views/storage_volumes/show.html.haml +3 -3
  201. metadata +90 -41
  202. data/views/errors/400.html.haml +0 -41
  203. data/views/errors/400.xml.haml +0 -3
  204. data/views/errors/401.html.haml +0 -26
  205. data/views/errors/401.xml.haml +0 -3
  206. data/views/errors/403.html.haml +0 -42
  207. data/views/errors/403.xml.haml +0 -9
  208. data/views/errors/404.html.haml +0 -28
  209. data/views/errors/404.xml.haml +0 -3
  210. data/views/errors/405.html.haml +0 -29
  211. data/views/errors/405.xml.haml +0 -5
  212. data/views/errors/409.html.haml +0 -47
  213. data/views/errors/409.xml.haml +0 -11
  214. data/views/errors/500.xml.haml +0 -13
  215. data/views/errors/501.html.haml +0 -44
  216. data/views/errors/501.xml.haml +0 -1
  217. data/views/errors/502.html.haml +0 -44
  218. data/views/errors/502.xml.haml +0 -1
  219. data/views/errors/504.html.haml +0 -43
  220. data/views/errors/504.xml.haml +0 -1
@@ -0,0 +1,43 @@
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::NetworkCreate < CIMI::Model::Base
17
+
18
+ ref :network_template, :required => true
19
+
20
+ def create(context)
21
+ validate!
22
+ if network_template.href?
23
+ template = network_template.find(context)
24
+ network_config = template.network_config.find(context)
25
+ forwarding_group = template.forwarding_group.find(context)
26
+ else
27
+ network_config = CIMI::Model::NetworkConfiguration.find(context.href_id(network_template.network_config.href, :network_configurations), context)
28
+ forwarding_group = CIMI::Model::ForwardingGroup.find(context.href_id(network_template.forwarding_group.href, :forwarding_groups), context)
29
+ end
30
+ params = {
31
+ :network_config => network_config,
32
+ :forwarding_group => forwarding_group,
33
+ :name => name,
34
+ :description => description,
35
+ :env => context # FIXME: We should not pass the context to the driver (!)
36
+ }
37
+ network = context.driver.create_network(context.credentials, params)
38
+ network.property = property if property
39
+ network.save
40
+ network
41
+ end
42
+
43
+ end
@@ -43,31 +43,31 @@ class CIMI::Model::NetworkPort < CIMI::Model::Base
43
43
 
44
44
  def self.create(request_body, context, type)
45
45
  input = (type == :xml)? XmlSimple.xml_in(request_body, {"ForceArray"=>false, "NormaliseSpace"=>2}) : JSON.parse(request_body)
46
- if input["vspTemplate"]["href"] #template by reference
47
- vsp_config, network = get_by_reference(input, context)
46
+ if input["networkPortTemplate"]["href"] #template by reference
47
+ network_port_config, network = get_by_reference(input, context)
48
48
  else
49
- if input["vspTemplate"]["vspConfig"]["href"] # configuration by reference
50
- vsp_config = CIMI::Model::VSPConfiguration.find(context.href_id(input["vspTemplate"]["vspConfig"]["href"],:vsp_configurations), context)
49
+ if input["networkPortTemplate"]["networkPortConfig"]["href"] # configuration by reference
50
+ network_port_config = CIMI::Model::NetworkPortConfiguration.find(context.href_id(input["networkPortTemplate"]["networkPortConfig"]["href"],:network_port_configurations), context)
51
51
  else #configuration by value
52
- vsp_config = get_by_value(request_body, type)
52
+ network_port_config = get_by_value(request_body, type)
53
53
  end
54
- network = CIMI::Model::Network.find(context.href_id(input["vspTemplate"]["network"]["href"], :networks), context)
54
+ network = CIMI::Model::Network.find(context.href_id(input["networkPortTemplate"]["network"]["href"], :networks), context)
55
55
  end
56
- params = {:vsp_config => vsp_config, :network => network, :name=>input["name"], :description=>input["description"], :env=>context}
56
+ params = {:network_port_config => network_port_config, :network => network, :name=>input["name"], :description=>input["description"], :env=>context}
57
57
  raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}") if params.has_value?(nil)
58
- context.driver.create_vsp(context.credentials, params)
58
+ context.driver.create_network_port(context.credentials, params)
59
59
  end
60
60
 
61
61
  def self.delete!(id, context)
62
- context.driver.delete_vsp(context.credentials, id)
62
+ context.driver.delete_network_port(context.credentials, id)
63
63
  end
64
64
 
65
65
  def perform(action, context, &block)
66
66
  begin
67
- if context.driver.send(:"#{action.name}_vsp", context.credentials, self.name)
67
+ if context.driver.send(:"#{action.name}_network_port", context.credentials, self.name)
68
68
  block.callback :success
69
69
  else
70
- raise "Operation #{action.name} failed to execute on the VSP #{self.name} "
70
+ raise "Operation #{action.name} failed to execute on the NetworkPort #{self.name} "
71
71
  end
72
72
  rescue => e
73
73
  block.callback :failure, e.message
@@ -91,19 +91,19 @@ class CIMI::Model::NetworkPort < CIMI::Model::Base
91
91
  private
92
92
 
93
93
  def self.get_by_reference(input, context)
94
- vsp_template = CIMI::Model::VSPTemplate.find(context.href_id(input["vspTemplate"]["href"], :vsp_templates), context)
95
- vsp_config = CIMI::Model::VSPConfiguration.find(context.href_id(vsp_template.vsp_config.href, :vsp_configurations), context)
96
- network = CIMI::Model::Network.find(context.href_id(vsp_template.network.href, :networks), context)
97
- return vsp_config, network
94
+ network_port_template = CIMI::Model::NetworkPortTemplate.find(context.href_id(input["networkPortTemplate"]["href"], :network_port_templates), context)
95
+ network_port_config = CIMI::Model::NetworkPortConfiguration.find(context.href_id(network_port_template.network_port_config.href, :network_port_configurations), context)
96
+ network = CIMI::Model::Network.find(context.href_id(network_port_template.network.href, :networks), context)
97
+ return network_port_config, network
98
98
  end
99
99
 
100
100
  def self.get_by_value(request_body, type)
101
101
  if type == :xml
102
102
  xml_arrays = XmlSimple.xml_in(request_body, {"NormaliseSpace"=>2})
103
- vsp_config = CIMI::Model::VSPConfiguration.from_xml(XmlSimple.xml_out(xml_arrays["vspTemplate"][0]["vspConfig"][0]))
103
+ network_port_config = CIMI::Model::NetworkPortConfiguration.from_xml(XmlSimple.xml_out(xml_arrays["networkPortTemplate"][0]["networkPortConfig"][0]))
104
104
  else
105
105
  json = JSON.parse(request_body)
106
- vsp_config = CIMI::Model::VSPConfiguration.from_json(JSON.generate(json["vspTemplate"]["vspConfig"]))
106
+ network_port_config = CIMI::Model::NetworkPortConfiguration.from_json(JSON.generate(json["networkPortTemplate"]["networkPortConfig"]))
107
107
  end
108
108
  end
109
109
  end
@@ -17,9 +17,8 @@ class CIMI::Model::NetworkTemplate < CIMI::Model::Base
17
17
 
18
18
  acts_as_root_entity
19
19
 
20
- href :network_config
21
-
22
- href :forwarding_group
20
+ ref :network_config, :required => true
21
+ ref :forwarding_group, :required => true
23
22
 
24
23
  array :operations do
25
24
  scalar :rel, :href
@@ -112,10 +112,18 @@ module CIMI
112
112
  end
113
113
 
114
114
  def parse(text, content_type)
115
- if content_type == "application/xml"
116
- from_xml(text)
115
+ if ["application/xml", "text/xml"].include? content_type
116
+ entity = from_xml(text)
117
+ entity.validate!(:xml)
118
+ entity
117
119
  elsif content_type == "application/json"
118
- from_json(text)
120
+ if text.kind_of? StringIO
121
+ entity = from_json(text.read)
122
+ else
123
+ entity = from_json(text)
124
+ end
125
+ entity.validate!(:json)
126
+ entity
119
127
  else
120
128
  raise "Can not parse content type #{content_type}"
121
129
  end
@@ -145,6 +153,10 @@ module CIMI
145
153
  xml["resourceURI"] = resource_uri
146
154
  XmlSimple.xml_out(xml, :root_name => xml_tag_name)
147
155
  end
156
+
157
+ def required_attributes
158
+ @schema.required_attributes
159
+ end
148
160
  end
149
161
 
150
162
  # END of class methods
@@ -172,6 +184,13 @@ module CIMI
172
184
  end
173
185
  end
174
186
 
187
+ def validate!(format=:xml)
188
+ failed_attrs = self.class.required_attributes.map do |attr|
189
+ attr.send("#{format}_name") unless attr.valid?(send(attr.name))
190
+ end.compact
191
+ raise CIMI::Model::ValidationError.new(failed_attrs, format) unless failed_attrs.empty?
192
+ end
193
+
175
194
  def base_id
176
195
  self.id || @base_id
177
196
  end
@@ -24,11 +24,13 @@ class CIMI::Model::Schema
24
24
  #
25
25
  class Attribute
26
26
  attr_reader :name, :xml_name, :json_name
27
+ attr_reader :required
27
28
 
28
29
  def initialize(name, opts = {})
29
30
  @name = name
30
31
  @xml_name = opts[:xml_name] || name.to_s.camelize(true)
31
32
  @json_name = opts[:json_name] || name.to_s.camelize(true)
33
+ @required = opts[:required] || false
32
34
  end
33
35
 
34
36
  def from_xml(xml, model)
@@ -50,6 +52,14 @@ class CIMI::Model::Schema
50
52
  def convert(value)
51
53
  value
52
54
  end
55
+
56
+ def required?
57
+ @required
58
+ end
59
+
60
+ def valid?(value)
61
+ !value.nil? and !value.to_s.empty?
62
+ end
53
63
  end
54
64
 
55
65
  class Scalar < Attribute
@@ -88,12 +98,9 @@ class CIMI::Model::Schema
88
98
 
89
99
  attr_accessor :schema
90
100
 
91
- def initialize(name, opts, &block)
101
+ def initialize(name, opts={}, &block)
92
102
  content = opts[:content]
93
103
  super(name, opts)
94
- if opts[:class]
95
- opts[:schema] = opts[:class].schema
96
- end
97
104
  if opts[:schema]
98
105
  if block_given?
99
106
  raise "Cannot provide :schema option and a block"
@@ -102,7 +109,7 @@ class CIMI::Model::Schema
102
109
  else
103
110
  @schema = CIMI::Model::Schema.new
104
111
  @schema.instance_eval(&block) if block_given?
105
- @schema.scalar(content, :text => :direct) if content
112
+ @schema.scalar(content, :text => :direct, :required => opts[:required]) if content
106
113
  end
107
114
  end
108
115
 
@@ -150,9 +157,69 @@ class CIMI::Model::Schema
150
157
  json
151
158
  end
152
159
 
160
+ def valid?(value)
161
+ @schema.required_attributes.all? { |a|
162
+ a.valid?(value.send(a.name))
163
+ }
164
+ end
165
+
166
+ def convert(value)
167
+ if @klass
168
+ @klass.new(value || {})
169
+ else
170
+ super(value)
171
+ end
172
+ end
173
+
153
174
  private
154
175
  def struct
155
- @struct_class ||= ::Struct.new(nil, *@schema.attribute_names)
176
+ if @klass
177
+ @klass
178
+ else
179
+ @struct_class ||= ::Struct.new(nil, *@schema.attribute_names)
180
+ end
181
+ end
182
+ end
183
+
184
+ class Ref < CIMI::Model::Schema::Struct
185
+
186
+ def initialize(name, opts={}, &block)
187
+ raise 'The :class attribute must be set' unless opts[:class]
188
+ refname = "#{opts[:class].name.split("::").last}Ref"
189
+ if CIMI::Model::const_defined?(refname)
190
+ @klass = CIMI::Model::const_get(refname)
191
+ else
192
+ @klass = Class.new(opts[:class]) do |m|
193
+ scalar :href
194
+
195
+ def ref_id(ctx)
196
+ # FIXME: We should use ctx's routes to split
197
+ # out the :id
198
+ href.split('/').last
199
+ end
200
+
201
+ def find(ctx)
202
+ klass.find(ref_id(ctx), ctx)
203
+ end
204
+
205
+ def klass
206
+ self.class.superclass
207
+ end
208
+ end
209
+ CIMI::Model::const_set(refname, @klass)
210
+ end
211
+ @klass.class_eval { def href?; !href.nil?; end }
212
+ opts[:schema] = @klass.schema
213
+ super(name, opts, &block)
214
+ end
215
+
216
+ # The 'ref' could be the reference to a CIMI entity or the full CIMI
217
+ # entity representation.
218
+ #
219
+ def valid?(value)
220
+ !value.href.nil? || @klass.schema.required_attributes.all? { |a|
221
+ a.valid?(value.send(a.name))
222
+ }
156
223
  end
157
224
  end
158
225
 
@@ -166,8 +233,15 @@ class CIMI::Model::Schema
166
233
  unless opts[:xml_name]
167
234
  opts[:xml_name] = name.to_s.singularize.camelize.uncapitalize
168
235
  end
236
+ if opts[:ref] && block_given?
237
+ raise "Provide only one of :ref or a block"
238
+ end
169
239
  super(name, opts)
170
- @struct = Struct.new(name, opts, &block)
240
+ if opts[:ref]
241
+ @struct = Ref.new(name, :class=> opts[:ref])
242
+ else
243
+ @struct = Struct.new(name, opts, &block)
244
+ end
171
245
  end
172
246
 
173
247
  def from_xml(xml, model)
@@ -337,6 +411,10 @@ class CIMI::Model::Schema
337
411
  @attributes.map { |a| a.name }
338
412
  end
339
413
 
414
+ def required_attributes
415
+ @attributes.select { |a| a.required? }
416
+ end
417
+
340
418
  #
341
419
  # The DSL
342
420
  #
@@ -355,7 +433,7 @@ class CIMI::Model::Schema
355
433
 
356
434
  def href(*args)
357
435
  opts = args.extract_opts!
358
- args.each { |arg| struct(arg, opts) { scalar :href } }
436
+ args.each { |arg| struct(arg, opts) { scalar :href, :required => opts[:required] } }
359
437
  end
360
438
 
361
439
  def text(*args)
@@ -375,6 +453,14 @@ class CIMI::Model::Schema
375
453
  add_attributes!([name, opts], Struct, &block)
376
454
  end
377
455
 
456
+ def ref(name, opts={})
457
+ unless opts[:class]
458
+ s = name.to_s.camelize.gsub(/Config$/, "Configuration")
459
+ opts[:class] = CIMI::Model::const_get(s)
460
+ end
461
+ add_attributes!([name, opts], Ref)
462
+ end
463
+
378
464
  def hash(name)
379
465
  add_attributes!([name, {}], Hash)
380
466
  end
@@ -0,0 +1,67 @@
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::System < CIMI::Model::Base
17
+
18
+ acts_as_root_entity
19
+
20
+ text :state
21
+
22
+ # collection :systems, :class => CIMI::Model::SystemSystem
23
+ # collection :machines, :class => CIMI::Model::SystemMachine
24
+ # collection :credentials, :class => CIMI::Model::SystemCredential
25
+ # collection :volumes, :class => CIMI::Model::SystemVolume
26
+ # collection :networks, :class => CIMI::Model::SystemNetwork
27
+ # collection :network_ports, :class => CIMI::Model::SystemNetworkPort
28
+ # collection :addresses, :class => CIMI::Model::SystemAddress
29
+ # collection :forwarding_groups, :class => CIMI::Model::SystemForwardingGroup
30
+
31
+ # array :meters do
32
+ # scalar :href
33
+ # end
34
+
35
+ # href :event_log
36
+
37
+ array :operations do
38
+ scalar :rel, :href
39
+ end
40
+
41
+ def self.find(id, context)
42
+ if id == :all
43
+ systems = context.driver.systems(context.credentials, {:env=>context})
44
+ else
45
+ systems = context.driver.systems(context.credentials, {:env=>context, :id=>id})
46
+ raise CIMI::Model::NotFound unless systems.first
47
+ systems.first
48
+ end
49
+ end
50
+
51
+ def perform(action, context, &block)
52
+ begin
53
+ if context.driver.send(:"#{action.name}_system", context.credentials, self.id.split("/").last)
54
+ block.callback :success
55
+ else
56
+ raise "Operation failed to execute on given System"
57
+ end
58
+ rescue => e
59
+ block.callback :failure, e.message
60
+ end
61
+ end
62
+
63
+ def self.delete!(id, context)
64
+ context.driver.destroy_system(context.credentials, id)
65
+ end
66
+
67
+ end
@@ -0,0 +1,63 @@
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::SystemTemplate < CIMI::Model::Base
17
+
18
+ acts_as_root_entity
19
+
20
+ array :component_descriptors do
21
+ text :name, :description
22
+ hash :properties
23
+ text :type
24
+ #component_template, comprises:
25
+ # struct :machine_template, :class => CIMI::Model::MachineTemplate
26
+ # struct :system_template, :class => CIMI::Model::SystemTemplate
27
+ # struct :credential_template, :class => CIMI::Model::CredentialTemplate
28
+ # struct :volume_template, :class => CIMI::Model::VolumeTemplate
29
+ # struct :network_template, :class => CIMI::Model::NetworkTemplate
30
+ # struct :network_port_template, :class => CIMI::Model::NetworkPortTemplate
31
+ # struct :forwarding_group_template, :class => CIMI::Model::ForwardingGroupTemplate
32
+ # struct :address_template, :class => CIMI::Model::AddressTemplate
33
+ text :quantity
34
+ end
35
+
36
+ # array :meter_templates do
37
+ # scalar :href
38
+ # end
39
+
40
+ # href :event_log_template
41
+
42
+ array :operations do
43
+ scalar :rel, :href
44
+ end
45
+
46
+ class << self
47
+ def find(id, context)
48
+ if id == :all
49
+ templates = context.driver.system_templates(context.credentials, {:env=>context})
50
+ else
51
+ templates = context.driver.system_templates(context.credentials, {:env=>context, :id=>id})
52
+ raise CIMI::Model::NotFound unless templates.first
53
+ templates.first
54
+ end
55
+ end
56
+
57
+ def delete!(id, context)
58
+ context.driver.destroy_system_template(context.credentials, id)
59
+ end
60
+
61
+ end
62
+
63
+ end