opennebula-cli 4.0.1 → 4.1.80.beta
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/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
|