occi-core 4.1.3 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +8 -0
  3. data/README.md +49 -17
  4. data/lib/occi/collection.rb +37 -21
  5. data/lib/occi/core/action.rb +5 -5
  6. data/lib/occi/core/action_instance.rb +45 -3
  7. data/lib/occi/core/actions.rb +2 -1
  8. data/lib/occi/core/attributes.rb +253 -73
  9. data/lib/occi/core/categories.rb +1 -0
  10. data/lib/occi/core/category.rb +25 -8
  11. data/lib/occi/core/entities.rb +1 -0
  12. data/lib/occi/core/entity.rb +51 -74
  13. data/lib/occi/core/kind.rb +15 -11
  14. data/lib/occi/core/kinds.rb +1 -1
  15. data/lib/occi/core/link.rb +14 -15
  16. data/lib/occi/core/links.rb +1 -1
  17. data/lib/occi/core/mixin.rb +5 -5
  18. data/lib/occi/core/mixins.rb +2 -2
  19. data/lib/occi/core/properties.rb +90 -12
  20. data/lib/occi/core/resource.rb +7 -3
  21. data/lib/occi/core/resources.rb +2 -2
  22. data/lib/occi/errors/attribute_definitions_converted_error.rb +5 -0
  23. data/lib/occi/errors/attribute_missing_error.rb +5 -0
  24. data/lib/occi/errors/attribute_name_invalid_error.rb +5 -0
  25. data/lib/occi/errors/attribute_not_defined_error.rb +5 -0
  26. data/lib/occi/errors/attribute_property_type_error.rb +5 -0
  27. data/lib/occi/errors/attribute_type_error.rb +5 -0
  28. data/lib/occi/errors/kind_not_defined_error.rb +5 -0
  29. data/lib/occi/errors/parser_input_error.rb +5 -0
  30. data/lib/occi/errors/parser_type_error.rb +5 -0
  31. data/lib/occi/errors.rb +1 -0
  32. data/lib/occi/extensions/hashie.rb +25 -0
  33. data/lib/occi/helpers/comparators/action_instance.rb +22 -0
  34. data/lib/occi/helpers/comparators/attributes.rb +22 -0
  35. data/lib/occi/helpers/comparators/categories.rb +22 -0
  36. data/lib/occi/helpers/comparators/category.rb +22 -0
  37. data/lib/occi/helpers/comparators/collection.rb +40 -0
  38. data/lib/occi/helpers/comparators/entities.rb +22 -0
  39. data/lib/occi/helpers/comparators/entity.rb +22 -0
  40. data/lib/occi/helpers/comparators/properties.rb +26 -0
  41. data/lib/occi/helpers/comparators.rb +1 -0
  42. data/lib/occi/infrastructure/compute.rb +11 -9
  43. data/lib/occi/infrastructure/network.rb +27 -27
  44. data/lib/occi/infrastructure/networkinterface.rb +22 -23
  45. data/lib/occi/infrastructure/os_tpl.rb +1 -1
  46. data/lib/occi/infrastructure/resource_tpl.rb +1 -1
  47. data/lib/occi/infrastructure/storage.rb +7 -6
  48. data/lib/occi/infrastructure/storagelink.rb +4 -4
  49. data/lib/occi/log.rb +13 -10
  50. data/lib/occi/model.rb +9 -8
  51. data/lib/occi/parser/json.rb +11 -9
  52. data/lib/occi/parser/ova.rb +12 -6
  53. data/lib/occi/parser/ovf.rb +173 -116
  54. data/lib/occi/parser/text/constants.rb +87 -0
  55. data/lib/occi/parser/text.rb +161 -200
  56. data/lib/occi/parser/xml.rb +10 -8
  57. data/lib/occi/parser.rb +100 -50
  58. data/lib/occi/settings.rb +2 -1
  59. data/lib/occi/version.rb +1 -1
  60. data/lib/occi-core.rb +6 -4
  61. data/occi-core.gemspec +0 -7
  62. data/spec/occi/collection_samples/collection1.json +1 -0
  63. data/spec/occi/collection_samples/directory2/collection2.json +1 -0
  64. data/spec/occi/collection_spec.rb +961 -31
  65. data/spec/occi/core/action_instance_spec.rb +317 -0
  66. data/spec/occi/core/action_spec.rb +71 -0
  67. data/spec/occi/core/attributes_spec.rb +582 -27
  68. data/spec/occi/core/category_spec.rb +194 -18
  69. data/spec/occi/core/entities_spec.rb +96 -0
  70. data/spec/occi/core/entity_spec.rb +317 -28
  71. data/spec/occi/core/kind_spec.rb +127 -16
  72. data/spec/occi/core/link_spec.rb +35 -0
  73. data/spec/occi/core/links_spec.rb +130 -0
  74. data/spec/occi/core/mixins_spec.rb +107 -0
  75. data/spec/occi/core/properties_spec.rb +167 -0
  76. data/spec/occi/core/resource_spec.rb +23 -9
  77. data/spec/occi/core_spec.rb +12 -0
  78. data/spec/occi/infrastructure/compute_spec.rb +218 -18
  79. data/spec/occi/infrastructure/network_spec.rb +96 -0
  80. data/spec/occi/infrastructure/networkinterface_spec.rb +96 -0
  81. data/spec/occi/infrastructure/storage_spec.rb +33 -0
  82. data/spec/occi/infrastructure/storagelink_spec.rb +45 -0
  83. data/spec/occi/log_spec.rb +104 -1
  84. data/spec/occi/model_spec.rb +251 -39
  85. data/spec/occi/{test.json → parser/json_samples/test.json} +0 -0
  86. data/spec/occi/parser/ova_samples/test.dump +0 -0
  87. data/spec/occi/{test.ova → parser/ova_samples/test.ova} +0 -0
  88. data/spec/occi/parser/ovf_samples/test.dump +0 -0
  89. data/spec/occi/{test.ovf → parser/ovf_samples/test.ovf} +0 -0
  90. data/spec/occi/parser/text_samples/occi_categories.dump +0 -0
  91. data/spec/occi/parser/text_samples/occi_categories.text +2 -0
  92. data/spec/occi/parser/text_samples/occi_compute_rocci_server.dump +0 -0
  93. data/spec/occi/parser/text_samples/occi_compute_rocci_server.resource.dump +0 -0
  94. data/spec/occi/parser/text_samples/occi_compute_rocci_server.text +10 -0
  95. data/spec/occi/parser/text_samples/occi_link_resource_instance.dump +0 -0
  96. data/spec/occi/parser/text_samples/occi_link_resource_instance.text +7 -0
  97. data/spec/occi/parser/text_samples/occi_link_simple.dump +0 -0
  98. data/spec/occi/parser/text_samples/occi_link_simple.link_string.dump +0 -0
  99. data/spec/occi/parser/text_samples/occi_link_simple.text +1 -0
  100. data/spec/occi/parser/text_samples/occi_link_w_attributes.dump +0 -0
  101. data/spec/occi/parser/text_samples/occi_link_w_attributes.text +7 -0
  102. data/spec/occi/parser/text_samples/occi_link_w_category.dump +0 -0
  103. data/spec/occi/parser/text_samples/occi_link_w_category.text +3 -0
  104. data/spec/occi/parser/text_samples/occi_model_rocci_server.dump +0 -0
  105. data/spec/occi/parser/text_samples/occi_model_rocci_server.text +51 -0
  106. data/spec/occi/parser/text_samples/occi_network_rocci_server.dump +0 -0
  107. data/spec/occi/parser/text_samples/occi_network_rocci_server.resource.dump +0 -0
  108. data/spec/occi/parser/text_samples/occi_network_rocci_server.text +11 -0
  109. data/spec/occi/parser/text_samples/occi_resource_w_attributes.dump +0 -0
  110. data/spec/occi/parser/text_samples/occi_resource_w_attributes.text +11 -0
  111. data/spec/occi/parser/text_samples/occi_resource_w_inline_links.dump +0 -0
  112. data/spec/occi/parser/text_samples/occi_resource_w_inline_links.text +16 -0
  113. data/spec/occi/parser/text_samples/occi_resource_w_inline_links_only.dump +0 -0
  114. data/spec/occi/parser/text_samples/occi_resource_w_inline_links_only.text +13 -0
  115. data/spec/occi/parser/text_samples/occi_storage_rocci_server.dump +0 -0
  116. data/spec/occi/parser/text_samples/occi_storage_rocci_server.resource.dump +0 -0
  117. data/spec/occi/parser/text_samples/occi_storage_rocci_server.text +9 -0
  118. data/spec/occi/parser/text_spec.rb +274 -78
  119. data/spec/occi/parser/xml_samples/test.xml +352 -0
  120. data/spec/occi/parser_spec.rb +255 -104
  121. data/spec/occi-core_spec.rb +31 -0
  122. data/spec/spec_helper.rb +6 -2
  123. metadata +110 -111
  124. checksums.yaml +0 -7
  125. data/spec/occi/core/attribute_spec.rb +0 -0
