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 CHANGED
@@ -9,6 +9,7 @@ gem "nokogiri"
9
9
  gem "builder"
10
10
  gem "activesupport"
11
11
  gem "rake"
12
+ gem "httparty"
12
13
 
13
14
  # development related gems
14
15
  group :development do
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.
@@ -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
@@ -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] ||= "string"
9
+ attributes[:type] ||= "string"
10
10
  attributes.required ||= false
11
- attributes.mutable ||= false
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
@@ -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 = self.text_locations(body)
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
@@ -1,3 +1,3 @@
1
1
  module OCCI
2
- VERSION = "2.1.2" unless defined?(::OCCI::VERSION)
2
+ VERSION = "2.2.0" unless defined?(::OCCI::VERSION)
3
3
  end
data/lib/occi.rb CHANGED
@@ -2,6 +2,7 @@ require 'occi/version'
2
2
  require 'occi/parser'
3
3
  require 'occi/model'
4
4
  require 'occi/log'
5
+ require 'occi/client'
5
6
  require 'occi/collection'
6
7
  require 'occi/core/action'
7
8
  require 'occi/core/attribute_properties'
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.1.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 00:00:00.000000000 Z
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