occi-cli 4.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ *.gem
2
+ *.swp
3
+ .project
4
+ .idea
5
+ .yardoc
6
+ .bundle
7
+ .rvmrc
8
+ lib/occiantlr/output/
9
+ pkg
10
+ tmp
11
+ log
12
+ coverage
13
+ vendor
14
+ collection
15
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper --color --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,43 @@
1
+ language: ruby
2
+
3
+ before_install:
4
+ - sudo apt-get install -qq libonig-dev
5
+
6
+ rvm:
7
+ - 1.8.7
8
+ - 1.9.3
9
+ - 2.0.0
10
+ - ruby-head
11
+ - jruby-19mode
12
+ - jruby-head
13
+
14
+ jdk:
15
+ - openjdk7
16
+ - oraclejdk7
17
+ - openjdk6
18
+
19
+ matrix:
20
+ allow_failures:
21
+ - rvm: ruby-head
22
+ - rvm: jruby-head
23
+ exclude:
24
+ - rvm: 1.8.7
25
+ jdk: openjdk7
26
+ - rvm: 1.8.7
27
+ jdk: oraclejdk7
28
+ - rvm: 1.9.3
29
+ jdk: openjdk7
30
+ - rvm: 1.9.3
31
+ jdk: oraclejdk7
32
+ - rvm: 2.0.0
33
+ jdk: openjdk7
34
+ - rvm: 2.0.0
35
+ jdk: oraclejdk7
36
+ - rvm: ruby-head
37
+ jdk: openjdk7
38
+ - rvm: ruby-head
39
+ jdk: oraclejdk7
40
+
41
+ branches:
42
+ only:
43
+ - master
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --title "Documentation of the OCCI gem" --markup markdown --private
data/AUTHORS ADDED
@@ -0,0 +1,9 @@
1
+ rOcci was designed and is mainly developed by Florian Feldhaus (GWDG) and Piotr Kasprzak (GWDG) in Germany.
2
+
3
+ Special thanks to the following extraordinary individuals, whithout whom rOcci would not be possible:
4
+
5
+ * Hayati Bice - who wrote the initial version of an Occi server rOcci is based on
6
+ * Max Günther - who wrote the EC2 backend
7
+ * Andre Thevapalan - for his input regarding the JSON rendering
8
+ * Boris Parak - especially for his input regarding the Client / Client DSL and CLI
9
+ * the OCCI Working Group - for developing OCCI
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org/"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'warbler', :git => 'git://github.com/jruby/warbler.git', :ref => 'ce3ce4df137504822e4cbb9399dee7e7dd767c44'
7
+ gem 'rubygems-tasks', :git => 'git://github.com/postmodern/rubygems-tasks.git'
8
+ end
9
+
10
+ platforms :jruby do
11
+ gem 'jruby-openssl' if ((defined? JRUBY_VERSION) && (JRUBY_VERSION.split('.')[1].to_i < 7))
12
+ end
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2012 GWDG
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,211 @@
1
+ rOCCI-cli - A Ruby OCCI Framework
2
+ =================================
3
+
4
+ [![Build Status](https://secure.travis-ci.org/gwdg/rOCCI-cli.png)](http://travis-ci.org/gwdg/rOCCI-cli)
5
+ [![Dependency Status](https://gemnasium.com/gwdg/rOCCI-cli.png)](https://gemnasium.com/gwdg/rOCCI-cli)
6
+ [![Gem Version](https://fury-badge.herokuapp.com/rb/occi-cli.png)](https://badge.fury.io/rb/occi-cli)
7
+ [![Code Climate](https://codeclimate.com/github/gwdg/rOCCI-cli.png)](https://codeclimate.com/github/gwdg/rOCCI-cli)
8
+
9
+ Requirements
10
+ ------------
11
+
12
+ Ruby
13
+ * at least version 1.8.7 is required
14
+
15
+ The following setup is recommended
16
+
17
+ * usage of the Ruby Version Manager
18
+ * Ruby 1.9.3
19
+ * RubyGems installed
20
+
21
+ The following libraries / packages may be required to use rOCCI-cli
22
+
23
+ * libxslt-dev
24
+ * libxml2-dev
25
+ * **only if using Ruby 1.8.7:** libonig-dev (Linux) or oniguruma (Mac)
26
+
27
+ To use rOCCI-cli with Java, you need JRE 6 or 7. To build rOCCI-cli for Java, you need JDK 6 or 7.
28
+
29
+ Installation
30
+ ------------
31
+
32
+ **[Mac OS X has some special requirements for the installation. Detailed information can be found in
33
+ doc/macosx.md.](doc/macosx.md)**
34
+
35
+ To install the most recent stable version
36
+
37
+ gem install occi-cli
38
+
39
+ To install the most recent beta version
40
+
41
+ gem install occi-cli --pre
42
+
43
+ ### Installation from source
44
+
45
+ To use rOCCI-cli from source it is very much recommended to use RVM. [Install RVM](https://rvm.io/rvm/install/) with
46
+
47
+ curl -L https://get.rvm.io | bash -s stable --ruby
48
+
49
+ #### Ruby
50
+
51
+ To build and install the bleeding edge version from master
52
+
53
+ git clone git://github.com/gwdg/rOCCI-cli.git
54
+ cd rOCCI-cli
55
+ rvm install ruby-1.9.3
56
+ rvm --create --ruby-version use 1.9.3@rOCCI-cli
57
+ bundle install --deployment
58
+ rake install
59
+
60
+ #### Java
61
+
62
+ To build a Java jar file from master use
63
+
64
+ git clone git://github.com/gwdg/rOCCI-cli.git
65
+ cd rOCCI-cli
66
+ rvm install jruby-1.7.1
67
+ rvm --create --ruby-version use jruby-1.7.1@rOCCI-cli
68
+ gem install bundler
69
+ bundle install
70
+ warble
71
+
72
+ For Linux / Mac OS X you can create a OCCI Java executable from the jar file using
73
+
74
+ sudo echo '#!/usr/bin/java -jar' | cat - occi.jar > occi ; sudo chmod +x occi
75
+
76
+ Usage
77
+ -----
78
+ ### Client
79
+ 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 ask for it later on. There is also an interactive mode, which will allow you to interact with the client through menus and answers to simple questions (this feature is still experimental).
80
+
81
+ To find out more about available options and defaults use
82
+
83
+ occi --help
84
+
85
+ To run the client in an interactive mode use
86
+
87
+ occi --interactive
88
+ occi --interactive --endpoint https://<ENDPOINT>:<PORT>/
89
+ occi --interactive --endpoint https://<ENDPOINT>:<PORT>/ --auth x509
90
+
91
+ To list available resources use
92
+
93
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action list --resource compute --auth x509
94
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action list --resource storage --auth x509
95
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action list --resource network --auth x509
96
+
97
+ To describe available resources use
98
+
99
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource compute --auth x509
100
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource storage --auth x509
101
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource network --auth x509
102
+
103
+ To describe specific resources use
104
+
105
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource /compute/<OCCI_ID> --auth x509
106
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource /storage/<OCCI_ID> --auth x509
107
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource /network/<OCCI_ID> --auth x509
108
+
109
+ To list available OS templates or Resource templates use
110
+
111
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action list --resource os_tpl --auth x509
112
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action list --resource resource_tpl --auth x509
113
+
114
+ To describe a specific OS template or Resource template use
115
+
116
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource os_tpl#debian6 --auth x509
117
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action describe --resource resource_tpl#small --auth x509
118
+
119
+ To create a compute resource with mixins use
120
+
121
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action create --resource compute --mixin os_tpl#debian6 --mixin resource_tpl#small --attributes title="My rOCCI VM" --auth x509
122
+
123
+ To delete a compute resource use
124
+
125
+ occi --endpoint https://<ENDPOINT>:<PORT>/ --action delete --resource /compute/<OCCI_ID> --auth x509
126
+
127
+ Changelog
128
+ ---------
129
+
130
+ ### Version 3.1
131
+ * added basic OS Keystone support
132
+ * added support for PKCS12 credentials for X.509 authN
133
+ * updated templates for plain output formatting
134
+ * minor client API changes
135
+ * several bugfixes
136
+
137
+ ### Version 3.0
138
+
139
+ * many bugfixes
140
+ * rewrote Core classes to use metaprogramming techniques
141
+ * added VCR cassettes for reliable testing against prerecorded server responses
142
+ * several updates to the OCCI Client
143
+ * started work on an OCCI Client using AMQP as transport protocol
144
+ * added support for keystone authentication to be used with the OpenStack OCCI server
145
+ * updated dependencies
146
+ * updated rspec tests
147
+ * started work on cucumber features
148
+
149
+ ### Version 2.5
150
+
151
+ * improved OCCI Client
152
+ * improved documentation
153
+ * several bugfixes
154
+
155
+ ### Version 2.4
156
+
157
+ * Changed OCCI attribute properties from lowercase to first letter uppercase (e.g. type -> Type, default -> Default, ...)
158
+
159
+ ### Version 2.3
160
+
161
+ * OCCI objects are now initialized with a list of attributes instead of a hash. Thus it is easier to check which
162
+ attributes are expected by a class and helps prevent errors.
163
+ * Parsing of a subset of the OVF specification is supported. Further parts of the specification will be covered in
164
+ future versions of rOCCI.
165
+
166
+ ### Version 2.2
167
+
168
+ * OCCI Client added. The client simplifies the execution of OCCI commands and provides shortcuts for often used steps.
169
+
170
+ ### Version 2.1
171
+
172
+ * 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.
173
+
174
+ ### Version 2.0
175
+
176
+ * Starting with version 2.0 Florian Feldhaus and Piotr Kasprzak took over the development of the OCCI gem. The codebase was taken from the rOCCI framework and improved to be bundled as a standalone gem.
177
+
178
+ ### Version 1.X
179
+
180
+ * Version 1.X of the OCCI gem has been developed by retr0h and served as a simple way to access the first OpenNebula OCCI implementation.
181
+
182
+ Development
183
+ -----------
184
+
185
+ Checkout latest version from GIT:
186
+
187
+ git clone git://github.com/gwdg/rOCCI-cli.git
188
+
189
+ Change to rOCCI-cli folder
190
+
191
+ cd rOCCI-cli
192
+
193
+ Install dependencies for deployment
194
+
195
+ bundle install
196
+
197
+ ### Code Documentation
198
+
199
+ [Code Documentation for rOCCI-cli by YARD](http://rubydoc.info/github/gwdg/rOCCI-cli/)
200
+
201
+ ### Continuous integration
202
+
203
+ [Continuous integration for rOCCI-cli by Travis-CI](http://travis-ci.org/gwdg/rOCCI-cli/)
204
+
205
+ ### Contribute
206
+
207
+ 1. Fork it.
208
+ 2. Create a branch (git checkout -b my_markup)
209
+ 3. Commit your changes (git commit -am "My changes")
210
+ 4. Push to the branch (git push origin my_markup)
211
+ 5. Create an Issue with a link to your branch
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ require 'rubygems/tasks'
2
+
3
+ task :default => 'test'
4
+
5
+ desc "Run all tests; includes rspec and coverage reports"
6
+ task :test => 'rcov:all'
7
+
8
+ Gem::Tasks.new(:build => {:tar => true, :zip => true}, :sign => {:checksum => true, :pgp => false})
9
+
10
+ namespace :rcov do
11
+
12
+ require 'rspec/core/rake_task'
13
+
14
+ RSpec::Core::RakeTask.new(:rspec) do |t|
15
+ ENV['COVERAGE'] = "true"
16
+ end
17
+
18
+ desc "Run rspec to generate aggregated coverage"
19
+ task :all do |t|
20
+ rm "coverage/coverage.data" if File.exist?("coverage/coverage.data")
21
+ Rake::Task['rcov:rspec'].invoke
22
+ end
23
+
24
+ end
25
+
26
+ require 'yard'
27
+ YARD::Rake::YardocTask.new(:yard) do |t|
28
+ t.options = ['--any', '--extra', '--opts'] # optional
29
+ end
data/bin/occi ADDED
@@ -0,0 +1,351 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # -------------------------------------------------------------------------- #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
+ # not use this file except in compliance with the License. You may obtain #
6
+ # a copy of the License at #
7
+ # #
8
+ # http://www.apache.org/licenses/LICENSE-2.0 #
9
+ # #
10
+ # Unless required by applicable law or agreed to in writing, software #
11
+ # distributed under the License is distributed on an "AS IS" BASIS, #
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
+ # See the License for the specific language governing permissions and #
14
+ # limitations under the License. #
15
+ #--------------------------------------------------------------------------- #
16
+
17
+ require 'rubygems'
18
+ require 'occi-cli'
19
+ require 'pp'
20
+ require 'highline/import'
21
+ require 'openssl'
22
+
23
+ extend Occi::Api::Dsl
24
+
25
+ # get arguments and validate/parse them to an ostruct
26
+ options = Occi::Cli::OcciOpts.parse ARGV
27
+
28
+ # initialize logger
29
+ logger = Occi::Log.new(options.log[:out])
30
+ logger.level = options.log[:level]
31
+ options.log[:logger] = logger
32
+
33
+ # initialize output factory
34
+ output = Occi::Cli::ResourceOutputFactory.new options.output_format
35
+
36
+ Occi::Log.info "Starting OCCI client ..."
37
+ Occi::Log.debug "Options: #{options}"
38
+
39
+ # running with an empty password, we should ask the user for one
40
+ # if auth method is not "none"
41
+ if options.auth[:password].nil? || options.auth[:user_cert_password].nil?
42
+ Occi::Log.debug "Password is not set, asking for it now ..."
43
+
44
+ say("\n")
45
+
46
+ options.auth[:user_cert_password] = ask("Enter a password: ") {
47
+ |q| q.echo = false
48
+ } unless options.auth[:type] == "none" || (options.auth[:voms] && options.auth[:type] == "x509")
49
+
50
+ options.auth[:password] = options.auth[:user_cert_password]
51
+ end
52
+
53
+ # establish a connection before entering the loop
54
+ # this will considerably speed-up the interactive mode and has
55
+ # no effect on the non-interactive one
56
+ begin
57
+ Occi::Log.info "Establishing a connection to #{options.endpoint} ..."
58
+
59
+ options.auto_connect = true
60
+ connect :http, options
61
+ rescue OpenSSL::SSL::SSLError => ssl_ex
62
+ # generic SSL error raised whilst establishing a connection
63
+ # possibly an untrusted server cert or invalid user credentials
64
+ Occi::Log.error "An SSL error occurred! Please, make sure your credentials " \
65
+ "are valid and recognized by the endpoint! Message: #{ssl_ex.message}"
66
+
67
+ raise ssl_ex if options.debug
68
+ exit!
69
+ rescue OpenSSL::PKey::RSAError => key_ex
70
+ # generic X509 error raised whilst reading user's credentials from a file
71
+ # possibly a wrong password or mangled/unsupported credential format
72
+ Occi::Log.error "An X509 error occurred! Please, make sure you are using the " \
73
+ "right password and the file contains both your certificate " \
74
+ "and your private key! Message: #{key_ex.message}"
75
+
76
+ raise key_ex if options.debug
77
+ exit!
78
+ rescue Errno::ECONNREFUSED
79
+ # the remote server has refused our connection attempt(s)
80
+ # there is nothing we can do ...
81
+ Occi::Log.error "Connection refused by #{options.endpoint}!"
82
+ exit!
83
+ rescue Exception => ex
84
+ # something went wrong during the execution
85
+ # hide the stack trace in non-debug modes
86
+ Occi::Log.error "An error occurred! Message: #{ex.message}"
87
+
88
+ raise ex if options.debug
89
+ exit!
90
+ end
91
+
92
+ # dump the occi model provided by the server and exit
93
+ if options.dump_model
94
+
95
+ if !model.respond_to? :instance_variables
96
+ Occi::Log.error "Your Ruby doesn't support 'instance_variables' calls!"
97
+ exit!
98
+ end
99
+
100
+ collection = model.get options.filter
101
+
102
+ # iterate through available instance variables
103
+ collection.instance_variables.each do |inst_var_sym|
104
+ puts "#"*79
105
+ puts "Dumping #{inst_var_sym.to_s}:"
106
+
107
+ inst_var = collection.instance_variable_get(inst_var_sym)
108
+ next unless inst_var.respond_to? :each
109
+
110
+ # iterate through collection elements
111
+ inst_var.each do |coll_elm|
112
+ # respect user's output-format preferences
113
+ if options.output_format == :json and coll_elm.respond_to? :as_json
114
+ puts "\n"
115
+ pp coll_elm.as_json
116
+ puts "\n"
117
+ elsif coll_elm.respond_to? :to_string
118
+ puts "\n#{coll_elm.to_string}\n"
119
+ else
120
+ puts "\n#{coll_elm.inspect}\n"
121
+ end
122
+ end
123
+
124
+ #
125
+ puts "#"*79
126
+ end
127
+
128
+ exit! true
129
+ end
130
+
131
+ # start of the main loop, this part of the code is responsible for
132
+ # interactive menus and actions execution
133
+ # this block will run while options.interactive is True, i.e.
134
+ # only once in the non-interactive mode
135
+ begin
136
+
137
+ # display menus in the interactive mode, there are two main variables
138
+ # that need to be set here: options.action and options.resource
139
+ if options.interactive
140
+
141
+ Occi::Log.debug "Running in an interactive mode ..."
142
+
143
+ # reset action and resource, just to be sure
144
+ options.action = nil
145
+ options.resource = nil
146
+
147
+ # offer just the resource types we will be able to process
148
+ menu_resources = Occi::Cli::ResourceOutputFactory.allowed_resource_types
149
+
150
+ # separate menus from each other
151
+ say("\n")
152
+
153
+ # first we need an action
154
+ choose do |menu|
155
+ menu.prompt = "Please, choose an action: "
156
+
157
+ # list action requires a resource type
158
+ menu.choice(:list) {
159
+ options.action = :list
160
+
161
+ # separate menus from each other
162
+ say("\n")
163
+
164
+ choose do |list_menu|
165
+ list_menu.prompt = "Which one should I list? "
166
+
167
+ menu_resources.each do |menu_resource|
168
+ list_menu.choice(menu_resource) { options.resource = menu_resource.to_s }
169
+ end
170
+
171
+ list_menu.choice(:back) { options.action = :skip }
172
+ end
173
+ }
174
+
175
+ # describe action requires a resource type or a resource location
176
+ menu.choice(:describe) {
177
+ options.action = :describe
178
+
179
+ # separate menus from each other
180
+ say("\n")
181
+
182
+ # display the resource types first
183
+ choose do |describe_menu|
184
+ describe_menu.prompt = "Which one should I describe? "
185
+
186
+ menu_resources.each do |menu_resource|
187
+ describe_menu.choice(menu_resource) {
188
+ options.resource = menu_resource.to_s
189
+
190
+ # separate menus from each other
191
+ say("\n")
192
+
193
+ # display available resources for this resource type
194
+ choose do |describe_menu_spec|
195
+ describe_menu_spec.prompt = "Should I describe a specific resource? "
196
+
197
+ describe_menu_spec.choice(:all) {
198
+ # leave options.resource set to compute/network/storage
199
+ }
200
+
201
+ found = helper_list options
202
+ found.each do |found_resource|
203
+ describe_menu_spec.choice(found_resource.to_sym) { options.resource = found_resource }
204
+ end
205
+
206
+ describe_menu_spec.choice(:back) { options.action = :skip }
207
+ end unless menu_resource.to_s.reverse.start_with? "lpt_"
208
+ }
209
+ end
210
+
211
+ describe_menu.choice(:back) { options.action = :skip }
212
+ end
213
+ }
214
+
215
+ # create action requires resource type, resource title
216
+ # and optionally mixins (usually two, os_tpl and resource_tpl)
217
+ menu.choice(:create) {
218
+ options.action = :create
219
+
220
+ # separate menus from each other
221
+ say("\n")
222
+
223
+ # display the resource types
224
+ choose do |create_menu|
225
+ create_menu.prompt = "Which one should I create? "
226
+
227
+ menu_resources.each do |menu_resource|
228
+ create_menu.choice(menu_resource) {
229
+ options.resource = menu_resource.to_s
230
+ } unless menu_resource.to_s.reverse.start_with? "lpt_"
231
+ end
232
+
233
+ create_menu.choice(:back) { options.action = :skip }
234
+ end
235
+
236
+ # if the user didn't choose "Back", ask for details
237
+ # TODO: currently only COMPUTE is supported
238
+ if options.action == :create
239
+ options.attributes = {} if options.attributes.nil?
240
+
241
+ options.attributes[:title] = ask("What name should I give to the new resource? ")
242
+ number_of_mixins = ask("How many mixins do you wish me to mix into this resource? ",
243
+ Integer) { |q| q.in = 0..2 }
244
+
245
+ options.mixins = {}
246
+ (1..number_of_mixins).each do |mixin_number|
247
+ mixin = ask("What mixin should I mix in? ") { |q| q.validate = /\A\w+#\w+\Z/ }
248
+ parts = mixin.split("#")
249
+
250
+ options.mixins[parts[0]] = [] if options.mixins[parts[0]].nil?
251
+ options.mixins[parts[0]] << parts[1]
252
+ end
253
+ end
254
+ }
255
+
256
+ # delete action requires a resource location
257
+ menu.choice(:delete) {
258
+ options.action = :delete
259
+
260
+ # separate menus from each other
261
+ say("\n")
262
+
263
+ # display the resource types first
264
+ choose do |delete_menu|
265
+ delete_menu.prompt = "Please, choose a resource type: "
266
+
267
+ menu_resources.each do |menu_resource|
268
+ delete_menu.choice(menu_resource) {
269
+
270
+ # separate menus from each other
271
+ say("\n")
272
+
273
+ # display available resources for this type
274
+ choose do |delete_menu_spec|
275
+ delete_menu_spec.prompt = "Which resource should I delete? "
276
+
277
+ opts = OpenStruct.new
278
+ opts.resource = menu_resource.to_s
279
+
280
+ found = helper_list opts
281
+ found.each do |found_resource|
282
+ delete_menu_spec.choice(found_resource.to_sym) { options.resource = found_resource }
283
+ end
284
+
285
+ delete_menu_spec.choice(:back) { options.action = :skip }
286
+ end unless menu_resource.to_s.reverse.start_with? "lpt_"
287
+ } unless menu_resource.to_s.reverse.start_with? "lpt_"
288
+ end
289
+
290
+ delete_menu.choice(:back) { options.action = :skip }
291
+ end
292
+ }
293
+
294
+ # TODO: trigger is not yet implemented
295
+ menu.choice(:trigger) {
296
+ options.action = :skip
297
+ say("Not implemented yet!")
298
+ }
299
+
300
+ # refresh the OCCI model structures without exiting/re-launching
301
+ # the client, useful when adding new os_tpls/resource_tpls on
302
+ # the server
303
+ menu.choice(:refresh) {
304
+ options.action = :refresh
305
+ }
306
+
307
+ # enough is enough, bye!
308
+ menu.choice(:quit) {
309
+ say("Good bye!")
310
+ exit!(true)
311
+ }
312
+ end
313
+ end
314
+
315
+ Occi::Log.info "Executing action #{options.action.to_s} on #{options.resource} ..."
316
+
317
+ # call the appropriate helper and then format its output
318
+ case options.action
319
+ when :list
320
+ helper_list options, output
321
+ when :describe
322
+ helper_describe options, output
323
+ when :create
324
+ helper_create options, output
325
+ when :delete
326
+ helper_delete options, output
327
+ when :trigger
328
+ helper_trigger options, output
329
+ when :refresh
330
+ refresh
331
+ when :skip
332
+ Occi::Log.info "Skipping this action, probably not implemented yet!"
333
+ else
334
+ raise "Unknown action [#{options.action}]!"
335
+ end
336
+
337
+ rescue Errno::ECONNREFUSED
338
+ # remote server refused our connection attempt(s)
339
+ # even though initial connect was successful
340
+ Occi::Log.error "Connection refused by #{options.endpoint}!"
341
+ exit!
342
+ rescue Exception => ex
343
+ # something went wrong during the execution
344
+ # hide the stack trace in non-debug modes
345
+ Occi::Log.error "An error occurred! Message: #{ex.message}"
346
+
347
+ raise ex if options.debug
348
+ exit!
349
+ end while options.interactive
350
+
351
+ Occi::Log.info "OCCI client is shutting down ..."