opennebula-cli 4.0.1 → 4.1.80.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/NOTICE +4 -0
- data/bin/onecluster +9 -3
- data/bin/onedatastore +9 -3
- data/bin/oneflow +673 -0
- data/bin/oneflow-template +451 -0
- data/bin/onehost +10 -4
- data/bin/oneimage +10 -4
- data/bin/onetemplate +10 -4
- data/bin/oneuser +10 -4
- data/bin/onevm +10 -5
- data/bin/onevnet +10 -4
- data/lib/one_helper.rb +26 -27
- data/lib/one_helper/onedatastore_helper.rb +27 -3
- metadata +38 -51
data/NOTICE
CHANGED
@@ -21,6 +21,9 @@ The following people have contributed to the development of the technology
|
|
21
21
|
- Daniel Molina Aranda (dmolina@opennebula.org)
|
22
22
|
- Hector Sanjuan Redondo (hsanjuan@opennebula.org)
|
23
23
|
|
24
|
+
The new features for service elasticity (oneFlow) introduced in OpenNebula 4.2
|
25
|
+
were funded by Blackberry in the context of the Fund a Feature Program.
|
26
|
+
|
24
27
|
OpenNebula Project also acknowledges the contributions of C12G Labs developers.
|
25
28
|
|
26
29
|
LICENSE
|
@@ -43,5 +46,6 @@ OpenNebula distribution includes third-party software under fully compatible
|
|
43
46
|
open-source licenses. See the following directories and the NOTICE files
|
44
47
|
they contain for more information:
|
45
48
|
|
49
|
+
- share/vendor
|
46
50
|
- src/sunstone/public/vendor
|
47
51
|
- src/oca/java/lib
|
data/bin/onecluster
CHANGED
@@ -185,10 +185,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
|
185
185
|
be launched to modify the current content.
|
186
186
|
EOT
|
187
187
|
|
188
|
-
command :update, update_desc, :clusterid, [:file, nil]
|
188
|
+
command :update, update_desc, :clusterid, [:file, nil],
|
189
|
+
:options=>OpenNebulaHelper::APPEND do
|
189
190
|
helper.perform_action(args[0],options,"modified") do |obj|
|
190
|
-
|
191
|
-
|
191
|
+
if options[:append]
|
192
|
+
str = OpenNebulaHelper.append_template(args[0], obj, args[1])
|
193
|
+
else
|
194
|
+
str = OpenNebulaHelper.update_template(args[0], obj, args[1])
|
195
|
+
end
|
196
|
+
|
197
|
+
obj.update(str, options[:append])
|
192
198
|
end
|
193
199
|
end
|
194
200
|
end
|
data/bin/onedatastore
CHANGED
@@ -162,10 +162,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
|
162
162
|
be launched to modify the current content.
|
163
163
|
EOT
|
164
164
|
|
165
|
-
command :update, update_desc, :datastoreid, [:file, nil]
|
165
|
+
command :update, update_desc, :datastoreid, [:file, nil],
|
166
|
+
:options=>OpenNebulaHelper::APPEND do
|
166
167
|
helper.perform_action(args[0],options,"modified") do |obj|
|
167
|
-
|
168
|
-
|
168
|
+
if options[:append]
|
169
|
+
str = OpenNebulaHelper.append_template(args[0], obj, args[1])
|
170
|
+
else
|
171
|
+
str = OpenNebulaHelper.update_template(args[0], obj, args[1])
|
172
|
+
end
|
173
|
+
|
174
|
+
obj.update(str, options[:append])
|
169
175
|
end
|
170
176
|
end
|
171
177
|
end
|
data/bin/oneflow
ADDED
@@ -0,0 +1,673 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# -------------------------------------------------------------------------- #
|
4
|
+
# Copyright 2010-2013, C12G Labs S.L. #
|
5
|
+
# #
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
7
|
+
# not use this file except in compliance with the License. You may obtain #
|
8
|
+
# a copy of the License at #
|
9
|
+
# #
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0 #
|
11
|
+
# #
|
12
|
+
# Unless required by applicable law or agreed to in writing, software #
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS, #
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
15
|
+
# See the License for the specific language governing permissions and #
|
16
|
+
# limitations under the License. #
|
17
|
+
#--------------------------------------------------------------------------- #
|
18
|
+
|
19
|
+
ONE_LOCATION=ENV["ONE_LOCATION"]
|
20
|
+
|
21
|
+
if !ONE_LOCATION
|
22
|
+
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
|
23
|
+
else
|
24
|
+
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
|
25
|
+
end
|
26
|
+
|
27
|
+
$: << RUBY_LIB_LOCATION
|
28
|
+
$: << RUBY_LIB_LOCATION+'/cli'
|
29
|
+
|
30
|
+
require 'command_parser'
|
31
|
+
require 'opennebula/oneflow_client'
|
32
|
+
|
33
|
+
require 'cli_helper'
|
34
|
+
require 'one_helper/onevm_helper'
|
35
|
+
|
36
|
+
require 'json'
|
37
|
+
|
38
|
+
USER_AGENT = "CLI"
|
39
|
+
|
40
|
+
# Base Path representing the resource to be used in the requests
|
41
|
+
RESOURCE_PATH = "/service"
|
42
|
+
|
43
|
+
#
|
44
|
+
# Table
|
45
|
+
#
|
46
|
+
|
47
|
+
SERVICE_TABLE = CLIHelper::ShowTable.new(nil, self) do
|
48
|
+
column :ID, "ID", :size=>10 do |d|
|
49
|
+
d["ID"]
|
50
|
+
end
|
51
|
+
|
52
|
+
column :USER, "Username", :left, :size=>15 do |d|
|
53
|
+
d["UNAME"]
|
54
|
+
end
|
55
|
+
|
56
|
+
column :GROUP, "Group", :left, :size=>15 do |d|
|
57
|
+
d["GNAME"]
|
58
|
+
end
|
59
|
+
|
60
|
+
column :NAME, "Name", :size=>25, :left=>true do |d|
|
61
|
+
d["NAME"]
|
62
|
+
end
|
63
|
+
|
64
|
+
column :STATE, "State", :size=>11, :left=>true do |d|
|
65
|
+
Service.state_str(d["TEMPLATE"]["BODY"]['state'])
|
66
|
+
end
|
67
|
+
|
68
|
+
default :ID, :USER, :GROUP, :NAME, :STATE
|
69
|
+
end
|
70
|
+
|
71
|
+
NODE_TABLE = CLIHelper::ShowTable.new(nil, self) do
|
72
|
+
column :VM_ID, "ONE identifier for Virtual Machine", :size=>6 do |d|
|
73
|
+
st = ""
|
74
|
+
if d['scale_up']
|
75
|
+
st << "\u2191 "
|
76
|
+
elsif d['disposed']
|
77
|
+
st << "\u2193 "
|
78
|
+
end
|
79
|
+
|
80
|
+
if d['vm_info'].nil?
|
81
|
+
st << d['deploy_id'].to_s
|
82
|
+
else
|
83
|
+
st << d['vm_info']['VM']["ID"]
|
84
|
+
end
|
85
|
+
|
86
|
+
st
|
87
|
+
end
|
88
|
+
|
89
|
+
column :NAME, "Name of the Virtual Machine", :left,
|
90
|
+
:size=>23 do |d|
|
91
|
+
if !d['vm_info'].nil?
|
92
|
+
if d['vm_info']['VM']["RESCHED"] == "1"
|
93
|
+
"*#{d["NAME"]}"
|
94
|
+
else
|
95
|
+
d['vm_info']['VM']["NAME"]
|
96
|
+
end
|
97
|
+
else
|
98
|
+
""
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
column :USER, "Username of the Virtual Machine owner", :left,
|
103
|
+
:size=>8 do |d|
|
104
|
+
if !d['vm_info'].nil?
|
105
|
+
d['vm_info']['VM']["UNAME"]
|
106
|
+
else
|
107
|
+
""
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
column :GROUP, "Group of the Virtual Machine", :left,
|
112
|
+
:size=>8 do |d|
|
113
|
+
if !d['vm_info'].nil?
|
114
|
+
d['vm_info']['VM']["GNAME"]
|
115
|
+
else
|
116
|
+
""
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
column :STAT, "Actual status", :size=>4 do |d,e|
|
121
|
+
if !d['vm_info'].nil?
|
122
|
+
OneVMHelper.state_to_str(d['vm_info']['VM']["STATE"], d['vm_info']['VM']["LCM_STATE"])
|
123
|
+
else
|
124
|
+
""
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
column :UCPU, "CPU percentage used by the VM", :size=>4 do |d|
|
129
|
+
if !d['vm_info'].nil?
|
130
|
+
d['vm_info']['VM']["CPU"]
|
131
|
+
else
|
132
|
+
""
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
column :UMEM, "Memory used by the VM", :size=>7 do |d|
|
137
|
+
if !d['vm_info'].nil?
|
138
|
+
OpenNebulaHelper.unit_to_str(d['vm_info']['VM']["MEMORY"].to_i, {})
|
139
|
+
else
|
140
|
+
""
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
column :HOST, "Host where the VM is running", :left, :size=>20 do |d|
|
145
|
+
if !d['vm_info'].nil?
|
146
|
+
if d['vm_info']['VM']['HISTORY_RECORDS'] && d['vm_info']['VM']['HISTORY_RECORDS']['HISTORY']
|
147
|
+
state_str = VirtualMachine::VM_STATE[d['vm_info']['VM']['STATE'].to_i]
|
148
|
+
if %w{ACTIVE SUSPENDED}.include? state_str
|
149
|
+
history = if d['vm_info']['VM']['HISTORY_RECORDS']['HISTORY'].instance_of?(Array)
|
150
|
+
d['vm_info']['VM']['HISTORY_RECORDS']['HISTORY'].last
|
151
|
+
else
|
152
|
+
d['vm_info']['VM']['HISTORY_RECORDS']['HISTORY']
|
153
|
+
end
|
154
|
+
|
155
|
+
history['HOSTNAME']
|
156
|
+
end
|
157
|
+
end
|
158
|
+
else
|
159
|
+
""
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
column :TIME, "Time since the VM was submitted", :size=>10 do |d|
|
164
|
+
if !d['vm_info'].nil?
|
165
|
+
stime = d['vm_info']['VM']["STIME"].to_i
|
166
|
+
etime = d['vm_info']['VM']["ETIME"]=="0" ? Time.now.to_i : d['vm_info']['VM']["ETIME"].to_i
|
167
|
+
dtime = etime-stime
|
168
|
+
OpenNebulaHelper.period_to_str(dtime, false)
|
169
|
+
else
|
170
|
+
""
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
default :VM_ID, :NAME, :STAT, :UCPU, :UMEM, :HOST, :TIME
|
175
|
+
end
|
176
|
+
|
177
|
+
# List the services. This method is used in top and list commands
|
178
|
+
# @param [Service::Client] client
|
179
|
+
# @param [Array] args
|
180
|
+
# @param [Hash] options
|
181
|
+
# @return [[Integer, String], Integer] Returns the exit_code and optionally
|
182
|
+
# a String to be printed
|
183
|
+
def list_services(client, args, options)
|
184
|
+
response = client.get(RESOURCE_PATH)
|
185
|
+
|
186
|
+
if CloudClient::is_error?(response)
|
187
|
+
[response.code.to_i, response.to_s]
|
188
|
+
else
|
189
|
+
#[0,response.body]
|
190
|
+
if options[:json]
|
191
|
+
[0,response.body]
|
192
|
+
else
|
193
|
+
array_list = JSON.parse(response.body)
|
194
|
+
SERVICE_TABLE.show(array_list['DOCUMENT_POOL']['DOCUMENT'])
|
195
|
+
0
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Show the service information. This method is used in top and show commands
|
201
|
+
# @param [Service::Client] client
|
202
|
+
# @param [Array] args
|
203
|
+
# @param [Hash] options
|
204
|
+
# @return [[Integer, String], Integer] Returns the exit_code and optionally
|
205
|
+
# a String to be printed
|
206
|
+
def show_service(client, args, options)
|
207
|
+
response = client.get("#{RESOURCE_PATH}/#{args[0]}")
|
208
|
+
|
209
|
+
if CloudClient::is_error?(response)
|
210
|
+
[response.code.to_i, response.to_s]
|
211
|
+
else
|
212
|
+
#[0,response.body]
|
213
|
+
if options[:json]
|
214
|
+
[0,response.body]
|
215
|
+
else
|
216
|
+
str="%-20s: %-20s"
|
217
|
+
str_h1="%-80s"
|
218
|
+
|
219
|
+
document_hash = JSON.parse(response.body)
|
220
|
+
template = document_hash['DOCUMENT']['TEMPLATE']['BODY']
|
221
|
+
|
222
|
+
CLIHelper.print_header(str_h1 % "SERVICE #{document_hash['DOCUMENT']['ID']} INFORMATION")
|
223
|
+
|
224
|
+
puts str % ["ID", document_hash['DOCUMENT']['ID']]
|
225
|
+
puts str % ["NAME", document_hash['DOCUMENT']['NAME']]
|
226
|
+
puts str % ["USER", document_hash['DOCUMENT']['UNAME']]
|
227
|
+
puts str % ["GROUP",document_hash['DOCUMENT']['GNAME']]
|
228
|
+
|
229
|
+
puts str % ["STRATEGY", template['deployment']]
|
230
|
+
puts str % ["SERVICE STATE", Service.state_str(template['state'])]
|
231
|
+
puts str % ["SHUTDOWN", template['shutdown_action']] if template['shutdown_action']
|
232
|
+
|
233
|
+
puts
|
234
|
+
|
235
|
+
CLIHelper.print_header(str_h1 % "PERMISSIONS",false)
|
236
|
+
|
237
|
+
["OWNER", "GROUP", "OTHER"].each { |e|
|
238
|
+
mask = "---"
|
239
|
+
mask[0] = "u" if document_hash['DOCUMENT']['PERMISSIONS']["#{e}_U"] == "1"
|
240
|
+
mask[1] = "m" if document_hash['DOCUMENT']['PERMISSIONS']["#{e}_M"] == "1"
|
241
|
+
mask[2] = "a" if document_hash['DOCUMENT']['PERMISSIONS']["#{e}_A"] == "1"
|
242
|
+
|
243
|
+
puts str % [e, mask]
|
244
|
+
}
|
245
|
+
|
246
|
+
puts
|
247
|
+
|
248
|
+
template['roles'].each {|role|
|
249
|
+
CLIHelper.print_header("ROLE #{role['name']}", false)
|
250
|
+
|
251
|
+
puts str % ["ROLE STATE", Role.state_str(role['state'])]
|
252
|
+
puts str % ["PARENTS", role['parents'].join(', ')] if role['parents']
|
253
|
+
puts str % ["VM TEMPLATE", role['vm_template']]
|
254
|
+
puts str % ["CARNIDALITY", role['cardinality']]
|
255
|
+
puts str % ["MIN VMS", role['min_vms']] if role['min_vms']
|
256
|
+
puts str % ["MAX VMS", role['max_vms']] if role['max_vms']
|
257
|
+
puts str % ["SHUTDOWN", role['shutdown_action']] if role['shutdown_action']
|
258
|
+
|
259
|
+
puts "NODES INFORMATION"
|
260
|
+
NODE_TABLE.show(role['nodes'])
|
261
|
+
|
262
|
+
if !role['elasticity_policies'].nil? || !role['scheduled_policies'].nil?
|
263
|
+
puts
|
264
|
+
puts "ELASTICITY RULES"
|
265
|
+
puts str % ["COOLDOWN", "#{role['cooldown']}s"] if role['cooldown']
|
266
|
+
|
267
|
+
if role['elasticity_policies']
|
268
|
+
puts
|
269
|
+
# puts "ELASTICITY POLICIES"
|
270
|
+
CLIHelper::ShowTable.new(nil, self) do
|
271
|
+
column :ADJUST, "", :left, :size=>12 do |d|
|
272
|
+
adjust_str(d)
|
273
|
+
end
|
274
|
+
|
275
|
+
column :EXPRESSION, "", :left, :size=>48 do |d|
|
276
|
+
if !d['expression_evaluated'].nil?
|
277
|
+
d['expression_evaluated']
|
278
|
+
else
|
279
|
+
d['expression']
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
column :'EVALS', "", :left, :size=>5 do |d|
|
284
|
+
"#{d['true_evals'].to_i} / #{d['period_number']}"
|
285
|
+
end
|
286
|
+
|
287
|
+
column :PERIOD, "", :size=>6 do |d|
|
288
|
+
"#{d['period']}s"
|
289
|
+
end
|
290
|
+
|
291
|
+
column :COOL, "", :size=>5 do |d|
|
292
|
+
d['cooldown'] ? "#{d['cooldown']}s" : '-'
|
293
|
+
end
|
294
|
+
|
295
|
+
default :ADJUST, :EXPRESSION, :EVALS, :PERIOD, :COOL
|
296
|
+
end.show([role['elasticity_policies']].flatten, {})
|
297
|
+
end
|
298
|
+
|
299
|
+
if role['scheduled_policies']
|
300
|
+
puts
|
301
|
+
# puts "SCHEDULED POLICIES"
|
302
|
+
CLIHelper::ShowTable.new(nil, self) do
|
303
|
+
column :ADJUST, "", :left, :size=>12 do |d|
|
304
|
+
adjust_str(d)
|
305
|
+
end
|
306
|
+
|
307
|
+
column :TIME, "", :left, :size=>67 do |d|
|
308
|
+
if d['start_time']
|
309
|
+
Time.parse(d['start_time']).to_s
|
310
|
+
else
|
311
|
+
d['recurrence']
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
default :ADJUST, :TIME
|
316
|
+
end.show([role['scheduled_policies']].flatten, {})
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
puts
|
321
|
+
}
|
322
|
+
|
323
|
+
puts
|
324
|
+
|
325
|
+
CLIHelper.print_header(str_h1 % "LOG MESSAGES",false)
|
326
|
+
|
327
|
+
if template['log']
|
328
|
+
template['log'].each { |log|
|
329
|
+
t = Time.at(log['timestamp']).strftime("%m/%d/%y %H:%M")
|
330
|
+
puts "#{t} [#{log['severity']}] #{log['message']}"
|
331
|
+
}
|
332
|
+
end
|
333
|
+
|
334
|
+
0
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def adjust_str(policy)
|
340
|
+
sign = policy['adjust'].to_i >= 0 ? "+" : "-"
|
341
|
+
adjust = policy['adjust'].to_i.abs
|
342
|
+
|
343
|
+
case policy['type']
|
344
|
+
when 'CARDINALITY'
|
345
|
+
"= #{adjust}"
|
346
|
+
when 'PERCENTAGE_CHANGE'
|
347
|
+
st = "#{sign} #{adjust} %"
|
348
|
+
if policy['min_adjust_step']
|
349
|
+
st << " (#{policy['min_adjust_step']})"
|
350
|
+
end
|
351
|
+
|
352
|
+
st
|
353
|
+
else
|
354
|
+
"#{sign} #{adjust}"
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
#
|
359
|
+
# Commands
|
360
|
+
#
|
361
|
+
|
362
|
+
cmd=CommandParser::CmdParser.new(ARGV) do
|
363
|
+
usage "`oneflow` <command> [<args>] [<options>]"
|
364
|
+
version OpenNebulaHelper::ONE_VERSION
|
365
|
+
|
366
|
+
set :option, Service::DEFAULT_OPTIONS
|
367
|
+
set :option, CommandParser::VERSION
|
368
|
+
set :option, CommandParser::HELP
|
369
|
+
|
370
|
+
#
|
371
|
+
# Formatters for arguments
|
372
|
+
#
|
373
|
+
set :format, :groupid, OpenNebulaHelper.rname_to_id_desc("GROUP") do |arg|
|
374
|
+
OpenNebulaHelper.rname_to_id(arg, "GROUP")
|
375
|
+
end
|
376
|
+
|
377
|
+
set :format, :userid, OpenNebulaHelper.rname_to_id_desc("USER") do |arg|
|
378
|
+
OpenNebulaHelper.rname_to_id(arg, "USER")
|
379
|
+
end
|
380
|
+
|
381
|
+
set :format, :service_id, Service.rname_to_id_desc("SERVICE") do |arg|
|
382
|
+
Service.rname_to_id(arg, "SERVICE")
|
383
|
+
end
|
384
|
+
|
385
|
+
set :format, :service_id_list, Service.list_to_id_desc("SERVICE") do |arg|
|
386
|
+
Service.list_to_id(arg, "SERVICE")
|
387
|
+
end
|
388
|
+
|
389
|
+
set :format, :vm_action, "Actions supported: #{Role::SCHEDULE_ACTIONS.join(', ')}" do |arg|
|
390
|
+
if Role::SCHEDULE_ACTIONS.include?(arg)
|
391
|
+
[0, arg]
|
392
|
+
else
|
393
|
+
[-1, "Action #{arg} is not supported. Actions supported: #{Role::SCHEDULE_ACTIONS.join(', ')}"]
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
#
|
398
|
+
# List
|
399
|
+
#
|
400
|
+
|
401
|
+
list_desc = <<-EOT.unindent
|
402
|
+
List the available services
|
403
|
+
EOT
|
404
|
+
|
405
|
+
command :list, list_desc, :options => Service::JSON_FORMAT do
|
406
|
+
client = Service::Client.new(
|
407
|
+
:username => options[:username],
|
408
|
+
:password => options[:password],
|
409
|
+
:url => options[:server],
|
410
|
+
:user_agent => USER_AGENT)
|
411
|
+
|
412
|
+
list_services(client, args, options)
|
413
|
+
end
|
414
|
+
|
415
|
+
#
|
416
|
+
# Show
|
417
|
+
#
|
418
|
+
|
419
|
+
show_desc = <<-EOT.unindent
|
420
|
+
Show detailed information of a given service
|
421
|
+
EOT
|
422
|
+
|
423
|
+
command :show, show_desc, :service_id, :options => Service::JSON_FORMAT do
|
424
|
+
client = Service::Client.new(
|
425
|
+
:username => options[:username],
|
426
|
+
:password => options[:password],
|
427
|
+
:url => options[:server],
|
428
|
+
:user_agent => USER_AGENT)
|
429
|
+
|
430
|
+
show_service(client, args, options)
|
431
|
+
end
|
432
|
+
|
433
|
+
#
|
434
|
+
# Top
|
435
|
+
#
|
436
|
+
|
437
|
+
top_desc = <<-EOT.unindent
|
438
|
+
Top the services or the extended information of the target service if a
|
439
|
+
id is specified
|
440
|
+
EOT
|
441
|
+
|
442
|
+
command :top, top_desc, [:service_id, nil],
|
443
|
+
:options => [Service::JSON_FORMAT, Service::TOP, CLIHelper::DELAY] do
|
444
|
+
client = Service::Client.new(
|
445
|
+
:username => options[:username],
|
446
|
+
:password => options[:password],
|
447
|
+
:url => options[:server],
|
448
|
+
:user_agent => USER_AGENT)
|
449
|
+
|
450
|
+
delay=options[:delay] ? options[:delay] : 3
|
451
|
+
|
452
|
+
begin
|
453
|
+
while true
|
454
|
+
CLIHelper.scr_cls
|
455
|
+
CLIHelper.scr_move(0,0)
|
456
|
+
|
457
|
+
if args[0]
|
458
|
+
rc, message = show_service(client, args, options)
|
459
|
+
|
460
|
+
if rc != 0
|
461
|
+
raise message
|
462
|
+
end
|
463
|
+
else
|
464
|
+
rc, message = list_services(client, args, options)
|
465
|
+
|
466
|
+
if rc != 0
|
467
|
+
raise message
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
sleep delay
|
472
|
+
end
|
473
|
+
rescue Exception => e
|
474
|
+
puts e.message
|
475
|
+
-1
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
#
|
480
|
+
# Delete
|
481
|
+
#
|
482
|
+
|
483
|
+
delete_desc = <<-EOT.unindent
|
484
|
+
Delete a given service
|
485
|
+
EOT
|
486
|
+
|
487
|
+
command :delete, delete_desc, [:range, :service_id_list] do
|
488
|
+
client = Service::Client.new(
|
489
|
+
:username => options[:username],
|
490
|
+
:password => options[:password],
|
491
|
+
:url => options[:server],
|
492
|
+
:user_agent => USER_AGENT)
|
493
|
+
|
494
|
+
Service.perform_actions(args[0]) { |service_id|
|
495
|
+
client.delete("#{RESOURCE_PATH}/#{service_id}")
|
496
|
+
}
|
497
|
+
end
|
498
|
+
|
499
|
+
#
|
500
|
+
# Shutdown
|
501
|
+
#
|
502
|
+
|
503
|
+
shutdown_desc = <<-EOT.unindent
|
504
|
+
Shutdown a service.
|
505
|
+
From RUNNING or WARNING shuts down the Service
|
506
|
+
EOT
|
507
|
+
|
508
|
+
command :shutdown, shutdown_desc, [:range, :service_id_list] do
|
509
|
+
client = Service::Client.new(
|
510
|
+
:username => options[:username],
|
511
|
+
:password => options[:password],
|
512
|
+
:url => options[:server],
|
513
|
+
:user_agent => USER_AGENT)
|
514
|
+
|
515
|
+
Service.perform_actions(args[0]) { |service_id|
|
516
|
+
json_action = Service.build_json_action('shutdown')
|
517
|
+
|
518
|
+
client.post("#{RESOURCE_PATH}/#{service_id}/action", json_action)
|
519
|
+
}
|
520
|
+
end
|
521
|
+
|
522
|
+
#
|
523
|
+
# Recover
|
524
|
+
#
|
525
|
+
|
526
|
+
recover_desc = <<-EOT.unindent
|
527
|
+
Recover a failed service, cleaning the failed VMs.
|
528
|
+
From FAILED_DEPLOYING continues deploying the Service
|
529
|
+
From FAILED_SCALING continues scaling the Service
|
530
|
+
From FAILED_UNDEPLOYING continues shutting down the Service
|
531
|
+
From COOLDOWN the Service is set to running ignoring the cooldown duration
|
532
|
+
From WARNING failed VMs are deleted, and new VMs are instantiated
|
533
|
+
EOT
|
534
|
+
|
535
|
+
command :recover, recover_desc, [:range, :service_id_list] do
|
536
|
+
client = Service::Client.new(
|
537
|
+
:username => options[:username],
|
538
|
+
:password => options[:password],
|
539
|
+
:url => options[:server],
|
540
|
+
:user_agent => USER_AGENT)
|
541
|
+
|
542
|
+
Service.perform_actions(args[0]) { |service_id|
|
543
|
+
json_action = Service.build_json_action('recover')
|
544
|
+
|
545
|
+
client.post("#{RESOURCE_PATH}/#{service_id}/action", json_action)
|
546
|
+
}
|
547
|
+
end
|
548
|
+
|
549
|
+
#
|
550
|
+
# Scale
|
551
|
+
#
|
552
|
+
|
553
|
+
scale_desc = <<-EOT.unindent
|
554
|
+
Scale a role to the given cardinality
|
555
|
+
EOT
|
556
|
+
|
557
|
+
command :'scale', scale_desc, :service_id, :role_name,
|
558
|
+
:cardinality, :options => [Service::FORCE] do
|
559
|
+
client = Service::Client.new(
|
560
|
+
:username => options[:username],
|
561
|
+
:password => options[:password],
|
562
|
+
:url => options[:server],
|
563
|
+
:user_agent => USER_AGENT)
|
564
|
+
|
565
|
+
if !(args[2] =~ /^\d+$/)
|
566
|
+
puts "Cardinality must be an integer number"
|
567
|
+
exit -1
|
568
|
+
end
|
569
|
+
|
570
|
+
exit_code = 0
|
571
|
+
|
572
|
+
json = "{ \"cardinality\" : #{args[2]},\n"<<
|
573
|
+
" \"force\" : #{options[:force] == true} }"
|
574
|
+
|
575
|
+
response = client.put("#{RESOURCE_PATH}/#{args[0]}/role/#{args[1]}", json)
|
576
|
+
|
577
|
+
if CloudClient::is_error?(response)
|
578
|
+
puts response.to_s
|
579
|
+
exit_code = response.code.to_i
|
580
|
+
end
|
581
|
+
|
582
|
+
exit_code
|
583
|
+
end
|
584
|
+
|
585
|
+
chgrp_desc = <<-EOT.unindent
|
586
|
+
Changes the service group
|
587
|
+
EOT
|
588
|
+
|
589
|
+
command :chgrp, chgrp_desc, [:range, :service_id_list], :groupid do
|
590
|
+
client = Service::Client.new(
|
591
|
+
:username => options[:username],
|
592
|
+
:password => options[:password],
|
593
|
+
:url => options[:server],
|
594
|
+
:user_agent => USER_AGENT)
|
595
|
+
|
596
|
+
Service.perform_actions(args[0]) { |service_id|
|
597
|
+
params = Hash.new
|
598
|
+
params['group_id'] = args[1].to_i
|
599
|
+
|
600
|
+
json_action = Service.build_json_action('chgrp', params)
|
601
|
+
|
602
|
+
client.post("#{RESOURCE_PATH}/#{service_id}/action", json_action)
|
603
|
+
}
|
604
|
+
end
|
605
|
+
|
606
|
+
chown_desc = <<-EOT.unindent
|
607
|
+
Changes the service owner and group
|
608
|
+
EOT
|
609
|
+
|
610
|
+
command :chown, chown_desc, [:range, :service_id_list], :userid, [:groupid, nil] do
|
611
|
+
client = Service::Client.new(
|
612
|
+
:username => options[:username],
|
613
|
+
:password => options[:password],
|
614
|
+
:url => options[:server],
|
615
|
+
:user_agent => USER_AGENT)
|
616
|
+
|
617
|
+
Service.perform_actions(args[0]) { |service_id|
|
618
|
+
params = Hash.new
|
619
|
+
params['owner_id'] = args[1]
|
620
|
+
params['group_id'] = args[2] if args[2]
|
621
|
+
|
622
|
+
json_action = Service.build_json_action('chown', params)
|
623
|
+
|
624
|
+
client.post("#{RESOURCE_PATH}/#{service_id}/action", json_action)
|
625
|
+
}
|
626
|
+
end
|
627
|
+
|
628
|
+
chmod_desc = <<-EOT.unindent
|
629
|
+
Changes the service permissions
|
630
|
+
EOT
|
631
|
+
|
632
|
+
command :chmod, chmod_desc, [:range, :service_id_list], :octet do
|
633
|
+
client = Service::Client.new(
|
634
|
+
:username => options[:username],
|
635
|
+
:password => options[:password],
|
636
|
+
:url => options[:server],
|
637
|
+
:user_agent => USER_AGENT)
|
638
|
+
|
639
|
+
Service.perform_actions(args[0]) { |service_id|
|
640
|
+
params = Hash.new
|
641
|
+
params['octet'] = args[1]
|
642
|
+
|
643
|
+
json_action = Service.build_json_action('chmod', params)
|
644
|
+
|
645
|
+
client.post("#{RESOURCE_PATH}/#{service_id}/action", json_action)
|
646
|
+
}
|
647
|
+
end
|
648
|
+
|
649
|
+
action_desc = <<-EOT.unindent
|
650
|
+
Perform an action on all the Virtual Machines of a given role.
|
651
|
+
Actions supported: #{Role::SCHEDULE_ACTIONS.join(",")}
|
652
|
+
EOT
|
653
|
+
|
654
|
+
command :"action", action_desc, :service_id, :role_name, :vm_action,
|
655
|
+
:options => [Service::PERIOD, Service::NUMBER] do
|
656
|
+
|
657
|
+
client = Service::Client.new(
|
658
|
+
:username => options[:username],
|
659
|
+
:password => options[:password],
|
660
|
+
:url => options[:server],
|
661
|
+
:user_agent => USER_AGENT)
|
662
|
+
|
663
|
+
Service.perform_actions([args[0]]) { |service_id|
|
664
|
+
params = Hash.new
|
665
|
+
params[:period] = options[:period].to_i if options[:period]
|
666
|
+
params[:number] = options[:number].to_i if options[:number]
|
667
|
+
|
668
|
+
json_action = Service.build_json_action(args[2], params)
|
669
|
+
|
670
|
+
client.post("#{RESOURCE_PATH}/#{service_id}/role/#{args[1]}/action", json_action)
|
671
|
+
}
|
672
|
+
end
|
673
|
+
end
|