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 +15 -0
- data/.rspec +1 -0
- data/.travis.yml +43 -0
- data/.yardopts +1 -0
- data/AUTHORS +9 -0
- data/Gemfile +12 -0
- data/LICENSE +13 -0
- data/README.md +211 -0
- data/Rakefile +29 -0
- data/bin/occi +351 -0
- data/config/warble.rb +151 -0
- data/doc/macosx.md +27 -0
- data/ext/mkrf_conf.rb +34 -0
- data/lib/occi/cli/helpers.rb +149 -0
- data/lib/occi/cli/occi_opts.rb +388 -0
- data/lib/occi/cli/resource_output_factory.rb +95 -0
- data/lib/occi/cli/templates/compute.erb +18 -0
- data/lib/occi/cli/templates/network.erb +9 -0
- data/lib/occi/cli/templates/os_tpl.erb +7 -0
- data/lib/occi/cli/templates/resource_tpl.erb +7 -0
- data/lib/occi/cli/templates/storage.erb +8 -0
- data/lib/occi/cli/version.rb +5 -0
- data/lib/occi-cli.rb +9 -0
- data/occi-cli.gemspec +35 -0
- data/spec/occi/cli/helpers_spec.rb +9 -0
- data/spec/occi/cli/occi_opts_spec.rb +57 -0
- data/spec/occi/cli/resource_output_factory_spec.rb +9 -0
- data/spec/spec_helper.rb +13 -0
- metadata +240 -0
data/.gitignore
ADDED
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 ..."
|