oxidized 0.36.0 → 0.37.0
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/.rubocop.yml +3 -0
- data/CHANGELOG.md +26 -0
- data/Rakefile +1 -1
- data/docs/Configuration.md +10 -1
- data/docs/Creating-Models.md +1 -1
- data/docs/Hooks.md +92 -67
- data/docs/Inputs.md +15 -12
- data/docs/Model-Notes/GrandstreamHT8xx.md +8 -0
- data/docs/Model-Notes/RouterOS.md +13 -0
- data/docs/Model-Notes/TrueNAS.md +11 -7
- data/docs/Release.md +6 -1
- data/docs/Supported-OS-Types.md +1 -0
- data/extra/hooks/modelrulesadvanced.rb +0 -1
- data/lib/oxidized/cli/support.rb +152 -0
- data/lib/oxidized/cli.rb +9 -0
- data/lib/oxidized/hook.rb +2 -0
- data/lib/oxidized/input/debugtext.rb +40 -0
- data/lib/oxidized/input/debugyaml.rb +82 -0
- data/lib/oxidized/input/exec.rb +1 -6
- data/lib/oxidized/input/ftp.rb +0 -4
- data/lib/oxidized/input/http.rb +1 -8
- data/lib/oxidized/input/ssh.rb +28 -21
- data/lib/oxidized/input/sshbase.rb +7 -12
- data/lib/oxidized/input/telnet.rb +12 -9
- data/lib/oxidized/input/tftp.rb +0 -4
- data/lib/oxidized/model/aoscx.rb +13 -9
- data/lib/oxidized/model/cumulus.rb +3 -3
- data/lib/oxidized/model/dlinknextgen.rb +1 -0
- data/lib/oxidized/model/fortigate.rb +1 -1
- data/lib/oxidized/model/grandstreamht8xx.rb +19 -0
- data/lib/oxidized/model/ios.rb +2 -0
- data/lib/oxidized/model/junos.rb +2 -2
- data/lib/oxidized/model/linuxgeneric.rb +4 -2
- data/lib/oxidized/model/nxos.rb +4 -1
- data/lib/oxidized/model/routeros.rb +4 -0
- data/lib/oxidized/model/tplink.rb +4 -6
- data/lib/oxidized/model/truenas.rb +56 -5
- data/lib/oxidized/model/vyos.rb +1 -0
- data/lib/oxidized/version.rb +2 -2
- metadata +6 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Oxidized
|
|
2
|
+
class DebugText
|
|
3
|
+
include SemanticLogger::Loggable
|
|
4
|
+
|
|
5
|
+
def initialize(config_debug, node, input_name)
|
|
6
|
+
return unless config_debug == true ||
|
|
7
|
+
(config_debug.is_a?(String) && config_debug.downcase.include?('text'))
|
|
8
|
+
|
|
9
|
+
@log = File.open(logfile(node, input_name), 'w')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Separate method to ease unit tests
|
|
13
|
+
def logfile(node, input_name)
|
|
14
|
+
timestamp = Time.now.strftime('%Y%m%d-%H%M%S')
|
|
15
|
+
file = Oxidized::Config::LOG + "/#{node&.ip}-#{input_name}-#{timestamp}.txt"
|
|
16
|
+
logger.debug "Writing I/O Debugging to #{file}"
|
|
17
|
+
file
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def send_data(data)
|
|
21
|
+
return unless @log
|
|
22
|
+
|
|
23
|
+
@log.puts "sent cmd #{data.dump}"
|
|
24
|
+
@log.flush
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def receive_data(data)
|
|
28
|
+
return unless @log
|
|
29
|
+
|
|
30
|
+
@log.puts "received #{data.dump}"
|
|
31
|
+
@log.flush
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def close
|
|
35
|
+
return unless @log
|
|
36
|
+
|
|
37
|
+
@log.close
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module Oxidized
|
|
2
|
+
class DebugYAML
|
|
3
|
+
include SemanticLogger::Loggable
|
|
4
|
+
|
|
5
|
+
def initialize(config_debug, node, input_name)
|
|
6
|
+
return unless config_debug == true ||
|
|
7
|
+
(config_debug.is_a?(String) && config_debug.downcase.include?('yaml'))
|
|
8
|
+
|
|
9
|
+
@log = File.open(logfile(node, input_name), 'w')
|
|
10
|
+
|
|
11
|
+
@partial_line = false
|
|
12
|
+
@first_line = true
|
|
13
|
+
@commands_started = false
|
|
14
|
+
|
|
15
|
+
@log.puts '---'
|
|
16
|
+
@log.puts 'init_prompt: |-'
|
|
17
|
+
@log.flush
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Separate method to ease unit tests
|
|
21
|
+
def logfile(node, input_name)
|
|
22
|
+
timestamp = Time.now.strftime('%Y%m%d-%H%M%S')
|
|
23
|
+
file = Oxidized::Config::LOG + "/#{node&.ip}-#{input_name}-#{timestamp}.yaml"
|
|
24
|
+
logger.debug "Writing YAML Simulation to #{file}"
|
|
25
|
+
file
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def send_data(data)
|
|
29
|
+
return unless @log
|
|
30
|
+
|
|
31
|
+
@log.puts
|
|
32
|
+
@log.puts 'commands:' unless @commands_started
|
|
33
|
+
@log.puts " - #{data.dump}: |-"
|
|
34
|
+
@first_line = true
|
|
35
|
+
@partial_line = false
|
|
36
|
+
@commands_started = true
|
|
37
|
+
@log.flush
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def receive_data(data)
|
|
41
|
+
return unless @log
|
|
42
|
+
return if data.empty?
|
|
43
|
+
|
|
44
|
+
lines = data.split("\n", -1)
|
|
45
|
+
|
|
46
|
+
lines.each_with_index do |line, idx|
|
|
47
|
+
is_last = idx == lines.length - 1
|
|
48
|
+
full_line = is_last ? (data[-1] == "\n") : true
|
|
49
|
+
# Escape line and strip surrounding double quotes
|
|
50
|
+
line = line.dump[1..-2]
|
|
51
|
+
if @first_line
|
|
52
|
+
# Make sure the leading space of the first line (if present)
|
|
53
|
+
# is coded with \0x20 or YAML block scalars won't work
|
|
54
|
+
line.sub!(/^ /, '\x20')
|
|
55
|
+
@first_line = false
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Make sure trailing white spaces are coded with \0x20
|
|
59
|
+
line.gsub!(/ $/, '\x20')
|
|
60
|
+
|
|
61
|
+
output = @partial_line ? line : (' ' + line)
|
|
62
|
+
@partial_line = false
|
|
63
|
+
|
|
64
|
+
if full_line
|
|
65
|
+
@log.puts output
|
|
66
|
+
else
|
|
67
|
+
@log.write output
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
@partial_line = data[-1] != "\n"
|
|
72
|
+
|
|
73
|
+
@log.flush
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def close
|
|
77
|
+
return unless @log
|
|
78
|
+
|
|
79
|
+
@log.close
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
data/lib/oxidized/input/exec.rb
CHANGED
|
@@ -2,7 +2,6 @@ module Oxidized
|
|
|
2
2
|
class Exec < Input
|
|
3
3
|
def connect(node)
|
|
4
4
|
@node = node
|
|
5
|
-
@log = File.open(Oxidized::Config::LOG + "/#{@node.ip}-exec", "w") if Oxidized.config.input.debug?
|
|
6
5
|
@node.model.cfg["exec"].each { |cb| instance_exec(&cb) }
|
|
7
6
|
end
|
|
8
7
|
|
|
@@ -15,10 +14,6 @@ module Oxidized
|
|
|
15
14
|
|
|
16
15
|
private
|
|
17
16
|
|
|
18
|
-
def disconnect
|
|
19
|
-
true
|
|
20
|
-
ensure
|
|
21
|
-
@log.close if Oxidized.config.input.debug?
|
|
22
|
-
end
|
|
17
|
+
def disconnect; end
|
|
23
18
|
end
|
|
24
19
|
end
|
data/lib/oxidized/input/ftp.rb
CHANGED
|
@@ -5,7 +5,6 @@ module Oxidized
|
|
|
5
5
|
def connect(node) # rubocop:disable Naming/PredicateMethod
|
|
6
6
|
@node = node
|
|
7
7
|
@node.model.cfg['ftp'].each { |cb| instance_exec(&cb) }
|
|
8
|
-
@log = File.open(Oxidized::Config::LOG + "/#{@node.ip}-ftp", 'w') if Oxidized.config.input.debug?
|
|
9
8
|
@ftp = Net::FTP.new(@node.ip)
|
|
10
9
|
@ftp.passive = Oxidized.config.input.ftp.passive
|
|
11
10
|
@ftp.login @node.auth[:username], @node.auth[:password]
|
|
@@ -34,9 +33,6 @@ module Oxidized
|
|
|
34
33
|
|
|
35
34
|
def disconnect
|
|
36
35
|
@ftp.close
|
|
37
|
-
# rescue Errno::ECONNRESET, IOError
|
|
38
|
-
ensure
|
|
39
|
-
@log.close if Oxidized.config.input.debug?
|
|
40
36
|
end
|
|
41
37
|
end
|
|
42
38
|
end
|
data/lib/oxidized/input/http.rb
CHANGED
|
@@ -10,7 +10,6 @@ module Oxidized
|
|
|
10
10
|
@username = nil
|
|
11
11
|
@password = nil
|
|
12
12
|
@headers = {}
|
|
13
|
-
@log = File.open(Oxidized::Config::LOG + "/#{@node.ip}-http", "w") if Oxidized.config.input.debug?
|
|
14
13
|
@node.model.cfg["http"].each { |cb| instance_exec(&cb) }
|
|
15
14
|
|
|
16
15
|
return true unless @main_page && defined?(login)
|
|
@@ -110,13 +109,7 @@ module Oxidized
|
|
|
110
109
|
"Basic " + ["#{@username}:#{@password}"].pack('m').delete("\r\n")
|
|
111
110
|
end
|
|
112
111
|
|
|
113
|
-
def
|
|
114
|
-
@log&.write(str)
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def disconnect
|
|
118
|
-
@log.close if Oxidized.config.input.debug?
|
|
119
|
-
end
|
|
112
|
+
def disconnect; end
|
|
120
113
|
|
|
121
114
|
def get_uri(path)
|
|
122
115
|
path = URI.parse(path)
|
data/lib/oxidized/input/ssh.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
require 'timeout'
|
|
2
|
+
require_relative 'sshbase'
|
|
3
|
+
require_relative 'debugyaml'
|
|
4
|
+
require_relative 'debugtext'
|
|
4
5
|
|
|
6
|
+
module Oxidized
|
|
5
7
|
class SSH < SSHBase
|
|
6
8
|
class NoShell < OxidizedError; end
|
|
7
9
|
|
|
@@ -18,11 +20,9 @@ module Oxidized
|
|
|
18
20
|
@output = String.new('')
|
|
19
21
|
@pty_options = { term: "vt100" }
|
|
20
22
|
@node.model.cfg['ssh'].each { |cb| instance_exec(&cb) }
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
logger.debug "I/O Debuging to #{logfile}"
|
|
25
|
-
end
|
|
23
|
+
|
|
24
|
+
@yaml_debug = DebugYAML.new(Oxidized.config.input.debug, @node, config_name)
|
|
25
|
+
@text_debug = DebugText.new(Oxidized.config.input.debug, @node, config_name)
|
|
26
26
|
|
|
27
27
|
logger.debug "Connecting to #{@node.name}"
|
|
28
28
|
@ssh = Net::SSH.start(@node.ip, @node.auth[:username], make_ssh_opts)
|
|
@@ -38,25 +38,30 @@ module Oxidized
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def cmd(cmd, expect = node.prompt)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@log.flush
|
|
41
|
+
unless cmd.is_a?(String)
|
|
42
|
+
logger.error "cmd must be a String (#{cmd.class}): #{cmd.inspect} @ #{node.name}"
|
|
43
|
+
raise ArgumentError, "cmd must be a String"
|
|
45
44
|
end
|
|
45
|
+
logger.debug "Sending '#{cmd.dump}' @ #{node.name} with expect: #{expect.inspect}"
|
|
46
46
|
cmd_output = if @exec
|
|
47
|
+
@yaml_debug&.send_data(cmd)
|
|
48
|
+
@text_debug&.send_data(cmd)
|
|
47
49
|
@ssh.exec! cmd
|
|
48
50
|
else
|
|
49
51
|
cmd_shell(cmd, expect).gsub("\r\n", "\n")
|
|
50
52
|
end
|
|
53
|
+
|
|
54
|
+
# only logging @exec as cmd_shell is handled in the ssh loop
|
|
55
|
+
@yaml_debug&.receive_data(cmd_output) if @exec
|
|
56
|
+
@text_debug&.receive_data(cmd_output) if @exec
|
|
57
|
+
|
|
51
58
|
# Make sure we return a String
|
|
52
59
|
cmd_output.to_s
|
|
53
60
|
end
|
|
54
61
|
|
|
55
62
|
def send(data)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
@log.flush
|
|
59
|
-
end
|
|
63
|
+
@yaml_debug&.send_data(data)
|
|
64
|
+
@text_debug&.send_data(data)
|
|
60
65
|
@ses.send_data data
|
|
61
66
|
end
|
|
62
67
|
|
|
@@ -79,17 +84,16 @@ module Oxidized
|
|
|
79
84
|
rescue Timeout::Error
|
|
80
85
|
logger.debug "#{@node.name} timed out while disconnecting"
|
|
81
86
|
ensure
|
|
82
|
-
@
|
|
87
|
+
@yaml_debug&.close
|
|
88
|
+
@text_debug&.close
|
|
83
89
|
(@ssh.close rescue true) unless @ssh.closed? # rubocop:disable Style/RedundantParentheses
|
|
84
90
|
end
|
|
85
91
|
|
|
86
92
|
def shell_open(ssh)
|
|
87
93
|
@ses = ssh.open_channel do |ch|
|
|
88
94
|
ch.on_data do |_ch, data|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
@log.flush
|
|
92
|
-
end
|
|
95
|
+
@yaml_debug&.receive_data(data)
|
|
96
|
+
@text_debug&.receive_data(data)
|
|
93
97
|
@output << data
|
|
94
98
|
@output = @node.model.expects @output
|
|
95
99
|
end
|
|
@@ -111,6 +115,9 @@ module Oxidized
|
|
|
111
115
|
|
|
112
116
|
def cmd_shell(cmd, expect_re)
|
|
113
117
|
@output = String.new('')
|
|
118
|
+
|
|
119
|
+
@yaml_debug&.send_data(cmd + newline)
|
|
120
|
+
@text_debug&.send_data(cmd + newline)
|
|
114
121
|
@ses.send_data cmd + newline
|
|
115
122
|
@ses.process
|
|
116
123
|
expect expect_re if expect_re
|
|
@@ -18,7 +18,6 @@ module Oxidized
|
|
|
18
18
|
def connect(node) # rubocop:disable Naming/PredicateMethod
|
|
19
19
|
@node = node
|
|
20
20
|
@node.model.cfg[config_name].each { |cb| instance_exec(&cb) }
|
|
21
|
-
setup_debug_logging
|
|
22
21
|
logger.debug "Connecting to #{@node.name}"
|
|
23
22
|
@ssh = Net::SSH.start(@node.ip, @node.auth[:username], make_ssh_opts)
|
|
24
23
|
connected?
|
|
@@ -28,14 +27,6 @@ module Oxidized
|
|
|
28
27
|
@ssh && (not @ssh.closed?)
|
|
29
28
|
end
|
|
30
29
|
|
|
31
|
-
def setup_debug_logging
|
|
32
|
-
return unless Oxidized.config.input.debug?
|
|
33
|
-
|
|
34
|
-
logfile = Oxidized::Config::LOG + "/#{@node.ip}-#{config_name}"
|
|
35
|
-
@log = File.open(logfile, 'w')
|
|
36
|
-
logger.debug "I/O Debugging to #{logfile}"
|
|
37
|
-
end
|
|
38
|
-
|
|
39
30
|
def make_ssh_opts
|
|
40
31
|
ssh_opts = {
|
|
41
32
|
number_of_password_prompts: 0,
|
|
@@ -65,7 +56,13 @@ module Oxidized
|
|
|
65
56
|
|
|
66
57
|
# Use our logger for Net::SSH
|
|
67
58
|
ssh_logger = SemanticLogger[Net::SSH]
|
|
68
|
-
|
|
59
|
+
config_debug = Oxidized.config.input.debug
|
|
60
|
+
if config_debug == true ||
|
|
61
|
+
(config_debug.is_a?(String) && config_debug.downcase.include?('library'))
|
|
62
|
+
ssh_logger.level = :debug
|
|
63
|
+
else
|
|
64
|
+
ssh_logger.level = :fatal
|
|
65
|
+
end
|
|
69
66
|
ssh_opts[:logger] = ssh_logger
|
|
70
67
|
|
|
71
68
|
ssh_opts
|
|
@@ -95,8 +92,6 @@ module Oxidized
|
|
|
95
92
|
"disconnecting, raising #{e.class} with #{e.message}"
|
|
96
93
|
rescue Timeout::Error
|
|
97
94
|
logger.debug "#{@node.name} timed out while disconnecting"
|
|
98
|
-
ensure
|
|
99
|
-
@log.close if Oxidized.config.input.debug?
|
|
100
95
|
end
|
|
101
96
|
|
|
102
97
|
# Methods to implement in subclasses
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require_relative 'debugtext'
|
|
2
|
+
|
|
1
3
|
module Oxidized
|
|
2
4
|
require 'net/telnet'
|
|
3
5
|
class Telnet < Input
|
|
@@ -7,7 +9,9 @@ module Oxidized
|
|
|
7
9
|
@node = node
|
|
8
10
|
@timeout = @node.timeout
|
|
9
11
|
@node.model.cfg['telnet'].each { |cb| instance_exec(&cb) }
|
|
10
|
-
|
|
12
|
+
|
|
13
|
+
@text_debug = DebugText.new(Oxidized.config.input.debug, @node, config_name)
|
|
14
|
+
|
|
11
15
|
port = vars(:telnet_port) || 23
|
|
12
16
|
|
|
13
17
|
telnet_opts = {
|
|
@@ -15,7 +19,7 @@ module Oxidized
|
|
|
15
19
|
'Port' => port.to_i,
|
|
16
20
|
'Timeout' => @timeout,
|
|
17
21
|
'Model' => @node.model,
|
|
18
|
-
'Log' => @
|
|
22
|
+
'Log' => @text_debug
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
@telnet = Net::Telnet.new telnet_opts
|
|
@@ -38,12 +42,14 @@ module Oxidized
|
|
|
38
42
|
# create a string to be passed to oxidized_expect and modified _there_
|
|
39
43
|
# default to a single space so it shouldn't be coerced to nil by any models.
|
|
40
44
|
out = String(' ')
|
|
45
|
+
@text_debug&.send_data(cmd_str)
|
|
41
46
|
@telnet.puts(cmd_str)
|
|
42
47
|
@telnet.oxidized_expect(timeout: @timeout, expect: expect, out: out)
|
|
43
48
|
out
|
|
44
49
|
end
|
|
45
50
|
|
|
46
51
|
def send(data)
|
|
52
|
+
@text_debug&.send_data(data)
|
|
47
53
|
@telnet.write data
|
|
48
54
|
end
|
|
49
55
|
|
|
@@ -63,7 +69,7 @@ module Oxidized
|
|
|
63
69
|
rescue Errno::ECONNRESET, IOError
|
|
64
70
|
# This exception is intented and therefore not handled here
|
|
65
71
|
ensure
|
|
66
|
-
@
|
|
72
|
+
@text_debug&.close
|
|
67
73
|
(@telnet.close rescue true) unless @telnet.sock.closed? # rubocop:disable Style/RedundantParentheses
|
|
68
74
|
end
|
|
69
75
|
end
|
|
@@ -76,8 +82,8 @@ module Net
|
|
|
76
82
|
attr_reader :output
|
|
77
83
|
|
|
78
84
|
def oxidized_expect(options)
|
|
79
|
-
model
|
|
80
|
-
|
|
85
|
+
model = @options["Model"]
|
|
86
|
+
text_debug = @options["Log"]
|
|
81
87
|
|
|
82
88
|
expects = [options[:expect]].flatten
|
|
83
89
|
time_out = options[:timeout] || @options["Timeout"]
|
|
@@ -103,10 +109,7 @@ module Net
|
|
|
103
109
|
buf = preprocess(c)
|
|
104
110
|
rest = ''
|
|
105
111
|
end
|
|
106
|
-
|
|
107
|
-
@log.print buf
|
|
108
|
-
@log.flush
|
|
109
|
-
end
|
|
112
|
+
text_debug&.receive_data buf
|
|
110
113
|
line += buf
|
|
111
114
|
line = model.expects line
|
|
112
115
|
# match is a regexp object. we need to return that for logins to work.
|
data/lib/oxidized/input/tftp.rb
CHANGED
|
@@ -20,7 +20,6 @@ module Oxidized
|
|
|
20
20
|
@node = node
|
|
21
21
|
|
|
22
22
|
@node.model.cfg['tftp'].each { |cb| instance_exec(&cb) }
|
|
23
|
-
@log = File.open(Oxidized::Config::LOG + "/#{@node.ip}-tftp", 'w') if Oxidized.config.input.debug?
|
|
24
23
|
@tftp = Net::TFTP.new @node.ip
|
|
25
24
|
end
|
|
26
25
|
|
|
@@ -36,9 +35,6 @@ module Oxidized
|
|
|
36
35
|
|
|
37
36
|
def disconnect
|
|
38
37
|
# TFTP uses UDP, there is no connection to close
|
|
39
|
-
true
|
|
40
|
-
ensure
|
|
41
|
-
@log.close if Oxidized.config.input.debug?
|
|
42
38
|
end
|
|
43
39
|
end
|
|
44
40
|
end
|
data/lib/oxidized/model/aoscx.rb
CHANGED
|
@@ -37,22 +37,23 @@ class Aoscx < Oxidized::Model
|
|
|
37
37
|
comment cfg
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
header + content
|
|
47
|
-
end
|
|
40
|
+
def with_section(cfg, section, &block)
|
|
41
|
+
cfg.sub!(/(show environment #{section}.*?-{10,}\n)(.*?)(?=\nshow environment|\z)/m) do
|
|
42
|
+
header = ::Regexp.last_match(1)
|
|
43
|
+
content = ::Regexp.last_match(2)
|
|
44
|
+
block.call(content) if block_given?
|
|
45
|
+
header + content
|
|
48
46
|
end
|
|
47
|
+
end
|
|
49
48
|
|
|
49
|
+
cmd 'show environment' do |cfg|
|
|
50
50
|
with_section(cfg, 'fan') do |content|
|
|
51
51
|
content.gsub!(/^((?:\S+ +){3})(slow |normal|medium|fast |max |N\/A ) (.*?)\d+ +$/, '\\1<speed> \\3<rpm>')
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
with_section(cfg, 'power-consumption') do |content|
|
|
55
55
|
content.gsub!(/^(.*?) (?:\d+\.\d+ +)+\d+\.\d+$/, '\\1 <power hidden>')
|
|
56
|
+
content.gsub!(/^(Total Power Consumption +)\d+\.\d+$/, '\\1<power hidden>')
|
|
56
57
|
end
|
|
57
58
|
|
|
58
59
|
with_section(cfg, 'power-allocation') do |content|
|
|
@@ -73,7 +74,10 @@ class Aoscx < Oxidized::Model
|
|
|
73
74
|
comment cfg
|
|
74
75
|
end
|
|
75
76
|
|
|
76
|
-
cmd 'show system
|
|
77
|
+
cmd 'show system' do |cfg|
|
|
78
|
+
cfg = cfg.reject_lines [
|
|
79
|
+
"Up Time", "CPU", "Memory", /Pkts .x/, "Lowest", "Missed"
|
|
80
|
+
]
|
|
77
81
|
comment cfg
|
|
78
82
|
end
|
|
79
83
|
|
|
@@ -5,9 +5,9 @@ class Cumulus < Oxidized::Model
|
|
|
5
5
|
# ^ : match begin of line, to have the most specific prompt
|
|
6
6
|
# [\w.-]+@[\w.-]+ : user@hostname
|
|
7
7
|
# (:mgmt)? : optional when logged in out of band
|
|
8
|
-
#
|
|
9
|
-
# which is always "~" in our context
|
|
10
|
-
prompt /^[\w.-]+@[\w.-]+(:mgmt)
|
|
8
|
+
# :?~[#$] ?$ : end of prompt, containing the linux path,
|
|
9
|
+
# which is always "~" in our context.
|
|
10
|
+
prompt /^[\w.-]+@[\w.-]+(:mgmt)?:?~[#$] ?$/
|
|
11
11
|
clean :escape_codes
|
|
12
12
|
comment '# '
|
|
13
13
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class GrandstreamHT8xx < Oxidized::Model
|
|
2
|
+
using Refinements
|
|
3
|
+
|
|
4
|
+
# Anchored prompt to avoid matching XML content
|
|
5
|
+
prompt /^(GS|CONFIG)>\s?$/
|
|
6
|
+
comment '# '
|
|
7
|
+
|
|
8
|
+
cfg :ssh do
|
|
9
|
+
# After login go to configuration submenu (looks like enabled in other devices)
|
|
10
|
+
post_login 'config'
|
|
11
|
+
# When logout use double exit - first from configuration submenu, and second to disconnect from device
|
|
12
|
+
pre_logout 'exit'
|
|
13
|
+
pre_logout 'exit'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
cmd 'export' do |cfg|
|
|
17
|
+
cfg.cut_both
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/oxidized/model/ios.rb
CHANGED
|
@@ -112,6 +112,8 @@ class IOS < Oxidized::Model
|
|
|
112
112
|
comments << "CPU:#{slave} #{cpu}#{cpuxtra}#{slaveslot}"
|
|
113
113
|
end
|
|
114
114
|
|
|
115
|
+
comments << line.chomp if line.start_with?('Motherboard')
|
|
116
|
+
|
|
115
117
|
comments << "Image: #{Regexp.last_match(1)}" if line =~ /^System image file is "([^"]*)"$/
|
|
116
118
|
end
|
|
117
119
|
comments << "\n"
|
data/lib/oxidized/model/junos.rb
CHANGED
|
@@ -44,8 +44,8 @@ class JunOS < Oxidized::Model
|
|
|
44
44
|
|
|
45
45
|
cmd('show chassis hardware') { |cfg| comment cfg }
|
|
46
46
|
cmd('show system license') do |cfg|
|
|
47
|
-
cfg.gsub!(/ fib
|
|
48
|
-
cfg.gsub!(/ rib
|
|
47
|
+
cfg.gsub!(/ fib[-\s]scale\s+(\d+)/i, ' fib-scale <count>')
|
|
48
|
+
cfg.gsub!(/ rib[-\s]scale\s+(\d+)/i, ' rib-scale <count>')
|
|
49
49
|
comment cfg
|
|
50
50
|
end
|
|
51
51
|
cmd('show system license keys') { |cfg| comment cfg }
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
class LinuxGeneric < Oxidized::Model
|
|
2
2
|
using Refinements
|
|
3
3
|
|
|
4
|
-
prompt
|
|
4
|
+
prompt /^\S.*[#$] $/
|
|
5
5
|
comment '# '
|
|
6
|
+
clean :escape_codes
|
|
6
7
|
|
|
7
8
|
# add a comment in the final conf
|
|
8
9
|
def add_comment(comment)
|
|
@@ -53,7 +54,7 @@ class LinuxGeneric < Oxidized::Model
|
|
|
53
54
|
end
|
|
54
55
|
|
|
55
56
|
cfg :telnet do
|
|
56
|
-
username
|
|
57
|
+
username /(Username|[Ll]ogin):/
|
|
57
58
|
password /^Password:/
|
|
58
59
|
end
|
|
59
60
|
|
|
@@ -63,6 +64,7 @@ class LinuxGeneric < Oxidized::Model
|
|
|
63
64
|
cmd "sudo su -", /^\[sudo\] password/
|
|
64
65
|
cmd @node.auth[:password]
|
|
65
66
|
elsif vars(:enable)
|
|
67
|
+
# This will only work without localisation (de: "Passwort:", fr: "Mot de passe :"...)
|
|
66
68
|
cmd "su -", /^Password:/
|
|
67
69
|
cmd vars(:enable)
|
|
68
70
|
end
|
data/lib/oxidized/model/nxos.rb
CHANGED
|
@@ -10,7 +10,10 @@ class NXOS < Oxidized::Model
|
|
|
10
10
|
|
|
11
11
|
cmd :secret do |cfg|
|
|
12
12
|
cfg.gsub! /^(snmp-server community).*/, '\\1 <secret hidden>'
|
|
13
|
-
cfg.gsub!
|
|
13
|
+
cfg.gsub!(
|
|
14
|
+
/^(snmp-server user \S+ \S+ auth \S+) \S+ (priv \S+) \S+ /,
|
|
15
|
+
'\\1 <secret hidden> \\2 <secret hidden> '
|
|
16
|
+
)
|
|
14
17
|
cfg.gsub! /^(snmp-server host.*? )\S+( udp-port \d+)?$/, '\\1<secret hidden>\\2'
|
|
15
18
|
cfg.gsub! /^(snmp-server mib community-map) \S+ ?(.*)/, '\\1 <secret hidden> \\2'
|
|
16
19
|
cfg.gsub! /(password \d+) (\S+)/, '\\1 <secret hidden>'
|
|
@@ -29,6 +29,10 @@ class RouterOS < Oxidized::Model
|
|
|
29
29
|
comment cfg
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
cmd :significant_changes do |cfg|
|
|
33
|
+
cfg.gsub(/^(#\s+installed-version: [^\n]+\n).*?^(?=# software id)/m, '\1')
|
|
34
|
+
end
|
|
35
|
+
|
|
32
36
|
post do
|
|
33
37
|
logger.debug "Running /export for routeros version #{@ros_version}"
|
|
34
38
|
run_cmd = if vars(:remove_secret)
|
|
@@ -48,19 +48,17 @@ class TPLink < Oxidized::Model
|
|
|
48
48
|
lines[0..lines.index("end\n")].join
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
+
macro :enable, regex: /^[pP]assword:/
|
|
52
|
+
|
|
51
53
|
cfg :telnet, :ssh do
|
|
52
54
|
username /^User ?[nN]ame:/
|
|
53
55
|
password /^\r?Password:/
|
|
56
|
+
newline "\r\n"
|
|
54
57
|
end
|
|
55
58
|
|
|
56
59
|
cfg :telnet, :ssh do
|
|
57
60
|
post_login do
|
|
58
|
-
|
|
59
|
-
cmd "enable"
|
|
60
|
-
elsif vars(:enable)
|
|
61
|
-
cmd "enable", /^[pP]assword:/
|
|
62
|
-
cmd vars(:enable)
|
|
63
|
-
end
|
|
61
|
+
cmd 'terminal length 0'
|
|
64
62
|
end
|
|
65
63
|
|
|
66
64
|
pre_logout do
|