data/lib/occi/log.rb CHANGED
@@ -5,21 +5,24 @@ module Occi
5
5
 
6
6
  include ::Logger::Severity
7
7
 
8
- attr_reader :logger
8
+ attr_reader :logger, :log_prefix
9
9
 
10
10
  # creates a new OCCI logger
11
11
  # @param [IO,String] log_dev The log device. This is a filename (String) or IO object (typically +STDOUT+,
12
+ # @param [String] log_prefix String placed in front of every logged message
12
13
  # +STDERR+, or an open file).
13
- def initialize(log_dev)
14
+ def initialize(log_dev, log_prefix = '[rOCCI-core]')
14
15
  if log_dev.kind_of? Logger
15
16
  @logger = log_dev
16
17
  else
17
18
  @logger = Logger.new(log_dev)
18
19
  end
19
20
 
21
+ @log_prefix = log_prefix.blank? ? '' : log_prefix.strip
22
+
20
23
  # subscribe to log messages and send to logger
21
- @log_subscriber = ActiveSupport::Notifications.subscribe("log") do |name, start, finish, id, payload|
22
- @logger.log(payload[:level], payload[:message]) if @logger
24
+ @log_subscriber = ActiveSupport::Notifications.subscribe("rOCCI-core.log") do |name, start, finish, id, payload|
25
+ @logger.log(payload[:level], "#{@log_prefix} #{payload[:message]}") if @logger
23
26
  end
24
27
  end
25
28
 
@@ -39,28 +42,28 @@ module Occi
39
42
 
40
43
  # @see info
41
44
  def self.debug(message)
42
- ActiveSupport::Notifications.instrument("log", :level => Logger::DEBUG, :message => message)
45
+ ActiveSupport::Notifications.instrument("rOCCI-core.log", :level => Logger::DEBUG, :message => message)
43
46
  end
44
47
 
45
48
  # Log an +INFO+ message
46
49
  # @param [String] message the message to log; does not need to be a String
47
50
  def self.info(message)
48
- ActiveSupport::Notifications.instrument("log", :level => Logger::INFO, :message => message)
51
+ ActiveSupport::Notifications.instrument("rOCCI-core.log", :level => Logger::INFO, :message => message)
49
52
  end
50
53
 
51
54
  # @see info
52
55
  def self.warn(message)
53
- ActiveSupport::Notifications.instrument("log", :level => Logger::WARN, :message => message)
56
+ ActiveSupport::Notifications.instrument("rOCCI-core.log", :level => Logger::WARN, :message => message)
54
57
  end
