occi 2.5.19 → 3.0.0.beta.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/.gitignore +4 -0
  2. data/.travis.yml +3 -1
  3. data/AUTHORS +4 -3
  4. data/Gemfile +9 -0
  5. data/Gemfile.lock +64 -21
  6. data/README.md +19 -14
  7. data/Rakefile +12 -8
  8. data/Test Results - discovery_interface.html +862 -0
  9. data/bin/occi +333 -83
  10. data/examples/dsl_example.rb +6 -6
  11. data/examples/x509auth_example.rb +6 -6
  12. data/features/common/step_definitions/common_steps.rb +32 -0
  13. data/features/occi/core/create/create.feature +17 -0
  14. data/features/occi/core/create/step_definitions/create_steps.rb +0 -0
  15. data/features/occi/core/delete/delete.feature +14 -0
  16. data/features/occi/core/delete/step_definitions/delete_steps.rb +0 -0
  17. data/features/occi/core/discovery_interface/discovery_interface.feature +35 -0
  18. data/features/occi/core/discovery_interface/step_definitions/discovery_interface_steps.rb +19 -0
  19. data/features/occi/core/miscellaneous/miscellaneous.feature +14 -0
  20. data/features/occi/core/miscellaneous/step_definitions/miscellaneous_steps.rb +0 -0
  21. data/features/occi/core/read/read.feature +14 -0
  22. data/features/occi/core/read/step_definitions/read_steps.rb +0 -0
  23. data/features/occi/core/update/step_definitions/update_steps.rb +0 -0
  24. data/features/occi/core/update/update.feature +14 -0
  25. data/features/occi/infrastructure/create/create.feature +14 -0
  26. data/features/occi/infrastructure/create/step_definitions/create_steps.rb +0 -0
  27. data/features/support/env.rb +4 -0
  28. data/lib/occi.rb +29 -3
  29. data/lib/occi/api/client/client_amqp.rb +756 -0
  30. data/lib/occi/api/client/client_http.rb +922 -0
  31. data/lib/occi/api/client/http/httparty_fix.rb +53 -0
  32. data/lib/occi/api/client/http/net_http_fix.rb +46 -0
  33. data/lib/occi/api/dsl.rb +77 -73
  34. data/lib/occi/bin/helpers.rb +91 -0
  35. data/lib/occi/bin/occi_opts.rb +251 -0
  36. data/lib/occi/bin/resource_output_factory.rb +90 -0
  37. data/lib/occi/bin/templates/compute.erb +15 -0
  38. data/lib/occi/bin/templates/network.erb +11 -0
  39. data/lib/occi/bin/templates/os_tpl.erb +9 -0
  40. data/lib/occi/bin/templates/resource_tpl.erb +9 -0
  41. data/lib/occi/bin/templates/storage.erb +10 -0
  42. data/lib/occi/collection.rb +122 -25
  43. data/lib/occi/core.rb +18 -9
  44. data/lib/occi/core/action.rb +20 -4
  45. data/lib/occi/core/action_instance.rb +24 -0
  46. data/lib/occi/core/actions.rb +22 -0
  47. data/lib/occi/core/attribute_properties.rb +33 -84
  48. data/lib/occi/core/attributes.rb +32 -14
  49. data/lib/occi/core/categories.rb +46 -0
  50. data/lib/occi/core/category.rb +94 -20
  51. data/lib/occi/core/entities.rb +50 -0
  52. data/lib/occi/core/entity.rb +130 -89
  53. data/lib/occi/core/kind.rb +28 -35
  54. data/lib/occi/core/kinds.rb +22 -0
  55. data/lib/occi/core/link.rb +43 -40
  56. data/lib/occi/core/links.rb +34 -0
  57. data/lib/occi/core/mixin.rb +28 -23
  58. data/lib/occi/core/mixins.rb +22 -0
  59. data/lib/occi/core/related.rb +20 -0
  60. data/lib/occi/core/resource.rb +40 -40
  61. data/lib/occi/core/resources.rb +14 -0
  62. data/lib/occi/infrastructure.rb +27 -0
  63. data/lib/occi/infrastructure/compute.rb +159 -0
  64. data/lib/occi/infrastructure/network.rb +131 -0
  65. data/lib/occi/infrastructure/network/ipnetwork.rb +34 -0
  66. data/lib/occi/infrastructure/networkinterface.rb +124 -0
  67. data/lib/occi/infrastructure/networkinterface/ipnetworkinterface.rb +34 -0
  68. data/lib/occi/infrastructure/os_tpl.rb +19 -0
  69. data/lib/occi/infrastructure/resource_tpl.rb +19 -0
  70. data/lib/occi/infrastructure/storage.rb +96 -0
  71. data/lib/occi/infrastructure/storagelink.rb +73 -0
  72. data/lib/occi/log.rb +6 -2
  73. data/lib/occi/model.rb +38 -70
  74. data/lib/occi/parser.rb +108 -88
  75. data/lib/occi/version.rb +2 -2
  76. data/lib/occiantlr/OCCIANTLR.g +6 -5
  77. data/lib/occiantlr/OCCIANTLRLexer.rb +52 -52
  78. data/lib/occiantlr/OCCIANTLRParser.rb +678 -569
  79. data/lib/occiantlr/README.md +1 -1
  80. data/occi.gemspec +2 -1
  81. data/spec/cassettes/client_http_text_plain.yml +1066 -0
  82. data/spec/occi/api/client/client_amqp_spec.rb +148 -0
  83. data/spec/occi/api/client/client_http_0.5_spec.rb +292 -0
  84. data/spec/occi/api/client/client_http_spec.rb +259 -0
  85. data/spec/occi/api/dsl_spec.rb +0 -0
  86. data/spec/occi/collection_spec.rb +23 -10
  87. data/spec/occi/core/categories_spec.rb +30 -0
  88. data/spec/occi/core/category_spec.rb +41 -0
  89. data/spec/occi/core/entity_spec.rb +52 -0
  90. data/spec/occi/core/resource_spec.rb +21 -0
  91. data/spec/occi/infrastructure/compute_spec.rb +32 -0
  92. data/spec/occi/log_spec.rb +10 -10
  93. data/spec/occi/model_spec.rb +24 -24
  94. data/spec/occi/parser_spec.rb +89 -39
  95. data/spec/occi/test.json +22 -58
  96. data/spec/occiantlr/parser_spec.rb +5 -7
  97. data/spec/spec_helper.rb +13 -3
  98. metadata +116 -19
  99. data/etc/model/infrastructure/compute.json +0 -108
  100. data/etc/model/infrastructure/ipnetwork.json +0 -40
  101. data/etc/model/infrastructure/ipnetworkinterface.json +0 -40
  102. data/etc/model/infrastructure/network.json +0 -55
  103. data/etc/model/infrastructure/networkinterface.json +0 -38
  104. data/etc/model/infrastructure/os_template.json +0 -9
  105. data/etc/model/infrastructure/resource_template.json +0 -9
  106. data/etc/model/infrastructure/storage.json +0 -72
  107. data/etc/model/infrastructure/storagelink.json +0 -38
  108. data/lib/occi/api/client.rb +0 -596
  109. data/lib/occi/client/occiopts.rb +0 -146
  110. data/spec/occi/client_spec.rb +0 -12
