deltacloud-core 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. data/Rakefile +10 -12
  2. data/config/drivers/{aruba.yaml → arubacloud.yaml} +2 -2
  3. data/deltacloud-core.gemspec +4 -4
  4. data/lib/cimi/collections/address_templates.rb +1 -1
  5. data/lib/cimi/collections/addresses.rb +2 -2
  6. data/lib/cimi/collections/base.rb +1 -0
  7. data/lib/cimi/collections/credentials.rb +1 -1
  8. data/lib/cimi/collections/forwarding_group_templates.rb +1 -1
  9. data/lib/cimi/collections/forwarding_groups.rb +1 -1
  10. data/lib/cimi/collections/machine_configurations.rb +1 -1
  11. data/lib/cimi/collections/machine_images.rb +1 -1
  12. data/lib/cimi/collections/machine_templates.rb +1 -1
  13. data/lib/cimi/collections/machines.rb +2 -2
  14. data/lib/cimi/collections/network_configurations.rb +1 -1
  15. data/lib/cimi/collections/network_port_configurations.rb +1 -1
  16. data/lib/cimi/collections/network_port_templates.rb +1 -1
  17. data/lib/cimi/collections/network_ports.rb +1 -1
  18. data/lib/cimi/collections/network_templates.rb +1 -1
  19. data/lib/cimi/collections/networks.rb +1 -1
  20. data/lib/cimi/collections/volume_configurations.rb +1 -1
  21. data/lib/cimi/collections/volume_images.rb +1 -1
  22. data/lib/cimi/collections/volume_templates.rb +1 -1
  23. data/lib/cimi/collections/volumes.rb +1 -1
  24. data/lib/cimi/helpers/database_helper.rb +16 -61
  25. data/lib/cimi/helpers/filter_helper.rb +41 -0
  26. data/lib/cimi/helpers/select_helper.rb +62 -0
  27. data/lib/cimi/models.rb +21 -2
  28. data/lib/cimi/models/address.rb +9 -7
  29. data/lib/cimi/models/address_template.rb +4 -4
  30. data/lib/cimi/models/base.rb +62 -197
  31. data/lib/cimi/models/collection.rb +78 -70
  32. data/lib/cimi/models/disk.rb +15 -8
  33. data/lib/cimi/models/machine.rb +27 -29
  34. data/lib/cimi/models/machine_image.rb +10 -13
  35. data/lib/cimi/models/machine_template.rb +3 -3
  36. data/lib/cimi/models/resource.rb +190 -0
  37. data/lib/cimi/models/schema.rb +9 -0
  38. data/lib/cimi/models/volume.rb +10 -13
  39. data/lib/cimi/models/volume_configuration.rb +3 -3
  40. data/lib/cimi/models/volume_template.rb +2 -2
  41. data/lib/cimi/server.rb +1 -0
  42. data/lib/db.rb +15 -0
  43. data/lib/db/address_template.rb +15 -0
  44. data/lib/db/entity.rb +55 -0
  45. data/lib/db/machine_template.rb +15 -0
  46. data/lib/db/provider.rb +40 -0
  47. data/lib/db/volume_configuration.rb +15 -0
  48. data/lib/db/volume_template.rb +15 -0
  49. data/lib/deltacloud/collections/base.rb +1 -0
  50. data/lib/deltacloud/collections/instances.rb +2 -1
  51. data/lib/deltacloud/collections/storage_snapshots.rb +3 -1
  52. data/lib/deltacloud/core_ext/array.rb +5 -0
  53. data/lib/deltacloud/drivers/{aruba/aruba_driver.rb → arubacloud/arubacloud_driver.rb} +3 -6
  54. data/lib/deltacloud/drivers/digitalocean/digitalocean_driver.rb +48 -75
  55. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +18 -3
  56. data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +25 -0
  57. data/lib/deltacloud/drivers/fgcp/fgcp_client.rb +1 -1
  58. data/lib/deltacloud/drivers/fgcp/fgcp_driver.rb +34 -14
  59. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +2 -0
  60. data/lib/deltacloud/drivers/mock/mock_driver.rb +3 -3
  61. data/lib/deltacloud/drivers/openstack/openstack_driver.rb +93 -33
  62. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +2 -0
  63. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +2 -2
  64. data/lib/deltacloud/helpers/deltacloud_helper.rb +3 -1
  65. data/lib/deltacloud/helpers/rabbit_helper.rb +1 -2
  66. data/lib/deltacloud/models/address.rb +1 -0
  67. data/lib/deltacloud/models/blob.rb +1 -0
  68. data/lib/deltacloud/models/bucket.rb +1 -0
  69. data/lib/deltacloud/models/firewall.rb +1 -0
  70. data/lib/deltacloud/models/hardware_profile.rb +3 -1
  71. data/lib/deltacloud/models/image.rb +7 -0
  72. data/lib/deltacloud/models/instance.rb +12 -3
  73. data/lib/deltacloud/models/key.rb +1 -0
  74. data/lib/deltacloud/models/load_balancer.rb +1 -0
  75. data/lib/deltacloud/models/metric.rb +1 -0
  76. data/lib/deltacloud/models/realm.rb +10 -1
  77. data/lib/deltacloud/models/storage_snapshot.rb +1 -0
  78. data/lib/deltacloud/models/storage_volume.rb +2 -1
  79. data/lib/deltacloud/runner.rb +2 -1
  80. data/lib/deltacloud/server.rb +1 -0
  81. data/lib/deltacloud/version.rb +1 -1
  82. data/lib/deltacloud_rack.rb +4 -0
  83. data/tests/cimi/collections/machines_test.rb +80 -0
  84. data/tests/cimi/db/database_helper_test.rb +54 -99
  85. data/tests/cimi/db/db_helper.rb +2 -0
  86. data/tests/cimi/db/entity_test.rb +29 -0
  87. data/tests/cimi/model/collection_spec.rb +2 -2
  88. data/tests/cimi/model/credential_spec.rb +2 -2
  89. data/tests/cimi/model/machine_configuration_spec.rb +2 -2
  90. data/tests/cimi/model/machine_image_spec.rb +2 -2
  91. data/tests/cimi/model/machine_spec.rb +4 -4
  92. data/tests/cimi/model/machine_template_spec.rb +2 -2
  93. data/tests/cimi/model/volume_configuration_spec.rb +2 -2
  94. data/tests/cimi/model/volume_image_spec.rb +2 -2
  95. data/tests/cimi/model/volume_spec.rb +2 -2
  96. data/tests/cimi/model/volume_template_spec.rb +2 -2
  97. data/tests/cimi/spec_helper.rb +4 -0
  98. data/tests/deltacloud/collections/instances_collection_test.rb +3 -1
  99. data/tests/deltacloud/launcher_test.rb +3 -5
  100. data/tests/drivers/ec2/images_test.rb +7 -0
  101. data/tests/drivers/gogrid/images_test.rb +7 -0
  102. data/tests/drivers/openstack/instances_test.rb +8 -8
  103. data/tests/drivers/openstack/realms_test.rb +13 -13
  104. data/views/errors/403.xml.haml +2 -1
  105. data/views/images/show.html.haml +4 -1
  106. data/views/images/show.xml.haml +1 -0
  107. data/views/instances/new.html.haml +1 -1
  108. data/views/instances/show.html.haml +3 -0
  109. data/views/realms/index.html.haml +2 -0
  110. data/views/realms/show.html.haml +4 -0
  111. data/views/realms/show.xml.haml +3 -0
  112. metadata +19 -14
