opennebula-cli 5.10.1 → 5.10.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/onevcenter +45 -0
- data/bin/onezone +35 -0
- data/lib/one_helper/onetemplate_helper.rb +14 -0
- data/lib/one_helper/onevcenter_helper.rb +55 -0
- data/lib/one_helper/onezone_helper.rb +426 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 295cccef022aa2264f24ed89bdd3c7ff0a88d7af
|
4
|
+
data.tar.gz: d0147da36b571179d0a783eb4a0aca095eb75170
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a09dc31b0b49468074f6ec70bdebf46e9f59f174226c328fe77b62add87a1b96c4620705e432271d9775875e529e92079fb19571bc142fa7aa55602e02d9711b
|
7
|
+
data.tar.gz: 4632563ed7e4098f7a20e48e30f6842574664ee0b3ab37ba2b3819a03294b07770fe54cd1247805d67429d375bd2247f2f611ef850da71076779880b6eb4684e
|
data/bin/onevcenter
CHANGED
@@ -286,4 +286,49 @@ CommandParser::CmdParser.new(ARGV) do
|
|
286
286
|
|
287
287
|
exit 0
|
288
288
|
end
|
289
|
+
|
290
|
+
############################################################################
|
291
|
+
# Clear VM tags
|
292
|
+
############################################################################
|
293
|
+
cleartags_desc = <<-EOT.unindent
|
294
|
+
Clear extraconfig tags from a vCenter VM, useful when a VM has been
|
295
|
+
launched by OpenNebula and needs to be reimported
|
296
|
+
|
297
|
+
Example:
|
298
|
+
- Clean VM 15:
|
299
|
+
|
300
|
+
onevcenter cleargs 15
|
301
|
+
EOT
|
302
|
+
command :cleartags, cleartags_desc, :vmid do
|
303
|
+
vmid = args[0]
|
304
|
+
remove_str = "\n onevm recover --delete-db #{vmid}" \
|
305
|
+
"\n\nAfter a monitoring cycle, the VM will appear "\
|
306
|
+
'as a Wild VM for reimport.'
|
307
|
+
|
308
|
+
print 'Extracting information from VM ' + vmid
|
309
|
+
|
310
|
+
begin
|
311
|
+
print '.'
|
312
|
+
vm, keys = helper.clear_tags(vmid)
|
313
|
+
print '.'
|
314
|
+
|
315
|
+
if keys.empty?
|
316
|
+
puts "\n\nNo OpenNebula keys present, is safe to remove the VM."
|
317
|
+
puts remove_str
|
318
|
+
exit 0
|
319
|
+
end
|
320
|
+
puts '.'
|
321
|
+
|
322
|
+
puts 'The following keys will be removed:'
|
323
|
+
keys.each {|key| puts "\t- #{key}" }
|
324
|
+
|
325
|
+
helper.remove_keys(vm, keys)
|
326
|
+
rescue StandardError => e
|
327
|
+
STDERR.puts "Couldn't clear VM tags. Reason: #{e.message}"
|
328
|
+
exit 1
|
329
|
+
end
|
330
|
+
puts "\nKeys removed from VM. Is safe to remove it"
|
331
|
+
puts remove_str
|
332
|
+
exit 0
|
333
|
+
end
|
289
334
|
end
|
data/bin/onezone
CHANGED
@@ -51,6 +51,12 @@ CommandParser::CmdParser.new(ARGV) do
|
|
51
51
|
:format => String
|
52
52
|
}
|
53
53
|
|
54
|
+
DATABASE = {
|
55
|
+
:name => 'database',
|
56
|
+
:large => '--db',
|
57
|
+
:description => 'Also sync database'
|
58
|
+
}
|
59
|
+
|
54
60
|
before_proc do
|
55
61
|
helper.set_client(options)
|
56
62
|
end
|
@@ -215,4 +221,33 @@ CommandParser::CmdParser.new(ARGV) do
|
|
215
221
|
helper.set_zone(args[0], false)
|
216
222
|
end
|
217
223
|
end
|
224
|
+
|
225
|
+
sync_desc = <<-EOT.unindent
|
226
|
+
Syncs configuration files and folders from another server
|
227
|
+
|
228
|
+
This command must be executed under root
|
229
|
+
EOT
|
230
|
+
|
231
|
+
command :serversync, sync_desc, :server, :options => [DATABASE] do
|
232
|
+
begin
|
233
|
+
gem 'augeas', '~> 0.6'
|
234
|
+
require 'augeas'
|
235
|
+
rescue Gem::LoadError
|
236
|
+
STDERR.puts(
|
237
|
+
'Augeas gem is not installed, run `gem install ' \
|
238
|
+
'augeas -v \'0.6\'` to install it'
|
239
|
+
)
|
240
|
+
exit(-1)
|
241
|
+
end
|
242
|
+
|
243
|
+
if !Process.uid.zero? || !Process.gid.zero?
|
244
|
+
STDERR.puts("'onezone serversync' must be run under root")
|
245
|
+
exit(-1)
|
246
|
+
end
|
247
|
+
|
248
|
+
server = Replicator.new('/var/lib/one/.ssh/id_rsa', args[0])
|
249
|
+
server.process_files(options.key?(:database))
|
250
|
+
|
251
|
+
0
|
252
|
+
end
|
218
253
|
end
|
@@ -183,6 +183,20 @@ EOT
|
|
183
183
|
answer = Base64::encode64(answer).strip.delete("\n")
|
184
184
|
end
|
185
185
|
|
186
|
+
when 'boolean'
|
187
|
+
print header
|
188
|
+
|
189
|
+
answer = STDIN.readline.chop
|
190
|
+
|
191
|
+
# use default in case it's empty
|
192
|
+
answer = initial if answer.empty?
|
193
|
+
|
194
|
+
unless %w[YES NO].include?(answer)
|
195
|
+
STDERR.puts "Invalid boolean '#{answer}'"
|
196
|
+
STDERR.puts 'Boolean has to be YES or NO'
|
197
|
+
exit(-1)
|
198
|
+
end
|
199
|
+
|
186
200
|
when 'password'
|
187
201
|
print header
|
188
202
|
|
@@ -425,4 +425,59 @@ class OneVcenterHelper < OpenNebulaHelper::OneHelper
|
|
425
425
|
|
426
426
|
return opts
|
427
427
|
end
|
428
|
+
|
429
|
+
def clear_tags(vmid)
|
430
|
+
client = Client.new
|
431
|
+
|
432
|
+
vm_pool = VirtualMachinePool.new(client, -1)
|
433
|
+
host_pool = HostPool.new(client)
|
434
|
+
deploy_id = -1
|
435
|
+
host_id = -1
|
436
|
+
hostname = ''
|
437
|
+
|
438
|
+
rc = vm_pool.info
|
439
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
440
|
+
|
441
|
+
rc = host_pool.info
|
442
|
+
raise rc.message if OpenNebula.is_error?(rc)
|
443
|
+
|
444
|
+
vm_pool.each do |vm|
|
445
|
+
next if vm.id.to_s != vmid
|
446
|
+
|
447
|
+
deploy_id = vm.deploy_id
|
448
|
+
vm_history = vm.to_hash['VM']['HISTORY_RECORDS']['HISTORY']
|
449
|
+
hostname = vm_history['HOSTNAME']
|
450
|
+
break
|
451
|
+
end
|
452
|
+
|
453
|
+
host_pool.each do |host|
|
454
|
+
if host.name == hostname
|
455
|
+
host_id = host.id
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
vi_client = VCenterDriver::VIClient.new_from_host(host_id)
|
460
|
+
vm = VCenterDriver::VirtualMachine
|
461
|
+
.new(vi_client, deploy_id, vmid)
|
462
|
+
|
463
|
+
keys_to_remove = []
|
464
|
+
vm['config.extraConfig'].each do |extraconfig|
|
465
|
+
if extraconfig.key.include?('opennebula.disk') ||
|
466
|
+
extraconfig.key.include?('opennebula.vm')
|
467
|
+
keys_to_remove << extraconfig.key
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
return vm, keys_to_remove
|
472
|
+
end
|
473
|
+
|
474
|
+
def remove_keys(vm, keys_to_remove)
|
475
|
+
spec_hash = keys_to_remove.map {|key| { :key => key, :value => '' } }
|
476
|
+
|
477
|
+
spec = RbVmomi::VIM.VirtualMachineConfigSpec(
|
478
|
+
:extraConfig => spec_hash
|
479
|
+
)
|
480
|
+
vm.item.ReconfigVM_Task(:spec => spec).wait_for_completion
|
481
|
+
end
|
482
|
+
|
428
483
|
end
|
@@ -14,8 +14,434 @@
|
|
14
14
|
# limitations under the License. #
|
15
15
|
#--------------------------------------------------------------------------- #
|
16
16
|
|
17
|
+
require 'fileutils'
|
18
|
+
require 'tempfile'
|
19
|
+
require 'CommandManager'
|
20
|
+
|
17
21
|
require 'one_helper'
|
18
22
|
|
23
|
+
# Check differences between files and copy them
|
24
|
+
class Replicator
|
25
|
+
|
26
|
+
SSH_OPTIONS = '-o stricthostkeychecking=no -o passwordauthentication=no'
|
27
|
+
ONE_AUTH = '/var/lib/one/.one/one_auth'
|
28
|
+
FED_ATTRS = %w[MODE ZONE_ID SERVER_ID MASTER_ONED]
|
29
|
+
|
30
|
+
FILES = [
|
31
|
+
{ :name => 'az_driver.conf',
|
32
|
+
:service => 'opennebula' },
|
33
|
+
{ :name => 'az_driver.default',
|
34
|
+
:service => 'opennebula' },
|
35
|
+
{ :name => 'ec2_driver.conf',
|
36
|
+
:service => 'opennebula' },
|
37
|
+
{ :name => 'ec2_driver.default',
|
38
|
+
:service => 'opennebula' },
|
39
|
+
{ :name => 'econe.conf',
|
40
|
+
:service => 'opennebula-econe' },
|
41
|
+
{ :name => 'oneflow-server.conf',
|
42
|
+
:service => 'opennebula-flow' },
|
43
|
+
{ :name => 'onegate-server.conf',
|
44
|
+
:service => 'opennebula-gate' },
|
45
|
+
{ :name => 'sched.conf',
|
46
|
+
:service => 'opennebula' },
|
47
|
+
{ :name => 'sunstone-logos.yaml',
|
48
|
+
:service => 'opennebula-sunstone' },
|
49
|
+
{ :name => 'sunstone-server.conf',
|
50
|
+
:service => 'opennebula-sunstone' },
|
51
|
+
{ :name => 'vcenter_driver.default',
|
52
|
+
:service => 'opennebula' }
|
53
|
+
]
|
54
|
+
|
55
|
+
FOLDERS = [
|
56
|
+
{ :name => 'sunstone-views', :service => 'opennebula-sunstone' },
|
57
|
+
{ :name => 'auth', :service => 'opennebula' },
|
58
|
+
{ :name => 'ec2query_templates', :service => 'opennebula' },
|
59
|
+
{ :name => 'hm', :service => 'opennebula' },
|
60
|
+
{ :name => 'sunstone-views', :service => 'opennebula' },
|
61
|
+
{ :name => 'vmm_exec', :service => 'opennebula' }
|
62
|
+
]
|
63
|
+
|
64
|
+
# Class constructor
|
65
|
+
#
|
66
|
+
# @param ssh_key [String] SSH key file path
|
67
|
+
# @param server [String] OpenNebula server IP address
|
68
|
+
def initialize(ssh_key, server)
|
69
|
+
@oneadmin_identity_file = ssh_key
|
70
|
+
@remote_server = server
|
71
|
+
|
72
|
+
# Get local configuration
|
73
|
+
l_credentials = File.read(ONE_AUTH).gsub("\n", '')
|
74
|
+
l_endpoint = 'http://localhost:2633/RPC2'
|
75
|
+
local_client = Client.new(l_credentials, l_endpoint)
|
76
|
+
|
77
|
+
@l_config = OpenNebula::System.new(local_client).get_configuration
|
78
|
+
@l_config_elements = { :raw => @l_config }
|
79
|
+
@l_fed_elements = { :raw => @l_config }
|
80
|
+
|
81
|
+
fetch_db_config(@l_config_elements)
|
82
|
+
fetch_fed_config(@l_fed_elements)
|
83
|
+
|
84
|
+
# Get remote configuration
|
85
|
+
r_credentials = ssh("cat #{ONE_AUTH}").stdout.gsub("\n", '')
|
86
|
+
r_endpoint = "http://#{server}:2633/RPC2"
|
87
|
+
remote_client = Client.new(r_credentials, r_endpoint)
|
88
|
+
|
89
|
+
@r_config = OpenNebula::System.new(remote_client).get_configuration
|
90
|
+
@r_config_elements = { :raw => @r_config }
|
91
|
+
@r_fed_elements = { :raw => @r_config }
|
92
|
+
|
93
|
+
fetch_db_config(@r_config_elements)
|
94
|
+
fetch_fed_config(@r_fed_elements)
|
95
|
+
|
96
|
+
# Set OpenNebula services to not restart
|
97
|
+
@opennebula_services = { 'opennebula' => false,
|
98
|
+
'opennebula-sunstone' => false,
|
99
|
+
'opennebula-gate' => false,
|
100
|
+
'opennebula-flow' => false,
|
101
|
+
'opennebula-econe' => false }
|
102
|
+
end
|
103
|
+
|
104
|
+
# Process files and folders
|
105
|
+
#
|
106
|
+
# @param sync_db [Boolean] True to sync database
|
107
|
+
def process_files(sync_db)
|
108
|
+
# Files to be copied
|
109
|
+
copy_onedconf
|
110
|
+
|
111
|
+
FILES.each do |file|
|
112
|
+
copy_and_check(file[:name], file[:service])
|
113
|
+
end
|
114
|
+
|
115
|
+
# Folders to be copied
|
116
|
+
FOLDERS.each do |folder|
|
117
|
+
copy_folder(folder[:name], folder[:service])
|
118
|
+
end
|
119
|
+
|
120
|
+
restart_services
|
121
|
+
|
122
|
+
# Sync database
|
123
|
+
sync_db
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
# Get database configuration
|
129
|
+
#
|
130
|
+
# @param configs [Object] Configuration
|
131
|
+
def fetch_db_config(configs)
|
132
|
+
configs.store(:backend, configs[:raw]['/TEMPLATE/DB/BACKEND'])
|
133
|
+
|
134
|
+
if configs[:backend] == 'mysql'
|
135
|
+
configs.store(:server, configs[:raw]['/TEMPLATE/DB/SERVER'])
|
136
|
+
configs.store(:user, configs[:raw]['/TEMPLATE/DB/USER'])
|
137
|
+
configs.store(:password, configs[:raw]['/TEMPLATE/DB/PASSWD'])
|
138
|
+
configs.store(:dbname, configs[:raw]['/TEMPLATE/DB/DB_NAME'])
|
139
|
+
configs.store(:port, configs[:raw]['/TEMPLATE/DB/PORT'])
|
140
|
+
configs[:port] = '3306' if configs[:port] == '0'
|
141
|
+
else
|
142
|
+
STDERR.puts 'No mysql backend configuration found'
|
143
|
+
exit(-1)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Get federation configuration
|
148
|
+
#
|
149
|
+
# @param configs [Object] Configuration
|
150
|
+
def fetch_fed_config(configs)
|
151
|
+
configs.store(:server_id,
|
152
|
+
configs[:raw]['/TEMPLATE/FEDERATION/SERVER_ID'])
|
153
|
+
configs.store(:zone_id,
|
154
|
+
configs[:raw]['/TEMPLATE/FEDERATION/ZONE_ID'])
|
155
|
+
end
|
156
|
+
|
157
|
+
# Replaces a file with the version located on a remote server
|
158
|
+
# Only replaces the file if it's different from the remote one
|
159
|
+
#
|
160
|
+
# @param file [String] File to check
|
161
|
+
# @param service [String] Service to restart
|
162
|
+
def copy_and_check(file, service)
|
163
|
+
puts "Checking #{file}"
|
164
|
+
|
165
|
+
temp_file = Tempfile.new("#{file}-temp")
|
166
|
+
|
167
|
+
scp("/etc/one/#{file}", temp_file.path)
|
168
|
+
|
169
|
+
if !FileUtils.compare_file(temp_file, "/etc/one/#{file}")
|
170
|
+
FileUtils.cp(temp_file.path, "/etc/one/#{file}")
|
171
|
+
|
172
|
+
puts "#{file} has been replaced by #{@remote_server}:#{file}"
|
173
|
+
|
174
|
+
@opennebula_services[service] = true
|
175
|
+
end
|
176
|
+
ensure
|
177
|
+
temp_file.unlink
|
178
|
+
end
|
179
|
+
|
180
|
+
# Copy folders
|
181
|
+
#
|
182
|
+
# @param folder [String] Folder to copy
|
183
|
+
# @param service [String] Service to restart
|
184
|
+
def copy_folder(folder, service)
|
185
|
+
puts "Checking #{folder}"
|
186
|
+
|
187
|
+
rc = run_command(
|
188
|
+
"rsync -ai\
|
189
|
+
-e \"ssh #{SSH_OPTIONS} -i #{@oneadmin_identity_file}\" " \
|
190
|
+
"#{@remote_server}:/etc/one/#{folder}/ " \
|
191
|
+
"/etc/one/#{folder}/"
|
192
|
+
)
|
193
|
+
|
194
|
+
unless rc
|
195
|
+
rc = run_command(
|
196
|
+
"rsync -ai\
|
197
|
+
-e \"ssh #{SSH_OPTIONS} -i #{@oneadmin_identity_file}\" " \
|
198
|
+
"oneadmin@#{@remote_server}:/etc/one/#{folder}/ " \
|
199
|
+
"/etc/one/#{folder}/"
|
200
|
+
)
|
201
|
+
end
|
202
|
+
|
203
|
+
unless rc
|
204
|
+
STDERR.puts 'ERROR'
|
205
|
+
STDERR.puts "Fail to sync #{folder}"
|
206
|
+
exit(-1)
|
207
|
+
end
|
208
|
+
|
209
|
+
output = rc.stdout
|
210
|
+
|
211
|
+
return if output.empty?
|
212
|
+
|
213
|
+
puts "Folder #{folder} has been sync with #{@remote_server}:#{folder}"
|
214
|
+
|
215
|
+
@opennebula_services[service] = true
|
216
|
+
end
|
217
|
+
|
218
|
+
# oned.conf file on distributed environments will always be different,
|
219
|
+
# due to the federation section.
|
220
|
+
# Replace oned.conf based on a remote server's version maintaining
|
221
|
+
# the old FEDERATION section
|
222
|
+
def copy_onedconf
|
223
|
+
puts 'Checking oned.conf'
|
224
|
+
|
225
|
+
# Create temporarhy files
|
226
|
+
l_oned = Tempfile.new('l_oned')
|
227
|
+
r_oned = Tempfile.new('r_oned')
|
228
|
+
|
229
|
+
l_oned.close
|
230
|
+
r_oned.close
|
231
|
+
|
232
|
+
# Copy remote and local oned.conf files to temporary files
|
233
|
+
scp('/etc/one/oned.conf', r_oned.path)
|
234
|
+
|
235
|
+
FileUtils.cp('/etc/one/oned.conf', l_oned.path)
|
236
|
+
|
237
|
+
# Create augeas objects to manage oned.conf files
|
238
|
+
l_work_file_dir = File.dirname(l_oned.path)
|
239
|
+
l_work_file_name = File.basename(l_oned.path)
|
240
|
+
|
241
|
+
r_work_file_dir = File.dirname(r_oned.path)
|
242
|
+
r_work_file_name = File.basename(r_oned.path)
|
243
|
+
|
244
|
+
l_aug = Augeas.create(:no_modl_autoload => true,
|
245
|
+
:no_load => true,
|
246
|
+
:root => l_work_file_dir,
|
247
|
+
:loadpath => l_oned.path)
|
248
|
+
|
249
|
+
l_aug.clear_transforms
|
250
|
+
l_aug.transform(:lens => 'Oned.lns', :incl => l_work_file_name)
|
251
|
+
l_aug.context = "/files/#{l_work_file_name}"
|
252
|
+
l_aug.load
|
253
|
+
|
254
|
+
r_aug = Augeas.create(:no_modl_autoload => true,
|
255
|
+
:no_load => true,
|
256
|
+
:root => r_work_file_dir,
|
257
|
+
:loadpath => r_oned.path)
|
258
|
+
|
259
|
+
r_aug.clear_transforms
|
260
|
+
r_aug.transform(:lens => 'Oned.lns', :incl => r_work_file_name)
|
261
|
+
r_aug.context = "/files/#{r_work_file_name}"
|
262
|
+
r_aug.load
|
263
|
+
|
264
|
+
# Get local federation information
|
265
|
+
fed_attrs = []
|
266
|
+
|
267
|
+
FED_ATTRS.each do |attr|
|
268
|
+
fed_attrs << l_aug.get("FEDERATION/#{attr}")
|
269
|
+
end
|
270
|
+
|
271
|
+
# Remove federation section
|
272
|
+
l_aug.rm('FEDERATION')
|
273
|
+
r_aug.rm('FEDERATION')
|
274
|
+
|
275
|
+
# Save augeas files in temporary directories
|
276
|
+
l_aug.save
|
277
|
+
r_aug.save
|
278
|
+
|
279
|
+
return if FileUtils.compare_file(l_oned.path, r_oned.path)
|
280
|
+
|
281
|
+
time_based_identifier = Time.now.to_i
|
282
|
+
|
283
|
+
# backup oned.conf
|
284
|
+
FileUtils.cp('/etc/one/oned.conf',
|
285
|
+
"/etc/one/oned.conf#{time_based_identifier}")
|
286
|
+
|
287
|
+
FED_ATTRS.zip(fed_attrs) do |name, value|
|
288
|
+
r_aug.set("FEDERATION/#{name}", value)
|
289
|
+
end
|
290
|
+
|
291
|
+
r_aug.save
|
292
|
+
|
293
|
+
FileUtils.cp(r_oned.path, '/etc/one/oned.conf')
|
294
|
+
|
295
|
+
puts 'oned.conf has been replaced by ' \
|
296
|
+
"#{@remote_server}:/etc/one/oned.conf"
|
297
|
+
|
298
|
+
puts 'A copy of your old oned.conf file is located here: ' \
|
299
|
+
"/etc/one/oned.conf#{time_based_identifier}"
|
300
|
+
|
301
|
+
@opennebula_services['opennebula'] = true
|
302
|
+
end
|
303
|
+
|
304
|
+
# Sync database
|
305
|
+
def sync_db
|
306
|
+
puts "Dumping and fetching database from #{@remote_server}, " \
|
307
|
+
'this could take a while'
|
308
|
+
|
309
|
+
ssh(
|
310
|
+
"onedb backup -f -u #{@r_config_elements[:user]} " \
|
311
|
+
"-p #{@r_config_elements[:password]} " \
|
312
|
+
"-d #{@r_config_elements[:dbname]} " \
|
313
|
+
"-P #{@r_config_elements[:port]} /tmp/one_db_dump.sql"
|
314
|
+
)
|
315
|
+
|
316
|
+
scp('/tmp/one_db_dump.sql', '/tmp/one_db_dump.sql')
|
317
|
+
|
318
|
+
puts "Local OpenNebula's database will be replaced, hang tight"
|
319
|
+
|
320
|
+
service_action('opennebula', 'stop')
|
321
|
+
|
322
|
+
puts 'Restoring database'
|
323
|
+
|
324
|
+
run_command(
|
325
|
+
"onedb restore -f -u #{@l_config_elements[:user]} " \
|
326
|
+
"-p #{@l_config_elements[:password]} " \
|
327
|
+
"-d #{@l_config_elements[:dbname]} " \
|
328
|
+
"-P #{@l_config_elements[:port]} " \
|
329
|
+
"-h #{@l_config_elements[:server]}" \
|
330
|
+
'/tmp/one_db_dump.sql',
|
331
|
+
true
|
332
|
+
)
|
333
|
+
|
334
|
+
service_action('opennebula', 'start')
|
335
|
+
end
|
336
|
+
|
337
|
+
# Run local command
|
338
|
+
#
|
339
|
+
# @param cmd [String] Command to run
|
340
|
+
# @param print_output [Boolean] True to show output
|
341
|
+
def run_command(cmd, print_output = false)
|
342
|
+
output = LocalCommand.run(cmd)
|
343
|
+
|
344
|
+
if output.code == 0
|
345
|
+
output
|
346
|
+
else
|
347
|
+
return false unless print_output
|
348
|
+
|
349
|
+
STDERR.puts 'ERROR'
|
350
|
+
STDERR.puts "Failed to run: #{cmd}"
|
351
|
+
STDERR.puts output.stderr
|
352
|
+
|
353
|
+
false
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
# Execute SSH command
|
358
|
+
#
|
359
|
+
# @param cmd [String] Command to execute
|
360
|
+
def ssh(cmd)
|
361
|
+
rc = run_command(
|
362
|
+
"ssh -i #{@oneadmin_identity_file} " \
|
363
|
+
"#{SSH_OPTIONS} #{@remote_server} " \
|
364
|
+
"#{cmd}"
|
365
|
+
)
|
366
|
+
|
367
|
+
# if default users doesn't work, try with oneadmin
|
368
|
+
unless rc
|
369
|
+
rc = run_command(
|
370
|
+
"ssh -i #{@oneadmin_identity_file} " \
|
371
|
+
"#{SSH_OPTIONS} oneadmin@#{@remote_server} " \
|
372
|
+
"#{cmd}"
|
373
|
+
)
|
374
|
+
end
|
375
|
+
|
376
|
+
# if oneadmin doesn't work neither, fail
|
377
|
+
unless rc
|
378
|
+
STDERR.puts 'ERROR'
|
379
|
+
STDERR.puts "Couldn't execute command #{cmd} on remote host"
|
380
|
+
exit(-1)
|
381
|
+
end
|
382
|
+
|
383
|
+
rc
|
384
|
+
end
|
385
|
+
|
386
|
+
# Execute SCP command
|
387
|
+
#
|
388
|
+
# @param src [String] Source path
|
389
|
+
# @param dest [String] Destination path
|
390
|
+
def scp(src, dest)
|
391
|
+
rc = run_command(
|
392
|
+
"scp -i #{@oneadmin_identity_file} " \
|
393
|
+
"#{SSH_OPTIONS} #{@remote_server}:/#{src} #{dest}"
|
394
|
+
)
|
395
|
+
|
396
|
+
# if default users doesn't work, try with oneadmin
|
397
|
+
unless rc
|
398
|
+
rc = run_command(
|
399
|
+
"scp -i #{@oneadmin_identity_file} " \
|
400
|
+
"#{SSH_OPTIONS} oneadmin@#{@remote_server}:#{src} #{dest}"
|
401
|
+
)
|
402
|
+
end
|
403
|
+
|
404
|
+
# if oneadmin doesn't work neither, fail
|
405
|
+
unless rc
|
406
|
+
STDERR.puts 'ERROR'
|
407
|
+
STDERR.puts "Couldn't execute command #{cmd} on remote host"
|
408
|
+
exit(-1)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
# Restart OpenNebula services
|
413
|
+
def restart_services
|
414
|
+
restarted = false
|
415
|
+
|
416
|
+
@opennebula_services.each do |service, status|
|
417
|
+
next unless status
|
418
|
+
|
419
|
+
service_action(service)
|
420
|
+
|
421
|
+
restarted = true
|
422
|
+
end
|
423
|
+
|
424
|
+
return if restarted
|
425
|
+
|
426
|
+
puts 'Everything seems synchronized, nothing was replaced.'
|
427
|
+
end
|
428
|
+
|
429
|
+
# Service action
|
430
|
+
#
|
431
|
+
# @param service [String] Service to restart
|
432
|
+
# @param action [String] Action to execute (start, stop, restart)
|
433
|
+
def service_action(service, action = 'try-restart')
|
434
|
+
if `file /sbin/init`.include? 'systemd'
|
435
|
+
puts "#{action}ing #{service} via systemd"
|
436
|
+
run_command("systemctl #{action} #{service}", true)
|
437
|
+
else
|
438
|
+
puts "#{action}ing #{service} via init"
|
439
|
+
run_command("service #{service} #{action}", true)
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
end
|
444
|
+
|
19
445
|
class OneZoneHelper < OpenNebulaHelper::OneHelper
|
20
446
|
|
21
447
|
SERVER_NAME={
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opennebula-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.10.
|
4
|
+
version: 5.10.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OpenNebula
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opennebula
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.10.
|
19
|
+
version: 5.10.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 5.10.
|
26
|
+
version: 5.10.2
|
27
27
|
description: Commands used to talk to OpenNebula
|
28
28
|
email: contact@opennebula.org
|
29
29
|
executables:
|