@@ -0,0 +1,73 @@
1
+ module Occi
2
+ module Infrastructure
3
+ class Storagelink < Occi::Core::Link
4
+
5
+ class Online < Occi::Core::Action
6
+ def initialize(scheme='http://schemas.ogf.org/occi/infrastructure/storagelink/action#',
7
+ term='online',
8
+ title='activate storagelink')
9
+ super
10
+ end
11
+ end
12
+
13
+ class Offline < Occi::Core::Action
14
+ def initialize(scheme='http://schemas.ogf.org/occi/infrastructure/storagelink/action#',
15
+ term='offline',
16
+ title='deactivate storagelink')
17
+ super
18
+ end
19
+ end
20
+
21
+ def self.actions
22
+ Occi::Core::Actions.new << Online.new << Offline.new
23
+ end
24
+
25
+ begin
26
+ @kind = Occi::Core::Kind.new('http://schemas.ogf.org/occi/infrastructure#', 'storagelink')
27
+
28
+ @kind.title = "storage link"
29
+
30
+ @kind.related << Occi::Core::Link.kind
31
+
32
+ @kind.attributes.occi!.storagelink!.deviceid = Occi::Core::AttributeProperties.new(
33
+ { :mutable => true })
34
+
35
+ @kind.attributes.occi!.storagelink!.mountpoint = Occi::Core::AttributeProperties.new(
36
+ { :mutable => true })
37
+
38
+ @kind.attributes.occi!.storagelink!.state = Occi::Core::AttributeProperties.new(
39
+ { :pattern => 'active|inactive|error',
40
+ :default => 'inactive' })
41
+
42
+ @kind.location = '/storagelink/'
43
+
44
+ @kind.actions = self.actions
45
+ end
46
+
47
+ def deviceid
48
+ @attributes.occi.storagelink.deviceid if @attributes.occi.storagelink if @attributes.occi
49
+ end
50
+
51
+ def deviceid=(deviceid)
52
+ @attributes.occi!.storagelink!.deviceid = deviceid
53
+ end
54
+
55
+ def mountpoint
56
+ @attributes.occi.storagelink.mountpoint if @attributes.occi.storagelink if @attributes.occi
57
+ end
58
+
59
+ def mountpoint=(mountpoint)
60
+ @attributes.occi!.storagelink!.mountpoint = mountpoint
61
+ end
62
+
63
+ def state
64
+ @attributes.occi.storagelink.state if @attributes.occi.storagelink if @attributes.occi
65
+ end
66
+
67
+ def state=(state)
68
+ @attributes.occi!.storagelink!.state = state
69
+ end
70
+
71
+ end
72
+ end
73
+ end
data/lib/occi/log.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'logger'
2
2
 
3
- module OCCI
3
+ module Occi
4
4
  class Log
5
5
 
6
6
  include ::Logger::Severity
@@ -19,10 +19,14 @@ module OCCI
19
19
 
20
20
  # subscribe to log messages and send to logger
21
21
  @log_subscriber = ActiveSupport::Notifications.subscribe("log") do |name, start, finish, id, payload|
22
- @logger.log(payload[:level], payload[:message])
22
+ @logger.log(payload[:level], payload[:message]) if @logger
23
23
  end
24
24
  end
25
25
 
26
+ def close
27
+ ActiveSupport::Notifications.unsubscribe(@log_subscriber)
28
+ end
29
+
26
30
  # @param [Logger::Severity] severity
27
31
  def level=(severity)
28
32
  @logger.level = severity