@@ -13,8 +13,26 @@
13
13
  # License for the specific language governing permissions and limitations
14
14
  # under the License.
15
15
  #
16
+
16
17
  module CIMI
17
- module Model; end
18
+ module Model
19
+ def self.register_as_root_entity!(klass, opts = {})
20
+ @root_entities ||= [CIMI::Model::CloudEntryPoint]
21
+ @root_entities << klass
22
+ name = klass.name.split("::").last.pluralize
23
+ unless CIMI::Model::CloudEntryPoint.href_defined?(name)
24
+ params = {}
25
+ if opts[:as]
26
+ params[:xml_name] = params[:json_name] = opts[:as]
27
+ end
28
+ CIMI::Model::CloudEntryPoint.send(:href, name.underscore, params)
29
+ end
30
+ end
31
+
32
+ def self.root_entities
33
+ @root_entities || []
34
+ end
35
+ end
18
36
  end
19
37
 
20
38
  require 'require_relative' if RUBY_VERSION < '1.9'
@@ -31,8 +49,9 @@ unless Deltacloud.test_environment?
31
49
  end
32
50
 
33
51
  require_relative './models/schema'
34
- require_relative './models/base'
52
+ require_relative './models/resource'
35
53
  require_relative './models/collection'
54
+ require_relative './models/base'
36
55
  require_relative './models/errors'