55
58
 
56
59
  # @see info
57
60
  def self.error(message)
58
- ActiveSupport::Notifications.instrument("log", :level => Logger::ERROR, :message => message)
61
+ ActiveSupport::Notifications.instrument("rOCCI-core.log", :level => Logger::ERROR, :message => message)
59
62
  end
60
63
 
61
64
  # @see info
62
65
  def self.fatal(message)
63
- ActiveSupport::Notifications.instrument("log", :level => Logger::FATAL, :message => message)
66
+ ActiveSupport::Notifications.instrument("rOCCI-core.log", :level => Logger::FATAL, :message => message)
64
67
  end
65
68
  end
66
- end
69
+ end
data/lib/occi/model.rb CHANGED
@@ -14,7 +14,7 @@ module Occi
14
14
 
15
15
  # register Occi Core categories enitity, resource and link
16
16
  def register_core
17
- Occi::Log.info "### Registering OCCI Core categories enitity, resource and link ###"
17
+ Occi::Log.info "[#{self.class}] Registering OCCI Core categories enitity, resource and link"
18
18
  register Occi::Core::Entity.kind
19
19
  register Occi::Core::Resource.kind
20
20
  register Occi::Core::Link.kind
@@ -22,7 +22,7 @@ module Occi
22
22
 
23
23
  # register Occi Infrastructure categories
24
24
  def register_infrastructure
25
- Occi::Log.info "### Registering OCCI Infrastructure categories ###"
25
+ Occi::Log.info "[#{self.class}] Registering OCCI Infrastructure categories"
26
26
  Occi::Infrastructure.categories.each { |category| register category }
27
27
  end
28
28
 
@@ -32,7 +32,8 @@ module Occi
32
32
  # recursively searched for files with the extension .json .
33
33
  # @param [Sting] scheme_base_url base location for provider specific extensions of the OCCI model
34
34
  def register_files(path, scheme_base_url='http://localhost')
35
- Occi::Log.info "### Initializing OCCI Model from #{path} ###"
35
+ Occi::Log.info "[#{self.class}] Initializing OCCI Model from #{path}"
36
+ raise ArgumentError, "Directory \"#{path}\" does not exist" unless File.directory?(path)
36
37
  Dir.glob(path + '/**/*.json').each do |file|
37
38
  collection = Occi::Collection.new(JSON.parse(File.read(file)))
38
39
  # add location of service provider to scheme if it has a relative location
@@ -53,12 +54,12 @@ module Occi
53
54
 
54
55
  # clear all entities from all categories
55
56
  def reset()
56
- categories.each { |category| category.entities = [] if category.respond_to? :entities }
57
+ categories.each { |category| category.entities = Occi::Core::Entities.new if category.respond_to? :entities }
57
58
  end
58
59
 
59
60
  # @param [Occi::Core::Category] category
60
61
  def register(category)
61
- Occi::Log.debug "### Registering category #{category}"
62
+ Occi::Log.debug "[#{self.class}] Registering category #{category}"
62
63
  # add model to category as back reference
63
64
  category.model = self
64
65
  @kinds << category unless get_by_id(category.to_s) if category.class.ancestors.include? Occi::Core::Kind
@@ -68,7 +69,7 @@ module Occi
68
69
 
69
70
  # @param [Occi::Core::Category] category
70
71
  def unregister(category)
71
- Occi::Log.debug "### Unregistering category #{category.type_identifier}"
72
+ Occi::Log.debug "[#{self.class}] Unregistering category #{category.type_identifier}"
72
73
  @kinds.delete category
73
74
  @mixins.delete category
74
75
  @actions.delete category
@@ -79,8 +80,8 @@ module Occi
79
80
  # @param [Occi::Collection,Occi::Core::Category,String] filter
80
81
  # @return [Occi::Collection] collection
81
82
  def get(filter = nil)
82
- filter ? self.get_related_to(filter) : self
83
+ (filter && !filter.empty? ) ? self.get_related_to(filter) : self
83
84
  end
84
85
 
85
86
  end
86
- end
87
+ end
@@ -1,16 +1,17 @@
1
1
  module Occi
2
2
  module Parser
3
3
  module Json
4
- # @param [String] string
4
+ # @param [String] body
5
5
  # @return [Occi::Collection]
6
- def self.collection(string)
7
- collection = Occi::Collection.new
8
- hash = Hashie::Mash.new(JSON.parse(string))
9
- collection.kinds.merge hash.kinds.collect { |kind| Occi::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.parent ||= kind.related, kind.actions) } if hash.kinds
10
- collection.mixins.merge hash.mixins.collect { |mixin| Occi::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.depends ||= mixin.related, mixin.actions, mixin.applies) } if hash.mixins
11
- collection.actions.merge hash.actions.collect { |action| Occi::Core::Action.new(action.scheme, action.term, action.title, action.attributes) } if hash.actions
12
- collection.resources.merge hash.resources.collect { |resource| Occi::Core::Resource.new(resource.kind, resource.mixins, resource.attributes, resource.actions, resource.links) } if hash.resources
13
- collection.links.merge hash.links.collect { |link| Occi::Core::Link.new(link.kind, link.mixins, link.attributes, [], nil, link.target) } if hash.links
6
+ def self.collection(body)
7
+
8
+ begin
9
+ hash = Hashie::Mash.new(JSON.parse(body))
10
+ rescue JSON::ParserError => perr
11
+ Occi::Log.error "[#{self}] Failed to parse JSON input: #{perr.message}"
12
+ raise Occi::Errors::ParserInputError, perr.message
13
+ end
14
+ collection = Occi::Collection.new(hash)
14
15
 
15
16
  if collection.resources.size == 1 && collection.links.size > 0
16
17
  if collection.resources.first.links.empty?
@@ -27,6 +28,7 @@ module Occi
27
28
  lnk ||= resource_link