data/lib/occi/model.rb CHANGED
@@ -1,31 +1,29 @@
1
- require 'hashie/mash'
2
- require 'occi/log'
1
+ module Occi
2
+ class Model < Occi::Collection
3
3
 
4
- module OCCI
5
- class Model
6
- attr_accessor :categories
7
- attr_accessor :locations
8
-
9
- # @param [OCCI::Core::Collection] collection
4
+ # @param [Occi::Core::Collection] collection
10
5
  def initialize(collection=nil)
11
- @categories = { }
12
- @locations = { }
6
+ super(nil, nil) # model must be empty for model class
13
7
  register_core
14
- register_collection collection if collection.kind_of? OCCI::Collection
8
+ register_collection collection if collection.kind_of? Occi::Collection
9
+ end
10
+
11
+ def model=(model)
12
+ # will not assign a model inside a model
15
13
  end
16
14
 
17
- # register OCCI Core categories enitity, resource and link
15
+ # register Occi Core categories enitity, resource and link
18
16
  def register_core
19
- OCCI::Log.info "### Registering OCCI Core categories enitity, resource and link ###"
20
- register OCCI::Core::Entity.kind_definition
21
- register OCCI::Core::Resource.kind_definition
22
- register OCCI::Core::Link.kind_definition
17
+ Occi::Log.info "### Registering OCCI Core categories enitity, resource and link ###"
18
+ register Occi::Core::Entity.kind
19
+ register Occi::Core::Resource.kind
20
+ register Occi::Core::Link.kind
23
21
  end
24
22
 
25
- # register OCCI Infrastructure categories
23
+ # register Occi Infrastructure categories
26
24
  def register_infrastructure
27
- OCCI::Log.info "### Registering OCCI Infrastructure categories ###"
28
- register_files File.dirname(__FILE__) + '/../../etc/model/infrastructure'
25
+ Occi::Log.info "### Registering OCCI Infrastructure categories ###"
26
+ Occi::Infrastructure.categories.each { |category| register category }
29
27
  end
30
28
 
31
29
  # register OCCI categories from files
@@ -34,9 +32,9 @@ module OCCI
34
32
  # recursively searched for files with the extension .json .
35
33
  # @param [Sting] scheme_base_url base location for provider specific extensions of the OCCI model
36
34
  def register_files(path, scheme_base_url='http://localhost')
37
- OCCI::Log.info "### Initializing OCCI Model from #{path} ###"
35
+ Occi::Log.info "### Initializing OCCI Model from #{path} ###"
38
36
  Dir.glob(path + '/**/*.json').each do |file|
39
- collection = OCCI::Collection.new(JSON.parse(File.read(file)))
37
+ collection = Occi::Collection.new(JSON.parse(File.read(file)))
40
38
  # add location of service provider to scheme if it has a relative location
41
39
  collection.kinds.collect { |kind| kind.scheme = scheme_base_url + kind.scheme if kind.scheme.start_with? '/' } if collection.kinds
42
40
  collection.mixins.collect { |mixin| mixin.scheme = scheme_base_url + mixin.scheme if mixin.scheme.start_with? '/' } if collection.mixins
@@ -47,71 +45,41 @@ module OCCI
47
45
 
48
46
  # register OCCI categories from OCCI collection
49
47
  def register_collection(collection)
50
- collection.categories.each { |category| register category }
48
+ collection.kinds.each { |kind| kind.model = self }
49
+ collection.mixins.each { |mixin| mixin.model = self }
50
+ collection.actions.each { |action| action.model = self }
51
+ merge! collection
51
52
  end
52
53
 
53
54
  # clear all entities from all categories
54
55
  def reset()
55
- @categories.each_value.each { |category| category.entities = [] if category.respond_to? :entities }
56
+ categories.each { |category| category.entities = [] if category.respond_to? :entities }
56
57
  end
57
58
 
58
- # @param [OCCI::Core::Category] category
59
+ # @param [Occi::Core::Category] category
59
60
  def register(category)
60
- OCCI::Log.debug "### Registering category #{category.type_identifier}"
61
- @categories[category.type_identifier] = category
62
- @locations[category.location] = category.type_identifier unless category.kind_of? OCCI::Core::Action
61
+ Occi::Log.debug "### Registering category #{category}"
63
62
  # add model to category as back reference
64
63
  category.model = self
64
+ @kinds << category unless get_by_id(category.to_s) if category.class.ancestors.include? Occi::Core::Kind
65
+ @mixins << category unless get_by_id(category.to_s) if category.class.ancestors.include? Occi::Core::Mixin
66
+ @actions << category unless get_by_id(category.to_s) if category.class.ancestors.include? Occi::Core::Action
65
67
  end
66
68
 
67
- # @param [OCCI::Core::Category] category
69
+ # @param [Occi::Core::Category] category
68
70
  def unregister(category)
69
- OCCI::Log.debug "### Unregistering category #{category.type_identifier}"
70
- @categories.delete category.type_identifier
71
- @locations.delete category.location unless category.kind_of? OCCI :Core::Action
72
- end
73
-
74
- # Returns the category corresponding to a given type identifier
75
- #
76
- # @param [URI] id type identifier of a category
77
- # @return [OCCI::Core::Category]
78
- def get_by_id(id)
79
- @categories.fetch(id) { OCCI::Log.debug("Category with id #{id} not found"); nil }
80
- end
81
-
82
- # Returns the category corresponding to a given location
83
- #
84
- # @param [URI] location
85
- # @return [OCCI::Core::Category]
86
- def get_by_location(location)
87
- id = @locations.fetch(location) { OCCI::Log.debug("Category with location #{location} not found"); nil }
88
- get_by_id id
71
+ Occi::Log.debug "### Unregistering category #{category.type_identifier}"
72
+ @kinds.delete category
73
+ @mixins.delete category
74
+ @actions.delete category
89
75
  end
