occi 2.5.7 → 2.5.8

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ *.swp
1
2
  .project
2
3
  .idea
3
4
  .yardoc
data/Gemfile CHANGED
@@ -10,6 +10,7 @@ gem "builder"
10
10
  gem "activesupport"
11
11
  gem "rake"
12
12
  gem "httparty"
13
+ gem "highline"
13
14
  gem "i18n"
14
15
 
15
16
  # development related gems
@@ -19,4 +20,4 @@ group :development do
19
20
  gem "yard"
20
21
  gem "yard-sinatra"
21
22
  gem "rspec-http"
22
- end
23
+ end
data/Gemfile.lock CHANGED
@@ -8,6 +8,7 @@ GEM
8
8
  builder (3.0.0)
9
9
  diff-lcs (1.1.3)
10
10
  hashie (1.2.0)
11
+ highline (1.6.11)
11
12
  httparty (0.8.1)
12
13
  multi_json
13
14
  multi_xml
@@ -44,6 +45,7 @@ DEPENDENCIES
44
45
  antlr3
45
46
  builder
46
47
  hashie
48
+ highline
47
49
  httparty
48
50
  i18n
49
51
  json
data/README.md CHANGED
@@ -8,7 +8,7 @@ Requirements
8
8
 
9
9
  The following setup is recommended
10
10
 
11
- * usage of the Ruby Version Manger
11
+ * usage of the Ruby Version Manager
12
12
  * Ruby 1.9.3
13
13
  * RubyGems installed
14
14
 
@@ -19,29 +19,52 @@ Installation
19
19
 
20
20
  Usage
21
21
  -----
22
+ ### Client
23
+ The OCCI gem includes a client you can use directly from shell with the following auth methods: x509 (with --password, --user-cred and --ca-path), basic (with --username and --password), digest (with --username and --password), none. If you won't set a password using --password, the client will run in an interactive mode and ask for it later on.
22
24
 
23
- Use the Interactive Ruby Shell (IRB) to interact with an OCCI server. If you have the occi gem installed, you just have
24
- to start irb from the command line:
25
+ To find out more about available options and defaults use
25
26
 
26
- irb
27
+ occi --help
27
28
 
28
- If you want to test newer versions of rOCCI, you have to tell irb from where it
29
- should load occi:
29
+ To list available resources use
30
30
 
31
- cd rOCCI
32
- irb -I lib
31
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action list --resource compute --auth x509
32
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action list --resource storage --auth x509
33
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action list --resource network --auth x509
33
34
 
34
- First require the gem, for Ruby 1.8.7 you also have to require rubygems
35
+ To describe available resources use
35
36
 
36
- require 'rubygems'
37
- require 'occi'
37
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource compute --auth x509
38
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource storage --auth x509
39
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource network --auth x509
38
40
 
39
- ### Client
41
+ To describe specific resources use
42
+
43
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource https://<ENDPOINT>:<PORT>/compute/<OCCI_ID> --auth x509
44
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource https://<ENDPOINT>:<PORT>/storage/<OCCI_ID> --auth x509
45
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource https://<ENDPOINT>:<PORT>/network/<OCCI_ID> --auth x509
46
+
47
+ To list available OS templates or Resource templates use
48
+
49
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action list --resource os_tpl --auth x509
50
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action list --resource resource_tpl --auth x509
51
+
52
+ To describe a specific OS template or Resource template use
40
53
 
41
- The OCCI gem includes a Client to simplify the usage of an OCCI endpoint. If you want to use authentication then you
42
- should create a hash with information either on username and password for basic authentication or with a X.509 user
43
- certificate, the user certificate password and the path to the Root CAs which are used to verify the certificate of the
44
- OCCI server.
54
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource os_tpl#debian6 --auth x509
55
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource resource_tpl#small --auth x509
56
+
57
+ To create a compute resource with mixins use
58
+
59
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action create --resource compute --mixin os_tpl#debian6 --mixin resource_tpl#small --resource-title "My rOCCI VM" --auth x509
60
+
61
+ To delete a compute resource use
62
+
63
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action delete --resource https://<ENDPOINT>:<PORT>/compute/<OCCI_ID> --auth x509
64
+
65
+ ### Client scripting
66
+
67
+ #### Auth
45
68
 