28
29
  end
29
30
  end
31
+
30
32
  collection
31
33
  end
32
34
  end
@@ -5,27 +5,33 @@ module Occi
5
5
  # @param [String] string
6
6
  # @return [Occi::Collection]
7
7
  def self.collection(string)
8
+ Occi::Log.debug "[#{self}] Parsing ova format"
8
9
  tar = Gem::Package::TarReader.new(StringIO.new(string))
9
10
  ovf = mf = cert = nil
10
11
  files = {}
12
+
11
13
  tar.each do |entry|
12
14
  tempfile = Tempfile.new(entry.full_name)
13
15
  tempfile.write(entry.read)
14
16
  tempfile.close
15
17
  files[entry.full_name] = tempfile.path
18
+
16
19
  ovf = tempfile.path if entry.full_name.end_with? '.ovf'
17
20
  mf = tempfile.path if entry.full_name.end_with? '.mf'
18
21
  cert = tempfile.path if entry.full_name.end_with? '.cert'
19
22
  end
20
23
 
24
+ Occi::Log.debug "[#{self}] In ova found: #{ovf} #{mf} #{cert}"
25
+ raise Occi::Errors::ParserInputError, 'No ovf file found' unless ovf
26
+
21
27
  File.read(mf).each_line do |line|
22
- name = line.scan(/SHA1\(([^\)]*)\)= (.*)/).flatten.first
23
- sha1 = line.scan(/SHA1\(([^\)]*)\)= (.*)/).flatten.last
24
- Occi::Log.debug "SHA1 hash #{Digest::SHA1.hexdigest(files[name])}"
25
- raise "SHA1 mismatch for file #{name}" if Digest::SHA1.hexdigest(File.read(files[name])) != sha1
26
- end if mf
28
+ line = line.scan(/SHA1\(([^\)]*)\)= (.*)/).flatten
29
+ name = line.first
30
+ sha1 = line.last
27
31
 
28
- raise 'no ovf file found' if ovf.nil?
32
+ Occi::Log.debug "[#{self}] SHA1 hash #{Digest::SHA1.hexdigest(files[name])}"
33
+ raise Occi::Errors::ParserInputError, "SHA1 mismatch for file #{name}" unless Digest::SHA1.hexdigest(File.read(files[name])) == sha1
34
+ end if mf
29
35
 
30
36
  Occi::Parser::Ovf.collection(File.read(ovf), files)
31
37
  end
@@ -9,145 +9,202 @@ module Occi
9
9
  OVFENV="http://schemas.dmtf.org/ovf/environment/1"
10
10
  CIM ="http://schemas.dmtf.org/wbem/wscim/1/common"
11
11
 
12
- # @param [String] string
13
- # @param [Hash] files key value pairs of file names and paths to the file
14
- def self.collection(string, files={})
15
- collection = Occi::Collection.new
16
- doc = Nokogiri::XML(string)
17
- references = {}
18
-
19
- doc.xpath('envelope:Envelope/envelope:References/envelope:File', 'envelope' => "#{OVF}").each do |file|
20
- href = URI.parse(file.attributes['href'].to_s)
21
- if href.relative?
22
- if files[href.to_s]
23
- references[file.attributes['id'].to_s] = 'file://' + files[href.to_s]
12
+ class << self
13
+
14
+ # @param [String] string
15
+ # @param [Hash] files key value pairs of file names and paths to the file
16
+ def collection(string, files={})
17
+ collection = Occi::Collection.new
18
+ doc = Nokogiri::XML(string)
19
+
20
+ references = parse_references(doc, files)
21
+ parse_storage(doc, references, collection)
22
+ parse_network(doc, collection)
23
+ parse_compute(doc, references, collection)
24
+
25
+ collection
26
+ end
27
+
28
+ def parse_references(doc, files)
29
+ references = {}
30
+
31
+ doc.xpath('envelope:Envelope/envelope:References/envelope:File', 'envelope' => "#{OVF}").each do |file|
32
+ href = URI.parse(file.attributes['href'].to_s)
33
+ references[file.attributes['id'].to_s] = if href.relative?
34
+ files[href.to_s] ? "file://#{files[href.to_s]}" : "file://#{href.to_s}"
24
35
  else
25
- references[file.attributes['id'].to_s] = 'file://' + href.to_s
36
+ href.to_s
26
37
  end
27
- else
28
- references[file.attributes['id'].to_s] = href.to_s
29
38
  end
39
+
40
+ references
30
41
  end
31
42
 
32
- doc.xpath('envelope:Envelope/envelope:DiskSection/envelope:Disk', 'envelope' => "#{OVF}").each do |disk|
33
- storage = Occi::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#storage')
34
- if disk.attributes['fileRef']
35
- storagelink = Occi::Core::Link.new("http://schemas.ogf.org/occi/infrastructure#storagelink")
36
- storagelink.attributes.occi!.core!.title = disk.attributes['fileRef'].to_s
37
- storagelink.attributes.occi!.core!.target = references[disk.attributes['fileRef'].to_s]
38
- storage.attributes.occi!.core!.title = disk.attributes['diskId'].to_s
39
- storage.links << storagelink
40
- else
41
- #OCCI accepts storage size in GB
42
- #OVF ver 1.1: The capacity of a virtual disk shall be specified by the ovf:capacity attribute with an xs:long integer
43
- #value. The default unit odf allocation shall be bytes. The optional string attribute
44
- #ovf:capacityAllocationUnits may be used to specify a particular unit of allocation.
45
- alloc_units = disk.attributes['capacityAllocationUnits'].to_s
46
- if alloc_units.empty?
47
- # The capacity is defined in bytes , convert to GB and pass it to OCCI
48
- capacity = disk.attributes['capacity'].to_s
49
- capacity =capacity.to_i
43
+ def parse_storage(doc, references, collection)
44
+ doc.xpath('envelope:Envelope/envelope:DiskSection/envelope:Disk', 'envelope' => "#{OVF}").each do |disk|
45
+ storage = Occi::Infrastructure::Storage.new
46
+
47
+ if disk.attributes['fileRef']
48
+ parse_storage_disk_file(disk, storage, references)
50
49
  else