90
76
 
91
77
  # Return all categories from model. If filter is present, return only the categories specified by filter
92
78
  #
93
- # @param [OCCI::Collection] filter
94
- # @return [OCCI::Collection] collection
95
- def get(filter = OCCI::Collection.new)
96
- collection = OCCI::Collection.new
97
- if filter.empty?
98
- @categories.each_value do |category|
99
- collection.kinds << category if category.kind_of? OCCI::Core::Kind
100
- collection.mixins << category if category.kind_of? OCCI::Core::Mixin
101
- collection.actions << category if category.kind_of? OCCI::Core::Action
102
- end
103
- else
104
- categories = filter.categories
105
- OCCI::Log.debug("### Filtering categories #{categories.collect { |c| c.type_identifier }.inspect}")
106
- while categories.any? do
107
- category = categories.pop
108
- categories.concat @categories.each_value.select { |cat| cat.related_to?(category.type_identifier) }
109
- collection.kinds << get_by_id(category.type_identifier) if category.kind_of? OCCI::Core::Kind
110
- collection.mixins << get_by_id(category.type_identifier) if category.kind_of? OCCI::Core::Mixin
111
- collection.actions << get_by_id(category.type_identifier) if category.kind_of? OCCI::Core::Action
112
- end
113
- end
114
- collection
79
+ # @param [Occi::Collection] filter
80
+ # @return [Occi::Collection] collection
81
+ def get(filter = nil)
82
+ filter ? intersect(filter) : self
115
83
  end
116
84
 
117
85
  end
data/lib/occi/parser.rb CHANGED
@@ -1,4 +1,4 @@
1
- module OCCI
1
+ module Occi
2
2
  class Parser
3
3
 
4
4
  # Declaring Class constants for OVF XML namespaces (defined in OVF specification ver.1.1)
@@ -12,24 +12,25 @@ module OCCI
12
12
  # @param [String] media_type the media type of the OCCI message
13
13
  # @param [String] body the body of the OCCI message
14
14
  # @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
15
- # @param [OCCI::Core::Resource,OCCI::Core::Link] entity_type entity type to use for parsing of text plain entities
15
+ # @param [Occi::Core::Resource,Occi::Core::Link] entity_type entity type to use for parsing of text plain entities
16
16
  # @param [Hash] header optional header of the OCCI message
17
- # @return [Array<Array, OCCI::Collection>] list consisting of an array of locations and the OCCI object collection
18
- def self.parse(media_type, body, category=false, entity_type=OCCI::Core::Resource, header={ })
19
- OCCI::Log.debug '### Parsing request data to OCCI data structure ###'
20
- collection = OCCI::Collection.new
17
+ # @return [Occi::Collection] list consisting of an array of locations and the OCCI object collection
18
+ def self.parse(media_type, body, category=false, entity_type=Occi::Core::Resource, header={ })
19
+ Occi::Log.debug '### Parsing request data to OCCI Collection ###'
20
+ collection = Occi::Collection.new
21
21
 
22
- locations = self.header_locations(header)
23
- category ? collection = self.header_categories(header) : collection = self.header_entity(header, entity_type) if locations.empty?
22
+ # remove trailing HTTP_ prefix if present
23
+ header = Hash[header.map {|k, v| [k.gsub('HTTP_','').upcase, v] }]
24
+
25
+ category ? collection = self.header_categories(header) : collection = self.header_entity(header, entity_type)
24
26
 
25
27
  case media_type
26
28
  when 'text/uri-list'
27
- body.each_line { |line| locations << URI.parse(line.chomp) }
29
+ nil
28
30
  when 'text/occi'
29
31
  nil
30
32
  when 'text/plain', nil
31
- locations.concat self.text_locations(body)
32
- category ? collection = self.text_categories(body) : collection = self.text_entity(body, entity_type) if locations.empty? && collection.empty?
33
+ category ? collection = self.text_categories(body) : collection = self.text_entity(body, entity_type) if collection.empty?
33
34
  when 'application/occi+json', 'application/json'
34
35
  collection = self.json(body)
35
36
  when 'application/occi+xml', 'application/xml'
@@ -41,7 +42,20 @@ module OCCI
41
42
  else
42
43
  raise "Content Type not supported"
43
44
  end
44
- return locations, collection
45
+ collection
46
+ end
47
+
48
+ def self.locations(media_type, body, header)
49
+ locations = self.header_locations(header)
50
+ case media_type
51
+ when 'text/uri-list'
52
+ body.each_line { |line| locations << URI.parse(line.chomp) }
53
+ when 'text/plain', nil
54
+ locations.concat self.text_locations(body)
55
+ else
56
+ nil
57
+ end
58
+ locations
45
59
  end
46
60
 
47
61
  private
@@ -49,33 +63,33 @@ module OCCI
49
63
  # @param [Hash] header
50
64
  # @return [Array] list of URIs
51
65
  def self.header_locations(header)