37
56
  require_relative './models/action'
38
57
  require_relative './models/machine_volume'
@@ -65,23 +65,26 @@ class CIMI::Model::Address < CIMI::Model::Base
65
65
  params = {:name=>input["name"], :description=>input["description"], :address_template=>address_template, :env=>context }
66
66
  raise CIMI::Model::BadRequest.new("Bad request - missing required parameters. Client sent: #{request_body} which produced #{params.inspect}") if params.has_value?(nil)
67
67
  address = context.driver.create_address(context.credentials, params)
68
- store_attributes_for(address, input)
69
- from_address(address, context)
68
+ result = from_address(address, context)
69
+ result.name = input['name'] if input['name']
70
+ result.description = input['description'] if input['description']
71
+ result.extract_properties!(input)
72
+ result.save
73
+ result
70
74
  end
71
75
 
72
76
  def self.delete!(id, context)
73
77
  context.driver.delete_address(context.credentials, id)
74
- delete_attributes_for(::Address.new(:id => id))
78
+ new(:id => id).destroy
75
79
  end
76
80
 
77
81
  private
78
82
 
79
83
  def self.from_address(address, context)
80
- stored_attributes = load_attributes_for(address)
81
84
  self.new(
82
- :name => stored_attributes[:name] || address.id,
85
+ :name => address.id,
83
86
  :id => context.address_url(address.id),
84
- :description => stored_attributes[:description] || "Address #{address.id}",
87
+ :description => "Address #{address.id}",
85
88
  :ip => address.id,
86
89
  :allocation => "dynamic", #or "static"
87
90
  :default_gateway => "unknown", #wtf
@@ -89,7 +92,6 @@ class CIMI::Model::Address < CIMI::Model::Base
89
92
  :protocol => protocol_from_address(address.id),
90
93
  :mask => "unknown",
91
94
  :resource => (address.instance_id) ? {:href=> context.machine_url(address.instance_id)} : nil,
92
- :property => stored_attributes[:property],
93
95
  :network => nil #unknown
94
96
  #optional:
95
97
  #:hostname =>
@@ -42,7 +42,7 @@ class CIMI::Model::AddressTemplate < CIMI::Model::Base
42
42
  if context.driver.respond_to? :address_templates
43
43
  context.driver.address_templates(context.credentials, {:env=>context})
44
44
  else
45
- current_db.address_teplates.map { |t| from_db(t, context) }
45
+ current_db.address_templates.map { |t| from_db(t, context) }
46
46
  end
47
47
  else
48
48
  if context.driver.respond_to? :address_template
@@ -67,7 +67,7 @@ class CIMI::Model::AddressTemplate < CIMI::Model::Base
67
67
  :dns => json['dns'],
68
68
  :protocol => json['protocol'],
69
69
  :mask => json['mask'],
70
- :ent_properties => json['properties'].to_json
70
+ :ent_properties => json['properties'] ? json['properties'].to_json : {}
71
71
  )
72
72
  from_db(new_template, context)
73
73
  end
@@ -85,7 +85,7 @@ class CIMI::Model::AddressTemplate < CIMI::Model::Base
85
85
  :dns => xml['dns'].first,
86
86
  :protocol => xml['protocol'].nil? ? nil : xml['protocol'].first,
87
87
  :mask => xml['mask'].first,
88
- :ent_properties => JSON::dump(xml['property'].inject({}) { |r, p| r[p['key']]=p['content']; r })
88
+ :ent_properties => xml['property'] ? JSON::dump(xml['property'].inject({}) { |r, p| r[p['key']]=p['content']; r }) : {}
89
89
  )
90
90
  from_db(new_template, context)
91
91
  end
@@ -108,7 +108,7 @@ class CIMI::Model::AddressTemplate < CIMI::Model::Base
108
108
  :dns => model.dns,
109
109
  :protocol => model.protocol,
110
110
  :mask => model.mask,
