occi 2.1.2 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +5 -0
- data/README.md +45 -0
- data/lib/occi/client.rb +167 -0
- data/lib/occi/collection.rb +9 -0
- data/lib/occi/core/attribute_properties.rb +16 -4
- data/lib/occi/core/attributes.rb +15 -1
- data/lib/occi/parser.rb +5 -4
- data/lib/occi/version.rb +1 -1
- data/lib/occi.rb +1 -0
- metadata +3 -2
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -8,9 +8,13 @@ GEM
|
|
8
8
|
builder (3.0.0)
|
9
9
|
diff-lcs (1.1.3)
|
10
10
|
hashie (1.2.0)
|
11
|
+
httparty (0.8.1)
|
12
|
+
multi_json
|
13
|
+
multi_xml
|
11
14
|
i18n (0.6.0)
|
12
15
|
json (1.6.6)
|
13
16
|
multi_json (1.3.5)
|
17
|
+
multi_xml (0.4.2)
|
14
18
|
nokogiri (1.5.3)
|
15
19
|
rake (0.9.2.2)
|
16
20
|
rspec (2.10.0)
|
@@ -40,6 +44,7 @@ DEPENDENCIES
|
|
40
44
|
antlr3
|
41
45
|
builder
|
42
46
|
hashie
|
47
|
+
httparty
|
43
48
|
json
|
44
49
|
nokogiri
|
45
50
|
rake
|
data/README.md
CHANGED
@@ -37,6 +37,47 @@ Usage
|
|
37
37
|
First require the gem
|
38
38
|
require 'occi'
|
39
39
|
|
40
|
+
### Client
|
41
|
+
|
42
|
+
The OCCI gem includes a Client to simplify the usage of an OCCI endpoint.
|
43
|
+
|
44
|
+
To connect to an OCCI endpoint/server (e.g. running at http://localhost:3000/ ) use
|
45
|
+
|
46
|
+
client = OCCI::Client.new('http://localhost:3000')
|
47
|
+
|
48
|
+
All available categories are automatically registered to the OCCI model during client initialization. You can get them via
|
49
|
+
|
50
|
+
OCCI::Model.get
|
51
|
+
|
52
|
+
To get all resources (as a list of OCCI::Resources) currently managed by the endpoint use
|
53
|
+
|
54
|
+
client.get_resources
|
55
|
+
|
56
|
+
To get only compute, storage or network resources use get_compute_resources, ...
|
57
|
+
|
58
|
+
To get the location of all resources use
|
59
|
+
|
60
|
+
client.get_resource_list
|
61
|
+
|
62
|
+
Analogue for compute, storage, network via get_compute_list, ...
|
63
|
+
|
64
|
+
To get a list of all OS / resource templates use
|
65
|
+
|
66
|
+
client.get_os_templates
|
67
|
+
client.get_resource_templates
|
68
|
+
|
69
|
+
To get all attributes with their default values for a given category use
|
70
|
+
|
71
|
+
client.get_attributes(client.compute)
|
72
|
+
|
73
|
+
To create a new compute resource use
|
74
|
+
|
75
|
+
os = client.get_os_templates.select { |template| template.term.include? 'my_os' }
|
76
|
+
size = client.get_resource_templates.select { |template| template.term.include? 'large' }
|
77
|
+
attributes = client.get_attributes([client.compute,os,size])
|
78
|
+
attributes['occi.core.title'] = "My VM"
|
79
|
+
client.post_compute(attributes,os,size)
|
80
|
+
|
40
81
|
### Logging
|
41
82
|
|
42
83
|
The OCCI gem includes its own logging mechanism using a message queue. By default, no one is listening to that queue.
|
@@ -84,6 +125,10 @@ The OCCI gem includes all OCCI Core classes necessary to handly arbitrary OCCI o
|
|
84
125
|
Changelog
|
85
126
|
---------
|
86
127
|
|
128
|
+
### Version 2.2
|
129
|
+
|
130
|
+
OCCI Client added. The client simplifies the execution of OCCI commands and provides shortcuts for often used steps.
|
131
|
+
|
87
132
|
### Version 2.1
|
88
133
|
|
89
134
|
Several improvements to the gem structure and code documentation. First rSpec test were added. Readme has been extended to include instructions how the gem can be used.
|
data/lib/occi/client.rb
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'httparty'
|
3
|
+
|
4
|
+
module OCCI
|
5
|
+
class Client
|
6
|
+
include HTTParty
|
7
|
+
format :json
|
8
|
+
headers 'Accept' => 'application/occi+json'
|
9
|
+
|
10
|
+
attr_reader :endpoint
|
11
|
+
|
12
|
+
attr_reader :compute
|
13
|
+
attr_reader :storage
|
14
|
+
attr_reader :network
|
15
|
+
|
16
|
+
def initialize(endpoint)
|
17
|
+
@endpoint = endpoint
|
18
|
+
collection = OCCI::Collection.new(get_model)
|
19
|
+
OCCI::Model.register_collection(collection)
|
20
|
+
@compute = OCCI::Model.get_by_id('http://schemas.ogf.org/occi/infrastructure#compute')
|
21
|
+
@storage = OCCI::Model.get_by_id('http://schemas.ogf.org/occi/infrastructure#storage')
|
22
|
+
@network = OCCI::Model.get_by_id('http://schemas.ogf.org/occi/infrastructure#network')
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_model
|
26
|
+
self.class.get(endpoint + '/-/')
|
27
|
+
end
|
28
|
+
|
29
|
+
def post_mixin
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def post_resources_to_mixin
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete_resources_from_mixin
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete_mixin
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_resources
|
46
|
+
OCCI::Collection.new(self.class.get(endpoint)).resources
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_resources_list
|
50
|
+
self.class.get(@endpoint, :headers => { 'Accept' => 'text/uri-list' }).split("\n").compact
|
51
|
+
end
|
52
|
+
|
53
|
+
def post_resource(attributes, kind, mixins, resources_to_link)
|
54
|
+
resource = OCCI::Core::Resource.new
|
55
|
+
resource.kind = kind.type_identifier
|
56
|
+
mixins = mixins.collect { |mixin| mixin.type_identifiers } unless mixins.first.kind_of? String
|
57
|
+
resource.mixins = mixins
|
58
|
+
attributes = OCCI::Core::Attributes.split(attributes) unless attributes.kind_of? OCCI::Core::Attributes
|
59
|
+
resource.attributes = attributes
|
60
|
+
resource.links = []
|
61
|
+
resources_to_link.each do |res|
|
62
|
+
link = OCCI::Link.new
|
63
|
+
link.kind = 'http://schemas.ogf.org/occi/infrastructure#storagelink' if OCCI::Model.get_by_id(res.kind).related_to? 'http://schemas.ogf.org/occi/infrastructure#storage'
|
64
|
+
link.kind = 'http://schemas.ogf.org/occi/infrastructure#networkinterface' if OCCI::Model.get_by_id(res.kind).related_to? 'http://schemas.ogf.org/occi/infrastructure#network'
|
65
|
+
link.titlte "Link to #{res.title}"
|
66
|
+
link.target = res.location
|
67
|
+
resource.links << link
|
68
|
+
end
|
69
|
+
resource.check
|
70
|
+
collection = OCCI::Collection.new(:resources => [resource])
|
71
|
+
self.class.post(@endpoint + kind.location, { :body => collection.to_json, :headers => { 'Content-Type' => 'application/occi+json', 'Accept' => 'text/uri-list' }, :format => 'text/plain' }).to_s
|
72
|
+
end
|
73
|
+
|
74
|
+
def delete_resources
|
75
|
+
self.class.delete(@endpoint)
|
76
|
+
end
|
77
|
+
|
78
|
+
def trigger_action(url)
|
79
|
+
self.class.post(url)
|
80
|
+
end
|
81
|
+
|
82
|
+
def trigger_action_on_resources(resources, action)
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def get_compute_list
|
87
|
+
self.class.get(@endpoint + @compute.location, {:headers => { 'Accept' => 'text/uri-list' }, :format => 'text/plain'}).split("\n").compact
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_compute_resources
|
91
|
+
self.class.get(endpoint + @compute.location)
|
92
|
+
end
|
93
|
+
|
94
|
+
def post_compute_resource(attributes=OCCI::Core::Attributes.new, os = nil, size = nil, mixins=[], resources_to_link=[])
|
95
|
+
mixins << os if os
|
96
|
+
mixins << size if size
|
97
|
+
post_resource(attributes, @compute, mixins, resources_to_link)
|
98
|
+
end
|
99
|
+
|
100
|
+
def delete_compute_resource(id)
|
101
|
+
self.class.delete(@endpoint + @compute.location + id)
|
102
|
+
end
|
103
|
+
|
104
|
+
def delete_compute_resources
|
105
|
+
self.class.delete(@endpoint + @compute.location)
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_storage_resources
|
109
|
+
self.class.get(@endpoint + @storage.location)
|
110
|
+
end
|
111
|
+
|
112
|
+
def post_storage_resource(attributes=OCCI::Core::Attributes.new, mixins=[], resources_to_link=[])
|
113
|
+
post_resource(attributes, @storage, mixins, resources_to_link)
|
114
|
+
end
|
115
|
+
|
116
|
+
def delete_storage_resource(id)
|
117
|
+
self.class.delete(@endpoint + @storage.location + id)
|
118
|
+
end
|
119
|
+
|
120
|
+
def delete_storage_resources
|
121
|
+
self.class.delete @endpoint + (@storage.location)
|
122
|
+
end
|
123
|
+
|
124
|
+
def get_network_resources
|
125
|
+
self.class.get(@endpoint + @network)
|
126
|
+
end
|
127
|
+
|
128
|
+
def post_network_resource(attributes=OCCI::Core::Attributes.new, mixins=[], resources_to_link=[])
|
129
|
+
post_resource(attributes, @network, mixins, resources_to_link)
|
130
|
+
end
|
131
|
+
|
132
|
+
def delete_network_resource(id)
|
133
|
+
self.class.delete(@endpoint + @network.location + id)
|
134
|
+
end
|
135
|
+
|
136
|
+
def delete_network_resources
|
137
|
+
self.class.delete(@endpoint + @network.location)
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_os_templates
|
141
|
+
OCCI::Collection.new(self.class.get(@endpoint + '/-/', :headers => { 'Accept' => 'application/occi+json', 'Content-Type' => 'text/occi', 'Category' => 'os_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin"' })).mixins.select { |mixin| mixin.term != 'os_tpl' }
|
142
|
+
end
|
143
|
+
|
144
|
+
def get_resource_templates
|
145
|
+
OCCI::Collection.new(self.class.get(@endpoint + '/-/', :headers => { 'Accept' => 'application/occi+json', 'Content-Type' => 'text/occi', 'Category' => 'resource_tpl;scheme="http://schemas.ogf.org/occi/infrastructure#";class="mixin"' })).mixins.select { |mixin| mixin.term != 'resource_tpl' }
|
146
|
+
end
|
147
|
+
|
148
|
+
def get_attributes(categories)
|
149
|
+
attributes = Hashie::Mash.new
|
150
|
+
[categories].flatten.each do |category|
|
151
|
+
category = OCCI::Model.get_by_id(category) if category.kind_of? String
|
152
|
+
attributes.merge! category.attributes.combine_with_defaults
|
153
|
+
end
|
154
|
+
attributes
|
155
|
+
end
|
156
|
+
|
157
|
+
def get_attribute_definitions(categories)
|
158
|
+
definitions = OCCI::Core::AttributeProperties.new
|
159
|
+
[categories].flatten.each do |category|
|
160
|
+
category = OCCI::Model.get_by_id(category) if category.kind_of? String
|
161
|
+
definitions.merge! category.attributes
|
162
|
+
end
|
163
|
+
definitions
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
data/lib/occi/collection.rb
CHANGED
@@ -34,5 +34,14 @@ module OCCI
|
|
34
34
|
def entities
|
35
35
|
@resources + @links
|
36
36
|
end
|
37
|
+
|
38
|
+
def empty?
|
39
|
+
@kinds.empty? && @mixins.empty? && @actions.empty? && @resources.empty? && @links.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_json(options = { })
|
43
|
+
{ :kinds => @kinds, :mixins => @mixins, :actions => @actions, :resources => @resources, :links => @links }.to_json
|
44
|
+
end
|
45
|
+
|
37
46
|
end
|
38
47
|
end
|
@@ -6,10 +6,10 @@ module OCCI
|
|
6
6
|
|
7
7
|
def initialize(attributes = nil, default = nil)
|
8
8
|
if attributes[:type] || attributes.required || attributes.mutable || attributes.pattern || attributes.minimum || attributes.maximum || attributes.description
|
9
|
-
attributes[:type]
|
9
|
+
attributes[:type] ||= "string"
|
10
10
|
attributes.required ||= false
|
11
|
-
attributes.mutable
|
12
|
-
attributes.pattern
|
11
|
+
attributes.mutable ||= false
|
12
|
+
attributes.pattern ||= ".*"
|
13
13
|
end unless attributes.nil?
|
14
14
|
super(attributes, default)
|
15
15
|
end
|
@@ -18,7 +18,7 @@ module OCCI
|
|
18
18
|
array = []
|
19
19
|
self.each_key do |key|
|
20
20
|
if self[key].include? 'type'
|
21
|
-
array << key
|
21
|
+
array << key
|
22
22
|
else
|
23
23
|
self[key].combine.each { |attr| array << key + '.' + attr }
|
24
24
|
end
|
@@ -26,6 +26,18 @@ module OCCI
|
|
26
26
|
return array
|
27
27
|
end
|
28
28
|
|
29
|
+
def combine_with_defaults
|
30
|
+
hash = {}
|
31
|
+
self.each_key do |key|
|
32
|
+
if self[key].include? 'type'
|
33
|
+
hash[key] = self[key]['default']
|
34
|
+
else
|
35
|
+
self[key].combine_with_defaults.each { |k,v| hash[key + '.' + k] = v }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
return hash
|
39
|
+
end
|
40
|
+
|
29
41
|
end
|
30
42
|
end
|
31
43
|
end
|
data/lib/occi/core/attributes.rb
CHANGED
@@ -5,7 +5,7 @@ module OCCI
|
|
5
5
|
class Attributes < Hashie::Mash
|
6
6
|
|
7
7
|
def combine
|
8
|
-
hash = {}
|
8
|
+
hash = { }
|
9
9
|
self.each_key do |key|
|
10
10
|
if self[key].kind_of? Hashie::Mash
|
11
11
|
self[key].combine.each_pair { |k, v| hash[key + '.' + k] = v }
|
@@ -16,6 +16,20 @@ module OCCI
|
|
16
16
|
return hash
|
17
17
|
end
|
18
18
|
|
19
|
+
def self.split(attributes)
|
20
|
+
attribute = Attributes.new
|
21
|
+
attributes.each do |name,value|
|
22
|
+
puts name
|
23
|
+
key, dot, rest = name.partition('.')
|
24
|
+
if rest.empty?
|
25
|
+
attribute[key] = value
|
26
|
+
else
|
27
|
+
attribute.merge! Attributes.new(key => self.split(rest => value))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
return attribute
|
31
|
+
end
|
32
|
+
|
19
33
|
end
|
20
34
|
end
|
21
35
|
end
|
data/lib/occi/parser.rb
CHANGED
@@ -44,15 +44,16 @@ module OCCI
|
|
44
44
|
OCCI::Log.debug('### Parsing request data to OCCI data structure ###')
|
45
45
|
collection = OCCI::Collection.new
|
46
46
|
|
47
|
+
locations = self.header_locations(header)
|
48
|
+
category ? collection = self.header_categories(header) : collection = self.header_entity(header) if locations.empty?
|
49
|
+
|
47
50
|
case media_type
|
48
51
|
when 'text/occi'
|
49
|
-
locations = self.header_locations(header)
|
50
|
-
category ? collection = self.header_categories(header) : collection = self.header_entity(header) if locations.empty?
|
51
52
|
when 'text/uri-list'
|
52
53
|
body.each_line { |line| locations << URI.parse(line) }
|
53
54
|
when 'text/plain', nil
|
54
|
-
locations
|
55
|
-
category ? collection = self.text_categories(body) : collection = self.text_entity(body) if locations.empty?
|
55
|
+
locations << self.text_locations(body)
|
56
|
+
category ? collection = self.text_categories(body) : collection = self.text_entity(body) if locations.empty? && collection.empty?
|
56
57
|
when 'application/occi+json', 'application/json'
|
57
58
|
collection = self.json(body)
|
58
59
|
when 'application/occi+xml', 'application/xml'
|
data/lib/occi/version.rb
CHANGED
data/lib/occi.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: occi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-06-
|
13
|
+
date: 2012-06-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -138,6 +138,7 @@ files:
|
|
138
138
|
- etc/model/infrastructure/storage.json
|
139
139
|
- etc/model/infrastructure/storagelink.json
|
140
140
|
- lib/occi.rb
|
141
|
+
- lib/occi/client.rb
|
141
142
|
- lib/occi/collection.rb
|
142
143
|
- lib/occi/core/action.rb
|
143
144
|
- lib/occi/core/attribute_properties.rb
|