52
- x_occi_location_strings = header['HTTP_X_OCCI_LOCATION'].to_s.split(',')
66
+ x_occi_location_strings = header['X_OCCI_LOCATION'].to_s.split(',')
53
67
  x_occi_location_strings.collect { |loc| OCCIANTLR::Parser.new('X-OCCI-Location: ' + loc).x_occi_location }
54
68
  end
55
69
 
56
70
  # @param [Hash] header
57
- # @return [OCCI::Collection]
71
+ # @return [Occi::Collection]
58
72
  def self.header_categories(header)
59
- collection = OCCI::Collection.new
60
- category_strings = header['HTTP_CATEGORY'].to_s.split(',')
73
+ collection = Occi::Collection.new
74
+ category_strings = header['CATEGORY'].to_s.split(',')
61
75
  category_strings.each do |cat|
62
76
  category = OCCIANTLR::Parser.new('Category: ' + cat).category
63
- collection.kinds.concat category.kinds.collect { |kind| OCCI::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) }
64
- collection.mixins.concat category.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) }
65
- collection.actions.concat category.actions.collect { |action| OCCI::Core::Action.new(action.scheme, action.term, action.title, action.attributes) }
77
+ collection.kinds.merge category.kinds.collect { |kind| Occi::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) }
78
+ collection.mixins.merge category.mixins.collect { |mixin| Occi::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) }
79
+ collection.actions.merge category.actions.collect { |action| Occi::Core::Action.new(action.scheme, action.term, action.title, action.attributes) }
66
80
  end
67
81
  collection
68
82
  end
69
83
 
70
84
  # @param [Hash] header
71
85
  # @param [Class] entity_type
72
- # @return [OCCI::Collection]
86
+ # @return [Occi::Collection]
73
87
  def self.header_entity(header, entity_type)
74
- collection = OCCI::Collection.new
88
+ collection = Occi::Collection.new
75
89
  entity = Hashie::Mash.new
76
- category_strings = header['HTTP_CATEGORY'].to_s.split(',')
90
+ category_strings = header['CATEGORY'].to_s.split(',')
77
91
  return collection if category_strings.empty?
78
- attribute_strings = header['HTTP_X_OCCI_ATTRIBUTE'].to_s.split(',')
92
+ attribute_strings = header['X_OCCI_ATTRIBUTE'].to_s.split(',')
79
93
  categories = Hashie::Mash.new({ :kinds => [], :mixins => [], :actions => [] })
80
94
  category_strings.each do |category|
81
95
  cat = OCCIANTLR::Parser.new('Category: ' + category).category
@@ -88,16 +102,16 @@ module OCCI
88
102
  entity.kind = categories.kinds.first.scheme + categories.kinds.first.term
89
103
  entity.mixins = categories.mixins.collect { |mixin| mixin.scheme + mixin.term } if categories.mixins.any?
90
104
  attribute_strings.each { |attr| entity.attributes!.merge!(OCCIANTLR::Parser.new('X-OCCI-Attribute: ' + attr).x_occi_attribute) }
91
- if entity_type == OCCI::Core::Link
105
+ if entity_type == Occi::Core::Link
92
106
  entity.target = link.attributes!.occi!.core!.target
93
107
  entity.source = link.attributes!.occi!.core!.source
94
108
  cats = entity.categories.split(' ')
95
109
  kind = cats.reverse!.pop
96
110
  mixins = cats.categories
97
- collection.links << OCCI::Core::Link.new(kind, mixins, entity.attributes)
98
- elsif entity_type == OCCI::Core::Resource
111
+ collection.links << Occi::Core::Link.new(kind, mixins, entity.attributes)
112
+ elsif entity_type == Occi::Core::Resource
99
113
  entity.links = []
100
- link_strings = header['HTTP_LINK'].to_s.split(',')
114
+ link_strings = header['LINK'].to_s.split(',')
101
115
  link_strings.each do |link_string|
102
116
  link = OCCIANTLR::Parser.new('Link: ' + link_string).link
103
117
  if link.rel.include? 'action#'
@@ -105,15 +119,14 @@ module OCCI
105
119
  else
106
120
  link.attributes!.occi!.core!.target = link.target
107
121
 
108
- link.category ||= 'http://schemas.ogf.org/occi/core#link'
109
- cats = link.category.split(' ')
110
- kind = cats.reverse!.pop
111
- mixins = cats
122
+ link.categories = (link.categories.presence || %w'http://schemas.ogf.org/occi/core#link')
123
+ kind = link.categories.reverse!.pop
124
+ mixins = link.categories
112
125
 
113
- entity.links << OCCI::Core::Link.new(kind, mixins, link.attributes, link.actions, link.rel, link.target, link.source)
126
+ entity.links << Occi::Core::Link.new(kind, mixins, link.attributes, link.actions, link.rel, link.target, link.source)
114
127
  end
115
128
  end
116
- collection.resources << OCCI::Core::Resource.new(entity.kind, entity.mixins, entity.attributes, entity.actions, entity.links)
129
+ collection.resources << Occi::Core::Resource.new(entity.kind, entity.mixins, entity.attributes, entity.actions, entity.links)
117
130
  end
118
131
  collection
119
132
  end
@@ -125,28 +138,27 @@ module OCCI
125
138
  end
126
139
 
127
140
  # @param [String] text
128
- # @return [OCCI::Collection]
141
+ # @return [Occi::Collection]
129
142
  def self.text_categories(text)
130
- collection = OCCI::Collection.new
143
+ collection = Occi::Collection.new
131
144
  text.each_line do |line|