111
- :property => JSON::parse(model.ent_properties),
111
+ :property => (model.ent_properties ? JSON::parse(model.ent_properties) : nil),
112
112
  :operations => [
113
113
  { :href => context.destroy_address_template_url(model.id), :rel => 'http://schemas.dmtf.org/cimi/1/action/delete' }
114
114
  ]
@@ -15,6 +15,8 @@
15
15
 
16
16
  require 'xmlsimple'
17
17
 
18
+ require_relative '../helpers/database_helper'
19
+
18
20
  # The base class for any CIMI object that we either read from a request or
19
21
  # write as a response. This class handles serializing/deserializing XML and
20
22
  # JSON into a common form.
@@ -61,7 +63,7 @@ require 'xmlsimple'
61
63
  # [struct(name, opts, &block)]
62
64
  # A structured subobject; the block defines the schema of the
63
65
  # subobject. The +:content+ option can be used to specify the attribute
64
- # that should receive the content of hte corresponding XML element
66
+ # that should receive the content of the corresponding XML element
65
67
  # [array(name, opts, &block)]
66
68
  # An array of structured subobjects; the block defines the schema of
67
69
  # the subobjects.
@@ -71,221 +73,84 @@ require 'xmlsimple'
71
73
 
72
74
  module CIMI::Model
73
75
 
74
- def self.register_as_root_entity!(klass, opts = {})
75
- @root_entities ||= [CIMI::Model::CloudEntryPoint]
76
- @root_entities << klass
77
- name = klass.name.split("::").last.pluralize
78
- unless CIMI::Model::CloudEntryPoint.href_defined?(name)
79
- params = {}
80
- if opts[:as]
81
- params[:xml_name] = params[:json_name] = opts[:as]
82
- end
83
- CIMI::Model::CloudEntryPoint.send(:href, name.underscore, params)
84
- end
85
- end
86
-
87
- def self.root_entities
88
- @root_entities || []
89
- end
90
-
91
- end
92
-
93
- class CIMI::Model::Resource
76
+ class Base < Resource
94
77
 
95
- #
96
- # We keep the values of the attributes in a hash
97
- #
98
- attr_reader :attribute_values
78
+ # Extend the base model with database methods
79
+ extend Deltacloud::Helpers::Database
99
80
 
100
- CMWG_NAMESPACE = "http://schemas.dmtf.org/cimi/1"
81
+ # Extend the base model with the collection handling methods
82
+ extend CIMI::Model::CollectionMethods
101
83
 
102
- # Keep the list of all attributes in an array +attributes+; for each
103
- # attribute, we also define a getter and a setter to access/change the
104
- # value for that attribute
105
- class << self
84
+ # Include methods needed to handle the $select query parameter
85
+ include CIMI::Helpers::SelectBaseMethods
86
+ #
87
+ # Common attributes for all resources
88
+ #
89
+ text :id, :name, :description, :created, :updated
90
+ hash :property
106
91
 
107
- def <<(model)
108
- clone_base_schema unless base_schema_cloned?
109
- member_name = model.name.split("::").last
110
- if ::Struct.const_defined?("CIMI_#{member_name}")
111
- ::Struct.send(:remove_const, "CIMI_#{member_name}")
112
- end
113
- member_symbol = member_name.underscore.pluralize.to_sym
114
- members = CIMI::Model::Schema::Array.new(member_symbol)
115
- members.struct.schema.attributes = model.schema.attributes
116
- base_schema.attributes << members
92
+ def initialize(values = {})
93
+ super(values)
94
+ retrieve_entity
117
95
  end
118
96
 
119
- def base_schema
120
- @schema ||= CIMI::Model::Schema.new
97
+ def []=(a, v)
98
+ v = super
99
+ retrieve_entity if a == :id
100
+ v
121
101
  end
122
102
 
123
- def clone_base_schema
124
- @schema_duped = true
125
- @schema = Marshal::load(Marshal.dump(superclass.base_schema))
103
+ # Save the common attributes name, description, and properties to the
104
+ # database
105
+ def save
106
+ if @entity
107
+ @entity.name = name
108
+ @entity.description = description
109
+ @entity.properties = property
110
+ @entity.save
111
+ end
112
+ self
126
113
  end
127
114
 
128
- def base_schema_cloned?
129
- @schema_duped
115
+ # Destroy the database attributes for this model
116
+ def destroy
117
+ @entity.destroy
118
+ self
130
119
  end
