occi 2.5.7 → 2.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/Gemfile +2 -1
- data/Gemfile.lock +2 -0
- data/README.md +164 -40
- data/bin/occi +121 -4
- data/examples/x509auth_example.rb +13 -12
- data/lib/occi/api/client.rb +3 -2
- data/lib/occi/client/occiopts.rb +146 -0
- data/lib/occi/collection.rb +7 -0
- data/lib/occi/core/category.rb +5 -0
- data/lib/occi/core/entity.rb +24 -0
- data/lib/occi/version.rb +1 -1
- data/occi.gemspec +2 -1
- data/spec/occiantlr/parser_spec.rb +4 -4
- metadata +19 -2
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
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
|
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
|
-
|
24
|
-
to start irb from the command line:
|
25
|
+
To find out more about available options and defaults use
|
25
26
|
|
26
|
-
|
27
|
+
occi --help
|
27
28
|
|
28
|
-
|
29
|
-
should load occi:
|
29
|
+
To list available resources use
|
30
30
|
|
31
|
-
|
32
|
-
|
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
|
-
|
35
|
+
To describe available resources use
|
35
36
|
|
36
|
-
|
37
|
-
|
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
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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://
|
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
|
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
|
-
|
183
|
+
To get the location of compute, storage or network resources use
|
79
184
|
|
80
|
-
|
185
|
+
client.list "compute"
|
186
|
+
client.list "storage"
|
187
|
+
client.list "network"
|
81
188
|
|
82
|
-
|
83
|
-
client.get storage
|
84
|
-
client.get network
|
189
|
+
To get the identifiers of specific mixins in specific mixin types use
|
85
190
|
|
86
|
-
|
191
|
+
client.find_mixin "my_template", "os_tpl"
|
192
|
+
client.find_mixin "small", "resource_tpl"
|
87
193
|
|
88
|
-
|
194
|
+
To get the identifiers of specific mixins with unknown types use
|
89
195
|
|
90
|
-
|
196
|
+
client.find_mixin "medium"
|
91
197
|
|
92
|
-
To get
|
198
|
+
To get mixin descriptions use
|
93
199
|
|
94
|
-
client.
|
95
|
-
client.
|
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.
|
100
|
-
size = client.
|
101
|
-
cmpt =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 '
|
20
|
+
require 'highline/import'
|
21
|
+
require 'openssl'
|
21
22
|
|
22
|
-
|
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
|
-
|
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
|
-
|
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
|
7
|
-
OS_TEMPLATE
|
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
|
9
|
+
clean_up_compute = true # issue DELETE <RESOURCE> after we are done
|
10
10
|
|
11
|
-
USER_CERT
|
11
|
+
USER_CERT = ENV['HOME'] + '/.globus/usercred.pem'
|
12
12
|
USER_CERT_PASSWORD = 'mypassphrase'
|
13
|
-
CA_PATH
|
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(
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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|
|
data/lib/occi/api/client.rb
CHANGED
@@ -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
|
-
|
436
|
-
|
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
|
data/lib/occi/collection.rb
CHANGED
@@ -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
|
data/lib/occi/core/category.rb
CHANGED
data/lib/occi/core/entity.rb
CHANGED
@@ -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
data/occi.gemspec
CHANGED
@@ -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 = '
|
48
|
-
attributes.occi!.networkinterface!.mac = '
|
49
|
-
attributes.occi!.networkinterface!.state = '
|
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 = '
|
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.
|
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-
|
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
|