oxidized 0.30.1 → 0.31.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +2 -2
- data/.github/workflows/stale.yml +4 -2
- data/.rubocop.yml +18 -2
- data/.rubocop_todo.yml +5 -12
- data/CHANGELOG.md +61 -1
- data/CONTRIBUTING.md +5 -0
- data/Dockerfile +82 -21
- data/README.md +5 -21
- data/Rakefile +3 -2
- data/docs/Configuration.md +36 -12
- data/docs/Creating-Models.md +45 -4
- data/docs/Hooks.md +34 -0
- data/docs/Issues.md +91 -0
- data/docs/Model-Notes/Cumulus.md +5 -0
- data/docs/Model-Notes/FSOS.md +5 -0
- data/docs/Model-Notes/FortiOS.md +21 -5
- data/docs/Model-Notes/HPEAruba.md +31 -0
- data/docs/Model-Notes/OS6.md +10 -0
- data/docs/Model-Notes/RouterOS.md +15 -0
- data/docs/Model-Notes/SikluMHTG.md +7 -0
- data/docs/Outputs.md +2 -0
- data/docs/Release.md +18 -15
- data/docs/Sources.md +21 -0
- data/docs/Supported-OS-Types.md +11 -5
- data/docs/Troubleshooting.md +35 -0
- data/examples/device-simulation/README.md +173 -0
- data/examples/device-simulation/cmdsets/aoscx +9 -0
- data/examples/device-simulation/cmdsets/arubainstant +5 -0
- data/examples/device-simulation/cmdsets/asa +7 -0
- data/examples/device-simulation/cmdsets/ios +7 -0
- data/examples/device-simulation/cmdsets/nxos +5 -0
- data/examples/device-simulation/cmdsets/routeros +5 -0
- data/examples/device-simulation/cmdsets/srosmd +11 -0
- data/examples/device-simulation/device2yaml.rb +225 -0
- data/examples/device-simulation/yaml/aoscx_R0X25A-6410_FL.10.10.1100.yaml +2281 -0
- data/examples/device-simulation/yaml/aoscx_R8N85A-C6000-48G-CL4_PL.10.08.1010.yaml +451 -0
- data/examples/device-simulation/yaml/arubainstant_IAP515_8.10.0.6_VWLC.yaml +213 -0
- data/examples/device-simulation/yaml/asa_5512_9.12-4-67_single-context.yaml +531 -0
- data/examples/device-simulation/yaml/asr920_16.8.1b.yaml +1122 -0
- data/examples/device-simulation/yaml/garderos_R7709_003_006_068.yaml +101 -0
- data/examples/device-simulation/yaml/iosxe_C9200L-24P-4G_17.09.04a.yaml +514 -0
- data/examples/device-simulation/yaml/iosxe_C9800-L-F-K9_17.06.05.yaml +417 -0
- data/examples/device-simulation/yaml/riverbed_915.yaml +123 -0
- data/examples/device-simulation/yaml/routeros_CHR_7.10.1.yaml +145 -0
- data/examples/device-simulation/yaml/routeros_CHR_7.16.yaml +79 -0
- data/examples/device-simulation/yaml/routeros_L009UiGS_7.15.2.yaml +353 -0
- data/examples/podman-compose/Makefile +60 -17
- data/examples/podman-compose/README.md +63 -27
- data/examples/podman-compose/docker-compose.yml +11 -2
- data/examples/podman-compose/gitserver/.gitignore +1 -0
- data/examples/podman-compose/gitserver/Dockerfile +14 -0
- data/examples/podman-compose/model-simulation/Dockerfile-model +1 -1
- data/examples/podman-compose/model-simulation/asternos.sh +2 -0
- data/examples/podman-compose/oxidized-config/.gitignore +2 -0
- data/examples/podman-compose/oxidized-config/config +1 -1
- data/examples/podman-compose/oxidized-config/config_csv-file +46 -0
- data/examples/podman-compose/oxidized-config/config_csv-gitserver +56 -0
- data/examples/podman-compose/oxidized-ssh/.gitignore +1 -0
- data/lib/oxidized/config.rb +7 -1
- data/lib/oxidized/hook/githubrepo.rb +37 -7
- data/lib/oxidized/hook/slackdiff.rb +29 -7
- data/lib/oxidized/input/http.rb +1 -0
- data/lib/oxidized/input/telnet.rb +1 -1
- data/lib/oxidized/manager.rb +17 -16
- data/lib/oxidized/model/aoscx.rb +16 -2
- data/lib/oxidized/model/aosw.rb +7 -1
- data/lib/oxidized/model/arubainstant.rb +90 -0
- data/lib/oxidized/model/audiocodes.rb +2 -2
- data/lib/oxidized/model/cnos.rb +13 -10
- data/lib/oxidized/model/cumulus.rb +3 -0
- data/lib/oxidized/model/dlink.rb +1 -0
- data/lib/oxidized/model/dlinknextgen.rb +3 -0
- data/lib/oxidized/model/edgecos.rb +2 -1
- data/lib/oxidized/model/eos.rb +2 -0
- data/lib/oxidized/model/f5os.rb +17 -0
- data/lib/oxidized/model/firewareos.rb +10 -1
- data/lib/oxidized/model/fortios.rb +24 -1
- data/lib/oxidized/model/garderos.rb +43 -0
- data/lib/oxidized/model/h3c.rb +1 -1
- data/lib/oxidized/model/ibos.rb +1 -0
- data/lib/oxidized/model/ios.rb +20 -12
- data/lib/oxidized/model/iosxr.rb +1 -1
- data/lib/oxidized/model/lenovonos.rb +2 -0
- data/lib/oxidized/model/linuxgeneric.rb +1 -1
- data/lib/oxidized/model/netgear.rb +1 -1
- data/lib/oxidized/model/nodegrid.rb +1 -1
- data/lib/oxidized/model/nsxdfw.rb +30 -0
- data/lib/oxidized/model/nxos.rb +2 -1
- data/lib/oxidized/model/os6.rb +48 -0
- data/lib/oxidized/model/rgos.rb +1 -1
- data/lib/oxidized/model/riverbed.rb +104 -0
- data/lib/oxidized/model/routeros.rb +2 -2
- data/lib/oxidized/model/saos.rb +18 -1
- data/lib/oxidized/model/siklumhtg.rb +22 -0
- data/lib/oxidized/model/uplinkolt.rb +46 -0
- data/lib/oxidized/model/vyatta.rb +2 -2
- data/lib/oxidized/model/xos.rb +7 -0
- data/lib/oxidized/node.rb +30 -18
- data/lib/oxidized/nodes.rb +13 -5
- data/lib/oxidized/output/file.rb +45 -42
- data/lib/oxidized/output/git.rb +185 -160
- data/lib/oxidized/output/gitcrypt.rb +188 -186
- data/lib/oxidized/output/http.rb +53 -51
- data/lib/oxidized/output/output.rb +6 -4
- data/lib/oxidized/source/csv.rb +44 -49
- data/lib/oxidized/source/http.rb +63 -81
- data/lib/oxidized/source/jsonfile.rb +63 -0
- data/lib/oxidized/source/source.rb +43 -18
- data/lib/oxidized/source/sql.rb +66 -59
- data/lib/oxidized/version.rb +2 -2
- data/oxidized.gemspec +22 -16
- metadata +111 -15
@@ -0,0 +1,173 @@
|
|
1
|
+
# Device simulation
|
2
|
+
Oxidized supports [150+ devices](/docs/Supported-OS-Types.md).
|
3
|
+
No developer has access to all of these devices, which makes the task of
|
4
|
+
maintaining Oxidized difficult:
|
5
|
+
|
6
|
+
- issues can't be resolved because the developer has no access to the device.
|
7
|
+
- further developments can produce regressions.
|
8
|
+
|
9
|
+
In order to address this, we can simulate the devices. An example for a
|
10
|
+
simulation are the [model unit tests](/spec/model) but one could also simulate
|
11
|
+
a device within a ssh server.
|
12
|
+
|
13
|
+
The simulation of devices is currently focused on ssh-based devices. This may
|
14
|
+
be extended to other inputs like telnet or ftp in the future.
|
15
|
+
|
16
|
+
## YAML Simulation Data
|
17
|
+
The underlying data for the simulation is a [YAML](https://yaml.org/) file in
|
18
|
+
which we store all relevant information about the device. The most important
|
19
|
+
information is the responses to the commands used in the oxidized models.
|
20
|
+
|
21
|
+
The YAML simulation files are stored under
|
22
|
+
[/examples/device-simulation/yaml/](/examples/device-simulation/yaml/).
|
23
|
+
|
24
|
+
### Creating a YAML file with device2yaml.rb
|
25
|
+
A device does not only output the ASCII text we can see in the console.
|
26
|
+
It adds ANSI-escape code for nice colors, bold and underline, \r and so on.
|
27
|
+
These are key factors in prompt issues so they must be represented in the YAML
|
28
|
+
file. We use the ruby string format with interpolations like \r \e and so on.
|
29
|
+
Another important point is trailing spaces at the end of lines. Some text
|
30
|
+
editors automatically remove trailing spaces, so we code them with \x20.
|
31
|
+
|
32
|
+
Although a YAML file could be written by hand, this is quite a tedious task to
|
33
|
+
catch all the extra codes and code them into YAML. This can be
|
34
|
+
automated with the ruby script
|
35
|
+
[device2yaml.rb](/examples/device-simulation/device2yaml.rb).
|
36
|
+
|
37
|
+
`device2yaml.rb` needs ruby and the gem
|
38
|
+
[net-ssh](https://rubygems.org/gems/net-ssh/) to run. On debian, you can install
|
39
|
+
them with `sudo apt install ruby-net-ssh`
|
40
|
+
|
41
|
+
Run `device2yaml.rb` in the directory `/examples/device-simulation/`, the
|
42
|
+
online help tells you the options.
|
43
|
+
```
|
44
|
+
device-simulation$ ./device2yaml.rb
|
45
|
+
Missing a host to connect to...
|
46
|
+
|
47
|
+
Usage: device2yaml.rb [user@]host [options]
|
48
|
+
-c, --cmdset file Mandatory: specify the commands to be run
|
49
|
+
-o, --output file Specify an output YAML-file
|
50
|
+
-t, --timeout value Specify the idle timeout beween commands (default: 5 seconds)
|
51
|
+
-e, --exec-mode Run ssh in exec mode (without tty)
|
52
|
+
-h, --help Print this help
|
53
|
+
```
|
54
|
+
|
55
|
+
- `[user@]host` specifies the user and host to connect to the device. The
|
56
|
+
password will be prompted interactively by the script. If you do not specify a
|
57
|
+
user, it will use the user executing the script.
|
58
|
+
- You must list the commands you want to run on the device in a file. Just
|
59
|
+
enter one command per line. It is important that you enter exactly the commands
|
60
|
+
used by the oxidized model, and no abbreviation like `sh run`. Do not forget
|
61
|
+
to insert the `post_login` commands at the beginning if the model has some and
|
62
|
+
also the `pre_logout`commands at the end.
|
63
|
+
Predefined command sets for some models are stored in
|
64
|
+
`/examples/device-simulation/cmdsets`.
|
65
|
+
- `device2yaml.rb` waits an idle timeout after the last received data before
|
66
|
+
sending the next command. The default is 5 seconds. If your device makes a
|
67
|
+
longer pause than 5 seconds before or within a command, you will see that the
|
68
|
+
output of the command is shortened or slips into the next command in the yaml
|
69
|
+
file. You will have to change the idle timeout to a greater value to address
|
70
|
+
this.
|
71
|
+
- When run without the output argument, `device2yaml.rb` will only print the ssh
|
72
|
+
output to the standard output. You must use `-o <model_HW_SW.yaml>` to store the
|
73
|
+
collected data in a YAML file.
|
74
|
+
- If your oxidized model uses ssh exec mode (look for `exec true` in the model),
|
75
|
+
you will have to use the option `-e` to run device2yaml in ssh exec mode.
|
76
|
+
|
77
|
+
Note that `device2yaml.rb` takes some time to run because of the idle
|
78
|
+
timeout of (default) 5 seconds between each command. You can press the "Escape"
|
79
|
+
key if you know there is no more data to come for the current command (when you
|
80
|
+
see the prompt for the next command), and the script will stop waiting and
|
81
|
+
directly process the next command.
|
82
|
+
|
83
|
+
Here are two examples of how to run the script:
|
84
|
+
```shell
|
85
|
+
./device2yaml.rb OX-SW123.sample.domain -c cmdsets/aoscx -o yaml/aoscx_R8N85A-C6000-48G-CL4_PL.10.08.1010.yaml
|
86
|
+
./device2yaml.rb admin@r7 -c cmdsets/routeros -e -o yaml/routeros_CHR_7.10.1.yaml
|
87
|
+
```
|
88
|
+
|
89
|
+
### Publishing the YAML simulation file to oxidized
|
90
|
+
Publishing the YAML simulation file of your device helps maintain oxidized.
|
91
|
+
This task may take some time, and we are very grateful that you take this time
|
92
|
+
for the community!
|
93
|
+
|
94
|
+
You should pay attention to removing or replacing anything you don't want to
|
95
|
+
share with the rest of the world, for example:
|
96
|
+
|
97
|
+
- Passwords
|
98
|
+
- IP Adresses
|
99
|
+
- Serial numbers
|
100
|
+
|
101
|
+
You can also shorten the configuration if you want - we don't need 48 times the
|
102
|
+
same config for each interface, but it doesn't hurt either.
|
103
|
+
|
104
|
+
Take your time, this is an important task: after you have
|
105
|
+
uploaded your file on github, it may be impossible to remove it. You can use
|
106
|
+
search/replace to make consistent and faster changes (change the hostname).
|
107
|
+
|
108
|
+
You can leave the section `oxidized_output` unchanged, it is only used for
|
109
|
+
[model unit tests](/spec/model). You will find an explanation of how to produce
|
110
|
+
the `oxidized_output`-section in the README.md there.
|
111
|
+
|
112
|
+
The YAML simulation file should be stored under
|
113
|
+
[/examples/device-simulation/yaml/](/examples/device-simulation/yaml/. It
|
114
|
+
should be named so that it can be easily recognized: model, hardware type,
|
115
|
+
software version and optionally a description if you need to differentiate two
|
116
|
+
YAML files:
|
117
|
+
|
118
|
+
- #model_#hardware_#software.yaml
|
119
|
+
- #model_#hardware_#software_#description.yaml
|
120
|
+
|
121
|
+
Examples:
|
122
|
+
|
123
|
+
- garderos_R7709_003_006_068.yaml
|
124
|
+
- iosxe_C9200L-24P-4G_17.09.04a.yaml
|
125
|
+
- asa_5512_9.12-4-67_single-context.yaml
|
126
|
+
|
127
|
+
### Interactive mode
|
128
|
+
The `device2yaml.rb` script is a little dumb and needs some help, especially
|
129
|
+
when having a device sending its output page by page and requiring you to press
|
130
|
+
space for the next page. `device2yaml.rb` does not know how to handle this.
|
131
|
+
|
132
|
+
While `device2yaml.rb` is running, you can type anything to the keyboard, it
|
133
|
+
will be send to the remote device. So you can press space or 'n' to get the
|
134
|
+
next page.
|
135
|
+
|
136
|
+
You can also use this to enter an enable password.
|
137
|
+
|
138
|
+
If you press the "Esc" key, `device2yaml.rb` will not wait for the idle timeout
|
139
|
+
and will process the next command right away.
|
140
|
+
|
141
|
+
### YAML Format
|
142
|
+
The yaml file has three sections:
|
143
|
+
- init_prompt: describing the lines send by the device before we can send a
|
144
|
+
command. It usually includes MOTD banners, and must include the first prompt.
|
145
|
+
- commands: the commands the oxidized model sends to the network device and the
|
146
|
+
expected output.
|
147
|
+
- oxidized_output: the expected output of oxidized, so that you can compare it
|
148
|
+
to the output generated by the unit test. This is optional and only used for
|
149
|
+
unit tests.
|
150
|
+
|
151
|
+
The outputs are multiline and use YAML block scalars (`|`), with the trailing \n
|
152
|
+
removed (`-` after `|`). The outputs include the echo of the given command and
|
153
|
+
the next prompt. Escape characters are coded in Ruby style (\n, \r...).
|
154
|
+
|
155
|
+
Here is a shortened example of a YAML file:
|
156
|
+
```yaml
|
157
|
+
---
|
158
|
+
init_prompt: |-
|
159
|
+
\e[4m\rLAB-R1234_Garderos#\e[m\x20
|
160
|
+
commands:
|
161
|
+
show system version: |-
|
162
|
+
show system version
|
163
|
+
grs-gwuz-armel/003_005_068 (Garderos; 2021-04-30 16:19:35)
|
164
|
+
\e[4m\rLAB-R1234_Garderos#\e[m\x20
|
165
|
+
# ...
|
166
|
+
exit: ""
|
167
|
+
oxidized_output: |
|
168
|
+
# grs-gwuz-armel/003_005_068 (Garderos; 2021-04-30 16:19:35)
|
169
|
+
#\x20
|
170
|
+
# ...
|
171
|
+
```
|
172
|
+
|
173
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
environment more false
|
2
|
+
show system information
|
3
|
+
show card state
|
4
|
+
show chassis
|
5
|
+
file show bootlog.txt
|
6
|
+
admin show configuration debug full-context
|
7
|
+
file show config.dbg
|
8
|
+
admin show configuration configure | match persistent-indices post-lines 10000
|
9
|
+
admin show configuration bof full-context
|
10
|
+
admin show configuration configure full-context
|
11
|
+
logout
|
@@ -0,0 +1,225 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'net/ssh'
|
5
|
+
require 'optparse'
|
6
|
+
require 'etc'
|
7
|
+
require 'timeout'
|
8
|
+
|
9
|
+
# This scripts logs in a network device and outputs a yaml file that can be
|
10
|
+
# used for model unit tests in spec/model/
|
11
|
+
|
12
|
+
# This script is quick & dirty - it grew with the time an could be a project
|
13
|
+
# for its own. It works, and that should be enough ;-)
|
14
|
+
|
15
|
+
################# Methods
|
16
|
+
# Runs cmd in the ssh session, either im exec mode or with a tty
|
17
|
+
# saves the output to @output
|
18
|
+
def ssh_exec(cmd)
|
19
|
+
puts "\n### Sending #{cmd}..."
|
20
|
+
@output&.puts " #{cmd}: |-"
|
21
|
+
|
22
|
+
if @exec_mode
|
23
|
+
@ssh_output = @ssh.exec! cmd + "\n"
|
24
|
+
else
|
25
|
+
@ses.send_data cmd + "\n"
|
26
|
+
shell_wait
|
27
|
+
end
|
28
|
+
yaml_output(' ')
|
29
|
+
end
|
30
|
+
|
31
|
+
# Wait for the ssh command to be executed, with an idle timout @idle_timeout
|
32
|
+
# Pressing CTRL-C exits the script
|
33
|
+
# Pressing ESC termiates the idle timeout
|
34
|
+
def shell_wait
|
35
|
+
@ssh_output = ''
|
36
|
+
# ssh_output gets appended by chanel.on-data (below)
|
37
|
+
# We store the current length of @ssh_output in @ssh_output_length
|
38
|
+
# if @ssh_output.length is bigger than @ssh_output_length, we got new data
|
39
|
+
@ssh_output_length = 0
|
40
|
+
|
41
|
+
# Keep track of time for idle timeout
|
42
|
+
start_time = Time.now
|
43
|
+
|
44
|
+
# Loop & wait for @idle_timeout seconds after last output
|
45
|
+
# 0.1 means that the loop should run at least once per 0.1 second
|
46
|
+
@ssh.loop(0.1) do
|
47
|
+
# if @ssh_output is longer than our saved length, we got new output
|
48
|
+
if @ssh_output_length < @ssh_output.length
|
49
|
+
# reset the timer and save the new output length
|
50
|
+
start_time = Time.now
|
51
|
+
@ssh_output_length = @ssh_output.length
|
52
|
+
end
|
53
|
+
|
54
|
+
# We wait for 0.1 seconds if a key was pressed
|
55
|
+
begin
|
56
|
+
Timeout.timeout(0.1) do
|
57
|
+
# Get input // this is a blocking call
|
58
|
+
char = $stdin.getch
|
59
|
+
# If ctrl-c is pressed, exit the script
|
60
|
+
if char == "\u0003"
|
61
|
+
puts '### CTRL-C pressed, exiting'
|
62
|
+
cleanup
|
63
|
+
exit
|
64
|
+
end
|
65
|
+
# If escape is pressed, terminate idle timeout
|
66
|
+
if char == "\e"
|
67
|
+
puts "\n### ESC pressed, skipping idle timeout"
|
68
|
+
return false
|
69
|
+
else
|
70
|
+
# if not, send the char through ssh
|
71
|
+
@ses.send_data char
|
72
|
+
end
|
73
|
+
end
|
74
|
+
rescue Timeout::Error
|
75
|
+
# No key pressed
|
76
|
+
end
|
77
|
+
|
78
|
+
# exit the loop when the @idle_timeout has been reached (false = exit)
|
79
|
+
Time.now - start_time < @idle_timeout
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def yaml_output(prepend = '')
|
84
|
+
# Now print the collected output to @output
|
85
|
+
firstline = true
|
86
|
+
|
87
|
+
# as we want to prepend 'prepend' to each line, we need each_line and chomp
|
88
|
+
# chomp removes the trainling \n
|
89
|
+
@ssh_output.each_line(chomp: true) do |line|
|
90
|
+
# encode line and remove the first and the trailing double quote
|
91
|
+
line = line.dump[1..-2]
|
92
|
+
if firstline
|
93
|
+
# Make sure the leading space of the first line (if present)
|
94
|
+
# is coded with \0x20 or YAML block scalars won't work
|
95
|
+
line.sub!(/^\A /, '\x20')
|
96
|
+
firstline = false
|
97
|
+
end
|
98
|
+
# Make sure trailing white spaces are coded with \0x20
|
99
|
+
line.gsub!(/ $/, '\x20')
|
100
|
+
# prepend white spaces for the yaml block scalar
|
101
|
+
line = prepend + line
|
102
|
+
@output&.puts line
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def cleanup
|
107
|
+
(@ssh.close rescue true) unless @ssh.closed?
|
108
|
+
@output&.close
|
109
|
+
end
|
110
|
+
|
111
|
+
################# Main loop
|
112
|
+
|
113
|
+
# Define options
|
114
|
+
options = {}
|
115
|
+
optparse = OptionParser.new do |opts|
|
116
|
+
opts.banner = "Usage: device2yaml.rb [user@]host [options]"
|
117
|
+
|
118
|
+
opts.on('-c', '--cmdset file', 'Mandatory: specify the commands to be run') do |file|
|
119
|
+
options[:cmdset] = file
|
120
|
+
end
|
121
|
+
opts.on('-o', '--output file', 'Specify an output YAML-file') do |file|
|
122
|
+
options[:output] = file
|
123
|
+
end
|
124
|
+
opts.on('-t', '--timeout value', Integer, 'Specify the idle timeout beween commands (default: 5 seconds)') do |timeout|
|
125
|
+
options[:timeout] = timeout
|
126
|
+
end
|
127
|
+
opts.on('-e', '--exec-mode', 'Run ssh in exec mode (without tty)') { @exec_mode = true }
|
128
|
+
opts.on '-h', '--help', 'Print this help' do
|
129
|
+
puts opts
|
130
|
+
exit
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Catch and parse the first argument
|
135
|
+
if ARGV[0] && ARGV[0][0] != '-'
|
136
|
+
argument = ARGV.shift
|
137
|
+
if argument.include?('@')
|
138
|
+
ssh_user, ssh_host = argument.split('@')
|
139
|
+
else
|
140
|
+
ssh_user = Etc.getlogin
|
141
|
+
ssh_host = argument
|
142
|
+
end
|
143
|
+
else
|
144
|
+
puts 'Missing a host to connect to...'
|
145
|
+
puts
|
146
|
+
puts optparse
|
147
|
+
exit 1
|
148
|
+
end
|
149
|
+
|
150
|
+
# Parse the options
|
151
|
+
optparse.parse!
|
152
|
+
|
153
|
+
# Get the commands to be run against ssh_host
|
154
|
+
unless options[:cmdset]
|
155
|
+
puts 'Missing a command set, use option -c'
|
156
|
+
puts
|
157
|
+
puts optparse
|
158
|
+
exit 1
|
159
|
+
end
|
160
|
+
# make an array of commands to send, ignore empty lines
|
161
|
+
ssh_commands = File.read(options[:cmdset]).split(/\n+|\r+/)
|
162
|
+
|
163
|
+
# Defaut idle timeout: 5 seconds, as tests showed that 2 seconds is too short
|
164
|
+
@idle_timeout = options[:timeout] || 5
|
165
|
+
|
166
|
+
# We will use safe navifation (&.) to call the methods on @output only
|
167
|
+
# if @output is not nil
|
168
|
+
@output = options[:output] ? File.open(options[:output], 'w') : nil
|
169
|
+
|
170
|
+
@ssh = Net::SSH.start(ssh_host,
|
171
|
+
ssh_user,
|
172
|
+
{ timeout: 10,
|
173
|
+
append_all_supported_algorithms: true })
|
174
|
+
|
175
|
+
@ssh_output = ''
|
176
|
+
|
177
|
+
unless @exec_mode
|
178
|
+
@ses = @ssh.open_channel do |ch|
|
179
|
+
ch.on_data do |_ch, data|
|
180
|
+
@ssh_output += data
|
181
|
+
# Output the data to stdout for interactive control
|
182
|
+
# remove ANSI escape codes, as they can produce problems
|
183
|
+
# The code will be printed as '\e[123m' in the output
|
184
|
+
print data.gsub("\e", '\e')
|
185
|
+
end
|
186
|
+
ch.request_pty(term: 'vt100') do |_ch, success_pty|
|
187
|
+
raise "Can't get PTY" unless success_pty
|
188
|
+
|
189
|
+
ch.send_channel_request 'shell' do |_ch, success_shell|
|
190
|
+
raise "Can't get shell" unless success_shell
|
191
|
+
end
|
192
|
+
end
|
193
|
+
ch.on_extended_data do |_ch, _type, data|
|
194
|
+
$stderr.print "Error: #{data}\n"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# YAML begin of file
|
200
|
+
@output&.puts '---'
|
201
|
+
|
202
|
+
if @exec_mode
|
203
|
+
# init prompt does not exist and is empty in exec mode
|
204
|
+
@output&.puts 'init_prompt:'
|
205
|
+
else
|
206
|
+
# get motd and first prompt
|
207
|
+
@output&.puts 'init_prompt: |-'
|
208
|
+
shell_wait
|
209
|
+
yaml_output ' '
|
210
|
+
end
|
211
|
+
|
212
|
+
@output&.puts "commands:"
|
213
|
+
|
214
|
+
begin
|
215
|
+
ssh_commands.each do |cmd|
|
216
|
+
ssh_exec cmd
|
217
|
+
end
|
218
|
+
rescue Errno::ECONNRESET, Net::SSH::Disconnect, IOError => e
|
219
|
+
puts "### Connection closed with message: #{e.message}"
|
220
|
+
end
|
221
|
+
|
222
|
+
@output&.puts 'oxidized_output: |'
|
223
|
+
@output&.puts ' !! needs to be written by hand or copy & paste from model output'
|
224
|
+
|
225
|
+
cleanup
|