132
145
  category = OCCIANTLR::Parser.new(line.chomp).category
133
146
  next if category.nil?
134
- collection.kinds.concat category.kinds.collect { |kind| OCCI::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) }
135
- collection.mixins.concat category.mixins.collect { |mixin| OCCI::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) }
136
- collection.actions.concat category.actions.collect { |action| OCCI::Core::Action.new(action.scheme, action.term, action.title, action.attributes) }
147
+ collection.kinds.merge category.kinds.collect { |kind| Occi::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) }
148
+ collection.mixins.merge category.mixins.collect { |mixin| Occi::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) }
149
+ collection.actions.merge category.actions.collect { |action| Occi::Core::Action.new(action.scheme, action.term, action.title, action.attributes) }
137
150
  end
138
151
  collection
139
152
  end
140
153
 
141
154
  # @param [String] text
142
155
  # @param [Class] entity_type
143
- # @return [OCCI::Collection]
156
+ # @return [Occi::Collection]
144
157
  def self.text_entity(text, entity_type)
145
- collection = OCCI::Collection.new
146
- entity = Hashie::Mash.new
147
- links = []
148
- entity.links = []
149
- categories = Hashie::Mash.new({ :kinds => [], :mixins => [], :actions => [] })
158
+ collection = Occi::Collection.new
159
+ entity = Hashie::Mash.new
160
+ links = []
161
+ categories = Hashie::Mash.new({ :kinds => [], :mixins => [], :actions => [] })
150
162
  text.each_line do |line|
151
163
  if line.include? 'Category'
152
164
  cat = (OCCIANTLR::Parser.new(line.chomp).category)
@@ -159,49 +171,48 @@ module OCCI
159
171
  end
160
172
  entity.kind = categories.kinds.first.scheme + categories.kinds.first.term if categories.kinds.first
161
173
  entity.mixins = categories.mixins.collect { |mixin| mixin.scheme + mixin.term } if categories.mixins
162
- if entity_type == OCCI::Core::Link
174
+ if entity_type == Occi::Core::Link
163
175
  entity.target = links.first.attributes!.occi!.core!.target
164
176
  entity.source = links.first.attributes!.occi!.core!.source
165
177
  cats = entity.categories.split(' ')
166
178
  kind = cats.reverse!.pop
167
- mixins = cats.categories
168
-
169
- collection.links << OCCI::Core::Link.new(kind, mixins, entity.attributes)
170
- elsif entity_type == OCCI::Core::Resource
179
+ mixins = cats
180
+ collection.links << Occi::Core::Link.new(kind, mixins, entity.attributes)
181
+ elsif entity_type == Occi::Core::Resource
182
+ entity.links = []
171
183
  links.each do |link|
172
184
  if link.rel.include? 'action#'
173
185
  entity.actions = [link.rel] + entity.actions.to_a
174
186
  else
175
187
  link.attributes!.occi!.core!.target = link.target
176
- link.category ||= 'http://schemas.ogf.org/occi/core#link'
177
- cats = link.category.split(' ')
178
- kind = cats.reverse!.pop
179
- mixins = cats
180
188
 
181
- link = OCCI::Core::Link.new(kind, mixins, link.attributes, link.actions, link.rel, link.target, link.source)
182
- collection.links << link
189
+ link.categories = (link.categories.presence || %w'http://schemas.ogf.org/occi/core#link')
190
+ cats = link.categories
191
+ kind = link.categories.reverse!.pop
192
+ mixins = link.categories
193
+
194
+ link = Occi::Core::Link.new(kind, mixins, link.attributes, link.actions, link.rel, link.target, link.source)
183
195
  entity.links << link
184
196
  end
185
197
  end
186
- collection.resources << OCCI::Core::Resource.new(entity.kind, entity.mixins, entity.attributes, entity.actions, entity.links)
198
+ collection.resources << Occi::Core::Resource.new(entity.kind, entity.mixins, entity.attributes, entity.actions, entity.links)
187
199
  end unless entity.kind.nil?
188
200
  collection
189
201
  end
190
202
 
191
203
  # @param [String] json
192
- # @return [OCCI::Collection]
204
+ # @return [Occi::Collection]
193
205
  def self.json(json)
194
- collection = OCCI::Collection.new
195
- hash = Hashie::Mash.new(JSON.parse(json))
196
- 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
197
- 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
198
- collection.actions.concat hash.actions.collect { |action| OCCI::Core::Action.new(action.scheme, action.term, action.title, action.attributes) } if hash.actions
199
- collection.resources.concat hash.resources.collect { |resource| OCCI::Core::Resource.new(resource.kind, resource.mixins, resource.attributes, resource.actions, resource.links) } if hash.resources
200
- collection.links.concat hash.links.collect { |link| OCCI::Core::Link.new(link.kind, link.mixins, link.attributes, link.actions, link.rel, link.target, link.source) } if hash.links
201
-
202
- if collection.resources.size == 1 && collection.links.size > 0
206
+ collection = Occi::Collection.new
207
+ hash = Hashie::Mash.new(JSON.parse(json))
208
+ collection.kinds.merge hash.kinds.collect { |kind| Occi::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) } if hash.kinds
209
+ collection.mixins.merge hash.mixins.collect { |mixin| Occi::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) } if hash.mixins
210
+ collection.actions.merge hash.actions.collect { |action| Occi::Core::Action.new(action.scheme, action.term, action.title, action.attributes) } if hash.actions
211
+ collection.resources.merge hash.resources.collect { |resource| Occi::Core::Resource.new(resource.kind, resource.mixins, resource.attributes, resource.actions, resource.links) } if hash.resources
212
+ collection.links.merge hash.links.collect { |link| Occi::Core::Link.new(link.kind, link.mixins, link.attributes) } if hash.links
213
+
214
+ if collection.resources.size == 1 & collection.links.size > 0
203
215
  if collection.resources.first.links.empty?