131
120
 
132
- private :clone_base_schema, :base_schema_cloned?
133
-
134
- def inherited(child)
135
- child.instance_eval do
136
- def schema
137
- base_schema_cloned? ? @schema : clone_base_schema
121
+ # FIXME: Kludge around the fact that we do not have proper *Create
122
+ # objects that deserialize properties by themselves
123
+ def extract_properties!(data)
124
+ h = {}
125
+ if data['property']
126
+ # Data came from XML
127
+ h = data['property'].inject({}) do |r,v|
128
+ r[v['key']] = v['content']
129
+ r
138
130
  end
131
+ elsif data['properties']
132
+ h = data['properties']
139
133
  end
134
+ property ||= {}
135
+ property.merge!(h)
140
136
  end
141
137
 
142
- def add_attributes!(names, attr_klass, &block)
143
- if self.respond_to? :schema
144
- schema.add_attributes!(names, attr_klass, &block)
138
+ private
139
+
140
+ # Load an existing database entity for this object, or create a new one
141
+ def retrieve_entity
142
+ if self.id
143
+ @entity = Deltacloud::Database::Entity::retrieve(self)
144
+ if @entity.exists?
145
+ self.name = @entity.name
146
+ self.description = @entity.description
147
+ self.property ||= {}
148
+ self.property.merge!(@entity.properties)
149
+ end
145
150
  else
146
- base_schema.add_attributes!(names, attr_klass, &block)
151
+ @entity = nil
147
152
  end
148
- names.each do |name|
149
- define_method(name) { self[name] }
150
- define_method(:"#{name}=") { |newval| self[name] = newval }
151
- end
152
- end
153
-
154
- # Return Array of links to current CIMI object
155
- def all_uri(context)
156
- self.all(context).map { |e| { :href => e.id } }
157
- end
158
- end
159
-
160
- extend CIMI::Model::Schema::DSL
161
-
162
- def [](a)
163
- @attribute_values[a]
164
- end
165
-
166
- def []=(a, v)
167
- @attribute_values[a] = self.class.schema.convert(a, v)
168
- end
169
-
170
- # Prepare to serialize
171
- def prepare
172
- self.class.schema.collections.map { |coll| coll.name }.each do |n|
173
- self[n].href = "#{self.id}/#{n}" unless self[n].href
174
- self[n].id = "#{self.id}/#{n}" if !self[n].entries.empty?
175
- end
176
- end
177
-
178
- #
179
- # Factory methods
180
- #
181
- def initialize(values = {})
182
- names = self.class.schema.attribute_names
183
- @attribute_values = names.inject(OrderedHash.new) do |hash, name|
184
- hash[name] = self.class.schema.convert(name, values[name])
185
- hash
186
153
  end
187
- end
188
-
189
- # Construct a new object from the XML representation +xml+
190
- def self.from_xml(text)
191
- xml = XmlSimple.xml_in(text, :force_content => true)
192
- model = self.new
193
- @schema.from_xml(xml, model)
194
- model
195
- end
196
154
 
197
- # Construct a new object
198
- def self.from_json(text)
199
- json = JSON::parse(text)
200
- model = self.new
201
- @schema.from_json(json, model)
202
- model
203
155
  end