46
69
  For Basic auth use
47
70
 
@@ -49,7 +72,7 @@ For Basic auth use
49
72
  auth.type = 'basic'
50
73
  auth.username = 'user'
51
74
  auth.password = 'mypass'
52
-
75
+
53
76
  For Digest auth use
54
77
 
55
78
  auth = Hashie::Mash.new
@@ -58,52 +81,153 @@ For Digest auth use
58
81
  auth.password = 'mypass'
59
82
 
60
83
  For X.509 auth use
61
-
84
+
62
85
  auth = Hashie::Mash.new
63
86
  auth.type = 'x509'
64
87
  auth.user_cert = '/Path/To/My/usercert.pem'
65
88
  auth.user_cert_password = 'MyPassword'
66
89
  auth.ca_path = '/Path/To/root-certificates'
67
90
 
91
+ #### DSL
92
+ In your scripts, you can use the OCCI client DSL.
93
+
94
+ To include the DSL definitions in your script use
95
+
96
+ extend OCCI::DSL
97
+
98
+ To connect to an OCCI endpoint/server (e.g. running on http://localhost:3000/ )
99
+
100
+ connect('http://localhost:3300',auth||=nil)
101
+
102
+ To get the list of available resource types or mixin types use
103
+
104
+ resource_types
105
+ mixin_types
106
+
107
+ To get compute, storage or network descriptions use
108
+
109
+ describe "compute"
110
+ describe "storage"
111
+ describe "network"
112
+
113
+ To get the location of compute, storage or network resources use
114
+
115
+ list "compute"
116
+ list "storage"
117
+ list "network"
118
+
119
+ To get the identifiers of specific mixins in specific mixin types use
120
+
121
+ mixin "my_template", "os_tpl"
122
+ mixin "small", "resource_tpl"
123
+
124
+ To get the identifiers of specific mixins with unknown types use
125
+
126
+ mixin "medium"
127
+
128
+ To get mixin descriptions use
129
+
130
+ mixin "medium", nil, true
131
+ mixin "my_template", "os_tpl", true
132
+
133
+ To get a list of names of all / OS templates / Resource templates mixins use
134
+
135
+ mixins
136
+ mixins "os_tpl"
137
+ mixins "resource_tpl"
138
+
139
+ To create a new compute resource use
140
+
141
+ os = mixin 'my_os', 'os_tpl'
142
+ size = mixin 'large', 'resource_tpl'
143
+ cmpt = resource "compute"
144
+ cmpt.mixins << os << size
145
+ cmpt.attributes.occi!.core!.title = "My VM"
146
+ create cmpt
147
+
148
+ To get a description of a specific resource use
149
+
150
+ describe "https://<ENDPOINT>:<PORT>/compute/<OCCI_ID>"
151
+ describe "https://<ENDPOINT>:<PORT>/storage/<OCCI_ID>"
152
+ describe "https://<ENDPOINT>:<PORT>/network/<OCCI_ID>"
153
+
154
+ To delete a specific resource use
155
+
156
+ delete "https://<ENDPOINT>:<PORT>/compute/<OCCI_ID>"
157
+ delete "https://<ENDPOINT>:<PORT>/storage/<OCCI_ID>"
158
+ delete "https://<ENDPOINT>:<PORT>/network/<OCCI_ID>"
159
+
160
+ #### API
161
+ If you need low level access to parts of the OCCI client or need to use more than one instance
162
+ at a time, you should use the OCCI client API directly.
163
+
68
164
  To connect to an OCCI endpoint/server (e.g. running on http://localhost:3000/ )
69
165
 
70
- client = OCCI::Client.new('http://occi.cloud.gwdg.de:3300',auth||=nil)
166
+ client = OCCI::Client.new('http://localhost:3300',auth||=nil)
71
167
 
72
168
  All available categories are automatically registered to the OCCI model during client initialization. You can get them via
73
169
 
74
170
  client.model
75
171
 
76
- To get all resources (as a list of OCCI::Resources) currently managed by the endpoint use
172
+ To get the list of available resource types or mixin types use
173
+
174
+ client.get_resource_types
175
+ client.get_mixin_types
176
+
177
+ To get compute, storage or network descriptions use
178
+
179
+ client.describe "compute"
180
+ client.describe "storage"
181
+ client.describe "network"
77
182
 
78
- client.get resources
183
+ To get the location of compute, storage or network resources use
79
184
 
80
- To get only compute, storage or network resources use
185
+ client.list "compute"
186
+ client.list "storage"
187
+ client.list "network"
81
188
 
82
- client.get compute
83
- client.get storage
84
- client.get network
189
+ To get the identifiers of specific mixins in specific mixin types use
85
190
 
86
- To get the location of all resources use
191
+ client.find_mixin "my_template", "os_tpl"
192
+ client.find_mixin "small", "resource_tpl"
87
193
 
88
- client.list resources
194
+ To get the identifiers of specific mixins with unknown types use
89
195
 
90
- Analogue for compute, storage, network.
196
+ client.find_mixin "medium"
91
197
 
92
- To get a list of all OS / resource templates use
198
+ To get mixin descriptions use
93
199
 
94
- client.get_os_templates
95
- client.get_resource_templates
200
+ client.find_mixin "medium", nil, true
201
+ client.find_mixin "my_template", "os_tpl", true
202
+
203
+ To get a list of names of all / OS templates / Resource templates mixins use
204
+
205
+ client.get_mixins
206
+ client.get_mixins "os_tpl"
207
+ client.get_mixins "resource_tpl"
96
208
 
97
209
  To create a new compute resource use
98
210
 
99
- os = client.get_os_templates.select { |template| template.term.include? 'my_os' }
100
- size = client.get_resource_templates.select { |template| template.term.include? 'large' }
101
- cmpt = OCCI::Core::Resource.new compute
211
+ os = client.find_mixin 'my_os', 'os_tpl'
212
+ size = client.find_mixin 'large', 'resource_tpl'
213
+ cmpt = client.get_resource "compute"
102
214
  cmpt.mixins << os << size
103
215
  cmpt.attributes.occi!.core!.title = "My VM"
104
216
  client.create cmpt
105
217
 
106
- ### Logging
218
+ To get a description of a specific resource use
219
+
220
+ client.describe "https://<ENDPOINT>:<PORT>/compute/<OCCI_ID>"
221
+ client.describe "https://<ENDPOINT>:<PORT>/storage/<OCCI_ID>"
222
+ client.describe "https://<ENDPOINT>:<PORT>/network/<OCCI_ID>"
223
+
224
+ To delete a specific resource use
225
+
226
+ client.delete "https://<ENDPOINT>:<PORT>/compute/<OCCI_ID>"
227
+ client.delete "https://<ENDPOINT>:<PORT>/storage/<OCCI_ID>"
228
+ client.delete "https://<ENDPOINT>:<PORT>/network/<OCCI_ID>"
229
+
230
+ #### Logging
107
231
 
108
232
  The OCCI gem includes its own logging mechanism using a message queue. By default, no one is listening to that queue.
109
233
  A new OCCI Logger can be initialized by specifying the log destination (either a filename or an IO object like
@@ -117,7 +241,7 @@ You can always, even if there is no logger defined, log output using the class m
117
241
 
118
242
  OCCI::Log.info("Test message")
119
243
 
120
- ### Registering categories in the OCCI Model
244
+ #### Registering categories in the OCCI Model
121
245
 
122
246
  Before the parser may be used, the available categories have to be registered in the OCCI Model.
123
247
 
@@ -129,7 +253,7 @@ For categories already specified by the OCCI WG a method exists in the OCCI Mode
129
253
  Further categories can either be registered from files which include OCCI collections in JSON formator or from parsed
130
254
  JSON objects (e.g. from the query interface of an OCCI service endpoint).
131
255
 
132
- ### Parsing OCCI messages
256
+ #### Parsing OCCI messages
133
257
 
134
258
  The OCCI gem includes a Parser to easily parse OCCI messages. With a given media type (e.g. json,
135
259
  xml or plain text) the parser analyses the content of the message body and, if supplied,
@@ -139,11 +263,11 @@ category and a message with an entity which has a kind, it has to be specified i
139
263
 
140
264
  OCCI messages can be parsed to an OCCI collection for example like
141
265
 
142
- media_type = text/plain
266
+ media_type = 'text/plain'
143
267
  body = %Q|Category: compute; scheme="http://schemas.ogf.org/occi/infrastructure#"; class="kind"|
144
268
  collection=OCCI::Parser.parse(media_type, body)
145
269
 
146
- ### Parsing OVF / OVA files
270
+ #### Parsing OVF / OVA files
147
271
 
148
272
  Parsing of OVF/OVA files is partly supported and will be improved in future versions.
149
273
 
@@ -236,4 +360,4 @@ Install dependencies for deployment
236
360
  2. Create a branch (git checkout -b my_markup)
237
361
  3. Commit your changes (git commit -am "My changes")
238
362
  4. Push to the branch (git push origin my_markup)
239
- 5. Create an Issue with a link to your branch
363
+ 5. Create an Issue with a link to your branch
data/bin/occi CHANGED
@@ -17,13 +17,130 @@
17
17
  require 'rubygems'
18
18
  require 'occi'
19
19
  require 'pp'
20
- require 'logger'
20
+ require 'highline/import'
21
+ require 'openssl'
21
22
 
22
- include OCCI::DSL
23
+ # OcciOpts is not part of the occi required above
24
+ require 'occi/client/occiopts'
25
+
26
+ extend OCCI::DSL
27
+
28
+ # get arguments and validate/parse them to an ostruct
29
+ options = OcciOpts.parse ARGV
30
+
31
+ # initiate the Logger
32
+ logger = OCCI::Log.new(options.log[:out])
33
+ logger.level = options.log[:level]
34
+ options.log[:logger] = logger
35
+
36
+ OCCI::Log.info "Starting OCCI client ..."
37
+ OCCI::Log.debug "Options: #{options}"
38
+
39
+ # running with an empty password?
40
+ if options.auth[:password].nil? or options.auth[:user_cert_password].nil?
41
+ options.auth[:password] = options.auth[:user_cert_password] = ask("Enter password: ") { |q| q.echo = false } unless options.auth[:type] == "none"
42
+ end
23
43
 
24
44
  begin
25
- puts "This is an OCCI client utility."
45
+
46
+ OCCI::Log.info "Establishing a connection to #{options.endpoint} ..."
47
+ connect options.endpoint, options.auth, options.log, true, options.media_type
48
+
49
+ OCCI::Log.info "Executing action #{options.action.to_s} on #{options.resource} ..."
50
+ case options.action
51
+ when :list
52
+
53
+ if resource_types.include? options.resource or resource_type_identifiers.include? options.resource
54
+ pp list options.resource
55
+ elsif mixin_types.include? options.resource
56
+ pp mixins options.resource
57
+ elsif mixin_type_identifiers.include? options.resource
58
+ pp mixins options.resource.split('#').last
59
+ else
60
+ puts "Unknown resource #{options.resource}, there is nothing to list here!"
61
+ end
62
+
63
+ when :describe
64
+
65
+ if resource_types.include? options.resource or resource_type_identifiers.include? options.resource or options.resource.start_with? options.endpoint
66
+ pp describe options.resource
67
+ elsif mixin_types.include? options.resource
68
+ mixins(options.resource).each do |mxn|
69
+ mxn = mxn.split("#").last
70
+ pp mixin(mxn, options.resource, true)
71
+ end
72
+ elsif mixin_type_identifiers.include? options.resource
73
+ mixins(options.resource.split('#').last).each do |mxn|
74
+ mxn = mxn.split("#").last
75
+ pp mixin(mxn, options.resource, true)
76
+ end
77
+ elsif mixins.include? options.resource
78
+ mxn_type,mxn = options.resource.split("/").last.split('#')
79
+ pp mixin(mxn, mxn_type, true)
80
+ elsif mixin_types.include? options.resource.split('#').first
81
+ mxn_type,mxn = options.resource.split('#')
82
+ pp mixin(mxn, mxn_type, true)
83
+ else
84
+ puts "Unknown resource #{options.resource}, there is nothing to describe here!"
85
+ end
86
+
87
+ when :create
88
+
89
+ if resource_types.include? options.resource or resource_type_identifiers.include? options.resource
90
+ raise "Not yet implemented!" unless options.resource.include? "compute"
91
+
92
+ res = resource options.resource
93
+
94
+ OCCI::Log.debug "Creating #{options.resource}:\n#{res.inspect}"
95
+ OCCI::Log.debug "with mixins:#{options.mixin}"
96
+
97
+ options.mixin.keys.each do |type|
98
+ OCCI::Log.debug "Adding mixins of type #{type} to #{options.resource}"
99
+ options.mixin[type].each do |name|
100
+ mxn = mixin name, type
101
+
102
+ raise "Unknown mixin #{type}##{name}, stopping here!" if mxn.nil?
103
+ OCCI::Log.debug "Adding mixin #{mxn} to #{options.resource}"
104
+ res.mixins << mxn
105
+ end
106
+ end
107
+
108
+ #TODO: set other attributes
109
+ res.attributes.occi!.core!.title = options.resource_title
110
+
111
+ puts create res
112
+ else
113
+ puts "Unknown resource #{options.resource}, there is nothing to create here!"
114
+ end
115
+
116
+ when :delete
117
+ result = delete options.resource
118
+
119
+ if result
120
+ puts "Resource #{options.resource} successfully removed!"
121
+ else
122
+ puts "Failed to remove resource #{options.resource}!"
123
+ end
124
+ when :trigger
125
+ raise "Not yet implemented!"
126
+ else
127
+ raise "Unknown action [#{options.action}]!"
128
+ end
129
+
130
+ rescue OpenSSL::SSL::SSLError => ssl_ex
131
+ OCCI::Log.error "An SSL Auth Error occurred! Please, make sure your credentials are valid and the endpoind is trusted! Message: #{ssl_ex.message}"
132
+ raise ssl_ex if options.debug
133
+ exit!
134
+ rescue OpenSSL::PKey::RSAError => key_ex
135
+ OCCI::Log.error "An X509 Error occurred! Please, check your credentials! Message: #{key_ex.message}"
136
+ raise key_ex if options.debug
137
+ exit!
26
138
  rescue Exception => ex
27
- puts "An error occurred!"
139
+ OCCI::Log.error "An error occurred! Message: #{ex.message}"
140
+ raise ex if options.debug
28
141
  exit!
29
142
  end
143
+
144
+ OCCI::Log.info "OCCI client is shutting down ..."
145
+
146
+ exit!(true)
@@ -3,23 +3,24 @@ require 'occi'
3
3
  require 'pp'
4
4
 
5
5
  ## options
6
- use_os_temlate = true # use OS_TEMPLATE or NETWORK + STORAGE + INSTANCE TYPE
7
- OS_TEMPLATE = 'monitoring' # name of the VM template in ON
6
+ use_os_temlate = true # use OS_TEMPLATE or NETWORK + STORAGE + INSTANCE TYPE
7
+ OS_TEMPLATE = 'monitoring' # name of the VM template in ON
8
8
 
9
- clean_up_compute = true # issue DELETE <RESOURCE> after we are done
9
+ clean_up_compute = true # issue DELETE <RESOURCE> after we are done
10
10
 
11
- USER_CERT = ENV['HOME'] + '/.globus/usercred.pem'
11
+ USER_CERT = ENV['HOME'] + '/.globus/usercred.pem'
12
12
  USER_CERT_PASSWORD = 'mypassphrase'
13
- CA_PATH = '/etc/grid-security/certificates'
13
+ CA_PATH = '/etc/grid-security/certificates'
14
+ ENDPOINT = 'https://localhost:3300'
14
15
 
15
16
  ## get an OCCI::Client instance
16
- client = OCCI::Client.new('https://localhost:3300',
17
- { :type => "x509",
18
- :user_cert => USER_CERT,
19
- :user_cert_password => USER_CERT_PASSWORD,
20
- :ca_path => CA_PATH },
21
- { :out => STDERR,
22
- :level => OCCI::Log::DEBUG})
17
+ client = OCCI::Client.new(ENDPOINT,
18
+ { :type => "x509",
19
+ :user_cert => USER_CERT,
20
+ :user_cert_password => USER_CERT_PASSWORD,
21
+ :ca_path => CA_PATH },
22
+ { :out => STDERR,
23
+ :level => OCCI::Log::DEBUG })
23
24
 
24
25
  puts "\n\nListing all available resource types:"
25
26
  client.get_resource_types.each do |type|
@@ -428,12 +428,13 @@ module OCCI
428
428
  response = if filter
429
429
  categories = filter.categories.collect { |category| category.to_text }.join(',')
430
430
  attributes = filter.entities.collect { |entity| entity.attributes.combine.collect { |k, v| k + '=' + v } }.join(',')
431
+
431
432
  headers = self.class.headers.clone
432
433
  headers['Content-Type'] = 'text/occi'
433
434
  headers['Category'] = categories unless categories.empty?
434
435
  headers['X-OCCI-Attributes'] = attributes unless attributes.empty?
435
- self.class.get(@endpoint + path,
436
- :headers => headers)
436
+
437
+ self.class.get(@endpoint + path, :headers => headers)
437
438
  else
438
439
  self.class.get(@endpoint + path)
439
440
  end
@@ -0,0 +1,146 @@
1
+ require 'ostruct'
2
+ require 'optparse'
3
+
4
+ class OcciOpts
5
+
6
+ def self.parse(args)
7
+
8
+ options = OpenStruct.new
9
+
10
+ options.debug = false
11
+ options.verbose = false
12
+
13
+ options.log = {}
14
+ options.log[:out] = STDERR
15
+ options.log[:level] = OCCI::Log::WARN
16
+
17
+ options.endpoint = "https://localhost:3300/"
18
+
19
+ options.auth = {}
20
+ options.auth[:type] = "none"
21
+ options.auth[:user_cert] = ENV['HOME'] + "/.globus/usercred.pem"
22
+ options.auth[:ca_path] = "/etc/grid-security/certificates"
23
+ options.auth[:username] = "anonymous"
24
+
25
+ options.media_type = "application/occi+json"
26
+
27
+ opts = OptionParser.new do |opts|
28
+ opts.banner = "Usage: occi [OPTIONS]"
29
+
30
+ opts.separator ""
31
+ opts.separator "Options:"
32
+
33
+ opts.on("--endpoint URI", String, "OCCI server URI, defaults to '#{options.endpoint}'") do |endpoint|
34
+ options.endpoint = endpoint
35
+ end
36
+
37
+ opts.on("--auth METHOD", [:x509, :basic, :digest, :none], "Authentication method, defaults to '#{options.auth[:type]}'") do |auth|
38
+ options.auth[:type] = auth.to_s
39
+ end
40
+
41
+ opts.on("--username USER", String, "Username for basic or digest authentication, defaults to '#{options.auth[:username]}'") do |username|
42
+ options.auth[:username] = username
43
+ end
44
+
45
+ opts.on("--password PASSWORD", String, "Password for basic, digest or x509 authentication") do |password|
46
+ options.auth[:password] = password
47
+ options.auth[:user_cert_password] = password
48
+ end
49
+
50
+ opts.on("--ca-path PATH", String, "Path to CA certificates, defaults to '#{options.auth[:ca_path]}'") do |ca_path|
51
+ options.auth[:ca_path] = ca_path
52
+ end
53
+
54
+ opts.on("--user-cred X509_CREDENTIALS", String, "Path to user's x509 credentials, defaults to '#{options.auth[:user_cert]}'") do |user_cred|
55
+ options.auth[:user_cert] = user_cred
56
+ end
57
+
58
+ opts.on("--media-type MEDIA_TYPE", ["application/occi+json", "application/occi+xml", "text/plain"], "Media type for client <-> server communication, defaults to '#{options.media_type}'") do |media_type|
59
+ options.media_type = media_type
60
+ end
61
+
62
+ opts.on("--resource RESOURCE", String, "Resource to be queried (e.g. network, compute, storage etc.), required") do |resource|
63
+ options.resource = resource
64
+ end
65
+
66
+ opts.on("--resource-title TITLE", String, "Resource title for new resources") do |resource_title|
67
+ options.resource_title = resource_title
68
+ end
69
+
70
+ opts.on("--action ACTION", [:list, :describe, :create, :delete, :trigger], "Action to be performed on the resource, required") do |action|
71
+ options.action = action
72
+ end
73
+
74
+ opts.on("--mixin NAME", String, "Type and name of the mixin as TYPE#NAME (e.g. os_tpl#monitoring, resource_tpl#medium)") do |mixin|
75
+ parts = mixin.split("#")
76
+
77
+ raise "Unknown mixin format! Use TYPE#NAME!" unless parts.length == 2
78
+
79
+ options.mixin = {} if options.mixin.nil?
80
+ options.mixin[parts[0]] = [] if options.mixin[parts[0]].nil?
81
+ options.mixin[parts[0]] << parts[1]
82
+ end
83
+
84
+ opts.on("--trigger-action TRIGGER_ACTION", String, "Action to be triggered on the resource") do |trigger_action|
85
+ options.trigger_action = trigger_action
86
+ end
87
+
88
+ opts.on("--log-to OUTPUT", [:STDOUT, :stdout, :STDERR, :stderr], "Log to the specified device, defaults to 'STDERR'") do |log_to|
89
+ options.log[:out] = STDOUT if log_to == :stdout or log_to == :STDOUT
90
+ end
91
+
92
+ opts.on_tail("--debug", "Enable debugging messages") do |debug|
93
+ options.debug = debug
94
+ options.log[:level] = OCCI::Log::DEBUG
95
+ end
96
+
97
+ opts.on_tail("--verbose", "Be more verbose, less intrusive than debug mode") do |verbose|
98
+ options.verbose = verbose
99
+ options.log[:level] = OCCI::Log::INFO unless options.log[:level] == OCCI::Log::DEBUG
100
+ end
101
+
102
+ opts.on_tail("-h", "--help", "Show this message") do
103
+ puts opts
104
+ exit!
105
+ end
106
+
107
+ opts.on_tail("--version", "Show version") do
108
+ puts OCCI::VERSION
109
+ exit!(true)
110
+ end
111
+
112
+ end
113
+
114
+ begin
115
+ opts.parse!(args)
116
+ rescue Exception => ex
117
+ puts ex.message.capitalize
118
+ puts opts
119
+ exit!
120
+ end
121
+
122
+ mandatory = []
123
+
124
+ if options.action == :trigger
125
+ mandatory << :trigger_action
126
+ end
127
+
128
+ if options.action == :create
129
+ mandatory << :mixin << :resource_title
130
+ end
131
+
132
+ mandatory.concat [:resource, :action]
133
+
134
+ options_hash = options.marshal_dump
135
+
136
+ missing = mandatory.select{ |param| options_hash[param].nil? }
137
+ if not missing.empty?
138
+ puts "Missing required arguments: #{missing.join(', ')}"
139
+ puts opts
140
+ exit!
141
+ end
142
+
143
+ options
144
+ end
145
+
146
+ end
@@ -59,6 +59,13 @@ module OCCI
59
59
  text
60
60
  end
61
61
 
62
+ def to_header
63
+ header = Hashie::Mash.new
64
+ header[:Category] = self.categories.collect {|category| category.to_text}.join(',') if self.categories.any?
65
+ header = self.entities.first.to_header if self.entities.any?
66
+ header
67
+ end
68
+
62
69
  def inspect
63
70
  JSON.pretty_generate(JSON.parse(to_json))
64
71
  end
@@ -52,6 +52,11 @@ module OCCI
52
52
  text
53
53
  end
54
54
 
55
+ def to_header
56
+ header = Hashie::Mash.new
57
+ header[:Category] = self.to_text
58
+ end
59
+
55
60
  def inspect
56
61
  JSON.pretty_generate(JSON.parse(to_json))
57
62
  end
@@ -167,6 +167,30 @@ module OCCI
167
167
  text
168
168
  end
169
169
 
170
+ def to_header
171
+ scheme, term = self.kind.split('#')
172
+ header = Hashie::Mash.new
173
+ header['Category'] = term + ';scheme=' + scheme.inspect + ';class="kind"'
174
+ @mixins.each do |mixin|
175
+ scheme, term = mixin.split('#')
176
+ header['Category'] += ',' + term + ';scheme=' + scheme.inspect + ';class="mixin"'
177
+ end
178
+ attributes = []
179
+ @attributes.combine.each_pair do |name, value|
180
+ name = name.inspect if name.kind_of? String
181
+ value = value.inspect if value.kind_of? String
182
+ attributes << name + '=' + value
183
+ end
184
+ header['X-OCCI-Attribute'] = attributes.join(',') if attributes.any?
185
+ links = []
186
+ @actions.each do |action|
187
+ _, term = mixin.split('#')
188
+ links << self.location + '?action=' + term + '>;rel=' + action.inspect
189
+ end
190
+ header['Link'] = links.join(',') if links.any?
191
+ header
192
+ end
193
+
170
194
  def inspect
171
195
  JSON.pretty_generate(JSON.parse(to_json))
172
196
  end
data/lib/occi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module OCCI
2
- VERSION = "2.5.7" unless defined?(::OCCI::VERSION)
2
+ VERSION = "2.5.8" unless defined?(::OCCI::VERSION)
3
3
  end
data/occi.gemspec CHANGED
@@ -25,7 +25,8 @@ Gem::Specification.new do |gem|
25
25
  gem.add_dependency 'nokogiri'
26
26
  gem.add_dependency 'activesupport'
27
27
  gem.add_dependency 'httparty'
28
+ gem.add_dependency 'highline'
28
29
  gem.add_dependency 'i18n'
29
30
 
30
31
  gem.required_ruby_version = ">= 1.8.7"
31
- end
32
+ end
@@ -44,9 +44,9 @@ module OCCI
44
44
  self_location = '/link/networkinterface/456'
45
45
  kind = 'http://schemas.ogf.org/occi/infrastructure#networkinterface'
46
46
  attributes = Hashie::Mash.new
47
- attributes.occi!.networkinterface!.interface = '"eth0"'
48
- attributes.occi!.networkinterface!.mac = '"00:11:22:33:44:55"'
49
- attributes.occi!.networkinterface!.state = '"active"'
47
+ attributes.occi!.networkinterface!.interface = 'eth0'
48
+ attributes.occi!.networkinterface!.mac = '00:11:22:33:44:55'
49
+ attributes.occi!.networkinterface!.state = 'active'
50
50
  attributes_string = %Q{occi.networkinterface.interface="eth0";occi.networkinterface.mac="00:11:22:33:44:55";occi.networkinterface.state="active"}
51
51
  link_string = %Q{Link: <#{target}>; rel="#{rel}"; self="#{self_location}"; category="#{kind}"; #{attributes_string}}
52
52
 
@@ -62,7 +62,7 @@ module OCCI
62
62
  describe "#X-OCCI-Attribute" do
63
63
  it "is parsed successful" do
64
64
  attribute = Hashie::Mash.new
65
- attribute.occi!.compute!.architecture = '"x86_64"'
65
+ attribute.occi!.compute!.architecture = 'x86_64'
66
66
 
67
67
  x_occi_attributes_string = %Q{X-OCCI-Attribute: occi.compute.architecture="x86_64"}
68
68
 
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.5.7
4
+ version: 2.5.8
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-09-10 00:00:00.000000000 Z
13
+ date: 2012-09-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -124,6 +124,22 @@ dependencies:
124
124
  - - ! '>='
125
125
  - !ruby/object:Gem::Version
126
126
  version: '0'
127
+ - !ruby/object:Gem::Dependency
128
+ name: highline
129
+ requirement: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ type: :runtime
136
+ prerelease: false
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
127
143
  - !ruby/object:Gem::Dependency
128
144
  name: i18n
129
145
  requirement: !ruby/object:Gem::Requirement
@@ -175,6 +191,7 @@ files:
175
191
  - lib/occi.rb
176
192
  - lib/occi/api/client.rb
177
193
  - lib/occi/api/dsl.rb
194
+ - lib/occi/client/occiopts.rb
178
195
  - lib/occi/collection.rb
179
196
  - lib/occi/core.rb
180
197
  - lib/occi/core/action.rb