204
- collection.links.each { |link| link.source = collection.resources.first }
205
216
  collection.resources.first.links = collection.links
206
217
  end
207
218
  end
@@ -218,14 +229,15 @@ module OCCI
218
229
  end
219
230
 
220
231
  # @param [String] xml
221
- # @return [OCCI::Collection]
232
+ # @return [Occi::Collection]
222
233
  def self.xml(xml)
223
- collection = OCCI::Collection.new
234
+ collection = Occi::Collection.new
224
235
  hash = Hashie::Mash.new(Hash.from_xml(Nokogiri::XML(xml)))
225
- 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
226
- 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
227
- collection.resources.concat hash.resources.collect { |resource| OCCI::Core::Resource.new(resource.kind, resource.mixins, resource.attributes, resource.actions, resource.links) } if hash.resources
228
- collection.links.concat hash.links.collect { |link| OCCI::Core::Link.new(link.kind, link.mixins, link.attributes) } if hash.links
236
+ collection.kinds.merge hash.kinds.collect { |kind| Occi::Core::Kind.new(kind.scheme, kind.term, kind.title, kind.attributes, kind.related, kind.actions) } if hash.kinds
237
+ collection.mixins.merge hash.mixins.collect { |mixin| Occi::Core::Mixin.new(mixin.scheme, mixin.term, mixin.title, mixin.attributes, mixin.related, mixin.actions) } if hash.mixins
238
+ collection.actions.merge hash.actions.collect { |action| Occi::Core::Action.new(action.scheme, action.term, action.title, action.attributes) } if hash.actions
239
+ collection.resources.merge hash.resources.collect { |resource| Occi::Core::Resource.new(resource.kind, resource.mixins, resource.attributes, resource.actions, resource.links) } if hash.resources
240
+ collection.links.merge hash.links.collect { |link| Occi::Core::Link.new(link.kind, link.mixins, link.attributes) } if hash.links
229
241
  collection
230
242
  end
231
243
 
@@ -239,7 +251,7 @@ module OCCI
239
251
 
240
252
 
241
253
  def self.calculate_capacity_gb(capacity)
242
- capacity_gb = capacity/(2**30)
254
+ capacity_gb = capacity.to_f/(2**30)
243
255
  capacity_gb
244
256
  end
245
257
 
@@ -256,7 +268,7 @@ module OCCI
256
268
  ###############End of Helper methods for OVF Parsing ##################################################################
257
269
 
258
270
  # @param [String] ova
259
- # @return [OCCI::Collection]
271
+ # @return [Occi::Collection]
260
272
  def self.ova(ova)
261
273
  tar = Gem::Package::TarReader.new(StringIO.new(ova))
262
274
  ovf = mf = cert = nil
@@ -274,7 +286,7 @@ module OCCI
274
286
  File.read(mf).each_line do |line|
275
287
  name = line.scan(/SHA1\(([^\)]*)\)= (.*)/).flatten.first
276
288
  sha1 = line.scan(/SHA1\(([^\)]*)\)= (.*)/).flatten.last
277
- puts Digest::SHA1.hexdigest(files[name])
289
+ Occi::Log.debug "SHA1 hash #{Digest::SHA1.hexdigest(files[name])}"
278
290
  raise "SHA1 mismatch for file #{name}" if Digest::SHA1.hexdigest(File.read(files[name])) != sha1
279
291
  end if mf
280
292
 
@@ -286,7 +298,7 @@ module OCCI
286
298
  # @param [String] ovf
287
299
  # @param [Hash] files key value pairs of file names and paths to the file
288
300
  def self.ovf(ovf, files={ })
289
- collection = OCCI::Collection.new
301
+ collection = Occi::Collection.new
290
302
  doc = Nokogiri::XML(ovf)
291
303
  references = { }
292
304
 
@@ -304,9 +316,9 @@ module OCCI
304
316
  end
305
317
 
306
318
  doc.xpath('envelope:Envelope/envelope:DiskSection/envelope:Disk', 'envelope' => "#{Parser::OVF}").each do |disk|
307
- storage = OCCI::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#storage')
319
+ storage = Occi::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#storage')
308
320
  if disk.attributes['fileRef']
309
- storagelink = OCCI::Core::Link.new("http://schemas.ogf.org/occi/infrastructure#storagelink")
321
+ storagelink = Occi::Core::Link.new("http://schemas.ogf.org/occi/infrastructure#storagelink")
310
322
  storagelink.attributes.occi!.core!.title = disk.attributes['fileRef'].to_s
311
323
  storagelink.attributes.occi!.core!.target = references[disk.attributes['fileRef'].to_s]
312
324
  storage.attributes.occi!.core!.title = disk.attributes['diskId'].to_s
@@ -326,7 +338,7 @@ module OCCI
326
338
  capacity = self.calculate_capacity_bytes(disk.attributes['capacity'].to_s, alloc_unit_bytes)