204
-
205
- def self.parse(text, content_type)
206
- if content_type == "application/xml"
207
- from_xml(text)
208
- elsif content_type == "application/json"
209
- from_json(text)
210
- else
211
- raise "Can not parse content type #{content_type}"
212
- end
213
- end
214
-
215
- #
216
- # Serialize
217
- #
218
-
219
- def self.xml_tag_name
220
- self.name.split("::").last
221
- end
222
-
223
- def self.resource_uri
224
- CMWG_NAMESPACE + "/" + self.name.split("::").last
225
- end
226
-
227
- def self.to_json(model)
228
- json = @schema.to_json(model)
229
- json[:resourceURI] = resource_uri
230
- JSON::unparse(json)
231
- end
232
-
233
- def self.to_xml(model)
234
- xml = @schema.to_xml(model)
235
- xml["xmlns"] = CMWG_NAMESPACE
236
- xml["resourceURI"] = resource_uri
237
- XmlSimple.xml_out(xml, :root_name => xml_tag_name)
238
- end
239
-
240
- def to_json
241
- self.class.to_json(self)
242
- end
243
-
244
- def to_xml
245
- self.class.to_xml(self)
246
- end
247
-
248
- def filter_by(filter_opts)
249
- return self if filter_opts.nil?
250
- return filter_attributes(filter_opts.split(',').map{ |a| a.intern }) if filter_opts.include? ','
251
- case filter_opts
252
- when /^([\w\_]+)$/ then filter_attributes([$1.intern])
253
- when /^([\w\_]+)\[(\d+\-\d+)\]$/ then filter_by_arr_range($1.intern, $2)
254
- when /^([\w\_]+)\[(\d+)\]$/ then filter_by_arr_index($1.intern, $2)
255
- else self
256
- end
257
- end
258
-
259
- def filter_by_arr_index(attr, filter)
260
- return self unless self.respond_to?(attr)
261
- self.class.new(attr => [self.send(attr)[filter.to_i]])
262
- end
263
-
264
- def filter_by_arr_range(attr, filter)
265
- return self unless self.respond_to?(attr)
266
- filter = filter.split('-').inject { |s,e| s.to_i..e.to_i }
267
- self.class.new(attr => self.send(attr)[filter])
268
- end
269
- end
270
-
271
- require_relative '../helpers/database_helper'
272
-
273
- class CIMI::Model::Base < CIMI::Model::Resource
274
- extend Deltacloud::Helpers::Database
275
- #
276
- # Common attributes for all resources
277
- #
278
- text :id, :name, :description, :created
279
-
280
- hash :property
281
-
282
- def filter_attributes(attr_list)
283
- attrs = attr_list.inject({}) do |result, attr|
284
- attr = attr.to_s.underscore
285
- result[attr.to_sym] = self.send(attr) if self.respond_to?(attr)
286
- result
287
- end
288
- self.class.new(attrs)
289
- end
290
-
291
156
  end
@@ -13,22 +13,56 @@
13
13
  # License for the specific language governing permissions and limitations
14
14
  # under the License.
15
15
 
16
+
16
17
  module CIMI::Model
17
18
  class Collection < Resource
18
19
 
19
20
  class << self
20
21
  attr_accessor :entry_name, :embedded
22
+
23
+ def xml_tag_name
24
+ 'Collection'
25
+ end
26
+
27
+ def generate(model_class, opts = {})
28
+ model_name = model_class.name.split("::").last
29
+ scope = opts[:scope] || CIMI::Model
30
+ coll_class = Class.new(CIMI::Model::Collection)
31
+ scope.const_set(:"#{model_name}Collection", coll_class)
32
+ coll_class.entry_name = model_name.underscore.pluralize.to_sym
33
+ coll_class.embedded = opts[:embedded]
34
+ entry_schema = model_class.schema
35
+ coll_class.instance_eval do
36
+ text :id
37
+ scalar :href
38
+ text :count
39
+ scalar :href if opts[:embedded]
40
+ array self.entry_name, :schema => entry_schema, :xml_name => model_name
41
+ array :operations do
42
+ scalar :rel, :href
43
+ end
44
+ end
45
+ coll_class
46
+ end
47
+
21
48
  end
22
49
 
23
50
  # Make sure the base schema gets cloned
24
- self.schema
51
+ schema
25
52
 
53
+ # You can initialize collection by passing the Hash representation of the
54
+ # collection or passing another Collection object.
55
+ #
26
56
  def initialize(values = {})
27
- if values[:entries]
28
- values[self.class.entry_name] = values.delete(:entries)
57
+ if values.kind_of?(Hash)
58
+ if values[:entries]
59
+ values[self.class.entry_name] = values.delete(:entries)
60
+ end
61
+ values[self.class.entry_name] ||= []
62
+ super(values)
63
+ else
64
+ super
29
65
  end
30
- values[self.class.entry_name] ||= []
31
- super(values)
32
66
  end
33
67
 
34
68
  def entries
@@ -53,91 +87,65 @@ module CIMI::Model
53
87
  end
54
88
 
55
89
  def [](a)
56
- a = entry_name if a == :entries
90
+ a = self.class.entry_name if a == :entries
57
91
  super(a)
58
92
  end
59
93
 
60
94
  def []=(a, v)
61
- a = entry_name if a == :entries
95
+ a = self.class.entry_name if a == :entries
62
96
  super(a, v)
