oxidized 0.18.0 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +50 -0
- data/CHANGELOG.md +14 -0
- data/Dockerfile +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +56 -3
- data/lib/oxidized/hook/awssns.rb +27 -0
- data/lib/oxidized/input/ssh.rb +11 -5
- data/lib/oxidized/model/{alvarion → alvarion.rb} +0 -0
- data/lib/oxidized/model/aosw.rb +16 -5
- data/lib/oxidized/model/casa.rb +46 -0
- data/lib/oxidized/model/ciscosmb.rb +4 -5
- data/lib/oxidized/model/dlink.rb +36 -0
- data/lib/oxidized/model/dnos.rb +4 -3
- data/lib/oxidized/model/eos.rb +1 -1
- data/lib/oxidized/model/fiberdriver.rb +21 -0
- data/lib/oxidized/model/fujitsupy.rb +42 -0
- data/lib/oxidized/model/hatteras.rb +52 -0
- data/lib/oxidized/model/hpebladesystem.rb +83 -0
- data/lib/oxidized/model/pfsense.rb +2 -1
- data/lib/oxidized/model/planet.rb +83 -0
- data/lib/oxidized/model/powerconnect.rb +1 -1
- data/lib/oxidized/model/procurve.rb +4 -0
- data/lib/oxidized/model/trango.rb +62 -0
- data/lib/oxidized/node.rb +2 -2
- data/lib/oxidized/output/file.rb +8 -6
- data/lib/oxidized/source/http.rb +1 -0
- data/lib/oxidized/version.rb +1 -1
- metadata +14 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd75468c104dc960d991ac69be65520c3af0ff6f
|
4
|
+
data.tar.gz: 5189f65c44b78a3f76916417126a11526f53dca3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d3c1ff69768064f89d7a5bfeb4d3ea1ff99cb7df051394e428f2b8168b3a7b60dc2e97cc0886c79d664f88c542ca3d3144db66d0c1a363fc187ab264012df30
|
7
|
+
data.tar.gz: e935f661d461388807ab7bcc83d1b90b1e13b9c4d0aef509efcdf3684357aa4c55d959c2a2177bd7abfa408e9ad9f599702122f0118a012c415c6e8391bd67ea
|
data/.gitignore
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
## Specific to RubyMotion:
|
17
|
+
.dat*
|
18
|
+
.repl_history
|
19
|
+
build/
|
20
|
+
*.bridgesupport
|
21
|
+
build-iPhoneOS/
|
22
|
+
build-iPhoneSimulator/
|
23
|
+
|
24
|
+
## Specific to RubyMotion (use of CocoaPods):
|
25
|
+
#
|
26
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
27
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
28
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
29
|
+
#
|
30
|
+
# vendor/Pods/
|
31
|
+
|
32
|
+
## Documentation cache and generated files:
|
33
|
+
/.yardoc/
|
34
|
+
/_yardoc/
|
35
|
+
/doc/
|
36
|
+
/rdoc/
|
37
|
+
|
38
|
+
## Environment normalization:
|
39
|
+
/.bundle/
|
40
|
+
/vendor/bundle
|
41
|
+
/lib/bundler/man/
|
42
|
+
|
43
|
+
# for a library or gem, you might want to ignore these files since the code is
|
44
|
+
# intended to run in multiple environments; otherwise, check them in:
|
45
|
+
# Gemfile.lock
|
46
|
+
# .ruby-version
|
47
|
+
# .ruby-gemset
|
48
|
+
|
49
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
|
+
.rvmrc
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
# 0.19.0
|
2
|
+
- FEATURE: allow setting ssh_keys (not relying on openssh config) (@denvera)
|
3
|
+
- FEATURE: fujitsupy model (@stokbaek)
|
4
|
+
- FEATURE: fiberdriver model (@emjemj)
|
5
|
+
- FEATURE: hpbladesystems model (@flokli)
|
6
|
+
- FEATURE: planetsgs model (@flokli)
|
7
|
+
- FEATURE: trango model (@rfdrake)
|
8
|
+
- FEATURE: casa model (@rfdrake)
|
9
|
+
- FEATURE: dlink model (@rfdrake)
|
10
|
+
- FEATURE: hatteras model (@rfdrake)
|
11
|
+
- FEATURE: ability to ignore SSL certs in http (@laf)
|
12
|
+
- FEATURE: awsns hooks, publish messages to AWS SNS topics (@natm)
|
13
|
+
- BUGFIX: pfsense, dnos, powerconnect, ciscosmb, eos, aosw
|
14
|
+
|
1
15
|
# 0.18.0
|
2
16
|
- FEATURE: APC model (by @davromaniak )
|
3
17
|
- BUGFIX: ironware, aosw
|
data/Dockerfile
CHANGED
@@ -3,7 +3,7 @@ MAINTAINER Samer Abdel-Hafez <sam@arahant.net>
|
|
3
3
|
|
4
4
|
RUN add-apt-repository ppa:brightbox/ruby-ng && \
|
5
5
|
apt-get update && \
|
6
|
-
apt-get install -y ruby2.3 ruby2.3-dev libsqlite3-dev libssl-dev pkg-config make cmake
|
6
|
+
apt-get install -y ruby2.3 ruby2.3-dev libsqlite3-dev libssl-dev pkg-config make cmake libssh2-1-dev
|
7
7
|
|
8
8
|
RUN gem install oxidized oxidized-web --no-ri --no-rdoc
|
9
9
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -70,6 +70,8 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen
|
|
70
70
|
* [NOS (Network Operating System)](lib/oxidized/model/nos.rb)
|
71
71
|
* [Vyatta](lib/oxidized/model/vyatta.rb)
|
72
72
|
* [6910](lib/oxidized/model/br6910.rb)
|
73
|
+
* Casa
|
74
|
+
* [Casa](lib/oxidized/model/casa.rb)
|
73
75
|
* Check Point
|
74
76
|
* [GaiaOS](lib/oxidized/model/gaiaos.rb)
|
75
77
|
* Ciena
|
@@ -94,6 +96,8 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen
|
|
94
96
|
* DELL
|
95
97
|
* [PowerConnect](lib/oxidized/model/powerconnect.rb)
|
96
98
|
* [AOSW](lib/oxidized/model/aosw.rb)
|
99
|
+
* D-Link
|
100
|
+
* [D-Link](lib/oxidized/model/dlink.rb)
|
97
101
|
* Ericsson/Redback
|
98
102
|
* [IPOS (former SEOS)](lib/oxidized/model/ipos.rb)
|
99
103
|
* Extreme Networks
|
@@ -106,9 +110,14 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen
|
|
106
110
|
* [FTOS](lib/oxidized/model/ftos.rb)
|
107
111
|
* FortiGate
|
108
112
|
* [FortiOS](lib/oxidized/model/fortios.rb)
|
113
|
+
* Fujitsu
|
114
|
+
* [PRIMERGY Blade switch 1/10Gbe](lib/oxidized/model/fujitsupy.rb)
|
115
|
+
* Hatteras
|
116
|
+
* [Hatteras](lib/oxidized/model/hatteras.rb)
|
109
117
|
* HP
|
110
118
|
* [Comware (HP A-series, H3C, 3Com)](lib/oxidized/model/comware.rb)
|
111
119
|
* [Procurve](lib/oxidized/model/procurve.rb)
|
120
|
+
* [BladeSystem (Onboard Administrator)](lib/oxidized/model/hpebladesystem.rb)
|
112
121
|
* Huawei
|
113
122
|
* [VRP](lib/oxidized/model/vrp.rb)
|
114
123
|
* Juniper
|
@@ -122,6 +131,7 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen
|
|
122
131
|
* [RFS](lib/oxidized/model/mtrlrfs.rb)
|
123
132
|
* MRV
|
124
133
|
* [MasterOS](lib/oxidized/model/masteros.rb)
|
134
|
+
* [FiberDriver](lib/oxidized/model/fiberdriver.rb)
|
125
135
|
* Netonix
|
126
136
|
* [WISP Switch (As Netonix)](lib/oxidized/model/netonix.rb)
|
127
137
|
* Nokia (formerly TiMetra, Alcatel, Alcatel-Lucent)
|
@@ -130,11 +140,14 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen
|
|
130
140
|
* [Opengear](lib/oxidized/model/opengear.rb)
|
131
141
|
* Palo Alto
|
132
142
|
* [PANOS](lib/oxidized/model/panos.rb)
|
143
|
+
* [PLANET SG/SGS Switches](lib/oxidized/model/planet.rb)
|
133
144
|
* [pfSense](lib/oxidized/model/pfsense.rb)
|
134
145
|
* Quanta
|
135
146
|
* [Quanta / VxWorks 6.6 (1.1.0.8)](lib/oxidized/model/quantaos.rb)
|
136
147
|
* Supermicro
|
137
148
|
* [Supermicro](lib/oxidized/model/supermicro.rb)
|
149
|
+
* Trango Systems
|
150
|
+
* [Trango](lib/oxidized/model/trango.rb)
|
138
151
|
* Ubiquiti
|
139
152
|
* [AirOS](lib/oxidized/model/airos.rb)
|
140
153
|
* [Edgeos](lib/oxidized/model/edgeos.rb)
|
@@ -294,17 +307,17 @@ this will bind port 8888 to all interfaces then expose port out. (Issue #445)
|
|
294
307
|
|
295
308
|
You can also use docker-compose to launch oxidized container:
|
296
309
|
```
|
297
|
-
# docker-compose.yml
|
310
|
+
# docker-compose.yml
|
298
311
|
# docker-compose file example for oxidized that will start along with docker daemon
|
299
312
|
oxidized:
|
300
313
|
restart: always
|
301
|
-
image: oxidized/oxidized:latest
|
314
|
+
image: oxidized/oxidized:latest
|
302
315
|
ports:
|
303
316
|
- 8888:8888/tcp
|
304
317
|
environment:
|
305
318
|
CONFIG_RELOAD_INTERVAL: 600
|
306
319
|
volumes:
|
307
|
-
- /etc/oxidized:/root/.config/oxidized
|
320
|
+
- /etc/oxidized:/root/.config/oxidized
|
308
321
|
```
|
309
322
|
|
310
323
|
create the `/etc/oxidized/router.db`
|
@@ -493,6 +506,17 @@ source:
|
|
493
506
|
X-Auth-Token: 'somerandomstring'
|
494
507
|
```
|
495
508
|
|
509
|
+
You can also pass `secure: false` if you want to disable ssl certificate verification:
|
510
|
+
|
511
|
+
```
|
512
|
+
source:
|
513
|
+
default: http
|
514
|
+
http:
|
515
|
+
url: https://url/api
|
516
|
+
scheme: https
|
517
|
+
secure: false
|
518
|
+
```
|
519
|
+
|
496
520
|
### Output: File
|
497
521
|
|
498
522
|
Parent directory needs to be created manually, one file per device, with most recent running config.
|
@@ -791,6 +815,35 @@ hooks:
|
|
791
815
|
password: pass
|
792
816
|
```
|
793
817
|
|
818
|
+
## Hook type: awssns
|
819
|
+
|
820
|
+
The `awssns` hook publishes messages to AWS SNS topics. This allows you to notify other systems of device configuration changes, for example a config orchestration pipeline. Multiple services can subscribe to the same AWS topic.
|
821
|
+
|
822
|
+
Fields sent in the message:
|
823
|
+
|
824
|
+
* `event`: Event type (e.g. `node_success`)
|
825
|
+
* `group`: Group name
|
826
|
+
* `model`: Model name (e.g. `eos`)
|
827
|
+
* `node`: Device hostname
|
828
|
+
|
829
|
+
Configuration example:
|
830
|
+
|
831
|
+
``` yaml
|
832
|
+
hooks:
|
833
|
+
hook_script:
|
834
|
+
type: awssns
|
835
|
+
events: [node_fail,node_success,post_store]
|
836
|
+
region: us-east-1
|
837
|
+
topic_arn: arn:aws:sns:us-east-1:1234567:oxidized-test-backup_events
|
838
|
+
```
|
839
|
+
|
840
|
+
AWS SNS hook requires the following configuration keys:
|
841
|
+
|
842
|
+
* `region`: AWS Region name
|
843
|
+
* `topic_arn`: ASN Topic reference
|
844
|
+
|
845
|
+
Your AWS credentials should be stored in `~/.aws/credentials`.
|
846
|
+
|
794
847
|
# Ruby API
|
795
848
|
|
796
849
|
The following objects exist in Oxidized.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
|
3
|
+
class AwsSns < Oxidized::Hook
|
4
|
+
def validate_cfg!
|
5
|
+
raise KeyError, 'hook.region is required' unless cfg.has_key?('region')
|
6
|
+
raise KeyError, 'hook.topic_arn is required' unless cfg.has_key?('topic_arn')
|
7
|
+
end
|
8
|
+
|
9
|
+
def run_hook(ctx)
|
10
|
+
sns = Aws::SNS::Resource.new(region: cfg.region)
|
11
|
+
topic = sns.topic(cfg.topic_arn)
|
12
|
+
message = {
|
13
|
+
:event => ctx.event.to_s
|
14
|
+
}
|
15
|
+
if ctx.node
|
16
|
+
message.merge!(
|
17
|
+
:group => ctx.node.group.to_s,
|
18
|
+
:model => ctx.node.model.class.name.to_s.downcase,
|
19
|
+
:node => ctx.node.name.to_s
|
20
|
+
)
|
21
|
+
end
|
22
|
+
topic.publish({
|
23
|
+
message: message.to_json
|
24
|
+
})
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
data/lib/oxidized/input/ssh.rb
CHANGED
@@ -17,8 +17,9 @@ module Oxidized
|
|
17
17
|
class NoShell < OxidizedError; end
|
18
18
|
|
19
19
|
def connect node
|
20
|
-
@node
|
21
|
-
@output
|
20
|
+
@node = node
|
21
|
+
@output = ''
|
22
|
+
@pty_options = { term: "vt100" }
|
22
23
|
@node.model.cfg['ssh'].each { |cb| instance_exec(&cb) }
|
23
24
|
secure = Oxidized.config.input.ssh.secure
|
24
25
|
@log = File.open(Oxidized::Config::Log + "/#{@node.ip}-ssh", 'w') if Oxidized.config.input.debug?
|
@@ -32,9 +33,10 @@ module Oxidized
|
|
32
33
|
:paranoid => secure,
|
33
34
|
:auth_methods => %w(none publickey password keyboard-interactive),
|
34
35
|
:number_of_password_prompts => 0,
|
35
|
-
:proxy => proxy
|
36
|
+
:proxy => proxy,
|
36
37
|
}
|
37
|
-
ssh_opts[:
|
38
|
+
ssh_opts[:keys] = vars(:ssh_keys).is_a?(Array) ? vars(:ssh_keys) : [vars(:ssh_keys)] if vars(:ssh_keys)
|
39
|
+
ssh_opts[:kex] = vars(:ssh_kex).split(/,\s*/) if vars(:ssh_kex)
|
38
40
|
ssh_opts[:encryption] = vars(:ssh_encryption).split(/,\s*/) if vars(:ssh_encryption)
|
39
41
|
|
40
42
|
Oxidized.logger.debug "lib/oxidized/input/ssh.rb: Connecting to #{@node.name}"
|
@@ -71,6 +73,10 @@ module Oxidized
|
|
71
73
|
@output
|
72
74
|
end
|
73
75
|
|
76
|
+
def pty_options hash
|
77
|
+
@pty_options = @pty_options.merge hash
|
78
|
+
end
|
79
|
+
|
74
80
|
private
|
75
81
|
|
76
82
|
def disconnect
|
@@ -93,7 +99,7 @@ module Oxidized
|
|
93
99
|
@output << data
|
94
100
|
@output = @node.model.expects @output
|
95
101
|
end
|
96
|
-
ch.request_pty (
|
102
|
+
ch.request_pty (@pty_options) do |_ch, success_pty|
|
97
103
|
raise NoShell, "Can't get PTY" unless success_pty
|
98
104
|
ch.send_channel_request 'shell' do |_ch, success_shell|
|
99
105
|
raise NoShell, "Can't get shell" unless success_shell
|
File without changes
|
data/lib/oxidized/model/aosw.rb
CHANGED
@@ -28,19 +28,21 @@ class AOSW < Oxidized::Model
|
|
28
28
|
|
29
29
|
cmd 'show version' do |cfg|
|
30
30
|
cfg = cfg.each_line.select { |line| not line.match /Switch uptime/i }
|
31
|
-
comment cfg.join
|
31
|
+
rstrip_cfg comment cfg.join
|
32
32
|
end
|
33
33
|
|
34
34
|
cmd 'show inventory' do |cfg|
|
35
|
-
clean cfg
|
35
|
+
rstrip_cfg clean cfg
|
36
36
|
end
|
37
37
|
|
38
38
|
cmd 'show slots' do |cfg|
|
39
|
-
comment cfg
|
39
|
+
rstrip_cfg comment cfg
|
40
40
|
end
|
41
|
+
|
41
42
|
cmd 'show license' do |cfg|
|
42
|
-
comment cfg
|
43
|
+
rstrip_cfg comment cfg
|
43
44
|
end
|
45
|
+
|
44
46
|
cmd 'show running-config' do |cfg|
|
45
47
|
out = []
|
46
48
|
cfg.each_line do |line|
|
@@ -61,7 +63,7 @@ class AOSW < Oxidized::Model
|
|
61
63
|
if vars :enable
|
62
64
|
post_login do
|
63
65
|
send "enable\n"
|
64
|
-
|
66
|
+
cmd vars(:enable)
|
65
67
|
end
|
66
68
|
end
|
67
69
|
post_login 'no paging'
|
@@ -72,6 +74,15 @@ class AOSW < Oxidized::Model
|
|
72
74
|
pre_logout 'exit'
|
73
75
|
end
|
74
76
|
|
77
|
+
def rstrip_cfg cfg
|
78
|
+
out = []
|
79
|
+
cfg.each_line do |line|
|
80
|
+
out << line.rstrip
|
81
|
+
end
|
82
|
+
out = out.join "\n"
|
83
|
+
out << "\n"
|
84
|
+
end
|
85
|
+
|
75
86
|
def clean cfg
|
76
87
|
out = []
|
77
88
|
cfg.each_line do |line|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Casa < Oxidized::Model
|
2
|
+
# Casa Systems CMTS
|
3
|
+
|
4
|
+
prompt /^([\w.@()-]+[#>]\s?)$/
|
5
|
+
comment '! '
|
6
|
+
|
7
|
+
cmd :secret do |cfg|
|
8
|
+
cfg.gsub! /^(snmp community) \S+/, '\\1 <configuration removed>'
|
9
|
+
cfg.gsub! /^(snmp comm-tbl) \S+ \S+/, '\\1 <removed> <removed>'
|
10
|
+
cfg.gsub! /^(console-password encrypted) \S+/, '\\1 <secret hidden>'
|
11
|
+
cfg.gsub! /^(password encrypted) \S+/, '\\1 <secret hidden>'
|
12
|
+
cfg.gsub! /^(tacacs-server key) \S+/, '\\1 <secret hidden>'
|
13
|
+
cfg
|
14
|
+
end
|
15
|
+
|
16
|
+
cmd :all do |cfg|
|
17
|
+
cfg.each_line.to_a[1..-2].join
|
18
|
+
end
|
19
|
+
|
20
|
+
cmd 'show system' do |cfg|
|
21
|
+
comment cfg.each_line.reject { |line| line.match /^\s+System (Time|Uptime): / }.join
|
22
|
+
end
|
23
|
+
|
24
|
+
cmd 'show version' do |cfg|
|
25
|
+
comment cfg
|
26
|
+
end
|
27
|
+
|
28
|
+
cmd 'show run'
|
29
|
+
|
30
|
+
cfg :telnet do
|
31
|
+
username /^Username:/
|
32
|
+
password /^Password:/
|
33
|
+
end
|
34
|
+
|
35
|
+
cfg :telnet, :ssh do
|
36
|
+
post_login 'page-off'
|
37
|
+
# preferred way to handle additional passwords
|
38
|
+
if vars :enable
|
39
|
+
post_login do
|
40
|
+
send "enable\n"
|
41
|
+
cmd vars(:enable)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
pre_logout 'logout'
|
45
|
+
end
|
46
|
+
end
|
@@ -33,14 +33,13 @@ class CiscoSMB < Oxidized::Model
|
|
33
33
|
cfg
|
34
34
|
end
|
35
35
|
|
36
|
-
cfg :telnet do
|
37
|
-
username /^User Name:/
|
38
|
-
password /^\r?Password:$/
|
39
|
-
end
|
40
|
-
|
41
36
|
cfg :telnet, :ssh do
|
37
|
+
username /^User ?[nN]ame:/
|
38
|
+
password /^\r?Password:$/
|
42
39
|
post_login 'terminal datadump' # Disable pager
|
43
40
|
post_login 'terminal width 0'
|
41
|
+
post_login 'terminal len 0'
|
42
|
+
pre_logout 'exit' #exit returns to previous priv level, no way to quit from exec(#)
|
44
43
|
pre_logout 'exit'
|
45
44
|
end
|
46
45
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Dlink < Oxidized::Model
|
2
|
+
# D-LINK Switches
|
3
|
+
|
4
|
+
prompt /^(\r*[\w.@():-]+[#>]\s?)$/
|
5
|
+
comment '# '
|
6
|
+
|
7
|
+
cmd :secret do |cfg|
|
8
|
+
cfg.gsub! /^(create snmp community) \S+/, '\\1 <removed>'
|
9
|
+
cfg.gsub! /^(create snmp group) \S+/, '\\1 <removed>'
|
10
|
+
cfg
|
11
|
+
end
|
12
|
+
|
13
|
+
cmd :all do |cfg|
|
14
|
+
cfg.each_line.to_a[2..-2].map{|line|line.delete("\r").rstrip}.join("\n") + "\n"
|
15
|
+
end
|
16
|
+
|
17
|
+
cmd 'show switch' do |cfg|
|
18
|
+
comment cfg
|
19
|
+
end
|
20
|
+
|
21
|
+
cmd 'show vlan' do |cfg|
|
22
|
+
comment cfg
|
23
|
+
end
|
24
|
+
|
25
|
+
cmd 'show config current'
|
26
|
+
|
27
|
+
cfg :telnet do
|
28
|
+
username /\r*username:/
|
29
|
+
password /\r*password:/
|
30
|
+
end
|
31
|
+
|
32
|
+
cfg :telnet, :ssh do
|
33
|
+
post_login 'disable clipaging'
|
34
|
+
pre_logout 'logout'
|
35
|
+
end
|
36
|
+
end
|
data/lib/oxidized/model/dnos.rb
CHANGED
@@ -33,15 +33,16 @@ class DNOS < Oxidized::Model
|
|
33
33
|
end
|
34
34
|
|
35
35
|
cfg :telnet, :ssh do
|
36
|
-
post_login 'terminal length 0'
|
37
|
-
post_login 'terminal width 0'
|
38
36
|
if vars :enable
|
39
37
|
post_login do
|
40
38
|
send "enable\n"
|
41
|
-
|
39
|
+
cmd vars(:enable)
|
42
40
|
end
|
43
41
|
end
|
42
|
+
post_login 'terminal length 0'
|
43
|
+
post_login 'terminal width 0'
|
44
44
|
pre_logout 'exit'
|
45
|
+
pre_logout 'exit'
|
45
46
|
end
|
46
47
|
|
47
48
|
end
|
data/lib/oxidized/model/eos.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
class FiberDriver < Oxidized::Model
|
2
|
+
prompt /\w+#/
|
3
|
+
comment "! "
|
4
|
+
|
5
|
+
cmd :all do |cfg|
|
6
|
+
cfg.each_line.to_a[1..-2].join
|
7
|
+
end
|
8
|
+
cmd 'show inventory' do |cfg|
|
9
|
+
comment cfg
|
10
|
+
end
|
11
|
+
|
12
|
+
cmd "show running-config" do |cfg|
|
13
|
+
cfg.each_line.to_a[3..-1].join
|
14
|
+
end
|
15
|
+
|
16
|
+
cfg :ssh do
|
17
|
+
post_login 'terminal length 0'
|
18
|
+
post_login 'terminal width 512'
|
19
|
+
pre_logout 'exit'
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class FujitsuPY < Oxidized::Model
|
2
|
+
|
3
|
+
prompt /^(\([\w.-]*\)\s#|^\S+\#\s)$/
|
4
|
+
comment '! '
|
5
|
+
|
6
|
+
cmd :all do |cfg|
|
7
|
+
cfg.each_line.to_a[1..-2].join
|
8
|
+
end
|
9
|
+
|
10
|
+
# 1Gbe switch
|
11
|
+
cmd 'show version' do |cfg|
|
12
|
+
cfg.gsub! /^(<ERROR> : 2 : format error)$/, ''
|
13
|
+
comment cfg
|
14
|
+
end
|
15
|
+
|
16
|
+
# 10Gbe switch
|
17
|
+
cmd 'show system information' do |cfg|
|
18
|
+
cfg.gsub! /^Current-time : [\w\s:]*$/, ''
|
19
|
+
cfg.gsub! /^(\s{33}\^)$/, ''
|
20
|
+
cfg.gsub! /^(\% Invalid input detected at '\^' marker.)$/, ''
|
21
|
+
comment cfg
|
22
|
+
end
|
23
|
+
|
24
|
+
cmd 'show running-config' do |cfg|
|
25
|
+
cfg
|
26
|
+
end
|
27
|
+
|
28
|
+
cfg :telnet do
|
29
|
+
username /^Username:/
|
30
|
+
password /^Password:/
|
31
|
+
end
|
32
|
+
|
33
|
+
cfg :telnet, :ssh do
|
34
|
+
post_login 'no pager'
|
35
|
+
post_login 'terminal pager disable'
|
36
|
+
pre_logout do
|
37
|
+
send "quit\n"
|
38
|
+
send "n\n"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class Hatteras < Oxidized::Model
|
2
|
+
# Hatteras Networks
|
3
|
+
|
4
|
+
prompt /^(\r?[\w.@()-]+[#>]\s?)$/
|
5
|
+
comment '# '
|
6
|
+
|
7
|
+
expect /WARNING: System configuration changes will be lost when the device restarts./ do |data, re|
|
8
|
+
send "y\r"
|
9
|
+
data.sub re, ''
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
cmd :secret do |cfg|
|
14
|
+
cfg.gsub! /^(community) \S+/, '\\1 "<configuration removed>"'
|
15
|
+
cfg.gsub! /^(communityString) "\S+"/, '\\1 "<configuration removed>"'
|
16
|
+
cfg.gsub! /^(key) "\S+"/, '\\1 "<secret hidden>"'
|
17
|
+
cfg
|
18
|
+
end
|
19
|
+
|
20
|
+
cmd :all do |cfg|
|
21
|
+
cfg.each_line.to_a[1..-2].join
|
22
|
+
end
|
23
|
+
|
24
|
+
cmd "show switch\r" do |cfg|
|
25
|
+
cfg = cfg.each_line.reject { |line| line.match /Switch uptime|Switch temperature|Last reset reason/ or
|
26
|
+
line.match /TermCpuUtil|^\s+\^$|ERROR: Bad command/ }.join
|
27
|
+
comment cfg
|
28
|
+
end
|
29
|
+
|
30
|
+
cmd "show card\r" do |cfg|
|
31
|
+
cfg = cfg.each_line.reject { |line| line.match /Card uptime|Card temperature|Last reset reason/ or
|
32
|
+
line.match /TermCpuUtil|^\s+\^$|ERROR: Bad command/ }.join
|
33
|
+
comment cfg
|
34
|
+
end
|
35
|
+
|
36
|
+
cmd "show sfp *\r" do |cfg|
|
37
|
+
comment cfg
|
38
|
+
end
|
39
|
+
|
40
|
+
cmd "show config run\r" do |cfg|
|
41
|
+
cfg
|
42
|
+
end
|
43
|
+
|
44
|
+
cfg :telnet do
|
45
|
+
username /^Login:/
|
46
|
+
password /^Password:/
|
47
|
+
end
|
48
|
+
|
49
|
+
cfg :telnet, :ssh do
|
50
|
+
pre_logout "logout\r"
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
class HPEBladeSystem < Oxidized::Model
|
2
|
+
# HPE Onboard Administrator
|
3
|
+
|
4
|
+
prompt /.*> /
|
5
|
+
comment '# '
|
6
|
+
|
7
|
+
expect /^\s*--More--\s+.*$/ do |data, re|
|
8
|
+
send ' '
|
9
|
+
data.sub re, ''
|
10
|
+
end
|
11
|
+
|
12
|
+
cmd :all do |cfg|
|
13
|
+
cfg = cfg.delete("\r").each_line.to_a[0..-1].map{|line|line.rstrip}.join("\n") + "\n"
|
14
|
+
cfg.each_line.to_a[0..-2].join
|
15
|
+
end
|
16
|
+
|
17
|
+
cmd :secret do |cfg|
|
18
|
+
cfg.gsub! /^(SET SNMP COMMUNITY (READ|WRITE)).*/, '\\1 <configuration removed>'
|
19
|
+
cfg
|
20
|
+
end
|
21
|
+
|
22
|
+
cmd 'show oa info' do |cfg|
|
23
|
+
comment cfg
|
24
|
+
end
|
25
|
+
|
26
|
+
cmd 'show oa network' do |cfg|
|
27
|
+
comment cfg
|
28
|
+
end
|
29
|
+
|
30
|
+
cmd 'show oa certificate' do |cfg|
|
31
|
+
comment cfg
|
32
|
+
end
|
33
|
+
|
34
|
+
cmd 'show sshfingerprint' do |cfg|
|
35
|
+
comment cfg
|
36
|
+
end
|
37
|
+
|
38
|
+
cmd 'show fru' do |cfg|
|
39
|
+
comment cfg
|
40
|
+
end
|
41
|
+
|
42
|
+
cmd 'show network' do |cfg|
|
43
|
+
comment cfg
|
44
|
+
end
|
45
|
+
|
46
|
+
cmd 'show vlan' do |cfg|
|
47
|
+
comment cfg
|
48
|
+
end
|
49
|
+
|
50
|
+
cmd 'show rack name' do |cfg|
|
51
|
+
comment cfg
|
52
|
+
end
|
53
|
+
|
54
|
+
cmd 'show server list' do |cfg|
|
55
|
+
comment cfg
|
56
|
+
end
|
57
|
+
|
58
|
+
cmd 'show server names' do |cfg|
|
59
|
+
comment cfg
|
60
|
+
end
|
61
|
+
|
62
|
+
cmd 'show server port map all' do |cfg|
|
63
|
+
comment cfg
|
64
|
+
end
|
65
|
+
|
66
|
+
cmd 'show server info all' do |cfg|
|
67
|
+
comment cfg
|
68
|
+
end
|
69
|
+
|
70
|
+
cmd 'show config' do |cfg|
|
71
|
+
cfg.gsub! /^#(Generated on:) .*$/, '\\1 <removed>'
|
72
|
+
cfg.gsub /^\s+/, ''
|
73
|
+
end
|
74
|
+
|
75
|
+
cfg :telnet do
|
76
|
+
username /\slogin:/
|
77
|
+
password /^Password: /
|
78
|
+
end
|
79
|
+
|
80
|
+
cfg :telnet, :ssh do
|
81
|
+
pre_logout "exit"
|
82
|
+
end
|
83
|
+
end
|
@@ -7,7 +7,8 @@ class PfSense < Oxidized::Model
|
|
7
7
|
end
|
8
8
|
|
9
9
|
cmd 'cat /cf/conf/config.xml' do |cfg|
|
10
|
-
cfg.gsub! /\s<revision>\s*<time>\d*<\/time>\s*.*\s
|
10
|
+
cfg.gsub! /\s<revision>\s*.*\s*<time>\d*<\/time>\s*.*\s*<\/revision>/, ''
|
11
|
+
cfg
|
11
12
|
end
|
12
13
|
|
13
14
|
cfg :ssh do
|
@@ -0,0 +1,83 @@
|
|
1
|
+
class Planet < Oxidized::Model
|
2
|
+
|
3
|
+
prompt /^\r?([\w.@()-]+[#>]\s?)$/
|
4
|
+
comment '! '
|
5
|
+
|
6
|
+
# example how to handle pager
|
7
|
+
#expect /^\s--More--\s+.*$/ do |data, re|
|
8
|
+
# send ' '
|
9
|
+
# data.sub re, ''
|
10
|
+
#end
|
11
|
+
|
12
|
+
# non-preferred way to handle additional PW prompt
|
13
|
+
#expect /^[\w.]+>$/ do |data|
|
14
|
+
# send "enable\n"
|
15
|
+
# send vars(:enable) + "\n"
|
16
|
+
# data
|
17
|
+
#end
|
18
|
+
|
19
|
+
cmd :all do |cfg|
|
20
|
+
#cfg.gsub! /\cH+\s{8}/, '' # example how to handle pager
|
21
|
+
#cfg.gsub! /\cH+/, '' # example how to handle pager
|
22
|
+
cfg.each_line.to_a[1..-2].join
|
23
|
+
end
|
24
|
+
|
25
|
+
cmd :secret do |cfg|
|
26
|
+
cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
|
27
|
+
cfg.gsub! /username (\S+) privilege (\d+) (\S+).*/, '<secret hidden>'
|
28
|
+
cfg.gsub! /^username \S+ password \d \S+/, '<secret hidden>'
|
29
|
+
cfg.gsub! /^enable password \d \S+/, '<secret hidden>'
|
30
|
+
cfg.gsub! /wpa-psk ascii \d \S+/, '<secret hidden>'
|
31
|
+
cfg.gsub! /^tacacs-server key \d \S+/, '<secret hidden>'
|
32
|
+
cfg
|
33
|
+
end
|
34
|
+
|
35
|
+
cmd 'show version' do |cfg|
|
36
|
+
cfg.gsub! "\n\r", "\n"
|
37
|
+
@planetgs = true if cfg.match /^System Name\w*:\w*GS-.*$/
|
38
|
+
@planetsgs = true if cfg.match /SGS-(.*) Device, Compiled on .*$/
|
39
|
+
|
40
|
+
cfg = cfg.each_line.to_a[0...-2]
|
41
|
+
|
42
|
+
# Strip system time and system uptime from planet gs switches
|
43
|
+
cfg = cfg.reject { |line| line.match /System Time\s*:.*/ }
|
44
|
+
cfg = cfg.reject { |line| line.match /System Uptime\s*:.*/ }
|
45
|
+
|
46
|
+
comment cfg.join
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
cmd 'show running-config' do |cfg|
|
51
|
+
cfg.gsub! "\n\r", "\n"
|
52
|
+
cfg = cfg.each_line.to_a
|
53
|
+
|
54
|
+
cfg = cfg.reject { |line| line.match "Building configuration..." }
|
55
|
+
|
56
|
+
if @planetsgs
|
57
|
+
cfg << cmd('show transceiver detail | include transceiver detail information|found|Type|length|Nominal|wavelength|Base information') do |cfg|
|
58
|
+
comment cfg
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
cfg.join
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
cfg :telnet do
|
67
|
+
username /^Username:/
|
68
|
+
password /^Password:/
|
69
|
+
end
|
70
|
+
|
71
|
+
cfg :telnet, :ssh do
|
72
|
+
post_login 'terminal length 0'
|
73
|
+
# preferred way to handle additional passwords
|
74
|
+
if vars :enable
|
75
|
+
post_login do
|
76
|
+
send "enable\n"
|
77
|
+
cmd vars(:enable)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
pre_logout 'exit'
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class Trango < Oxidized::Model
|
2
|
+
# take a Trangolink sysinfo output and turn it into a configuration file
|
3
|
+
|
4
|
+
prompt /^#>\s?/
|
5
|
+
comment '# '
|
6
|
+
|
7
|
+
cmd 'sysinfo' do |cfg|
|
8
|
+
out = []
|
9
|
+
comments = []
|
10
|
+
cfg.each_line do |line|
|
11
|
+
if line.match /\[Opmode\] (off|on) \[Default Opmode\] (off|on)/
|
12
|
+
out << "opmode " + Regexp.last_match[1]
|
13
|
+
out << "defaultopmode " + Regexp.last_match[2]
|
14
|
+
end
|
15
|
+
if line.match /\[Tx Power\] ([\-\d]+) dBm/
|
16
|
+
out << "power " + Regexp.last_match[1]
|
17
|
+
end
|
18
|
+
if line.match /\[Active Channel\] (\d+) (v|h)/
|
19
|
+
out << "freq " + Regexp.last_match[1] + ' ' + Regexp.last_match[2]
|
20
|
+
end
|
21
|
+
if line.match /\[Peer ID\] ([A-F0-9]+)/
|
22
|
+
out << "peerid " + Regexp.last_match[1]
|
23
|
+
end
|
24
|
+
if line.match /\[Unit Type\] (\S+)/
|
25
|
+
out << "utype " + Regexp.last_match[1]
|
26
|
+
end
|
27
|
+
if line.match /\[(Hardware Version|Firmware Version|Model|S\/N)\] (\S+)/
|
28
|
+
comments << '# ' + Regexp.last_match[1] + ': ' + Regexp.last_match[2]
|
29
|
+
end
|
30
|
+
if line.match /\[Remarks\] (\S+)/
|
31
|
+
out << "remarks " + Regexp.last_match[1]
|
32
|
+
end
|
33
|
+
if line.match /\[RSSI LED\] (on|off)/
|
34
|
+
out << "rssiled " + Regexp.last_match[1]
|
35
|
+
end
|
36
|
+
if line.match /\[Speed\] (\d+) Mbps/
|
37
|
+
speed = Regexp.last_match[1]
|
38
|
+
end
|
39
|
+
if line.match /\[Tx MIR\] (\d+) Kbps/
|
40
|
+
out << "mir ".concat(Regexp.last_match[1])
|
41
|
+
end
|
42
|
+
if line.match /\[Auto Rate Shift\] (on|off)/
|
43
|
+
out << "autorateshift ".concat(Regexp.last_match[1])
|
44
|
+
if Regexp.last_match[1].eql? 'off'
|
45
|
+
out << "speed $speed"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
if line.match /\[IP\] (\S+) \[Subnet Mask\] (\S+) \[Gateway\] (\S+)/
|
49
|
+
out << "ipconfig " + Regexp.last_match[1] + ' ' +
|
50
|
+
Regexp.last_match[2] + ' ' +
|
51
|
+
Regexp.last_match[3]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
comments.push(*out).join "\n"
|
55
|
+
end
|
56
|
+
|
57
|
+
cfg :telnet do
|
58
|
+
password /Password:/
|
59
|
+
pre_logout 'exit'
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
data/lib/oxidized/node.rb
CHANGED
@@ -130,8 +130,8 @@ module Oxidized
|
|
130
130
|
def resolve_auth opt
|
131
131
|
# Resolve configured username/password
|
132
132
|
{
|
133
|
-
username:
|
134
|
-
password:
|
133
|
+
username: resolve_key(:username, opt),
|
134
|
+
password: resolve_key(:password, opt),
|
135
135
|
}
|
136
136
|
end
|
137
137
|
|
data/lib/oxidized/output/file.rb
CHANGED
@@ -28,20 +28,22 @@ class OxidizedFile < Output
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def fetch node, group
|
31
|
-
cfg_dir
|
31
|
+
cfg_dir = File.expand_path @cfg.directory
|
32
32
|
node_name = node.name
|
33
33
|
|
34
34
|
if group # group is explicitly defined by user
|
35
|
-
|
35
|
+
cfg_dir = File.join File.dirname(cfg_dir), group
|
36
|
+
File.read File.join(cfg_dir, node_name)
|
36
37
|
else
|
37
38
|
if File.exists? File.join(cfg_dir, node_name) # node configuration file is stored on base directory
|
38
|
-
|
39
|
+
File.read File.join(cfg_dir, node_name)
|
39
40
|
else
|
40
|
-
path = Dir.glob
|
41
|
-
|
42
|
-
open(path[0], 'r').readlines
|
41
|
+
path = Dir.glob(File.join(File.dirname(cfg_dir), '**', node_name)).first # fetch node in all groups
|
42
|
+
File.read path
|
43
43
|
end
|
44
44
|
end
|
45
|
+
rescue Errno::ENOENT
|
46
|
+
return nil
|
45
47
|
end
|
46
48
|
|
47
49
|
def version node, group
|
data/lib/oxidized/source/http.rb
CHANGED
data/lib/oxidized/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oxidized
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Saku Ytti
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-
|
13
|
+
date: 2016-12-12 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: asetus
|
@@ -168,6 +168,7 @@ executables:
|
|
168
168
|
extensions: []
|
169
169
|
extra_rdoc_files: []
|
170
170
|
files:
|
171
|
+
- ".gitignore"
|
171
172
|
- ".ruby-version"
|
172
173
|
- ".travis.yml"
|
173
174
|
- CHANGELOG.md
|
@@ -199,6 +200,7 @@ files:
|
|
199
200
|
- lib/oxidized/config/vars.rb
|
200
201
|
- lib/oxidized/core.rb
|
201
202
|
- lib/oxidized/hook.rb
|
203
|
+
- lib/oxidized/hook/awssns.rb
|
202
204
|
- lib/oxidized/hook/exec.rb
|
203
205
|
- lib/oxidized/hook/githubrepo.rb
|
204
206
|
- lib/oxidized/hook/noophook.rb
|
@@ -214,7 +216,7 @@ files:
|
|
214
216
|
- lib/oxidized/model/acos.rb
|
215
217
|
- lib/oxidized/model/aireos.rb
|
216
218
|
- lib/oxidized/model/airos.rb
|
217
|
-
- lib/oxidized/model/alvarion
|
219
|
+
- lib/oxidized/model/alvarion.rb
|
218
220
|
- lib/oxidized/model/aos.rb
|
219
221
|
- lib/oxidized/model/aos7.rb
|
220
222
|
- lib/oxidized/model/aosw.rb
|
@@ -222,6 +224,7 @@ files:
|
|
222
224
|
- lib/oxidized/model/asa.rb
|
223
225
|
- lib/oxidized/model/br6910.rb
|
224
226
|
- lib/oxidized/model/c4cmts.rb
|
227
|
+
- lib/oxidized/model/casa.rb
|
225
228
|
- lib/oxidized/model/catos.rb
|
226
229
|
- lib/oxidized/model/ciscosmb.rb
|
227
230
|
- lib/oxidized/model/comware.rb
|
@@ -229,15 +232,20 @@ files:
|
|
229
232
|
- lib/oxidized/model/corianttmos.rb
|
230
233
|
- lib/oxidized/model/cumulus.rb
|
231
234
|
- lib/oxidized/model/datacom.rb
|
235
|
+
- lib/oxidized/model/dlink.rb
|
232
236
|
- lib/oxidized/model/dnos.rb
|
233
237
|
- lib/oxidized/model/edgeos.rb
|
234
238
|
- lib/oxidized/model/edgeswitch.rb
|
235
239
|
- lib/oxidized/model/eos.rb
|
236
240
|
- lib/oxidized/model/fabricos.rb
|
241
|
+
- lib/oxidized/model/fiberdriver.rb
|
237
242
|
- lib/oxidized/model/firewareos.rb
|
238
243
|
- lib/oxidized/model/fortios.rb
|
239
244
|
- lib/oxidized/model/ftos.rb
|
245
|
+
- lib/oxidized/model/fujitsupy.rb
|
240
246
|
- lib/oxidized/model/gaiaos.rb
|
247
|
+
- lib/oxidized/model/hatteras.rb
|
248
|
+
- lib/oxidized/model/hpebladesystem.rb
|
241
249
|
- lib/oxidized/model/ios.rb
|
242
250
|
- lib/oxidized/model/iosxr.rb
|
243
251
|
- lib/oxidized/model/ipos.rb
|
@@ -256,6 +264,7 @@ files:
|
|
256
264
|
- lib/oxidized/model/outputs.rb
|
257
265
|
- lib/oxidized/model/panos.rb
|
258
266
|
- lib/oxidized/model/pfsense.rb
|
267
|
+
- lib/oxidized/model/planet.rb
|
259
268
|
- lib/oxidized/model/powerconnect.rb
|
260
269
|
- lib/oxidized/model/procurve.rb
|
261
270
|
- lib/oxidized/model/quantaos.rb
|
@@ -265,6 +274,7 @@ files:
|
|
265
274
|
- lib/oxidized/model/supermicro.rb
|
266
275
|
- lib/oxidized/model/timos.rb
|
267
276
|
- lib/oxidized/model/tmos.rb
|
277
|
+
- lib/oxidized/model/trango.rb
|
268
278
|
- lib/oxidized/model/vrp.rb
|
269
279
|
- lib/oxidized/model/vyatta.rb
|
270
280
|
- lib/oxidized/model/xos.rb
|
@@ -304,7 +314,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
304
314
|
version: '0'
|
305
315
|
requirements: []
|
306
316
|
rubyforge_project: oxidized
|
307
|
-
rubygems_version: 2.5.
|
317
|
+
rubygems_version: 2.5.2
|
308
318
|
signing_key:
|
309
319
|
specification_version: 4
|
310
320
|
summary: feeble attempt at rancid
|