327
339
  end
328
340
  capacity_gb = self.calculate_capacity_gb(capacity)
329
- OCCI::Log.debug('capacity in gb ' + capacity_gb.to_s)
341
+ Occi::Log.debug('capacity in gb ' + capacity_gb.to_s)
330
342
  storage.attributes.occi!.storage!.size = capacity_gb.to_s if capacity_gb
331
343
  storage.attributes.occi!.core!.title = disk.attributes['diskId'].to_s if disk.attributes['diskId']
332
344
  end
@@ -334,14 +346,14 @@ module OCCI
334
346
  end
335
347
 
336
348
  doc.xpath('envelope:Envelope/envelope:NetworkSection/envelope:Network', 'envelope' => "#{Parser::OVF}").each do |nw|
337
- network = OCCI::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#network')
349
+ network = Occi::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#network')
338
350
  network.attributes.occi!.core!.title = nw.attributes['name'].to_s
339
351
  collection.resources << network
340
352
  end
341
353
 
342
354
  # Iteration through all the virtual hardware sections,and a sub-iteration on each Item defined in the Virtual Hardware section
343
355
  doc.xpath('envelope:Envelope/envelope:VirtualSystem', 'envelope' => "#{Parser::OVF}").each do |virtsys|
344
- compute = OCCI::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#compute')
356
+ compute = Occi::Core::Resource.new('http://schemas.ogf.org/occi/infrastructure#compute')
345
357
 
346
358
  doc.xpath('envelope:Envelope/envelope:VirtualSystem/envelope:VirtualHardwareSection', 'envelope' => "#{Parser::OVF}").each do |virthwsec|
347
359
  compute.attributes.occi!.core!.summary = virthwsec.xpath("item:Info/text()", 'item' => "#{Parser::RASD}").to_s
@@ -351,27 +363,35 @@ module OCCI
351
363
  case resType.to_s
352
364
  # 4 is the ResourceType for memory in the CIM_ResourceAllocationSettingData
353
365
  when "4" then
354
- compute.attributes.occi!.compute!.memory = resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{Parser::RASD}").to_s.to_i
366
+ Occi::Log.debug('calculating memory in gb ')
367
+ alloc_units = resource_alloc.xpath("item:AllocationUnits/text()", 'item' => "#{Parser::RASD}").to_s
368
+ Occi::Log.debug('allocated units in ovf file: ' + alloc_units)
369
+ alloc_unit_bytes = self.alloc_units_bytes(alloc_units)
370
+ capacity = self.calculate_capacity_bytes(resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{Parser::RASD}").to_s, alloc_unit_bytes)
371
+ capacity_gb = self.calculate_capacity_gb(capacity)
372
+ Occi::Log.debug('virtual quantity of memory configured in gb: ' + capacity_gb.to_s)
373
+ compute.attributes.occi!.compute!.memory = capacity_gb
374
+ # compute.attributes.occi!.compute!.memory = resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{Parser::RASD}").to_s.to_i
355
375
  # 3 is the ResourceType for processor in the CIM_ResourceAllocationSettingData
356
376
  when "3" then
357
377
  compute.attributes.occi!.compute!.cores = resource_alloc.xpath("item:VirtualQuantity/text()", 'item' => "#{Parser::RASD}").to_s.to_i
358
378
  when "10" then
359
- networkinterface = OCCI::Core::Link.new('http://schemas.ogf.org/occi/infrastructure#networkinterface')
379
+ networkinterface = Occi::Core::Link.new('http://schemas.ogf.org/occi/infrastructure#networkinterface')
360
380
  networkinterface.attributes.occi!.core!.title = resource_alloc.xpath("item:ElementName/text()", 'item' => "#{Parser::RASD}").to_s
361
381
  id = resource_alloc.xpath("item:Connection/text()", 'item' => "#{Parser::RASD}").to_s
362
382
  network = collection.resources.select { |resource| resource.attributes.occi!.core!.title == id }.first
363
383
  raise "Network with id #{id} not found" unless network
364
- networkinterface.attributes.occi!.core!.target = network.location
384
+ networkinterface.attributes.occi!.core!.target = network
365
385
  when "17" then
366
- storagelink = OCCI::Core::Link.new("http://schemas.ogf.org/occi/infrastructure#storagelink")
386
+ storagelink = Occi::Core::Link.new("http://schemas.ogf.org/occi/infrastructure#storagelink")
367
387
  storagelink.attributes.occi!.core!.title = resource_alloc.xpath("item:ElementName/text()", 'item' => "#{Parser::RASD}").to_s
368
388
  # extract the mountpoint
369
389
  host_resource = resource_alloc.xpath("item:HostResource/text()", 'item' => "#{Parser::RASD}").to_s
370
390
  if host_resource.start_with? 'ovf:/disk/'
371
- id = host_resource.gsub('ovf:/disk/', '')
391
+ id = host_resource.gsub('ovf:/disk/', '')
372
392
  storage = collection.resources.select { |resource| resource.attributes.occi!.core!.title == id }.first
373
393
  raise "Disk with id #{id} not found" unless storage
374
- storagelink.attributes.occi!.core!.target = storage.location
394
+ storagelink.attributes.occi!.core!.target = storage
375
395
  elsif host_resource.start_with? 'ovf:/file/'
376
396
  id = host_resource.gsub('ovf:/file/', '')
377
397
  storagelink.attributes.occi!.core!.target = references[id]