occi 2.2.2 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/README.md +48 -18
- data/lib/occi/client.rb +54 -17
- data/lib/occi/collection.rb +25 -7
- data/lib/occi/core/action.rb +7 -0
- data/lib/occi/core/attribute_properties.rb +2 -2
- data/lib/occi/core/attributes.rb +2 -2
- data/lib/occi/core/category.rb +43 -23
- data/lib/occi/core/entity.rb +62 -67
- data/lib/occi/core/kind.rb +32 -5
- data/lib/occi/core/link.rb +14 -51
- data/lib/occi/core/mixin.rb +31 -5
- data/lib/occi/core/resource.rb +34 -33
- data/lib/occi/log.rb +16 -4
- data/lib/occi/model.rb +53 -47
- data/lib/occi/parser.rb +192 -65
- data/lib/occi/version.rb +1 -1
- data/spec/occi/client_spec.rb +12 -0
- data/spec/occi/log_spec.rb +2 -1
- data/spec/occi/model_spec.rb +43 -14
- data/spec/occi/parser_spec.rb +18 -3
- data/spec/occi/test.ova +0 -0
- metadata +6 -3
data/lib/occi/parser.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
require 'rubygems'
|
1
2
|
require 'json'
|
2
3
|
require 'nokogiri'
|
3
4
|
require 'hashie/mash'
|
5
|
+
require 'rubygems/package'
|
6
|
+
require 'zlib'
|
7
|
+
require 'tempfile'
|
4
8
|
require 'occi/collection'
|
5
9
|
require 'occi/log'
|
6
10
|
require 'occiantlr/OCCIANTLRParser'
|
@@ -8,58 +12,41 @@ require 'occiantlr/OCCIANTLRParser'
|
|
8
12
|
module OCCI
|
9
13
|
class Parser
|
10
14
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
$image_path = OCCI::Server.config[:one_image_tmp_dir] + '/' + params['file'][:filename]
|
18
|
-
FileUtils.cp(params['file'][:tempfile].path, $image_path)
|
19
|
-
end
|
20
|
-
|
21
|
-
# handle file upload in multipart requests
|
22
|
-
request.POST.values.each do |body|
|
23
|
-
if body.kind_of?(String)
|
24
|
-
parse_text(body)
|
25
|
-
elsif body.kind_of?(Hash)
|
26
|
-
if body['type'].include?('application/json')
|
27
|
-
# try to parse body as JSON object
|
28
|
-
parse_json(body.read)
|
29
|
-
elsif body['type'].include?('text/plain') # text/plain
|
30
|
-
parse_text(body.read)
|
31
|
-
end unless body['type'].nil?
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
=end
|
15
|
+
# Declaring Class constants for OVF XML namespaces (defined in OVF specification ver.1.1)
|
16
|
+
OVF ="http://schemas.dmtf.org/ovf/envelope/1"
|
17
|
+
RASD ="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
|
18
|
+
VSSD ="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData"
|
19
|
+
OVFENV="http://schemas.dmtf.org/ovf/environment/1"
|
20
|
+
CIM ="http://schemas.dmtf.org/wbem/wscim/1/common"
|
36
21
|
|
37
22
|
# Parses an OCCI message and extracts OCCI relevant information
|
38
23
|
# @param [String] media_type the media type of the OCCI message
|
39
24
|
# @param [String] body the body of the OCCI message
|
40
25
|
# @param [true, false] category for text/plain and text/occi media types information e.g. from the HTTP request location is needed to determine if the OCCI message includes a category or an entity
|
26
|
+
# @param [OCCI::Core::Resource,OCCI::Core::Link] entity_type entity type to use for parsing of text plain entities
|
41
27
|
# @param [Hash] header optional header of the OCCI message
|
42
28
|
# @return [Array<Array, OCCI::Collection>] list consisting of an array of locations and the OCCI object collection
|
43
|
-
def self.parse(media_type, body, category=false, header={ })
|
44
|
-
OCCI::Log.debug
|
29
|
+
def self.parse(media_type, body, category=false, entity_type=OCCI::Core::Resource, header={ })
|
30
|
+
OCCI::Log.debug '### Parsing request data to OCCI data structure ###'
|
45
31
|
collection = OCCI::Collection.new
|
46
32
|
|
47
33
|
locations = self.header_locations(header)
|
48
|
-
category ? collection = self.header_categories(header) : collection = self.header_entity(header) if locations.empty?
|
34
|
+
category ? collection = self.header_categories(header) : collection = self.header_entity(header, entity_type) if locations.empty?
|
49
35
|
|
50
36
|
case media_type
|
51
|
-
when 'text/occi'
|
52
37
|
when 'text/uri-list'
|
53
38
|
body.each_line { |line| locations << URI.parse(line) }
|
54
39
|
when 'text/plain', nil
|
55
40
|
locations.concat self.text_locations(body)
|
56
|
-
|
41
|
+
category ? collection = self.text_categories(body) : collection = self.text_entity(body, entity_type) if locations.empty? && collection.empty?
|
57
42
|
when 'application/occi+json', 'application/json'
|
58
43
|
collection = self.json(body)
|
59
44
|
when 'application/occi+xml', 'application/xml'
|
60
45
|
collection = self.xml(body)
|
61
|
-
|
62
|
-
|
46
|
+
when 'application/ovf', 'application/ovf+xml'
|
47
|
+
collection = self.ovf(body)
|
48
|
+
when 'application/ova'
|
49
|
+
collection = self.ova(body)
|
63
50
|
else
|
64
51
|
raise "Content Type not supported"
|
65
52
|
end
|
@@ -78,14 +65,14 @@ module OCCI
|
|
78
65
|
category_strings = header['HTTP_CATEGORY'].to_s.split(',')
|
79
66
|
category_strings.each do |cat|
|
80
67
|
category = OCCIANTLR::Parser.new('Category: ' + cat).category
|
81
|
-
collection.kinds.concat category.kinds.collect { |kind| OCCI::Core::Kind.new(kind) }
|
82
|
-
collection.mixins.concat category.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin) }
|
83
|
-
collection.actions.concat category.actions.collect { |action| OCCI::Core::Action.new(action) }
|
68
|
+
collection.kinds.concat category.kinds.collect { |kind| OCCI::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) }
|
69
|
+
collection.mixins.concat category.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) }
|
70
|
+
collection.actions.concat category.actions.collect { |action| OCCI::Core::Action.new(action.scheme, action.term, action.title, action.attributes) }
|
84
71
|
end
|
85
72
|
collection
|
86
73
|
end
|
87
74
|
|
88
|
-
def self.header_entity(header)
|
75
|
+
def self.header_entity(header, entity_type)
|
89
76
|
collection = OCCI::Collection.new
|
90
77
|
entity = Hashie::Mash.new
|
91
78
|
category_strings = header['HTTP_CATEGORY'].to_s.split(',')
|
@@ -97,14 +84,11 @@ module OCCI
|
|
97
84
|
entity.kind = categories.kinds.first.scheme + categories.kinds.first.term
|
98
85
|
entity.mixins = categories.mixins.collect { |mixin| mixin.scheme + mixin.term } if categories.mixins.any?
|
99
86
|
attribute_strings.each { |attr| entity.attributes!.merge!(OCCIANTLR::Parser.new('X-OCCI-Attribute: ' + attr).x_occi_attribute) }
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
if kind.entity_type == OCCI::Core::Link.name
|
104
|
-
entity.target = link.attributes.occi!.core!.target
|
105
|
-
entity.source = link.attributes.occi!.core!.source
|
87
|
+
if entity_type == OCCI::Core::Link
|
88
|
+
entity.target = link.attributes!.occi!.core!.target
|
89
|
+
entity.source = link.attributes!.occi!.core!.source
|
106
90
|
collection.links << OCCI::Core::Link.new(entity)
|
107
|
-
elsif
|
91
|
+
elsif entity_type == OCCI::Core::Resource
|
108
92
|
link_strings = header['HTTP_LINK'].to_s.split(',')
|
109
93
|
link_strings.each { |link| entity.links << OCCIANTLR::Parser.new('Link: ' + link).link }
|
110
94
|
collection.resources << OCCI::Core::Resource.new(entity)
|
@@ -121,14 +105,14 @@ module OCCI
|
|
121
105
|
text.each_line do |line|
|
122
106
|
category = OCCIANTLR::Parser.new(line).category
|
123
107
|
next if category.nil?
|
124
|
-
collection.kinds.concat category.kinds.collect { |kind| OCCI::Core::Kind.new(kind) }
|
125
|
-
collection.mixins.concat category.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin) }
|
126
|
-
collection.actions.concat category.actions.collect { |action| OCCI::Core::Action.new(action) }
|
108
|
+
collection.kinds.concat category.kinds.collect { |kind| OCCI::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) }
|
109
|
+
collection.mixins.concat category.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) }
|
110
|
+
collection.actions.concat category.actions.collect { |action| OCCI::Core::Action.new(action.scheme, action.term, action.title, action.attributes) }
|
127
111
|
end
|
128
112
|
collection
|
129
113
|
end
|
130
114
|
|
131
|
-
def self.text_entity(text)
|
115
|
+
def self.text_entity(text, entity_type)
|
132
116
|
collection = OCCI::Collection.new
|
133
117
|
entity = Hashie::Mash.new
|
134
118
|
links = []
|
@@ -140,14 +124,11 @@ module OCCI
|
|
140
124
|
end
|
141
125
|
entity.kind = categories.kinds.first.scheme + categories.kinds.first.term if categories.kinds.first
|
142
126
|
entity.mixins = categories.mixins.collect { |mixin| mixin.scheme + mixin.term } if entity.mixins
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
if OCCI::Model.get_by_id(entity.kind).entity_type == OCCI::Core::Link.name
|
147
|
-
entity.target = links.first.attributes.occi!.core!.target
|
148
|
-
entity.source = links.first.attributes.occi!.core!.source
|
127
|
+
if entity_type == OCCI::Core::Link
|
128
|
+
entity.target = links.first.attributes!.occi!.core!.target
|
129
|
+
entity.source = links.first.attributes!.occi!.core!.source
|
149
130
|
collection.links << OCCI::Core::Link.new(entity)
|
150
|
-
elsif
|
131
|
+
elsif entity_type == OCCI::Core::Resource
|
151
132
|
entity.links = links
|
152
133
|
collection.resources << OCCI::Core::Resource.new(entity)
|
153
134
|
end unless entity.kind.nil?
|
@@ -157,27 +138,173 @@ module OCCI
|
|
157
138
|
def self.json(json)
|
158
139
|
collection = OCCI::Collection.new
|
159
140
|
hash = Hashie::Mash.new(JSON.parse(json))
|
160
|
-
collection.kinds.concat hash.kinds.collect { |kind| OCCI::Core::Kind.new(kind) } if hash.kinds
|
161
|
-
collection.mixins.concat hash.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin) } if hash.mixins
|
162
|
-
collection.resources.concat hash.resources.collect { |resource| OCCI::Core::Resource.new(resource) } if hash.resources
|
163
|
-
collection.links.concat hash.links.collect { |link| OCCI::Core::Link.new(link) } if hash.links
|
141
|
+
collection.kinds.concat hash.kinds.collect { |kind| OCCI::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) } if hash.kinds
|
142
|
+
collection.mixins.concat hash.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) } if hash.mixins
|
143
|
+
collection.resources.concat hash.resources.collect { |resource| OCCI::Core::Resource.new(resource.kind, resource.mixins, resource.attributes, resource.links) } if hash.resources
|
144
|
+
collection.links.concat hash.links.collect { |link| OCCI::Core::Link.new(link.kind, link.mixins, link.attributes) } if hash.links
|
164
145
|
collection
|
165
146
|
end
|
166
147
|
|
167
148
|
def self.xml(xml)
|
168
149
|
collection = OCCI::Collection.new
|
169
150
|
hash = Hashie::Mash.new(Hash.from_xml(Nokogiri::XML(xml)))
|
170
|
-
collection.kinds.concat hash.kinds.collect { |kind| OCCI::Core::Kind.new(kind) } if hash.kinds
|
171
|
-
collection.mixins.concat hash.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin) } if hash.mixins
|
172
|
-
collection.resources.concat hash.resources.collect { |resource| OCCI::Core::Resource.new(resource) } if hash.resources
|
173
|
-
collection.links.concat hash.links.collect { |link| OCCI::Core::Link.new(link) } if hash.links
|
151
|
+
collection.kinds.concat hash.kinds.collect { |kind| OCCI::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) } if hash.kinds
|
152
|
+
collection.mixins.concat hash.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) } if hash.mixins
|
153
|
+
collection.resources.concat hash.resources.collect { |resource| OCCI::Core::Resource.new(resource.kind, resource.mixins, resource.attributes, resource.links) } if hash.resources
|
154
|
+
collection.links.concat hash.links.collect { |link| OCCI::Core::Link.new(link.kind, link.mixins, link.attributes) } if hash.links
|
174
155
|
collection
|
175
156
|
end
|
176
157
|
|
177
|
-
#def self.ovf(ovf)
|
178
|
-
# TODO: implement ovf / ova messages
|
179
|
-
#end
|
180
158
|
|
159
|
+
####################Helper method for calculation of storage size based on allocation units configured###########
|
160
|
+
def self.calculate_capacity_bytes(capacity, alloc_units_bytes)
|
161
|
+
total_capacity_bytes = alloc_units_bytes * capacity.to_i
|
162
|
+
total_capacity_bytes
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
def self.calculate_capacity_gb(capacity)
|
167
|
+
capacity_gb = capacity/(2**30)
|
168
|
+
capacity_gb
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
def self.alloc_units_bytes(alloc_units)
|
173
|
+
units = alloc_units.split('*')
|
174
|
+
#check units[1] is nil??
|
175
|
+
units[1].strip!
|
176
|
+
alloc_vars = units[1].split('^')
|
177
|
+
alloc_units_bytes = (alloc_vars[0].to_i**alloc_vars[1].to_i)
|
178
|
+
alloc_units_bytes
|
179
|
+
end
|
180
|
+
|
181
|
+
###############End of Helper methods for OVF Parsing ##################################################################
|
182
|
+
|
183
|
+
def self.ova(ova)
|
184
|
+
tar = Gem::Package::TarReader.new(StringIO.new(ova))
|
185
|
+
ovf = mf = cert = nil
|
186
|
+
files = { }
|
187
|
+
tar.each do |entry|
|
188
|
+
tempfile = Tempfile.new(entry.full_name)
|
189
|
+
tempfile.write(entry.read)
|
190
|
+
tempfile.close
|
191
|
+
files[entry.full_name] = tempfile.path
|
192
|
+
ovf = tempfile.path if entry.full_name.end_with? '.ovf'
|
193
|
+
mf = tempfile.path if entry.full_name.end_with? '.mf'
|
194
|
+
cert = tempfile.path if entry.full_name.end_with? '.cert'
|
195
|
+
end
|
196
|
+
|
197
|
+
File.read(mf).each_line do |line|
|
198
|
+
name = line.scan(/SHA1\(([^\)]*)\)= (.*)/).flatten.first
|
199
|
+
sha1 = line.scan(/SHA1\(([^\)]*)\)= (.*)/).flatten.last
|
200
|
+
puts Digest::SHA1.hexdigest(files[name])
|
201
|
+
raise "SHA1 mismatch for file #{name}" if Digest::SHA1.hexdigest(File.read(files[name])) != sha1
|
202
|
+
end if mf
|
203
|
+
|
204
|
+
raise 'no ovf file found' if ovf.nil?
|
205
|
+
|
206
|
+
self.ovf(File.read(ovf), files)
|
207
|
+
end
|
208
|
+
|
209
|
+
def self.ovf(ovf, files={ })
|
210
|
+
collection = OCCI::Collection.new
|
211
|
+
doc = Nokogiri::XML(ovf)
|
212
|
+
references = { }
|
213
|
+
|
214
|
+
doc.xpath('envelope:Envelope/envelope:References/envelope:File', 'envelope' => "#{Parser::OVF}").each do |file|
|
215
|
+
href = URI.parse(file.attributes['href'].to_s)
|
216
|
+
if href.relative?
|
217
|
+
references[file.attributes['id'].to_s] = 'file://' + files[href.to_s] if files[href.to_s]
|
218
|
+
else
|
219
|
+
references[file.attributes['id'].to_s] = href
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
doc.xpath('envelope:Envelope/envelope:DiskSection/envelope:Disk', 'envelope' => "#{Parser::OVF}").each do |disk|
|
224
|
+
storage = OCCI::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#storage')
|
225
|
+
if disk.attributes['fileRef']
|
226
|
+
storagelink = OCCI::Core::Link.new("http://schemas.ogf.org/occi/infrastructure#storagelink")
|
227
|
+
storagelink.attributes.occi!.core!.title = disk.attributes['fileRef'].to_s
|
228
|
+
storagelink.attributes.occi!.core!.target = references[disk.attributes['fileRef'].to_s]
|
229
|
+
storage.attributes.occi!.core!.title = disk.attributes['diskId'].to_s
|
230
|
+
storage.links << storagelink
|
231
|
+
else
|
232
|
+
#OCCI accepts storage size in GB
|
233
|
+
#OVF ver 1.1: The capacity of a virtual disk shall be specified by the ovf:capacity attribute with an xs:long integer
|
234
|
+
#value. The default unit odf allocation shall be bytes. The optional string attribute
|
235
|
+
#ovf:capacityAllocationUnits may be used to specify a particular unit of allocation.
|
236
|
+
alloc_units = disk.attributes['capacityAllocationUnits'].to_s
|
237
|
+
if alloc_units.empty?
|
238
|
+
# The capacity is defined in bytes , convert to GB and pass it to OCCI
|
239
|
+
capacity = disk.attributes['capacity'].to_s
|
240
|
+
capacity =capacity.to_i
|
241
|
+
else
|
242
|
+
alloc_unit_bytes = self.alloc_units_bytes(alloc_units)
|
243
|
+
capacity = self.calculate_capacity_bytes(disk.attributes['capacity'].to_s, alloc_unit_bytes)
|
244
|
+
end
|
245
|
+
capacity_gb = self.calculate_capacity_gb(capacity)
|
246
|
+
OCCI::Log.debug('capacity in gb ' + capacity_gb.to_s)
|
247
|
+
storage.attributes.occi!.storage!.size = capacity_gb.to_s if capacity_gb
|
248
|
+
storage.attributes.occi!.core!.title = disk.attributes['diskId'].to_s if disk.attributes['diskId']
|
249
|
+
end
|
250
|
+
collection.resources << storage
|
251
|
+
end
|
252
|
+
|
253
|
+
doc.xpath('envelope:Envelope/envelope:NetworkSection/envelope:Network', 'envelope' => "#{Parser::OVF}").each do |nw|
|
254
|
+
network = OCCI::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#network')
|
255
|
+
network.attributes.occi!.core!.title = nw.attributes['name'].to_s
|
256
|
+
collection.resources << network
|
257
|
+
end
|
258
|
+
|
259
|
+
# Iteration through all the virtual hardware sections,and a sub-iteration on each Item defined in the Virtual Hardware section
|
260
|
+
doc.xpath('envelope:Envelope/envelope:VirtualSystem', 'envelope' => "#{Parser::OVF}").each do |virtsys|
|
261
|
+
compute = OCCI::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#compute')
|
262
|
+
|
263
|
+
doc.xpath('envelope:Envelope/envelope:VirtualSystem/envelope:VirtualHardwareSection', 'envelope' => "#{Parser::OVF}").each do |virthwsec|
|
264
|
+
compute.attributes.occi!.core!.summary = virthwsec.xpath("item:Info/text()", 'item' => "#{Parser::RASD}").to_s
|
265
|
+
|
266
|
+
virthwsec.xpath('envelope:Item', 'envelope' => "#{Parser::OVF}").each do |resource_alloc|
|
267
|
+
resType = resource_alloc.xpath("item:ResourceType/text()", 'item' => "#{Parser::RASD}")
|
268
|
+
case resType.to_s
|
269
|
+
# 4 is the ResourceType for memory in the CIM_ResourceAllocationSettingData
|
270
|
+
when "4" then
|
271
|
+
compute.attributes.occi!.compute!.memory = resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{Parser::RASD}").to_s.to_i
|
272
|
+
# 3 is the ResourceType for processor in the CIM_ResourceAllocationSettingData
|
273
|
+
when "3" then
|
274
|
+
compute.attributes.occi!.compute!.cores = resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{Parser::RASD}").to_s.to_i
|
275
|
+
when "10" then
|
276
|
+
networkinterface = OCCI::Core::Link.new('http://schemas.ogf.org/occi/infrastructure#networkinterface')
|
277
|
+
networkinterface.attributes.occi!.core!.title = resource_alloc.xpath("item:ElementName/text()", 'item' => "#{Parser::RASD}").to_s
|
278
|
+
id = resource_alloc.xpath("item:Connection/text()", 'item' => "#{Parser::RASD}").to_s
|
279
|
+
network = collection.resources.select { |resource| resource.attributes.occi!.core!.title == id }.first
|
280
|
+
raise "Network with id #{id} not found" unless network
|
281
|
+
networkinterface.attributes.occi!.core!.target = network.location
|
282
|
+
when "17" then
|
283
|
+
storagelink = OCCI::Core::Link.new("http://schemas.ogf.org/occi/infrastructure#storagelink")
|
284
|
+
storagelink.attributes.occi!.core!.title = resource_alloc.xpath("item:ElementName/text()", 'item' => "#{Parser::RASD}").to_s
|
285
|
+
# extract the mountpoint
|
286
|
+
host_resource = resource_alloc.xpath("item:HostResource/text()", 'item' => "#{Parser::RASD}").to_s
|
287
|
+
if host_resource.start_with? 'ovf:/disk/'
|
288
|
+
id = host_resource.gsub('ovf:/disk/', '')
|
289
|
+
storage = collection.resources.select { |resource| resource.attributes.occi!.core!.title == id }.first
|
290
|
+
raise "Disk with id #{id} not found" unless storage
|
291
|
+
storagelink.attributes.occi!.core!.target = storage.location
|
292
|
+
elsif host_resource.start_with? 'ovf:/file/'
|
293
|
+
id = host_resource.gsub('ovf:/file/','')
|
294
|
+
storagelink.attributes.occi!.core!.target = references[id]
|
295
|
+
end
|
296
|
+
compute.links << storagelink
|
297
|
+
end
|
298
|
+
##Add the cpu architecture
|
299
|
+
#system_sec = virthwsec.xpath('envelope:System', 'envelope' => "#{Parser::OVF}")
|
300
|
+
#virtsys_type = system_sec.xpath('vssd_:VirtualSystemType/text()', 'vssd_' => "#{Parser::VSSD}")
|
301
|
+
#compute.attributes.occi!.compute!.architecture = virtsys_type
|
302
|
+
end
|
303
|
+
end
|
304
|
+
collection.resources << compute
|
305
|
+
end
|
306
|
+
collection
|
307
|
+
end
|
181
308
|
end
|
182
309
|
|
183
310
|
end
|
data/lib/occi/version.rb
CHANGED
data/spec/occi/log_spec.rb
CHANGED
data/spec/occi/model_spec.rb
CHANGED
@@ -4,23 +4,52 @@ require 'occi/model'
|
|
4
4
|
describe "Model" do
|
5
5
|
|
6
6
|
it "initializes Core Model successfully" do
|
7
|
-
OCCI::Model.
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
model = OCCI::Model.new
|
8
|
+
model.get_by_id('http://schemas.ogf.org/occi/core#entity').should be_kind_of OCCI::Core::Kind
|
9
|
+
model.get_by_id('http://schemas.ogf.org/occi/core#resource').should be_kind_of OCCI::Core::Kind
|
10
|
+
model.get_by_id('http://schemas.ogf.org/occi/core#link').should be_kind_of OCCI::Core::Kind
|
11
11
|
end
|
12
12
|
|
13
13
|
it "initializes Infrastructure Model successfully" do
|
14
|
-
OCCI::Model.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
14
|
+
model = OCCI::Model.new
|
15
|
+
model.register_infrastructure
|
16
|
+
model.get_by_id('http://schemas.ogf.org/occi/infrastructure#compute').should be_kind_of OCCI::Core::Kind
|
17
|
+
model.get_by_id('http://schemas.ogf.org/occi/infrastructure#os_tpl').should be_kind_of OCCI::Core::Mixin
|
18
|
+
model.get_by_id('http://schemas.ogf.org/occi/infrastructure#resource_tpl').should be_kind_of OCCI::Core::Mixin
|
19
|
+
model.get_by_id('http://schemas.ogf.org/occi/infrastructure#network').should be_kind_of OCCI::Core::Kind
|
20
|
+
model.get_by_id('http://schemas.ogf.org/occi/infrastructure/network#ipnetwork').should be_kind_of OCCI::Core::Mixin
|
21
|
+
model.get_by_id('http://schemas.ogf.org/occi/infrastructure#networkinterface').should be_kind_of OCCI::Core::Kind
|
22
|
+
model.get_by_id('http://schemas.ogf.org/occi/infrastructure/networkinterface#ipnetworkinterface').should be_kind_of OCCI::Core::Mixin
|
23
|
+
model.get_by_id('http://schemas.ogf.org/occi/infrastructure#storage').should be_kind_of OCCI::Core::Kind
|
24
|
+
model.get_by_id('http://schemas.ogf.org/occi/infrastructure#storagelink').should be_kind_of OCCI::Core::Kind
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns all registered categories" do
|
28
|
+
model = OCCI::Model.new
|
29
|
+
collection = model.get
|
30
|
+
collection.kind_of? OCCI::Collection
|
31
|
+
collection.kinds.should have(3).kinds
|
32
|
+
collection.mixins.should be_empty
|
33
|
+
collection.actions.should be_empty
|
34
|
+
collection.resources.should be_empty
|
35
|
+
collection.links.should be_empty
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns categories with filter" do
|
39
|
+
model = OCCI::Model.new
|
40
|
+
model.register_infrastructure
|
41
|
+
compute = OCCI::Core::Kind.new('http://schemas.ogf.org/occi/infrastructure#','compute')
|
42
|
+
ipnetwork = OCCI::Core::Mixin.new('http://schemas.ogf.org/occi/infrastructure/network#','ipnetwork')
|
43
|
+
filter = OCCI::Collection.new
|
44
|
+
filter.kinds << compute
|
45
|
+
filter.mixins << ipnetwork
|
46
|
+
collection = model.get(filter)
|
47
|
+
collection.kind_of? OCCI::Collection
|
48
|
+
collection.kinds.first.attributes.should be_kind_of OCCI::Core::AttributeProperties
|
49
|
+
collection.mixins.first.attributes.should be_kind_of OCCI::Core::AttributeProperties
|
50
|
+
collection.actions.should be_empty
|
51
|
+
collection.resources.should be_empty
|
52
|
+
collection.links.should be_empty
|
24
53
|
end
|
25
54
|
|
26
55
|
end
|
data/spec/occi/parser_spec.rb
CHANGED
@@ -5,8 +5,23 @@ describe "Parser" do
|
|
5
5
|
|
6
6
|
it "should parse OCCI message with entity in text plain format" do
|
7
7
|
media_type = 'text/plain'
|
8
|
-
body
|
9
|
-
|
10
|
-
|
8
|
+
body = %Q|Category: compute; scheme="http://schemas.ogf.org/occi/infrastructure#"; class="kind"\nX-OCCI-Attribute: occi.compute.cores=2|
|
9
|
+
locations, collection = OCCI::Parser.parse(media_type, body)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should parse an OVA container" do
|
13
|
+
media_type = 'application/ova'
|
14
|
+
body = File.read('spec/occi/test.ova')
|
15
|
+
locations, collection = OCCI::Parser.parse(media_type, body)
|
16
|
+
storage_resources = collection.resources.select { |resource| resource.kind == 'http://schemas.ogf.org/occi/infrastructure#storage' }
|
17
|
+
storage_resources.should have(1).storage_resource
|
18
|
+
storage_resources.first.attributes.occi!.core!.title.should == 'lamp'
|
19
|
+
network_resources = collection.resources.select { |resource| resource.kind == 'http://schemas.ogf.org/occi/infrastructure#network' }
|
20
|
+
network_resources.should have(1).network_resource
|
21
|
+
network_resources.first.attributes.occi!.core!.title.should == 'VM Network'
|
22
|
+
compute_resources = collection.resources.select { |resource| resource.kind == 'http://schemas.ogf.org/occi/infrastructure#compute' }
|
23
|
+
compute_resources.should have(1).compute_resource
|
24
|
+
compute_resources.first.attributes.occi!.compute!.cores.should == 1
|
25
|
+
compute_resources.first.attributes.occi!.compute!.memory.should == 256
|
11
26
|
end
|
12
27
|
end
|