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.
- data/Rakefile +10 -12
- data/config/drivers/{aruba.yaml → arubacloud.yaml} +2 -2
- data/deltacloud-core.gemspec +4 -4
- data/lib/cimi/collections/address_templates.rb +1 -1
- data/lib/cimi/collections/addresses.rb +2 -2
- data/lib/cimi/collections/base.rb +1 -0
- data/lib/cimi/collections/credentials.rb +1 -1
- data/lib/cimi/collections/forwarding_group_templates.rb +1 -1
- data/lib/cimi/collections/forwarding_groups.rb +1 -1
- data/lib/cimi/collections/machine_configurations.rb +1 -1
- data/lib/cimi/collections/machine_images.rb +1 -1
- data/lib/cimi/collections/machine_templates.rb +1 -1
- data/lib/cimi/collections/machines.rb +2 -2
- data/lib/cimi/collections/network_configurations.rb +1 -1
- data/lib/cimi/collections/network_port_configurations.rb +1 -1
- data/lib/cimi/collections/network_port_templates.rb +1 -1
- data/lib/cimi/collections/network_ports.rb +1 -1
- data/lib/cimi/collections/network_templates.rb +1 -1
- data/lib/cimi/collections/networks.rb +1 -1
- data/lib/cimi/collections/volume_configurations.rb +1 -1
- data/lib/cimi/collections/volume_images.rb +1 -1
- data/lib/cimi/collections/volume_templates.rb +1 -1
- data/lib/cimi/collections/volumes.rb +1 -1
- data/lib/cimi/helpers/database_helper.rb +16 -61
- data/lib/cimi/helpers/filter_helper.rb +41 -0
- data/lib/cimi/helpers/select_helper.rb +62 -0
- data/lib/cimi/models.rb +21 -2
- data/lib/cimi/models/address.rb +9 -7
- data/lib/cimi/models/address_template.rb +4 -4
- data/lib/cimi/models/base.rb +62 -197
- data/lib/cimi/models/collection.rb +78 -70
- data/lib/cimi/models/disk.rb +15 -8
- data/lib/cimi/models/machine.rb +27 -29
- data/lib/cimi/models/machine_image.rb +10 -13
- data/lib/cimi/models/machine_template.rb +3 -3
- data/lib/cimi/models/resource.rb +190 -0
- data/lib/cimi/models/schema.rb +9 -0
- data/lib/cimi/models/volume.rb +10 -13
- data/lib/cimi/models/volume_configuration.rb +3 -3
- data/lib/cimi/models/volume_template.rb +2 -2
- data/lib/cimi/server.rb +1 -0
- data/lib/db.rb +15 -0
- data/lib/db/address_template.rb +15 -0
- data/lib/db/entity.rb +55 -0
- data/lib/db/machine_template.rb +15 -0
- data/lib/db/provider.rb +40 -0
- data/lib/db/volume_configuration.rb +15 -0
- data/lib/db/volume_template.rb +15 -0
- data/lib/deltacloud/collections/base.rb +1 -0
- data/lib/deltacloud/collections/instances.rb +2 -1
- data/lib/deltacloud/collections/storage_snapshots.rb +3 -1
- data/lib/deltacloud/core_ext/array.rb +5 -0
- data/lib/deltacloud/drivers/{aruba/aruba_driver.rb → arubacloud/arubacloud_driver.rb} +3 -6
- data/lib/deltacloud/drivers/digitalocean/digitalocean_driver.rb +48 -75
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +18 -3
- data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +25 -0
- data/lib/deltacloud/drivers/fgcp/fgcp_client.rb +1 -1
- data/lib/deltacloud/drivers/fgcp/fgcp_driver.rb +34 -14
- data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +2 -0
- data/lib/deltacloud/drivers/mock/mock_driver.rb +3 -3
- data/lib/deltacloud/drivers/openstack/openstack_driver.rb +93 -33
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +2 -0
- data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +2 -2
- data/lib/deltacloud/helpers/deltacloud_helper.rb +3 -1
- data/lib/deltacloud/helpers/rabbit_helper.rb +1 -2
- data/lib/deltacloud/models/address.rb +1 -0
- data/lib/deltacloud/models/blob.rb +1 -0
- data/lib/deltacloud/models/bucket.rb +1 -0
- data/lib/deltacloud/models/firewall.rb +1 -0
- data/lib/deltacloud/models/hardware_profile.rb +3 -1
- data/lib/deltacloud/models/image.rb +7 -0
- data/lib/deltacloud/models/instance.rb +12 -3
- data/lib/deltacloud/models/key.rb +1 -0
- data/lib/deltacloud/models/load_balancer.rb +1 -0
- data/lib/deltacloud/models/metric.rb +1 -0
- data/lib/deltacloud/models/realm.rb +10 -1
- data/lib/deltacloud/models/storage_snapshot.rb +1 -0
- data/lib/deltacloud/models/storage_volume.rb +2 -1
- data/lib/deltacloud/runner.rb +2 -1
- data/lib/deltacloud/server.rb +1 -0
- data/lib/deltacloud/version.rb +1 -1
- data/lib/deltacloud_rack.rb +4 -0
- data/tests/cimi/collections/machines_test.rb +80 -0
- data/tests/cimi/db/database_helper_test.rb +54 -99
- data/tests/cimi/db/db_helper.rb +2 -0
- data/tests/cimi/db/entity_test.rb +29 -0
- data/tests/cimi/model/collection_spec.rb +2 -2
- data/tests/cimi/model/credential_spec.rb +2 -2
- data/tests/cimi/model/machine_configuration_spec.rb +2 -2
- data/tests/cimi/model/machine_image_spec.rb +2 -2
- data/tests/cimi/model/machine_spec.rb +4 -4
- data/tests/cimi/model/machine_template_spec.rb +2 -2
- data/tests/cimi/model/volume_configuration_spec.rb +2 -2
- data/tests/cimi/model/volume_image_spec.rb +2 -2
- data/tests/cimi/model/volume_spec.rb +2 -2
- data/tests/cimi/model/volume_template_spec.rb +2 -2
- data/tests/cimi/spec_helper.rb +4 -0
- data/tests/deltacloud/collections/instances_collection_test.rb +3 -1
- data/tests/deltacloud/launcher_test.rb +3 -5
- data/tests/drivers/ec2/images_test.rb +7 -0
- data/tests/drivers/gogrid/images_test.rb +7 -0
- data/tests/drivers/openstack/instances_test.rb +8 -8
- data/tests/drivers/openstack/realms_test.rb +13 -13
- data/views/errors/403.xml.haml +2 -1
- data/views/images/show.html.haml +4 -1
- data/views/images/show.xml.haml +1 -0
- data/views/instances/new.html.haml +1 -1
- data/views/instances/show.html.haml +3 -0
- data/views/realms/index.html.haml +2 -0
- data/views/realms/show.html.haml +4 -0
- data/views/realms/show.xml.haml +3 -0
- metadata +19 -14
data/lib/cimi/models/disk.rb
CHANGED
|
@@ -24,11 +24,20 @@ class CIMI::Model::Disk < CIMI::Model::Base
|
|
|
24
24
|
|
|
25
25
|
def self.find(instance, machine_config, context, id=:all)
|
|
26
26
|
if id == :all
|
|
27
|
-
|
|
27
|
+
name = instance.id+"_disk_" #assuming one disk for now...
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
if machine_config
|
|
30
|
+
mach_config_disks = machine_config.disks
|
|
31
|
+
return mach_config_disks.map do |d|
|
|
32
|
+
self.new(
|
|
33
|
+
:id => context.machine_url(instance.id) + "/disks/#{name}#{d[:capacity]}",
|
|
34
|
+
:name => "#{name}#{d[:capacity]}",
|
|
35
|
+
:description => "Disk for Machine #{instance.id}",
|
|
36
|
+
:created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time).xmlschema,
|
|
37
|
+
:capacity => d[:capacity]
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
else
|
|
32
41
|
if instance.instance_profile.override? :storage
|
|
33
42
|
capacity = context.to_kibibyte(instance.instance_profile.storage, 'MB')
|
|
34
43
|
else
|
|
@@ -40,11 +49,9 @@ class CIMI::Model::Disk < CIMI::Model::Base
|
|
|
40
49
|
|
|
41
50
|
return [] unless capacity
|
|
42
51
|
|
|
43
|
-
name = instance.id+"_disk_#{capacity}" #assuming one disk for now...
|
|
44
|
-
|
|
45
52
|
[self.new(
|
|
46
|
-
:id => context.machine_url(instance.id)+"/disks/#{name}",
|
|
47
|
-
:name => name,
|
|
53
|
+
:id => context.machine_url(instance.id)+"/disks/#{name}#{capacity}",
|
|
54
|
+
:name => name + capacity.to_s,
|
|
48
55
|
:description => "Disk for Machine #{instance.id}",
|
|
49
56
|
:created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time).xmlschema,
|
|
50
57
|
:capacity => capacity
|
data/lib/cimi/models/machine.rb
CHANGED
|
@@ -52,6 +52,7 @@ class CIMI::Model::Machine < CIMI::Model::Base
|
|
|
52
52
|
|
|
53
53
|
def self.create_from_json(body, context)
|
|
54
54
|
json = JSON.parse(body)
|
|
55
|
+
additional_params={}
|
|
55
56
|
machine_template = json['machineTemplate']
|
|
56
57
|
if !machine_template['href'].nil?
|
|
57
58
|
template = current_db.machine_templates.first(:id => machine_template['href'].split('/').last)
|
|
@@ -65,21 +66,28 @@ class CIMI::Model::Machine < CIMI::Model::Base
|
|
|
65
66
|
additional_params[:keyname] = machine_template['credential']["href"].split('/').last
|
|
66
67
|
end
|
|
67
68
|
end
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
if machine_template.has_key? "initialState"
|
|
70
|
+
additional_params[:initial_state] = machine_template["initialState"].strip
|
|
71
|
+
end
|
|
70
72
|
additional_params[:name] = json['name'] if json['name']
|
|
73
|
+
additional_params[:realm_id] = json['realm'] if json['realm']
|
|
71
74
|
instance = context.driver.create_instance(context.credentials, image_id, {
|
|
72
75
|
:hwp_id => hardware_profile_id
|
|
73
76
|
}.merge(additional_params))
|
|
74
77
|
|
|
75
78
|
# Store attributes that are not supported by the backend cloud to local
|
|
76
79
|
# database:
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
machine = from_instance(instance, context)
|
|
81
|
+
machine.name = json['name'] || machine.name
|
|
82
|
+
machine.description = json['description']
|
|
83
|
+
machine.extract_properties!(json)
|
|
84
|
+
machine.save
|
|
85
|
+
machine
|
|
79
86
|
end
|
|
80
87
|
|
|
81
88
|
def self.create_from_xml(body, context)
|
|
82
89
|
xml = XmlSimple.xml_in(body)
|
|
90
|
+
additional_params = {}
|
|
83
91
|
if xml['machineTemplate'][0]['href']
|
|
84
92
|
template = current_db.machine_templates_dataset.first(:id => xml['machineTemplate'][0]['href'].split('/').last)
|
|
85
93
|
hardware_profile_id = template.machine_config.split('/').last
|
|
@@ -92,16 +100,23 @@ class CIMI::Model::Machine < CIMI::Model::Base
|
|
|
92
100
|
additional_params[:keyname] = machine_template['credential'][0]["href"].split('/').last
|
|
93
101
|
end
|
|
94
102
|
end
|
|
95
|
-
|
|
103
|
+
if xml["machineTemplate"][0].has_key? "initialState"
|
|
104
|
+
additional_params[:initial_state] = xml["machineTemplate"][0]["initialState"].first.strip
|
|
105
|
+
end
|
|
96
106
|
additional_params[:name] = xml['name'][0] if xml['name']
|
|
107
|
+
additional_params[:realm_id] = xml['realm'][0] if xml['realm']
|
|
97
108
|
instance = context.driver.create_instance(context.credentials, image_id, {
|
|
98
109
|
:hwp_id => hardware_profile_id
|
|
99
110
|
}.merge(additional_params))
|
|
100
111
|
|
|
101
112
|
# Store attributes that are not supported by the backend cloud to local
|
|
102
113
|
# database:
|
|
103
|
-
|
|
104
|
-
|
|
114
|
+
machine = from_instance(instance, context)
|
|
115
|
+
machine.name = xml['name'] || machine.name
|
|
116
|
+
machine.description = xml['description']
|
|
117
|
+
machine.extract_properties!(xml)
|
|
118
|
+
machine.save
|
|
119
|
+
machine
|
|
105
120
|
end
|
|
106
121
|
|
|
107
122
|
def perform(action, context, &block)
|
|
@@ -117,8 +132,8 @@ class CIMI::Model::Machine < CIMI::Model::Base
|
|
|
117
132
|
end
|
|
118
133
|
|
|
119
134
|
def self.delete!(id, context)
|
|
120
|
-
delete_attributes_for Instance.new(:id => id)
|
|
121
135
|
context.driver.destroy_instance(context.credentials, id)
|
|
136
|
+
new(:id => id).destroy
|
|
122
137
|
end
|
|
123
138
|
|
|
124
139
|
#returns the newly attach machine_volume
|
|
@@ -136,15 +151,9 @@ class CIMI::Model::Machine < CIMI::Model::Base
|
|
|
136
151
|
end
|
|
137
152
|
|
|
138
153
|
private
|
|
139
|
-
def self.from_instance(instance, context
|
|
154
|
+
def self.from_instance(instance, context)
|
|
140
155
|
cpu = memory = (instance.instance_profile.id == "opaque")? "n/a" : nil
|
|
141
156
|
machine_conf = CIMI::Model::MachineConfiguration.find(instance.instance_profile.name, context)
|
|
142
|
-
stored_attributes ||= load_attributes_for(instance)
|
|
143
|
-
if stored_attributes[:property]
|
|
144
|
-
stored_attributes[:property].merge!(convert_instance_properties(instance, context))
|
|
145
|
-
else
|
|
146
|
-
stored_attributes[:property] = convert_instance_properties(instance, context)
|
|
147
|
-
end
|
|
148
157
|
machine_spec = {
|
|
149
158
|
:name => instance.name,
|
|
150
159
|
:created => instance.launch_time.nil? ? Time.now.xmlschema : Time.parse(instance.launch_time.to_s).xmlschema,
|
|
@@ -155,9 +164,8 @@ class CIMI::Model::Machine < CIMI::Model::Base
|
|
|
155
164
|
:memory => memory || convert_instance_memory(instance.instance_profile, context),
|
|
156
165
|
:disks => { :href => context.machine_url(instance.id)+"/disks"},
|
|
157
166
|
:volumes => { :href=>context.machine_url(instance.id)+"/volumes"},
|
|
158
|
-
:operations => convert_instance_actions(instance, context)
|
|
159
|
-
|
|
160
|
-
}.merge(stored_attributes)
|
|
167
|
+
:operations => convert_instance_actions(instance, context)
|
|
168
|
+
}
|
|
161
169
|
if context.expand? :disks
|
|
162
170
|
machine_spec[:disks] = CIMI::Model::Disk.find(instance, machine_conf, context, :all)
|
|
163
171
|
end
|
|
@@ -166,8 +174,7 @@ class CIMI::Model::Machine < CIMI::Model::Base
|
|
|
166
174
|
end
|
|
167
175
|
machine_spec[:realm] = instance.realm_id if instance.realm_id
|
|
168
176
|
machine_spec[:machine_image] = { :href => context.machine_image_url(instance.image_id) } if instance.image_id
|
|
169
|
-
|
|
170
|
-
machine
|
|
177
|
+
self.new(machine_spec)
|
|
171
178
|
end
|
|
172
179
|
|
|
173
180
|
# FIXME: This will convert 'RUNNING' state to 'STARTED'
|
|
@@ -181,15 +188,6 @@ class CIMI::Model::Machine < CIMI::Model::Base
|
|
|
181
188
|
end
|
|
182
189
|
end
|
|
183
190
|
|
|
184
|
-
def self.convert_instance_properties(instance, context)
|
|
185
|
-
properties = {}
|
|
186
|
-
properties["machine_image"] = context.machine_image_url(instance.image_id)
|
|
187
|
-
if instance.respond_to? :keyname
|
|
188
|
-
properties["credential"] = context.credential_url(instance.keyname)
|
|
189
|
-
end
|
|
190
|
-
properties
|
|
191
|
-
end
|
|
192
|
-
|
|
193
191
|
def self.convert_instance_cpu(profile, context)
|
|
194
192
|
cpu_override = profile.overrides.find { |p, v| p == :cpu }
|
|
195
193
|
if cpu_override.nil?
|
|
@@ -38,17 +38,13 @@ class CIMI::Model::MachineImage < CIMI::Model::Base
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def self.from_image(image, context)
|
|
41
|
-
stored_attributes = load_attributes_for(image)
|
|
42
41
|
self.new(
|
|
43
42
|
:id => context.machine_image_url(image.id),
|
|
44
|
-
:name =>
|
|
45
|
-
:description =>
|
|
43
|
+
:name => image.id,
|
|
44
|
+
:description => image.description,
|
|
46
45
|
:state => image.state || 'UNKNOWN',
|
|
47
46
|
:type => "IMAGE",
|
|
48
|
-
:created => image.creation_time.nil? ? Time.now.xmlschema : Time.parse(image.creation_time.to_s).xmlschema
|
|
49
|
-
:image_location => (stored_attributes[:property] && stored_attributes[:property]['image_location']) ?
|
|
50
|
-
stored_attributes[:property].delete('image_location') : 'unknown',
|
|
51
|
-
:property => stored_attributes[:property]
|
|
47
|
+
:created => image.creation_time.nil? ? Time.now.xmlschema : Time.parse(image.creation_time.to_s).xmlschema
|
|
52
48
|
)
|
|
53
49
|
end
|
|
54
50
|
|
|
@@ -61,23 +57,24 @@ class CIMI::Model::MachineImage < CIMI::Model::Base
|
|
|
61
57
|
input = XmlSimple.xml_in(request_body.read, {"ForceArray"=>false,"NormaliseSpace"=>2})
|
|
62
58
|
raise 'imageLocation attribute is mandatory' unless input['imageLocation']
|
|
63
59
|
input['property'] ||= {}
|
|
64
|
-
input['property'].kind_of?(Array) ?
|
|
65
|
-
input['property'] << { 'image_location' => input['imageLocation'] } : input['property'].merge!('image_location' => input['imageLocation'])
|
|
66
60
|
else
|
|
67
61
|
input = JSON.parse(request_body.read)
|
|
68
62
|
raise 'imageLocation attribute is mandatory' unless input['imageLocation']
|
|
69
63
|
input['properties'] ||= []
|
|
70
|
-
input['properties'] << { 'image_location' => input['imageLocation'] }
|
|
71
64
|
end
|
|
72
65
|
params = {:id => context.href_id(input["imageLocation"], :machines), :name=>input["name"], :description=>input["description"]}
|
|
73
66
|
image = context.driver.create_image(context.credentials, params)
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
result = from_image(image, context)
|
|
68
|
+
result.name = input['name'] if input['name']
|
|
69
|
+
result.description = input['description'] if input['description']
|
|
70
|
+
result.extract_properties!(input)
|
|
71
|
+
result.save
|
|
72
|
+
result
|
|
76
73
|
end
|
|
77
74
|
|
|
78
75
|
def self.delete!(image_id, context)
|
|
79
76
|
context.driver.destroy_image(context.credentials, image_id)
|
|
80
|
-
|
|
77
|
+
new(:id => image_id).destroy
|
|
81
78
|
end
|
|
82
79
|
|
|
83
80
|
end
|
|
@@ -59,7 +59,7 @@ class CIMI::Model::MachineTemplate < CIMI::Model::Base
|
|
|
59
59
|
:description => json['description'],
|
|
60
60
|
:machine_config => json['machineConfig']['href'],
|
|
61
61
|
:machine_image => json['machineImage']['href'],
|
|
62
|
-
:ent_properties => json['properties'].to_json
|
|
62
|
+
:ent_properties => json['properties'] ? json['properties'].to_json : {}
|
|
63
63
|
)
|
|
64
64
|
from_db(new_template, context)
|
|
65
65
|
end
|
|
@@ -71,7 +71,7 @@ class CIMI::Model::MachineTemplate < CIMI::Model::Base
|
|
|
71
71
|
:description => xml['description'].first,
|
|
72
72
|
:machine_config => xml['machineConfig'].first['href'],
|
|
73
73
|
:machine_image => xml['machineImage'].first['href'],
|
|
74
|
-
:ent_properties => JSON::dump(xml['property'].inject({}) { |r, p| r[p['key']]=p['content']; r })
|
|
74
|
+
:ent_properties => xml['property'] ? JSON::dump(xml['property'].inject({}) { |r, p| r[p['key']]=p['content']; r }) : {}
|
|
75
75
|
)
|
|
76
76
|
from_db(new_template, context)
|
|
77
77
|
end
|
|
@@ -89,7 +89,7 @@ class CIMI::Model::MachineTemplate < CIMI::Model::Base
|
|
|
89
89
|
:description => model.description,
|
|
90
90
|
:machine_config => { :href => model.machine_config },
|
|
91
91
|
:machine_image => { :href => model.machine_image },
|
|
92
|
-
:property => JSON::parse(model.ent_properties),
|
|
92
|
+
:property => (model.ent_properties ? JSON::parse(model.ent_properties) : nil),
|
|
93
93
|
:created => Time.parse(model.created_at.to_s).xmlschema,
|
|
94
94
|
:operations => [
|
|
95
95
|
{ :href => context.destroy_machine_template_url(model.id), :rel => 'http://schemas.dmtf.org/cimi/1/action/delete' }
|
|
@@ -0,0 +1,190 @@
|
|
|
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_relative '../helpers/filter_helper'
|
|
17
|
+
require_relative '../helpers/select_helper'
|
|
18
|
+
|
|
19
|
+
module CIMI
|
|
20
|
+
module Model
|
|
21
|
+
class Resource
|
|
22
|
+
|
|
23
|
+
extend CIMI::Model::Schema::DSL
|
|
24
|
+
include CIMI::Helpers::SelectResourceMethods
|
|
25
|
+
include CIMI::Helpers::FilterResourceMethods
|
|
26
|
+
|
|
27
|
+
#
|
|
28
|
+
# We keep the values of the attributes in a hash
|
|
29
|
+
#
|
|
30
|
+
attr_reader :attribute_values
|
|
31
|
+
|
|
32
|
+
CMWG_NAMESPACE = "http://schemas.dmtf.org/cimi/1"
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# Factory methods
|
|
36
|
+
#
|
|
37
|
+
def initialize(values = {})
|
|
38
|
+
names = self.class.schema.attribute_names
|
|
39
|
+
@select_attrs = values[:select_attr_list] || []
|
|
40
|
+
# Make sure we always have the :id of the entity even
|
|
41
|
+
# the $select parameter is used and :id is filtered out
|
|
42
|
+
#
|
|
43
|
+
@base_id = values[:base_id] || values[:id]
|
|
44
|
+
@attribute_values = names.inject(OrderedHash.new) do |hash, name|
|
|
45
|
+
hash[name] = self.class.schema.convert(name, values[name])
|
|
46
|
+
hash
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# The CIMI::Model::Resource class methods
|
|
51
|
+
class << self
|
|
52
|
+
|
|
53
|
+
def base_schema
|
|
54
|
+
@schema ||= CIMI::Model::Schema.new
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def clone_base_schema
|
|
58
|
+
@schema_duped = true
|
|
59
|
+
@schema = superclass.base_schema.deep_clone
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def base_schema_cloned?
|
|
63
|
+
@schema_duped
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private :clone_base_schema, :base_schema_cloned?
|
|
67
|
+
|
|
68
|
+
# If the model is inherited by another model, we want to clone
|
|
69
|
+
# the base schema instead of using the parent model schema, which
|
|
70
|
+
# might be modified
|
|
71
|
+
#
|
|
72
|
+
def inherited(child)
|
|
73
|
+
child.instance_eval do
|
|
74
|
+
def schema
|
|
75
|
+
base_schema_cloned? ? @schema : clone_base_schema
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def add_attributes!(names, attr_klass, &block)
|
|
81
|
+
if self.respond_to? :schema
|
|
82
|
+
schema.add_attributes!(names, attr_klass, &block)
|
|
83
|
+
else
|
|
84
|
+
base_schema.add_attributes!(names, attr_klass, &block)
|
|
85
|
+
end
|
|
86
|
+
names.each do |name|
|
|
87
|
+
define_method(name) { self[name] }
|
|
88
|
+
define_method(:"#{name}=") { |newval| self[name] = newval }
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Return Array of links to current CIMI object
|
|
93
|
+
#
|
|
94
|
+
def all_uri(context)
|
|
95
|
+
self.all(context).map { |e| { :href => e.id } }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Construct a new object from the XML representation +xml+
|
|
99
|
+
def from_xml(text)
|
|
100
|
+
xml = XmlSimple.xml_in(text, :force_content => true)
|
|
101
|
+
model = self.new
|
|
102
|
+
@schema.from_xml(xml, model)
|
|
103
|
+
model
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Construct a new object
|
|
107
|
+
def from_json(text)
|
|
108
|
+
json = JSON::parse(text)
|
|
109
|
+
model = self.new
|
|
110
|
+
@schema.from_json(json, model)
|
|
111
|
+
model
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def parse(text, content_type)
|
|
115
|
+
if content_type == "application/xml"
|
|
116
|
+
from_xml(text)
|
|
117
|
+
elsif content_type == "application/json"
|
|
118
|
+
from_json(text)
|
|
119
|
+
else
|
|
120
|
+
raise "Can not parse content type #{content_type}"
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
#
|
|
125
|
+
# Serialize
|
|
126
|
+
#
|
|
127
|
+
|
|
128
|
+
def xml_tag_name
|
|
129
|
+
self.name.split("::").last
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def resource_uri
|
|
133
|
+
CMWG_NAMESPACE + "/" + self.name.split("::").last
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def to_json(model)
|
|
137
|
+
json = @schema.to_json(model)
|
|
138
|
+
json[:resourceURI] = resource_uri
|
|
139
|
+
JSON::unparse(json)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def to_xml(model)
|
|
143
|
+
xml = @schema.to_xml(model)
|
|
144
|
+
xml["xmlns"] = CMWG_NAMESPACE
|
|
145
|
+
xml["resourceURI"] = resource_uri
|
|
146
|
+
XmlSimple.xml_out(xml, :root_name => xml_tag_name)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# END of class methods
|
|
151
|
+
|
|
152
|
+
def [](a)
|
|
153
|
+
@attribute_values[a]
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def []=(a, v)
|
|
157
|
+
return @attribute_values.delete(a) if v.nil?
|
|
158
|
+
@attribute_values[a] = self.class.schema.convert(a, v)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Apply the $select options to all sub-collections and prepare then
|
|
162
|
+
# to serialize by setting correct :href and :id attributes.
|
|
163
|
+
#
|
|
164
|
+
def prepare
|
|
165
|
+
self.class.schema.collections.map { |coll| coll.name }.each do |n|
|
|
166
|
+
if @select_attrs.empty? or @select_attrs.include?(n)
|
|
167
|
+
self[n].href = "#{self.base_id}/#{n}" if !self[n].href
|
|
168
|
+
self[n].id = "#{self.base_id}/#{n}" if !self[n].entries.empty?
|
|
169
|
+
else
|
|
170
|
+
self[n] = nil
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def base_id
|
|
176
|
+
self.id || @base_id
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def to_json
|
|
180
|
+
self.class.to_json(self)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def to_xml
|
|
184
|
+
self.class.to_xml(self)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
end
|
|
190
|
+
end
|
data/lib/cimi/models/schema.rb
CHANGED
|
@@ -91,6 +91,9 @@ class CIMI::Model::Schema
|
|
|
91
91
|
def initialize(name, opts, &block)
|
|
92
92
|
content = opts[:content]
|
|
93
93
|
super(name, opts)
|
|
94
|
+
if opts[:class]
|
|
95
|
+
opts[:schema] = opts[:class].schema
|
|
96
|
+
end
|
|
94
97
|
if opts[:schema]
|
|
95
98
|
if block_given?
|
|
96
99
|
raise "Cannot provide :schema option and a block"
|
|
@@ -241,6 +244,7 @@ class CIMI::Model::Schema
|
|
|
241
244
|
end
|
|
242
245
|
|
|
243
246
|
def to_xml(model, xml)
|
|
247
|
+
return if model[name].nil?
|
|
244
248
|
model[name].prepare
|
|
245
249
|
if model[name].entries.empty?
|
|
246
250
|
xml[xml_name] = { "href" => model[name].href }
|
|
@@ -250,6 +254,7 @@ class CIMI::Model::Schema
|
|
|
250
254
|
end
|
|
251
255
|
|
|
252
256
|
def to_json(model, json)
|
|
257
|
+
return if model[name].nil?
|
|
253
258
|
model[name].prepare
|
|
254
259
|
if model[name].entries.empty?
|
|
255
260
|
json[json_name] = { "href" => model[name].href }
|
|
@@ -278,6 +283,10 @@ class CIMI::Model::Schema
|
|
|
278
283
|
@attributes = []
|
|
279
284
|
end
|
|
280
285
|
|
|
286
|
+
def deep_clone
|
|
287
|
+
Marshal::load(Marshal.dump(self))
|
|
288
|
+
end
|
|
289
|
+
|
|
281
290
|
def collections
|
|
282
291
|
@attributes.select { |a| a.is_a?(Collection) }
|
|
283
292
|
end
|