occi 2.2.2 → 2.3.0
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/.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
|