kanrisuru 0.1.0 → 0.2.1
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.
- checksums.yaml +4 -4
- data/.gitignore +17 -0
- data/.rubocop.yml +47 -0
- data/.rubocop_todo.yml +0 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +2 -5
- data/LICENSE.txt +1 -1
- data/README.md +143 -7
- data/Rakefile +5 -3
- data/bin/console +4 -3
- data/kanrisuru.gemspec +21 -12
- data/lib/kanrisuru.rb +41 -2
- data/lib/kanrisuru/command.rb +99 -0
- data/lib/kanrisuru/core.rb +53 -0
- data/lib/kanrisuru/core/archive.rb +154 -0
- data/lib/kanrisuru/core/disk.rb +302 -0
- data/lib/kanrisuru/core/file.rb +332 -0
- data/lib/kanrisuru/core/find.rb +108 -0
- data/lib/kanrisuru/core/group.rb +97 -0
- data/lib/kanrisuru/core/ip.rb +1032 -0
- data/lib/kanrisuru/core/mount.rb +138 -0
- data/lib/kanrisuru/core/path.rb +140 -0
- data/lib/kanrisuru/core/socket.rb +168 -0
- data/lib/kanrisuru/core/stat.rb +104 -0
- data/lib/kanrisuru/core/stream.rb +121 -0
- data/lib/kanrisuru/core/system.rb +348 -0
- data/lib/kanrisuru/core/transfer.rb +203 -0
- data/lib/kanrisuru/core/user.rb +198 -0
- data/lib/kanrisuru/logger.rb +8 -0
- data/lib/kanrisuru/mode.rb +277 -0
- data/lib/kanrisuru/os_package.rb +235 -0
- data/lib/kanrisuru/remote.rb +10 -0
- data/lib/kanrisuru/remote/cluster.rb +95 -0
- data/lib/kanrisuru/remote/cpu.rb +68 -0
- data/lib/kanrisuru/remote/env.rb +33 -0
- data/lib/kanrisuru/remote/file.rb +354 -0
- data/lib/kanrisuru/remote/fstab.rb +412 -0
- data/lib/kanrisuru/remote/host.rb +191 -0
- data/lib/kanrisuru/remote/memory.rb +19 -0
- data/lib/kanrisuru/remote/os.rb +87 -0
- data/lib/kanrisuru/result.rb +78 -0
- data/lib/kanrisuru/template.rb +32 -0
- data/lib/kanrisuru/util.rb +40 -0
- data/lib/kanrisuru/util/bits.rb +203 -0
- data/lib/kanrisuru/util/fs_mount_opts.rb +655 -0
- data/lib/kanrisuru/util/os_family.rb +213 -0
- data/lib/kanrisuru/util/signal.rb +161 -0
- data/lib/kanrisuru/version.rb +3 -1
- data/spec/functional/core/archive_spec.rb +228 -0
- data/spec/functional/core/disk_spec.rb +80 -0
- data/spec/functional/core/file_spec.rb +341 -0
- data/spec/functional/core/find_spec.rb +52 -0
- data/spec/functional/core/group_spec.rb +65 -0
- data/spec/functional/core/ip_spec.rb +71 -0
- data/spec/functional/core/path_spec.rb +93 -0
- data/spec/functional/core/socket_spec.rb +31 -0
- data/spec/functional/core/stat_spec.rb +98 -0
- data/spec/functional/core/stream_spec.rb +99 -0
- data/spec/functional/core/system_spec.rb +96 -0
- data/spec/functional/core/transfer_spec.rb +108 -0
- data/spec/functional/core/user_spec.rb +76 -0
- data/spec/functional/os_package_spec.rb +75 -0
- data/spec/functional/remote/cluster_spec.rb +45 -0
- data/spec/functional/remote/cpu_spec.rb +41 -0
- data/spec/functional/remote/env_spec.rb +36 -0
- data/spec/functional/remote/fstab_spec.rb +76 -0
- data/spec/functional/remote/host_spec.rb +68 -0
- data/spec/functional/remote/memory_spec.rb +29 -0
- data/spec/functional/remote/os_spec.rb +63 -0
- data/spec/functional/remote/remote_file_spec.rb +180 -0
- data/spec/helper/test_hosts.rb +68 -0
- data/spec/hosts.json +92 -0
- data/spec/spec_helper.rb +11 -3
- data/spec/unit/fstab_spec.rb +22 -0
- data/spec/unit/kanrisuru_spec.rb +9 -0
- data/spec/unit/mode_spec.rb +183 -0
- data/spec/unit/template_spec.rb +13 -0
- data/spec/unit/util_spec.rb +177 -0
- data/spec/zz_reboot_spec.rb +46 -0
- metadata +136 -13
- data/spec/kanrisuru_spec.rb +0 -9
@@ -0,0 +1,412 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kanrisuru
|
4
|
+
module Remote
|
5
|
+
class Fstab
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(host, path = '/etc/fstab')
|
9
|
+
@host = host
|
10
|
+
@path = path
|
11
|
+
@file = nil
|
12
|
+
@backup = nil
|
13
|
+
|
14
|
+
init_from_os
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](device)
|
18
|
+
get_entry(device)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_entry(device)
|
22
|
+
result = @entries[device]
|
23
|
+
|
24
|
+
return result[:entry] if result
|
25
|
+
|
26
|
+
result = nil
|
27
|
+
|
28
|
+
## Lookup by uuid or label
|
29
|
+
@entries.each do |_, entry|
|
30
|
+
result = entry[:entry] if !@result && (entry[:entry].uuid == device || entry[:entry].label == device)
|
31
|
+
end
|
32
|
+
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
def <<(entry)
|
37
|
+
append(entry)
|
38
|
+
end
|
39
|
+
|
40
|
+
def append(entry)
|
41
|
+
if entry.instance_of?(Kanrisuru::Remote::Fstab::Entry)
|
42
|
+
return if @entries.key?(entry.device)
|
43
|
+
elsif entry.instance_of?(String)
|
44
|
+
entry = Kanrisuru::Remote::Fstab::Entry.new(host: @host, line: entry)
|
45
|
+
return if @entries.key?(entry.device)
|
46
|
+
else
|
47
|
+
raise ArgumentError, 'Invalid entry type'
|
48
|
+
end
|
49
|
+
|
50
|
+
@entries[entry.device] = {
|
51
|
+
entry: entry,
|
52
|
+
new: true
|
53
|
+
}
|
54
|
+
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def find_device(device); end
|
59
|
+
|
60
|
+
def each(&block)
|
61
|
+
@entries.each do |_, entry|
|
62
|
+
block.call(entry[:entry])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
## Only append new entries to file
|
67
|
+
def append_file!
|
68
|
+
@file.append do |f|
|
69
|
+
@entries.each do |_, entry|
|
70
|
+
f << entry.to_s if entry[:new]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
reload!
|
75
|
+
end
|
76
|
+
|
77
|
+
## Rewrites entire fstab file with new and old entries
|
78
|
+
def write_file!
|
79
|
+
@file.write do |f|
|
80
|
+
@entries.each do |_, entry|
|
81
|
+
f << entry.to_s
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
reload!
|
86
|
+
end
|
87
|
+
|
88
|
+
def reload!
|
89
|
+
init_from_os
|
90
|
+
end
|
91
|
+
|
92
|
+
def inspect
|
93
|
+
format('#<Kanrisuru::Remote::Fstab:0x%<object_id>s @path=%<path>s @entries=%<entries>s>',
|
94
|
+
object_id: object_id, path: @path, entries: @entries)
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def init_from_os
|
100
|
+
@entries = {}
|
101
|
+
|
102
|
+
raise 'Not implemented' unless @host.os && @host.os.kernel == 'Linux'
|
103
|
+
|
104
|
+
initialize_linux
|
105
|
+
end
|
106
|
+
|
107
|
+
def initialize_linux
|
108
|
+
if @file
|
109
|
+
@file.reload!
|
110
|
+
else
|
111
|
+
@file = @host.file(@path)
|
112
|
+
end
|
113
|
+
|
114
|
+
raise ArgumentError, 'Invalid file' if !@file.exists? || !@file.file?
|
115
|
+
|
116
|
+
@file.each do |line|
|
117
|
+
next if line.strip.chomp.empty?
|
118
|
+
next if line =~ /\s*#/
|
119
|
+
|
120
|
+
entry = Fstab::Entry.new(host: @host, line: line)
|
121
|
+
@entries[entry.device] = {
|
122
|
+
entry: entry,
|
123
|
+
new: false
|
124
|
+
}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Entry
|
129
|
+
attr_reader :device, :uuid, :invalid, :label, :type, :opts, :freq, :passno
|
130
|
+
attr_accessor :mount_point
|
131
|
+
|
132
|
+
def initialize(opts = {})
|
133
|
+
@host = opts[:host]
|
134
|
+
@line = opts[:line]
|
135
|
+
|
136
|
+
@default = nil
|
137
|
+
|
138
|
+
@device = opts[:device] || nil
|
139
|
+
@opts = opts[:opts] || nil
|
140
|
+
@label = opts[:label] || nil
|
141
|
+
@uuid = opts[:uuid] || nil
|
142
|
+
@mount_point = opts[:mount_point] || nil
|
143
|
+
@type = opts[:type] || nil
|
144
|
+
@freq = opts[:freq] || nil
|
145
|
+
@passno = opts[:passno] || nil
|
146
|
+
|
147
|
+
@changed = false
|
148
|
+
|
149
|
+
@ucount = 0
|
150
|
+
@special = false
|
151
|
+
@invalid = false
|
152
|
+
|
153
|
+
if Kanrisuru::Util.present?(@line) && @line.instance_of?(String)
|
154
|
+
parse_line!
|
155
|
+
elsif Kanrisuru::Util.present?(@opts) && @opts.instance_of?(String) || @opts.instance_of?(Hash)
|
156
|
+
@opts = Kanrisuru::Remote::Fstab::Options.new(@type, @opts)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def inspect
|
161
|
+
str = '#<Kanrisuru::Remote::Fstab::Entry:0x%<object_id>s ' \
|
162
|
+
'@line=%<line>s @device=%<device>s @label=%<label>s' \
|
163
|
+
'@uuid=%<uuid>s @freq=%<freq>s @pasno=%<passno>s' \
|
164
|
+
'@opts=%<opts>s}>'
|
165
|
+
|
166
|
+
format(
|
167
|
+
str,
|
168
|
+
object_id: object_id,
|
169
|
+
line: @line,
|
170
|
+
device: @device,
|
171
|
+
label: @label,
|
172
|
+
uuid: @uuid,
|
173
|
+
freq: @freq,
|
174
|
+
passno: @passno,
|
175
|
+
opts: @opts.inspect
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
def valid?
|
180
|
+
!@invalid
|
181
|
+
end
|
182
|
+
|
183
|
+
def to_s(override = nil)
|
184
|
+
mode = override || @default
|
185
|
+
|
186
|
+
case mode
|
187
|
+
when 'uuid'
|
188
|
+
"UUID=#{@uuid} #{@mount_point} #{@type} #{@opts} #{@freq} #{@passno}"
|
189
|
+
when 'label'
|
190
|
+
"LABEL=#{@label} #{@mount_point} #{@type} #{@opts} #{@freq} #{@passno}"
|
191
|
+
else
|
192
|
+
"#{@device} #{@mount_point} #{@type} #{@opts} #{@freq} #{@passno}"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
def parse_line!
|
199
|
+
fsline, mp, @type, opts, freq, passno = @line.split
|
200
|
+
|
201
|
+
@mount_point = mp
|
202
|
+
@freq = freq || '0'
|
203
|
+
@passno = passno || '0'
|
204
|
+
|
205
|
+
@opts = Fstab::Options.new(@type, opts)
|
206
|
+
|
207
|
+
case @line
|
208
|
+
when /^\s*LABEL=/
|
209
|
+
@default = 'label'
|
210
|
+
parse_label(fsline)
|
211
|
+
when /^\s*UUID=/
|
212
|
+
@default = 'uuid'
|
213
|
+
parse_uuid(fsline)
|
214
|
+
when %r{^\s*/dev}
|
215
|
+
@default = 'dev'
|
216
|
+
parse_dev(fsline)
|
217
|
+
else
|
218
|
+
# TODO: somewhat risky to assume that everything else
|
219
|
+
# can be considered a special device, but validating this
|
220
|
+
# is really tricky.
|
221
|
+
@special = true
|
222
|
+
@device = fsline
|
223
|
+
end
|
224
|
+
|
225
|
+
# Fstab entries not matching real devices have device unknown
|
226
|
+
@invalid = (@line.split.count != 6) # invalid entry if < 6 columns
|
227
|
+
|
228
|
+
if (@uuid.nil? && @label.nil? && !@special) ||
|
229
|
+
@device =~ /^unknown_/ ||
|
230
|
+
(!@host.inode?(@device) && !@special)
|
231
|
+
@invalid = true
|
232
|
+
@ucount += 1
|
233
|
+
end
|
234
|
+
|
235
|
+
@invalid = true unless @freq =~ /0|1|2/ && @passno =~ /0|1|2/
|
236
|
+
end
|
237
|
+
|
238
|
+
def parse_label(fsline)
|
239
|
+
@label = fsline.split('=').last.strip.chomp
|
240
|
+
path = @host.realpath("/dev/disk/by-label/#{@label}").path
|
241
|
+
|
242
|
+
@device = begin
|
243
|
+
"/dev/#{path.split('/').last}"
|
244
|
+
rescue StandardError
|
245
|
+
"unknown_#{@ucount}"
|
246
|
+
end
|
247
|
+
|
248
|
+
result = @host.blkid(device: @device)
|
249
|
+
@uuid = result.success? ? result.uuid : nil
|
250
|
+
end
|
251
|
+
|
252
|
+
def parse_uuid(fsline)
|
253
|
+
@uuid = fsline.split('=').last.strip.chomp
|
254
|
+
path = @host.realpath("/dev/disk/by-uuid/#{uuid}").path
|
255
|
+
|
256
|
+
@device = begin
|
257
|
+
"/dev/#{path.split('/').last}"
|
258
|
+
rescue StandardError
|
259
|
+
"unknown_#{@ucount}"
|
260
|
+
end
|
261
|
+
|
262
|
+
result = @host.blkid(device: @device)
|
263
|
+
@label = result.success? ? result.label : nil
|
264
|
+
end
|
265
|
+
|
266
|
+
def parse_dev(fsline)
|
267
|
+
@device = fsline
|
268
|
+
result = @host.blkid(device: @device)
|
269
|
+
|
270
|
+
@label = result.success? ? result.label : nil
|
271
|
+
@uuid = result.success? ? result.uuid : nil
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
class Options
|
276
|
+
def initialize(type, opts)
|
277
|
+
@type = type
|
278
|
+
@valid = false
|
279
|
+
|
280
|
+
if opts.instance_of?(String)
|
281
|
+
@opts = parse_opts(opts)
|
282
|
+
elsif opts.instance_of?(Hash)
|
283
|
+
@opts = opts.transform_keys(&:to_s)
|
284
|
+
else
|
285
|
+
raise ArgumentError, 'Invalid option type'
|
286
|
+
end
|
287
|
+
|
288
|
+
validate_opts!
|
289
|
+
end
|
290
|
+
|
291
|
+
def inspect
|
292
|
+
format('<Kanrisuru::Remote::Fstab::Options:0x%<object_id>s @opts=%<opts>s @type=%<type>s>',
|
293
|
+
object_id: object_id, opts: @opts, type: @type)
|
294
|
+
end
|
295
|
+
|
296
|
+
def [](option)
|
297
|
+
@opts[option]
|
298
|
+
end
|
299
|
+
|
300
|
+
def []=(option, value)
|
301
|
+
option = option.to_s
|
302
|
+
|
303
|
+
unless Kanrisuru::Remote::Fstab::Options.option_exists?(option, @type)
|
304
|
+
raise ArgumentError,
|
305
|
+
"Invalid option: #{option} for #{@type} file system."
|
306
|
+
end
|
307
|
+
|
308
|
+
unless Kanrisuru::Remote::Fstab::Options.valid_option?(option, value, @type)
|
309
|
+
raise ArgumentError,
|
310
|
+
"Invalid option value: #{value} for #{option} on #{@type} file system."
|
311
|
+
end
|
312
|
+
|
313
|
+
@opts[option] = value
|
314
|
+
end
|
315
|
+
|
316
|
+
def to_s
|
317
|
+
string = ''
|
318
|
+
opts_length = @opts.length
|
319
|
+
|
320
|
+
@opts.each_with_index do |(key, value), index|
|
321
|
+
append_comma = true
|
322
|
+
|
323
|
+
if value == true
|
324
|
+
string += key.to_s
|
325
|
+
elsif value.instance_of?(String) || value.instance_of?(Integer) || value.instance_of?(Float)
|
326
|
+
string += "#{key}=#{value}"
|
327
|
+
else
|
328
|
+
append_comma = false
|
329
|
+
end
|
330
|
+
|
331
|
+
string += ',' if append_comma && index < opts_length - 1
|
332
|
+
end
|
333
|
+
|
334
|
+
string
|
335
|
+
end
|
336
|
+
|
337
|
+
def to_h
|
338
|
+
@opts
|
339
|
+
end
|
340
|
+
|
341
|
+
def self.option_exists?(value, type = nil)
|
342
|
+
value = value.to_sym
|
343
|
+
type = type ? type.to_sym : nil
|
344
|
+
|
345
|
+
common = Kanrisuru::Util::FsMountOpts[:common]
|
346
|
+
fs_opts = Kanrisuru::Util::FsMountOpts[type]
|
347
|
+
|
348
|
+
common.key?(value) ||
|
349
|
+
fs_opts&.key?(value)
|
350
|
+
end
|
351
|
+
|
352
|
+
def self.valid_option?(value, field, type = nil)
|
353
|
+
value = value.to_sym
|
354
|
+
type = type ? type.to_sym : nil
|
355
|
+
|
356
|
+
common = Kanrisuru::Util::FsMountOpts[:common]
|
357
|
+
fs_opts = Kanrisuru::Util::FsMountOpts[type]
|
358
|
+
|
359
|
+
if common.key?(value)
|
360
|
+
case common[value]
|
361
|
+
when 'boolean'
|
362
|
+
[true, false].include?(field)
|
363
|
+
when 'value'
|
364
|
+
field.instance_of?(String) || field.instance_of?(Float) || field.instance_of?(Integer)
|
365
|
+
else
|
366
|
+
false
|
367
|
+
end
|
368
|
+
elsif fs_opts&.key?(value)
|
369
|
+
case fs_opts[value]
|
370
|
+
when 'boolean'
|
371
|
+
[true, false].include?(field)
|
372
|
+
when 'value'
|
373
|
+
field.instance_of?(String) || field.instance_of?(Float) || field.instance_of?(Integer)
|
374
|
+
else
|
375
|
+
false
|
376
|
+
end
|
377
|
+
else
|
378
|
+
raise ArgumentError, 'Invalid option'
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
private
|
383
|
+
|
384
|
+
def validate_opts!
|
385
|
+
@opts.each do |key, value|
|
386
|
+
unless Kanrisuru::Remote::Fstab::Options.valid_option?(key, value, @type)
|
387
|
+
raise ArgumentError, "Invalid option: #{key} for #{@type}"
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
@valid = true
|
392
|
+
end
|
393
|
+
|
394
|
+
def parse_opts(string)
|
395
|
+
opts = {}
|
396
|
+
|
397
|
+
options = string.split(',')
|
398
|
+
options.each do |option|
|
399
|
+
if option.include?('=')
|
400
|
+
opt, value = option.split('=')
|
401
|
+
opts[opt] = value
|
402
|
+
else
|
403
|
+
opts[option] = true
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
opts
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/ssh'
|
4
|
+
require 'net/scp'
|
5
|
+
require 'net/ping'
|
6
|
+
|
7
|
+
module Kanrisuru
|
8
|
+
module Remote
|
9
|
+
class Host
|
10
|
+
extend OsPackage::Include
|
11
|
+
|
12
|
+
attr_reader :host, :username, :password, :port, :keys
|
13
|
+
|
14
|
+
def initialize(opts = {})
|
15
|
+
@host = opts[:host]
|
16
|
+
@username = opts[:username]
|
17
|
+
@login_user = @username
|
18
|
+
|
19
|
+
@port = opts[:port]
|
20
|
+
@password = opts[:password] if opts[:password]
|
21
|
+
@keys = opts[:keys] if opts[:keys]
|
22
|
+
@shell = opts[:shell] || '/bin/bash'
|
23
|
+
|
24
|
+
@current_dir = ''
|
25
|
+
end
|
26
|
+
|
27
|
+
def remote_user
|
28
|
+
@remote_user ||= @username
|
29
|
+
end
|
30
|
+
|
31
|
+
def hostname
|
32
|
+
@hostname ||= init_hostname
|
33
|
+
end
|
34
|
+
|
35
|
+
def os
|
36
|
+
@os ||= init_os
|
37
|
+
end
|
38
|
+
|
39
|
+
def env
|
40
|
+
@env ||= init_env
|
41
|
+
end
|
42
|
+
|
43
|
+
def template(path, args = {})
|
44
|
+
Kanrisuru::Template.new(path, args)
|
45
|
+
end
|
46
|
+
|
47
|
+
def fstab(file = '/etc/fstab')
|
48
|
+
@fstab ||= init_fstab(file)
|
49
|
+
end
|
50
|
+
|
51
|
+
def chdir(path = '~')
|
52
|
+
cd(path)
|
53
|
+
end
|
54
|
+
|
55
|
+
def cd(path = '~')
|
56
|
+
@current_dir = pwd.path if Kanrisuru::Util.blank?(@current_dir)
|
57
|
+
|
58
|
+
@current_dir =
|
59
|
+
if path == '~'
|
60
|
+
realpath('~').path
|
61
|
+
elsif path[0] == '.' || path[0] != '/'
|
62
|
+
## Use strip to preserve symlink directories
|
63
|
+
realpath("#{@current_dir}/#{path}", strip: true).path
|
64
|
+
else
|
65
|
+
## Use strip to preserve symlink directories
|
66
|
+
realpath(path, strip: true).path
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def cpu
|
71
|
+
@cpu ||= init_cpu
|
72
|
+
end
|
73
|
+
|
74
|
+
def memory
|
75
|
+
@memory ||= init_memory
|
76
|
+
end
|
77
|
+
|
78
|
+
def su(user)
|
79
|
+
@remote_user = user
|
80
|
+
end
|
81
|
+
|
82
|
+
def file(path)
|
83
|
+
Kanrisuru::Remote::File.new(path, self)
|
84
|
+
end
|
85
|
+
|
86
|
+
def ssh
|
87
|
+
@ssh ||= Net::SSH.start(@host, @username, keys: @keys, password: @password)
|
88
|
+
end
|
89
|
+
|
90
|
+
def ping?
|
91
|
+
check = Net::Ping::External.new(@host)
|
92
|
+
check.ping?
|
93
|
+
end
|
94
|
+
|
95
|
+
def execute_shell(command)
|
96
|
+
command = Kanrisuru::Command.new(command) if command.instance_of?(String)
|
97
|
+
|
98
|
+
command.remote_user = remote_user
|
99
|
+
command.remote_shell = @shell
|
100
|
+
command.remote_path = @current_dir
|
101
|
+
command.remote_env = env.to_s
|
102
|
+
|
103
|
+
execute_with_retries(command)
|
104
|
+
end
|
105
|
+
|
106
|
+
def execute(command)
|
107
|
+
command = Kanrisuru::Command.new(command) if command.instance_of?(String)
|
108
|
+
execute_with_retries(command)
|
109
|
+
end
|
110
|
+
|
111
|
+
def disconnect
|
112
|
+
ssh.close
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def execute_with_retries(command)
|
118
|
+
raise 'Invalid command type' unless command.instance_of?(Kanrisuru::Command)
|
119
|
+
|
120
|
+
retry_attempts = 3
|
121
|
+
|
122
|
+
Kanrisuru.logger.debug { "kanrisuru:~$ #{command.prepared_command}" }
|
123
|
+
|
124
|
+
begin
|
125
|
+
channel = ssh.open_channel do |ch|
|
126
|
+
ch.exec(command.prepared_command) do |_, success|
|
127
|
+
raise "could not execute command: #{command.prepared_command}" unless success
|
128
|
+
|
129
|
+
ch.on_request('exit-status') do |_, data|
|
130
|
+
command.handle_status(data.read_long)
|
131
|
+
end
|
132
|
+
|
133
|
+
ch.on_request('exit-signal') do |_, data|
|
134
|
+
command.handle_signal(data.read_long)
|
135
|
+
end
|
136
|
+
|
137
|
+
ch.on_data do |_, data|
|
138
|
+
command.handle_data(data)
|
139
|
+
end
|
140
|
+
|
141
|
+
ch.on_extended_data do |_, _type, data|
|
142
|
+
command.handle_data(data)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
channel.wait
|
148
|
+
|
149
|
+
Kanrisuru.logger.debug { command.to_a }
|
150
|
+
|
151
|
+
command
|
152
|
+
rescue Net::SSH::ConnectionTimeout, Net::SSH::Timeout => e
|
153
|
+
if retry_attempts > 1
|
154
|
+
retry_attempts -= 1
|
155
|
+
retry
|
156
|
+
else
|
157
|
+
disconnect
|
158
|
+
raise e.class
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def init_hostname
|
164
|
+
command = Kanrisuru::Command.new('hostname')
|
165
|
+
execute(command)
|
166
|
+
|
167
|
+
command.success? ? command.to_s : nil
|
168
|
+
end
|
169
|
+
|
170
|
+
def init_env
|
171
|
+
Env.new
|
172
|
+
end
|
173
|
+
|
174
|
+
def init_fstab(file)
|
175
|
+
Fstab.new(self, file)
|
176
|
+
end
|
177
|
+
|
178
|
+
def init_memory
|
179
|
+
Memory.new(self)
|
180
|
+
end
|
181
|
+
|
182
|
+
def init_os
|
183
|
+
Os.new(self)
|
184
|
+
end
|
185
|
+
|
186
|
+
def init_cpu
|
187
|
+
Cpu.new(self)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|