51
- alloc_unit_bytes = self.alloc_units_bytes(alloc_units)
52
- capacity = self.calculate_capacity_bytes(disk.attributes['capacity'].to_s, alloc_unit_bytes)
50
+ parse_storage_disk_alloc(disk, storage, references)
53
51
  end
54
- capacity_gb = self.calculate_capacity_gb(capacity)
55
- Occi::Log.debug('capacity in gb ' + capacity_gb.to_s)
56
- storage.attributes.occi!.storage!.size = capacity_gb.to_s if capacity_gb
57
- storage.attributes.occi!.core!.title = disk.attributes['diskId'].to_s if disk.attributes['diskId']
52
+
53
+ collection.resources << storage
54
+ end
55
+
56
+ collection
57
+ end
58
+
59
+ def parse_storage_disk_file(disk, storage, references)
60
+ storagelink = Occi::Infrastructure::Storagelink.new
61
+ storagelink.title = disk.attributes['fileRef'].to_s
62
+ storagelink.target = references[disk.attributes['fileRef'].to_s]
63
+
64
+ storage.title = disk.attributes['diskId'].to_s
65
+ storage.links << storagelink
66
+
67
+ storage
68
+ end
69
+
70
+ def parse_storage_disk_alloc(disk, storage)
71
+ #OCCI accepts storage size in GB
72
+ #OVF ver 1.1: The capacity of a virtual disk shall be specified by the ovf:capacity attribute with an xs:long integer
73
+ #value. The default unit odf allocation shall be bytes. The optional string attribute
74
+ #ovf:capacityAllocationUnits may be used to specify a particular unit of allocation.
75
+ alloc_units = disk.attributes['capacityAllocationUnits'].to_s
76
+
77
+ if alloc_units.empty?
78
+ # The capacity is defined in bytes, convert to GB and pass it to OCCI
79
+ capacity = disk.attributes['capacity'].to_s.to_i
80
+ else
81
+ alloc_unit_bytes = alloc_units_bytes(alloc_units)
82
+ capacity = calculate_capacity_bytes(disk.attributes['capacity'].to_s, alloc_unit_bytes)
83
+ end
84
+
85
+ capacity_gb = calculate_capacity_gb(capacity)
86
+ storage.size = capacity_gb.to_s if capacity_gb
87
+ storage.title = disk.attributes['diskId'].to_s if disk.attributes['diskId']
88
+
89
+ storage
90
+ end
91
+
92
+ def parse_network(doc, collection)
93
+ doc.xpath('envelope:Envelope/envelope:NetworkSection/envelope:Network', 'envelope' => "#{OVF}").each do |nw|
94
+ network = Occi::Infrastructure::Network.new
95
+ network.title = nw.attributes['name'].to_s
96
+ collection.resources << network
58
97
  end
59
- collection.resources << storage
98
+
99
+ collection
60
100
  end
61
101
 
62
- doc.xpath('envelope:Envelope/envelope:NetworkSection/envelope:Network', 'envelope' => "#{OVF}").each do |nw|
63
- network = Occi::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#network')
64
- network.attributes.occi!.core!.title = nw.attributes['name'].to_s
65
- collection.resources << network
102
+ def parse_compute(doc, references, collection)
103
+ # Iteration through all the virtual hardware sections,and a sub-iteration on each Item defined in the Virtual Hardware section
104
+ doc.xpath('envelope:Envelope/envelope:VirtualSystem', 'envelope' => "#{OVF}").each do |virtsys|
105
+ compute = Occi::Infrastructure::Compute.new
106
+
107
+ doc.xpath('envelope:Envelope/envelope:VirtualSystem/envelope:VirtualHardwareSection', 'envelope' => "#{OVF}").each do |virthwsec|
108
+ compute.summary = virthwsec.xpath("item:Info/text()", 'item' => "#{RASD}").to_s
109
+ parse_compute_resources(collection, compute, virthwsec)
110
+ end
111
+
112
+ collection.resources << compute
113
+ end
114
+
115
+ collection
66
116
  end
67
117
 
