occi 2.2.2 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/README.md +48 -18
- data/lib/occi/client.rb +54 -17
- data/lib/occi/collection.rb +25 -7
- data/lib/occi/core/action.rb +7 -0
- data/lib/occi/core/attribute_properties.rb +2 -2
- data/lib/occi/core/attributes.rb +2 -2
- data/lib/occi/core/category.rb +43 -23
- data/lib/occi/core/entity.rb +62 -67
- data/lib/occi/core/kind.rb +32 -5
- data/lib/occi/core/link.rb +14 -51
- data/lib/occi/core/mixin.rb +31 -5
- data/lib/occi/core/resource.rb +34 -33
- data/lib/occi/log.rb +16 -4
- data/lib/occi/model.rb +53 -47
- data/lib/occi/parser.rb +192 -65
- data/lib/occi/version.rb +1 -1
- data/spec/occi/client_spec.rb +12 -0
- data/spec/occi/log_spec.rb +2 -1
- data/spec/occi/model_spec.rb +43 -14
- data/spec/occi/parser_spec.rb +18 -3
- data/spec/occi/test.ova +0 -0
- metadata +6 -3
data/lib/occi/core/kind.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'json'
|
1
|
+
require 'active_support/json'
|
2
2
|
require 'occi/core/category'
|
3
3
|
require 'occi/core/action'
|
4
4
|
require 'occi/core/attribute_properties'
|
@@ -7,13 +7,22 @@ module OCCI
|
|
7
7
|
module Core
|
8
8
|
class Kind < OCCI::Core::Category
|
9
9
|
|
10
|
-
attr_accessor :entities
|
10
|
+
attr_accessor :entities, :related, :actions
|
11
11
|
|
12
|
-
|
12
|
+
# @param [String ] scheme
|
13
|
+
# @param [String] term
|
14
|
+
# @param [String] title
|
15
|
+
# @param [OCCI::Core::AttributeProperties] attributes
|
16
|
+
# @param [Array] related
|
17
|
+
# @param [Array] actions
|
18
|
+
def initialize(scheme, term, title=nil, attributes=nil, related=nil, actions=nil)
|
13
19
|
@entities = []
|
14
|
-
|
20
|
+
@related = related.to_a
|
21
|
+
@actions = actions.to_a
|
22
|
+
super(scheme, term, title, attributes)
|
15
23
|
end
|
16
24
|
|
25
|
+
# @return [String] name of the OCCI core class the entity is related to
|
17
26
|
def entity_type
|
18
27
|
case type_identifier
|
19
28
|
when "http://schemas.ogf.org/occi/core#resource"
|
@@ -25,8 +34,26 @@ module OCCI
|
|
25
34
|
end
|
26
35
|
end
|
27
36
|
|
37
|
+
# @return [String] string containing location URI of kind
|
28
38
|
def location
|
29
|
-
'/' +
|
39
|
+
'/' + @term + '/'
|
40
|
+
end
|
41
|
+
|
42
|
+
def as_json(options={ })
|
43
|
+
kind = Hashie::Mash.new
|
44
|
+
kind.related = @related if @related.any?
|
45
|
+
kind.actions = @actions if @actions.any?
|
46
|
+
kind.merge! super
|
47
|
+
kind
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_text
|
51
|
+
text = super
|
52
|
+
text << ';rel=' + @related.join(' ').inspect if @related.any?
|
53
|
+
text << ';location=' + self.location.inspect
|
54
|
+
text << ';attributes=' + @attributes.combine.join(' ').inspect if @attributes.any?
|
55
|
+
text << ';actions=' + @actions.join(' ').inspect if @actions.any?
|
56
|
+
text
|
30
57
|
end
|
31
58
|
|
32
59
|
end
|
data/lib/occi/core/link.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'hashie/mash'
|
2
|
-
require 'occi/model'
|
3
2
|
require 'occi/core/entity'
|
4
3
|
require 'occi/core/kind'
|
5
4
|
|
@@ -7,60 +6,24 @@ module OCCI
|
|
7
6
|
module Core
|
8
7
|
class Link < Entity
|
9
8
|
|
10
|
-
#
|
11
|
-
def self.
|
12
|
-
|
13
|
-
data[:actions] = []
|
14
|
-
data[:related] = %w{http://schemas.ogf.org/occi/core#entity}
|
15
|
-
data[:term] = "link"
|
16
|
-
data[:scheme] = "http://schemas.ogf.org/occi/core#"
|
17
|
-
data[:title] = "Link"
|
9
|
+
# @return [OCCI::Core::Kind] kind definition of Link type
|
10
|
+
def self.kind_definition
|
11
|
+
kind = OCCI::Core::Kind.new('http://schemas.ogf.org/occi/core#','link')
|
18
12
|
|
19
|
-
|
20
|
-
|
21
|
-
data.attributes!.occi!.core!.target!.required = false
|
22
|
-
data.attributes!.occi!.core!.target!.mutable = true
|
13
|
+
kind.related = %w{http://schemas.ogf.org/occi/core#entity}
|
14
|
+
kind.title = "Link"
|
23
15
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
16
|
+
kind.attributes.occi!.core!.target!.type = "string"
|
17
|
+
kind.attributes.occi!.core!.target!.pattern = ".*"
|
18
|
+
kind.attributes.occi!.core!.target!.required = false
|
19
|
+
kind.attributes.occi!.core!.target!.mutable = true
|
28
20
|
|
29
|
-
kind =
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
def target
|
34
|
-
return self[:target]
|
35
|
-
end
|
36
|
-
|
37
|
-
def target=(target)
|
38
|
-
self[:target] = target
|
39
|
-
self.attributes!.occi!.core!.target = target
|
40
|
-
end
|
41
|
-
|
42
|
-
def source
|
43
|
-
return self[:source]
|
44
|
-
end
|
45
|
-
|
46
|
-
def source=(source)
|
47
|
-
self[:source] = source
|
48
|
-
self.attributes!.occi!.core!.source = source
|
49
|
-
end
|
21
|
+
kind.attributes.occi!.core!.source!.type = "string"
|
22
|
+
kind.attributes.occi!.core!.source!.pattern = ".*"
|
23
|
+
kind.attributes.occi!.core!.source!.required = false
|
24
|
+
kind.attributes.occi!.core!.source!.mutable = true
|
50
25
|
|
51
|
-
|
52
|
-
case val
|
53
|
-
when self.class
|
54
|
-
val.dup
|
55
|
-
when ::Hash
|
56
|
-
val = val.dup if duping
|
57
|
-
self.class.subkey_class.new.merge(val) unless val.kind_of?(Hashie::Mash)
|
58
|
-
val
|
59
|
-
when Array
|
60
|
-
val.collect { |e| convert_value(e) }
|
61
|
-
else
|
62
|
-
val
|
63
|
-
end
|
26
|
+
kind
|
64
27
|
end
|
65
28
|
|
66
29
|
end
|
data/lib/occi/core/mixin.rb
CHANGED
@@ -1,19 +1,45 @@
|
|
1
|
-
require 'json'
|
1
|
+
require 'active_support/json'
|
2
2
|
require 'occi/core/category'
|
3
3
|
|
4
4
|
module OCCI
|
5
5
|
module Core
|
6
6
|
class Mixin < OCCI::Core::Category
|
7
7
|
|
8
|
-
attr_accessor :entities
|
8
|
+
attr_accessor :entities, :related, :actions
|
9
9
|
|
10
|
-
|
10
|
+
# @param [String ] scheme
|
11
|
+
# @param [String] term
|
12
|
+
# @param [String] title
|
13
|
+
# @param [OCCI::Core::AttributeProperties] attributes
|
14
|
+
# @param [Array] related
|
15
|
+
# @param [Array] actions
|
16
|
+
def initialize(scheme, term, title=nil, attributes=nil, related=nil, actions=nil)
|
11
17
|
@entities = []
|
12
|
-
|
18
|
+
@related = related.to_a
|
19
|
+
@actions = actions.to_a
|
20
|
+
super(scheme, term, title, attributes)
|
13
21
|
end
|
14
22
|
|
23
|
+
# @return [String] string containing location URI of mixin
|
15
24
|
def location
|
16
|
-
'/
|
25
|
+
'/mixins/' + @term + '/'
|
26
|
+
end
|
27
|
+
|
28
|
+
def as_json(options={ })
|
29
|
+
mixin = Hashie::Mash.new
|
30
|
+
mixin.related = @related if @related.any?
|
31
|
+
mixin.actions = @actions if @actions.any?
|
32
|
+
mixin.merge! super
|
33
|
+
mixin
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_text
|
37
|
+
text = super
|
38
|
+
text << ';rel=' + @related.join(' ').inspect if @related.any?
|
39
|
+
text << ';location=' + self.location.inspect
|
40
|
+
text << ';attributes=' + @attributes.combine.join(' ').inspect if @attributes.any?
|
41
|
+
text << ';actions=' + @actions.join(' ').inspect if @actions.any?
|
42
|
+
text
|
17
43
|
end
|
18
44
|
|
19
45
|
end
|
data/lib/occi/core/resource.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'hashie/mash'
|
2
|
-
require '
|
2
|
+
require 'active_support/json'
|
3
3
|
require 'occi/core/entity'
|
4
4
|
require 'occi/core/kind'
|
5
5
|
|
@@ -7,46 +7,47 @@ module OCCI
|
|
7
7
|
module Core
|
8
8
|
class Resource < Entity
|
9
9
|
|
10
|
-
|
11
|
-
data = Hashie::Mash.new
|
12
|
-
data[:related] = %w{http://schemas.ogf.org/occi/core#entity}
|
13
|
-
data[:term] = "resource"
|
14
|
-
data[:scheme] = "http://schemas.ogf.org/occi/core#"
|
15
|
-
data[:title] = "Resource"
|
10
|
+
attr_accessor :links
|
16
11
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
def initialize(kind, mixins=nil, attributes=nil, links=nil)
|
13
|
+
@href = nil
|
14
|
+
@links = links.to_a
|
15
|
+
super(kind, mixins, attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.kind_definition
|
19
|
+
kind = OCCI::Core::Kind.new('http://schemas.ogf.org/occi/core#', 'resource')
|
20
|
+
|
21
|
+
kind.related = %w{http://schemas.ogf.org/occi/core#entity}
|
22
|
+
kind.title = 'Resource'
|
23
|
+
|
24
|
+
kind.attributes.occi!.core!.summary!.type = 'string'
|
25
|
+
kind.attributes.occi!.core!.summary!.pattern = '.*'
|
26
|
+
kind.attributes.occi!.core!.summary!.required = false
|
27
|
+
kind.attributes.occi!.core!.summary!.mutable = true
|
21
28
|
|
22
|
-
kind
|
23
|
-
OCCI::Model.register(kind)
|
29
|
+
kind
|
24
30
|
end
|
25
31
|
|
26
|
-
|
27
|
-
|
28
|
-
|
32
|
+
# set id for resource and update the the source of all links
|
33
|
+
# @param [UUIDTools::UUID] id
|
34
|
+
def id=(id)
|
35
|
+
super(id)
|
36
|
+
@links.each { |link| link.attributes.occi!.core!.source = self.location }
|
29
37
|
end
|
30
38
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
39
|
+
# update the source of all links before returning them
|
40
|
+
# @return [Array] links of resource
|
41
|
+
def links
|
42
|
+
@links.each { |link| link.attributes.occi!.core!.source = self.location }
|
43
|
+
@links
|
35
44
|
end
|
36
45
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
val = val.dup if duping
|
43
|
-
self.class.subkey_class.new.merge(val) unless val.kind_of?(Hashie::Mash)
|
44
|
-
val
|
45
|
-
when Array
|
46
|
-
val.collect { |e| convert_value(e) }
|
47
|
-
else
|
48
|
-
val
|
49
|
-
end
|
46
|
+
def as_json(options={ })
|
47
|
+
resource = Hashie::Mash.new
|
48
|
+
resource.links = @links if @links.any?
|
49
|
+
resource.merge! super
|
50
|
+
resource
|
50
51
|
end
|
51
52
|
|
52
53
|
end
|
data/lib/occi/log.rb
CHANGED
@@ -6,13 +6,17 @@ module OCCI
|
|
6
6
|
|
7
7
|
include Logger::Severity
|
8
8
|
|
9
|
+
attr_reader :logger
|
10
|
+
|
9
11
|
# creates a new OCCI logger
|
10
12
|
# @param [IO,String] logdev The log device. This is a filename (String) or IO object (typically +STDOUT+,
|
11
13
|
# +STDERR+, or an open file).
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
def initialize(logdev)
|
15
|
+
if logdev.kind_of? Logger
|
16
|
+
@logger = logdev
|
17
|
+
else
|
18
|
+
@logger = Logger.new(logdev)
|
19
|
+
end
|
16
20
|
|
17
21
|
# subscribe to log messages and send to logger
|
18
22
|
@log_subscriber = ActiveSupport::Notifications.subscribe("log") do |name, start, finish, id, payload|
|
@@ -20,6 +24,14 @@ module OCCI
|
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
27
|
+
def level=(severity)
|
28
|
+
@logger.level = severity
|
29
|
+
end
|
30
|
+
|
31
|
+
def level
|
32
|
+
@logger.level
|
33
|
+
end
|
34
|
+
|
23
35
|
# @see info
|
24
36
|
def self.debug(message)
|
25
37
|
ActiveSupport::Notifications.instrument("log", :level => Logger::DEBUG, :message => message)
|
data/lib/occi/model.rb
CHANGED
@@ -3,21 +3,28 @@ require 'occi/log'
|
|
3
3
|
|
4
4
|
module OCCI
|
5
5
|
class Model
|
6
|
-
|
7
|
-
|
6
|
+
attr_accessor :categories
|
7
|
+
attr_accessor :locations
|
8
|
+
|
9
|
+
def initialize(collection=nil)
|
10
|
+
@categories = { }
|
11
|
+
@locations = { }
|
12
|
+
register_core
|
13
|
+
register_collection collection if collection
|
14
|
+
end
|
8
15
|
|
9
16
|
# register OCCI Core categories enitity, resource and link
|
10
|
-
def
|
11
|
-
OCCI::Log.info
|
12
|
-
OCCI::Core::Entity.
|
13
|
-
OCCI::Core::Resource.
|
14
|
-
OCCI::Core::Link.
|
17
|
+
def register_core
|
18
|
+
OCCI::Log.info "### Registering OCCI Core categories enitity, resource and link ###"
|
19
|
+
register OCCI::Core::Entity.kind_definition
|
20
|
+
register OCCI::Core::Resource.kind_definition
|
21
|
+
register OCCI::Core::Link.kind_definition
|
15
22
|
end
|
16
23
|
|
17
24
|
# register OCCI Infrastructure categories
|
18
|
-
def
|
19
|
-
OCCI::Log.info
|
20
|
-
|
25
|
+
def register_infrastructure
|
26
|
+
OCCI::Log.info "### Registering OCCI Infrastructure categories ###"
|
27
|
+
register_files 'etc/model/infrastructure'
|
21
28
|
end
|
22
29
|
|
23
30
|
# register OCCI categories from files
|
@@ -25,81 +32,80 @@ module OCCI
|
|
25
32
|
# @param [String] path to a folder containing files which include OCCI collections in JSON format. The path is
|
26
33
|
# recursively searched for files with the extension .json .
|
27
34
|
# @param [Sting] scheme_base_url base location for provider specific extensions of the OCCI model
|
28
|
-
def
|
29
|
-
OCCI::Log.info
|
35
|
+
def register_files(path, scheme_base_url='http://localhost')
|
36
|
+
OCCI::Log.info "### Initializing OCCI Model from #{path} ###"
|
30
37
|
Dir.glob(path + '/**/*.json').each do |file|
|
31
38
|
collection = OCCI::Collection.new(JSON.parse(File.read(file)))
|
32
39
|
# add location of service provider to scheme if it has a relative location
|
33
40
|
collection.kinds.collect { |kind| kind.scheme = scheme_base_url + kind.scheme if kind.scheme.start_with? '/' } if collection.kinds
|
34
41
|
collection.mixins.collect { |mixin| mixin.scheme = scheme_base_url + mixin.scheme if mixin.scheme.start_with? '/' } if collection.mixins
|
35
42
|
collection.actions.collect { |action| action.scheme = scheme_base_url + action.scheme if action.scheme.start_with? '/' } if collection.actions
|
36
|
-
|
43
|
+
register_collection collection
|
37
44
|
end
|
38
45
|
end
|
39
46
|
|
40
47
|
# register OCCI categories from OCCI collection
|
41
|
-
def
|
42
|
-
collection.
|
43
|
-
collection.mixins.each { |mixin| self.register(OCCI::Core::Mixin.new(mixin)) } if collection.mixins
|
44
|
-
collection.actions.each { |action| self.register(OCCI::Core::Action.new(action)) } if collection.actions
|
48
|
+
def register_collection(collection)
|
49
|
+
collection.categories.each { |category| register category }
|
45
50
|
end
|
46
51
|
|
47
|
-
def
|
48
|
-
|
52
|
+
def reset()
|
53
|
+
@categories.each_value.each { |category| category.entities = [] if category.entities }
|
49
54
|
end
|
50
55
|
|
51
56
|
# ---------------------------------------------------------------------------------------------------------------------
|
52
|
-
def
|
53
|
-
OCCI::Log.debug
|
54
|
-
|
55
|
-
|
57
|
+
def register(category)
|
58
|
+
OCCI::Log.debug "### Registering category #{category.type_identifier}"
|
59
|
+
@categories[category.type_identifier] = category
|
60
|
+
@locations[category.location] = category.type_identifier unless category.kind_of? OCCI::Core::Action
|
56
61
|
end
|
57
62
|
|
58
63
|
# ---------------------------------------------------------------------------------------------------------------------
|
59
|
-
def
|
60
|
-
OCCI::Log.debug
|
61
|
-
|
62
|
-
|
64
|
+
def unregister(category)
|
65
|
+
OCCI::Log.debug "### Unregistering category #{category.type_identifier}"
|
66
|
+
@categories.delete category.type_identifier
|
67
|
+
@locations.delete category.location unless category.kind_of? OCCI :Core::Action
|
63
68
|
end
|
64
69
|
|
65
70
|
# Returns the category corresponding to a given type identifier
|
66
71
|
#
|
67
72
|
# @param [URI] type identifier of a category
|
68
|
-
def
|
69
|
-
|
73
|
+
def get_by_id(id)
|
74
|
+
@categories.fetch(id) { OCCI::Log.debug("Category with id #{id} not found"); nil }
|
70
75
|
end
|
71
76
|
|
72
77
|
# Returns the category corresponding to a given location
|
73
78
|
#
|
74
79
|
# @param [URI] Location of a category
|
75
|
-
def
|
76
|
-
id =
|
77
|
-
|
80
|
+
def get_by_location(location)
|
81
|
+
id = @locations.fetch(location) { OCCI::Log.debug("Category with location #{location} not found"); nil }
|
82
|
+
get_by_id id
|
78
83
|
end
|
79
84
|
|
80
85
|
# Return all categories from model. If filter is present, return only the categories specified by filter
|
81
86
|
#
|
82
|
-
# @param [
|
83
|
-
# @return [
|
84
|
-
def
|
85
|
-
collection =
|
87
|
+
# @param [OCCI::Collection] filter
|
88
|
+
# @return [OCCI::Collection] collection
|
89
|
+
def get(filter = [])
|
90
|
+
collection = OCCI::Collection.new
|
86
91
|
if filter.empty?
|
87
|
-
|
92
|
+
@categories.each_value do |category|
|
88
93
|
collection.kinds << category if category.kind_of? OCCI::Core::Kind
|
89
94
|
collection.mixins << category if category.kind_of? OCCI::Core::Mixin
|
90
95
|
collection.actions << category if category.kind_of? OCCI::Core::Action
|
91
96
|
end
|
97
|
+
else
|
98
|
+
categories = filter.categories
|
99
|
+
OCCI::Log.debug("### Filtering categories #{categories.collect { |c| c.type_identifier }.inspect}")
|
100
|
+
while categories.any? do
|
101
|
+
category = categories.pop
|
102
|
+
categories.concat @categories.each_value.select { |cat| cat.related_to?(category.type_identifier, self) }
|
103
|
+
collection.kinds << get_by_id(category.type_identifier) if category.kind_of? OCCI::Core::Kind
|
104
|
+
collection.mixins << get_by_id(category.type_identifier) if category.kind_of? OCCI::Core::Mixin
|
105
|
+
collection.actions << get_by_id(category.type_identifier) if category.kind_of? OCCI::Core::Action
|
106
|
+
end
|
92
107
|
end
|
93
|
-
|
94
|
-
while filter.any? do
|
95
|
-
cat = filter.pop
|
96
|
-
filter.concat @@categories.each_value.select { |category| category.related_to?(cat.type_identifier) }
|
97
|
-
category = get_by_id(cat.type_identifier)
|
98
|
-
collection.kinds << category if category.kind_of?(OCCI::Core::Kind)
|
99
|
-
collection.mixins << category if category.kind_of?(OCCI::Core::Mixin)
|
100
|
-
collection.actions << category if category.kind_of?(OCCI::Core::Action)
|
101
|
-
end
|
102
|
-
return collection
|
108
|
+
collection
|
103
109
|
end
|
104
110
|
|
105
111
|
end
|