63
97
  end
64
98
 
65
- def filter_attributes(attr_list)
99
+ def select_attributes(attr_list)
66
100
  self[self.class.entry_name] = entries.map do |e|
67
- e.filter_attributes(attr_list)
101
+ e.select_attributes(attr_list)
68
102
  end
69
103
  self
70
104
  end
71
-
72
- def self.xml_tag_name
73
- "Collection"
74
- end
75
-
76
- def self.generate(model_class, opts = {})
77
- model_name = model_class.name.split("::").last
78
- scope = opts[:scope] || CIMI::Model
79
- coll_class = Class.new(CIMI::Model::Collection)
80
- scope.const_set(:"#{model_name}Collection", coll_class)
81
- coll_class.entry_name = model_name.underscore.pluralize.to_sym
82
- coll_class.embedded = opts[:embedded]
83
- entry_schema = model_class.schema
84
- coll_class.instance_eval do
85
- text :id
86
- scalar :href
87
- text :count
88
- scalar :href if opts[:embedded]
89
- array self.entry_name, :schema => entry_schema, :xml_name => model_name
90
- array :operations do
91
- scalar :rel, :href
92
- end
93
- end
94
- coll_class
95
- end
96
105
  end
97
106
 
98
- #
99
- # We need to reopen Base and add some stuff to avoid circular dependencies
100
- #
101
- class Base
102
- #
103
- # Toplevel collections
104
- #
107
+ module CollectionMethods
105
108
 
106
- class << self
109
+ def collection_class=(klass)
110
+ @collection_class = klass
111
+ end
107
112
 
108
- attr_accessor :collection_class
113
+ def collection_class
114
+ @collection_class
115
+ end
109
116
 
110
- def acts_as_root_entity(opts = {})
111
- self.collection_class = Collection.generate(self)
112
- CIMI::Model.register_as_root_entity! self, opts
113
- end
117
+ def acts_as_root_entity(opts = {})
118
+ self.collection_class = Collection.generate(self)
119
+ CIMI::Model.register_as_root_entity! self, opts
120
+ end
114
121
 
115
- # Return a collection of entities
116
- def list(context)
117
- entries = find(:all, context)
118
- desc = "#{self.name.split("::").last} Collection for the #{context.driver.name.capitalize} driver"
119
- acts_as_root_entity unless collection_class
120
- id = context.send("#{collection_class.entry_name}_url")
121
- ops = []
122
- cimi_entity = collection_class.entry_name.to_s.singularize
123
- cimi_create = "create_#{cimi_entity}_url"
124
- dcloud_create = context.deltacloud_create_method_for(cimi_entity)
125
- if(context.respond_to?(cimi_create) &&
126
- context.driver.respond_to?(dcloud_create)) ||
127
- provides?(cimi_entity)
128
- url = context.send(cimi_create)
129
- ops << { :rel => "add", :href => url }
130
- end
131
- collection_class.new(:id => id,
132
- :count => entries.size,
133
- :entries => entries,
134
- :operations => ops,
135
- :description => desc)
122
+ # Return a collection of entities
123
+ def list(context)
124
+ entries = find(:all, context)
125
+ desc = "#{self.name.split("::").last} Collection for the #{context.driver.name.capitalize} driver"
126
+ acts_as_root_entity unless collection_class
127
+ id = context.send("#{collection_class.entry_name}_url")
128
+ ops = []
129
+ cimi_entity = collection_class.entry_name.to_s.singularize
130
+ cimi_create = "create_#{cimi_entity}_url"
131
+ dcloud_create = context.deltacloud_create_method_for(cimi_entity)
132
+ if(context.respond_to?(cimi_create) &&
133
+ context.driver.respond_to?(dcloud_create)) ||
134
+ provides?(cimi_entity)
135
+ url = context.send(cimi_create)
136
+ ops << { :rel => "add", :href => url }
136
137
  end
138
+ collection_class.new(:id => id,
139
+ :count => entries.size,
140
+ :entries => entries,
141
+ :operations => ops,
142
+ :description => desc)
137
143
  end
138
144
 
139
- def self.all(context)
140
- find(:all, context)
145
+ def all(context)
146
+ find :all, context
141
147
  end
148
+
142
149
  end
150
+
143
151
  end