68
- # Iteration through all the virtual hardware sections,and a sub-iteration on each Item defined in the Virtual Hardware section
69
- doc.xpath('envelope:Envelope/envelope:VirtualSystem', 'envelope' => "#{OVF}").each do |virtsys|
70
- compute = Occi::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#compute')
71
-
72
- doc.xpath('envelope:Envelope/envelope:VirtualSystem/envelope:VirtualHardwareSection', 'envelope' => "#{OVF}").each do |virthwsec|
73
- compute.attributes.occi!.core!.summary = virthwsec.xpath("item:Info/text()", 'item' => "#{RASD}").to_s
74
-
75
- virthwsec.xpath('envelope:Item', 'envelope' => "#{OVF}").each do |resource_alloc|
76
- resType = resource_alloc.xpath("item:ResourceType/text()", 'item' => "#{RASD}")
77
- case resType.to_s
78
- # 4 is the ResourceType for memory in the CIM_ResourceAllocationSettingData
79
- when "4" then
80
- Occi::Log.debug('calculating memory in gb ')
81
- alloc_units = resource_alloc.xpath("item:AllocationUnits/text()", 'item' => "#{RASD}").to_s
82
- Occi::Log.debug('allocated units in ovf file: ' + alloc_units)
83
- alloc_unit_bytes = self.alloc_units_bytes(alloc_units)
84
- capacity = self.calculate_capacity_bytes(resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{RASD}").to_s, alloc_unit_bytes)
85
- capacity_gb = self.calculate_capacity_gb(capacity)
86
- Occi::Log.debug('virtual quantity of memory configured in gb: ' + capacity_gb.to_s)
87
- compute.attributes.occi!.compute!.memory = capacity_gb
88
- # compute.attributes.occi!.compute!.memory = resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{RASD}").to_s.to_i
89
- # 3 is the ResourceType for processor in the CIM_ResourceAllocationSettingData
90
- when "3" then
91
- compute.attributes.occi!.compute!.cores = resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{RASD}").to_s.to_i
92
- when "10" then
93
- networkinterface = Occi::Core::Link.new('http://schemas.ogf.org/occi/infrastructure#networkinterface')
94
- networkinterface.attributes.occi!.core!.title = resource_alloc.xpath("item:ElementName/text()", 'item' => "#{RASD}").to_s
95
- id = resource_alloc.xpath("item:Connection/text()", 'item' => "#{RASD}").to_s
96
- network = collection.resources.select { |resource| resource.attributes.occi!.core!.title.to_s == id }.first
97
- raise "Network with id #{id} not found" unless network
98
- networkinterface.attributes.occi!.core!.target = network
99
- when "17" then
100
- storagelink = Occi::Core::Link.new("http://schemas.ogf.org/occi/infrastructure#storagelink")
101
- storagelink.attributes.occi!.core!.title = resource_alloc.xpath("item:ElementName/text()", 'item' => "#{RASD}").to_s
102
- # extract the mountpoint
103
- host_resource = resource_alloc.xpath("item:HostResource/text()", 'item' => "#{RASD}").to_s
104
- if host_resource.start_with? 'ovf:/disk/'
105
- id = host_resource.gsub('ovf:/disk/', '')
106
- storage = collection.resources.select { |resource| resource.attributes.occi!.core!.title.to_s == id }.first
107
- raise "Disk with id #{id} not found" unless storage
108
- storagelink.attributes.occi!.core!.target = storage
109
- elsif host_resource.start_with? 'ovf:/file/'
110
- id = host_resource.gsub('ovf:/file/', '')
111
- storagelink.attributes.occi!.core!.target = references[id]
112
- end
113
- compute.links << storagelink
114
- end
115
- ##Add the cpu architecture
116
- #system_sec = virthwsec.xpath('envelope:System', 'envelope' => "#{OVF}")
117
- #virtsys_type = system_sec.xpath('vssd_:VirtualSystemType/text()', 'vssd_' => "#{VSSD}")
118
- #compute.attributes.occi!.compute!.architecture = virtsys_type
118
+ def parse_compute_resources(collection, compute, virthwsec)
119
+ virthwsec.xpath('envelope:Item', 'envelope' => "#{OVF}").each do |resource_alloc|
120
+ resType = resource_alloc.xpath("item:ResourceType/text()", 'item' => "#{RASD}")
121
+
122
+ case resType.to_s
123
+ when "4" then
124
+ # 4 is the ResourceType for memory in the CIM_ResourceAllocationSettingData
125
+ parse_compute_memory(resource_alloc, compute)
126
+ when "3" then
127
+ # 3 is the ResourceType for processor in the CIM_ResourceAllocationSettingData
128
+ compute.cores = resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{RASD}").to_s.to_i
129
+ when "10" then
130
+ # extract the network
131
+ parse_compute_network(resource_alloc, compute, collection)
132
+ when "17" then
133
+ # extract the mountpoint
134
+ parse_compute_storage(resource_alloc, compute, collection)
119
135
  end
136
+
137
+ ##Add the cpu architecture
138
+ #system_sec = virthwsec.xpath('envelope:System', 'envelope' => "#{OVF}")
139
+ #compute.architecture = system_sec.xpath('vssd_:VirtualSystemType/text()', 'vssd_' => "#{VSSD}")
120
140
  end
121
- collection.resources << compute
141
+
142
+ compute
122
143
  end
123
- collection
124
- end
125
144
 
126
- ####################Helper method for calculation of storage size based on allocation units configured###########
145
+ def parse_compute_memory(resource_alloc, compute)
146
+ alloc_units = resource_alloc.xpath("item:AllocationUnits/text()", 'item' => "#{RASD}").to_s
127
147
 
128
- def self.calculate_capacity_bytes(capacity, alloc_units_bytes)
129
- total_capacity_bytes = alloc_units_bytes * capacity.to_i
130
- total_capacity_bytes
131
- end
148
+ alloc_unit_bytes = alloc_units_bytes(alloc_units)
149
+ capacity = calculate_capacity_bytes(resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{RASD}").to_s, alloc_unit_bytes)
150
+ capacity_gb = calculate_capacity_gb(capacity)
132
151
 
152
+ compute.memory = capacity_gb
153
+ # compute.attributes.occi!.compute!.memory = resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{RASD}").to_s.to_i
133
154
 
134
- def self.calculate_capacity_gb(capacity)
135
- capacity_gb = capacity.to_f/(2**30)
136
- capacity_gb
137
- end
155
+ compute
156
+ end
138
157
 
158
+ def parse_compute_network(resource_alloc, compute, collection)
159
+ id = resource_alloc.xpath("item:Connection/text()", 'item' => "#{RASD}").to_s
160
+ network = collection.resources.select { |resource| resource.title == id }.first
161
+ raise Occi::Errors::ParserInputError, "Network with id #{id} not found" unless network
139
162
 
140
- def self.alloc_units_bytes(alloc_units)
141
- units = alloc_units.split('*')
142
- #check units[1] is nil??
143
- units[1].strip!
144
- alloc_vars = units[1].split('^')
145
- alloc_units_bytes = (alloc_vars[0].to_i**alloc_vars[1].to_i)
146
- alloc_units_bytes
147
- end
163
+ networkinterface = compute.networkinterface(network)
164
+ networkinterface.title = resource_alloc.xpath("item:ElementName/text()", 'item' => "#{RASD}").to_s
148
165
 
149
- ###############End of Helper methods for OVF Parsing ##################################################################
166
+ compute
167
+ end
168
+
169
+ def parse_compute_storage(resource_alloc, compute, collection)
170
+ host_resource = resource_alloc.xpath("item:HostResource/text()", 'item' => "#{RASD}").to_s
171
+
172
+ if host_resource.start_with? 'ovf:/disk/'
173
+ id = host_resource.gsub('ovf:/disk/', '')
174
+ storage = collection.resources.select { |resource| resource.title == id }.first
175
+ raise Occi::Errors::ParserInputError, "Disk with id #{id} not found" unless storage
176
+ elsif host_resource.start_with? 'ovf:/file/'
177
+ raise Occi::Errors::ParserInputError, 'OVF files are not supported!'
178
+ #id = host_resource.gsub('ovf:/file/', '')
179
+ #storagelink.attributes.occi!.core!.target = references[id]
180
+ end
181
+
182
+ storagelink = compute.storagelink(storage)
183
+ storagelink.title = resource_alloc.xpath("item:ElementName/text()", 'item' => "#{RASD}").to_s
150
184
 
185
+ compute
186
+ end
187
+
188
+ def calculate_capacity_bytes(capacity, alloc_units_bytes)
189
+ total_capacity_bytes = alloc_units_bytes * capacity.to_i
190
+ total_capacity_bytes
191
+ end
192
+
193
+ def calculate_capacity_gb(capacity)
194
+ capacity_gb = capacity.to_f/(2**30)
195
+ capacity_gb
196
+ end
197
+
198
+ def alloc_units_bytes(alloc_units)
199
+ units = alloc_units.split('*')
200
+ #check units[1] is nil??
201
+ units[1].strip!
202
+ alloc_vars = units[1].split('^')
203
+ alloc_units_bytes = (alloc_vars[0].to_i**alloc_vars[1].to_i)
204
+ alloc_units_bytes
205
+ end
206
+
207
+ end
151
208
 
152
209
  end
153
210
  end
@@ -0,0 +1,87 @@
1
+ module Occi
2
+ module Parser
3
+ module Text
4
+ module Constants
5
+
6
+ # Regular expressions
7
+ REGEXP_QUOTED_STRING = /([^"\\]|\\.)*/
8
+ REGEXP_LOALPHA = /[a-z]/
9
+ REGEXP_ALPHA = /[a-zA-Z]/
10
+ REGEXP_DIGIT = /[0-9]/
11
+ REGEXP_INT = /#{REGEXP_DIGIT}+/
12
+ REGEXP_FLOAT = /#{REGEXP_INT}\.#{REGEXP_INT}/
13
+ REGEXP_NUMBER = /#{REGEXP_FLOAT}|#{REGEXP_INT}/
14
+ REGEXP_BOOL = /\b(?<!\|)true(?!\|)\b|\b(?<!\|)false(?!\|)\b/
15
+
16
+ # Regular expressions for OCCI
17
+ REGEXP_TERM = /(#{REGEXP_ALPHA}|#{REGEXP_DIGIT})(#{REGEXP_ALPHA}|#{REGEXP_DIGIT}|-|_)*/# Compatibility with terms starting with a number
18
+ REGEXP_TERM_STRICT = /#{REGEXP_LOALPHA}(#{REGEXP_LOALPHA}|#{REGEXP_DIGIT}|-|_)*/
19
+ REGEXP_SCHEME = /#{URI::ABS_URI_REF}#/
20
+ REGEXP_TYPE_IDENTIFIER = /#{REGEXP_SCHEME}#{REGEXP_TERM}/
21
+ REGEXP_TYPE_IDENTIFIER_STRICT = /#{REGEXP_SCHEME}#{REGEXP_TERM_STRICT}/
22
+ REGEXP_CLASS = /\b(?<!\|)action(?!\|)\b|\b(?<!\|)mixin(?!\|)\b|\b(?<!\|)kind(?!\|)\b/
23
+
24
+ REGEXP_ATTR_COMPONENT = /#{REGEXP_LOALPHA}(#{REGEXP_LOALPHA}|#{REGEXP_DIGIT}|-|_)*/
25
+ REGEXP_ATTRIBUTE_NAME = /#{REGEXP_ATTR_COMPONENT}(\.#{REGEXP_ATTR_COMPONENT})*/
26
+ REGEXP_ATTRIBUTE_PROPERTY = /\b(?<!\|)immutable(?!\|)\b|\b(?<!\|)required(?!\|)\b/
27
+ REGEXP_ATTRIBUTE_DEF = /(#{REGEXP_ATTRIBUTE_NAME})(\{#{REGEXP_ATTRIBUTE_PROPERTY}(\s+#{REGEXP_ATTRIBUTE_PROPERTY})*\})?/
28
+ REGEXP_ATTRIBUTE_LIST = /#{REGEXP_ATTRIBUTE_DEF}(\s+#{REGEXP_ATTRIBUTE_DEF})*/
29
+ REGEXP_ATTRIBUTE_REPR = /#{REGEXP_ATTRIBUTE_NAME}=("#{REGEXP_QUOTED_STRING}"|#{REGEXP_NUMBER}|#{REGEXP_BOOL})/
30
+
31
+ REGEXP_ACTION = /#{REGEXP_TYPE_IDENTIFIER}/
32
+ REGEXP_ACTION_STRICT = /#{REGEXP_TYPE_IDENTIFIER_STRICT}/
33
+ REGEXP_ACTION_LIST = /#{REGEXP_ACTION}(\s+#{REGEXP_ACTION})*/
34
+ REGEXP_ACTION_LIST_STRICT = /#{REGEXP_ACTION_STRICT}(\s+#{REGEXP_ACTION_STRICT})*/
35
+
36
+ REGEXP_RESOURCE_TYPE = /#{REGEXP_TYPE_IDENTIFIER}(\s+#{REGEXP_TYPE_IDENTIFIER})*/
37
+ REGEXP_RESOURCE_TYPE_STRICT = /#{REGEXP_TYPE_IDENTIFIER_STRICT}(\s+#{REGEXP_TYPE_IDENTIFIER_STRICT})*/
38
+ REGEXP_LINK_INSTANCE = /#{URI::URI_REF}/
39
+ REGEXP_LINK_TYPE = /#{REGEXP_TYPE_IDENTIFIER}(\s+#{REGEXP_TYPE_IDENTIFIER})*/
40
+ REGEXP_LINK_TYPE_STRICT = /#{REGEXP_TYPE_IDENTIFIER_STRICT}(\s+#{REGEXP_TYPE_IDENTIFIER_STRICT})*/
41
+
42
+ # Regular expression for OCCI Categories
43
+ REGEXP_CATEGORY = "Category:\\s*(?<term>#{REGEXP_TERM})" << # term (mandatory)
44
+ ";\\s*scheme=\"(?<scheme>#{REGEXP_SCHEME})#{REGEXP_TERM}?\"" << # scheme (mandatory)
45
+ ";\\s*class=\"?(?<class>#{REGEXP_CLASS})\"?" << # class (mandatory)
46
+ "(;\\s*title=\"(?<title>#{REGEXP_QUOTED_STRING})\")?" << # title (optional)
47
+ "(;\\s*rel=\"(?<rel>#{REGEXP_TYPE_IDENTIFIER})\")?"<< # rel (optional)
48
+ "(;\\s*location=\"(?<location>#{URI::URI_REF})\")?" << # location (optional)
49
+ "(;\\s*attributes=\"(?<attributes>#{REGEXP_ATTRIBUTE_LIST})\")?" << # attributes (optional)
50
+ "(;\\s*actions=\"(?<actions>#{REGEXP_ACTION_LIST})\")?" << # actions (optional)
51
+ ';?' # additional semicolon at the end (not specified, for interoperability)
52
+ REGEXP_CATEGORY_STRICT = "Category:\\s*(?<term>#{REGEXP_TERM_STRICT})" << # term (mandatory)
53
+ ";\\s*scheme=\"(?<scheme>#{REGEXP_SCHEME})\"" << # scheme (mandatory)
54
+ ";\\s*class=\"(?<class>#{REGEXP_CLASS})\"" << # class (mandatory)
55
+ "(;\\s*title=\"(?<title>#{REGEXP_QUOTED_STRING})\")?" << # title (optional)
56
+ "(;\\s*rel=\"(?<rel>#{REGEXP_TYPE_IDENTIFIER_STRICT})\")?"<< # rel (optional)
57
+ "(;\\s*location=\"(?<location>#{URI::URI_REF})\")?" << # location (optional)
58
+ "(;\\s*attributes=\"(?<attributes>#{REGEXP_ATTRIBUTE_LIST})\")?" << # attributes (optional)
59
+ "(;\\s*actions=\"(?<actions>#{REGEXP_ACTION_LIST_STRICT})\")?" << # actions (optional)
60
+ ';?' # additional semicolon at the end (not specified, for interoperability)
61
+
62
+ # Regular expression for OCCI Link Instance References
63
+ REGEXP_LINK = "Link:\\s*\\<(?<uri>#{URI::URI_REF})\\>" << # uri (mandatory)
64
+ ";\\s*rel=\"(?<rel>#{REGEXP_RESOURCE_TYPE})\"" << # rel (mandatory)
65
+ "(;\\s*self=\"(?<self>#{REGEXP_LINK_INSTANCE})\")?" << # self (optional)
66
+ "(;\\s*category=\"(?<category>(;?\\s*(#{REGEXP_LINK_TYPE}))+)\")?" << # category (optional)
67
+ "(?<attributes>(;?\\s*(#{REGEXP_ATTRIBUTE_REPR}))*)" << # attributes (optional)
68
+ ';?' # additional semicolon at the end (not specified, for interoperability)
69
+ REGEXP_LINK_STRICT = "Link:\\s*\\<(?<uri>#{URI::URI_REF})\\>" << # uri (mandatory)
70
+ ";\\s*rel=\"(?<rel>#{REGEXP_RESOURCE_TYPE_STRICT})\"" << # rel (mandatory)
71
+ "(;\\s*self=\"(?<self>#{REGEXP_LINK_INSTANCE})\")?" << # self (optional)
72
+ "(;\\s*category=\"(?<category>(;?\\s*(#{REGEXP_LINK_TYPE_STRICT}))+)\")?" << # category (optional)
73
+ "(?<attributes>(;\\s*(#{REGEXP_ATTRIBUTE_REPR}))*)" << # attributes (optional)
74
+ ';?' # additional semicolon at the end (not specified, for interoperability)
75
+
76
+ # Regular expression for OCCI Entity Attributes
77
+ REGEXP_ATTRIBUTE = "X-OCCI-Attribute:\\s*(?<name>#{REGEXP_ATTRIBUTE_NAME})=(\"(?<string>#{REGEXP_QUOTED_STRING})\"|(?<number>#{REGEXP_NUMBER})|(?<bool>#{REGEXP_BOOL}))" <<
78
+ ';?' # additional semicolon at the end (not specified, for interoperability)
79
+
80
+ # Regular expression for OCCI Location
81
+ REGEXP_LOCATION = "X-OCCI-Location:\\s*(?<location>#{URI::URI_REF})" <<
82
+ ';?' # additional semicolon at the end (not specified, for interoperability)
83
+
84
+ end
85
+ end
86
+ end
87
+ end