oxidized 0.12.2 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6abed81dacfe3d68bc4abd336da9ba97b39f47a7
4
+ data.tar.gz: 5110c826165ef2d14c19369e0c6662fde52c7bd6
5
+ SHA512:
6
+ metadata.gz: 96c4383cfa03d6ef2def511de0b23c2b28c4d275caa3f16f1c9e2b926514245ad8bdf945a0726892152fcda4a04454b43ec7cab6d0f10cb474dc6a4974767839
7
+ data.tar.gz: f6292b48c50e0d74d971df1345c7d391ef44b9a003eb429482f90e113f59633b2cf30b3227e8b8a372b1ff8203a169b49963f5bec75bb0f00d6f2f8a73de081a
data/.travis.yml CHANGED
@@ -1,3 +1,5 @@
1
1
  language: ruby
2
+ sudo: false
3
+ cache: bundler
2
4
  rvm:
3
5
  - 2.1.6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ # 0.13.0
2
+ - FEATURE: http post for configs (by @jgroom33)
3
+ - FEATURE: support ericsson redbacks (by @roedie)
4
+ - FEATURE: support motorola wireless controllers (by @roadie)
5
+ - FEATURE: support citrix netscaler (by @roadie)
6
+ - FEATURE: support datacom devices (by @danilopopeye)
7
+ - FEATURE: support netonix devices
8
+ - FEATURE: support specifying ssh cipher and kex (by @roadie)
9
+ - FEATURE: rename proxy to ssh_proxy (by @roadie)
10
+ - FEATURE: support ssh keys on ssh_proxy (by @awix)
11
+ - BUGFIX: various (by @danilopopeye)
12
+ - BUGFIX: Node#repo with groups (by @danilopopeye)
13
+ - BUGFIX: githubrepohoook (by @danilopopeye)
14
+ - BUGFIX: fortios, airos, junos, xos, edgeswitch, nos, tmos, procurve, ipos models
15
+
1
16
  # 0.12.2
2
17
  - BUGFIX: more MRV model fixes (by @natm)
3
18
 
@@ -12,7 +27,7 @@
12
27
  - FEATURE: EdgeSwitch support (by @doogieconsulting)
13
28
  - BUGFIX: rename input debug log files
14
29
  - BUGFIX: powerconnect model fixes (by @Madpilot0)
15
- - BUGFIX: fortigate model fixes (by @ElvinEfendi)
30
+ - BUGFIX: fortigate model fixes (by @ElvinEfendi)
16
31
  - BUGFIX: various (by @mikebryant)
17
32
  - BUGFIX: write SSH debug to file without buffering
18
33
  - BUGFIX: fix IOS XR prompt handling
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- oxidized (0.11.0)
4
+ oxidized (0.12.2)
5
5
  asetus (~> 0.1)
6
6
  net-ssh (~> 3.0, >= 3.0.2)
7
7
  rugged (~> 0.21, >= 0.21.4)
data/README.md CHANGED
@@ -31,6 +31,7 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen
31
31
  * [Source: SQLite](#source-sqlite)
32
32
  * [Source: HTTP](#source-http)
33
33
  * [Output: GIT](#output-git)
34
+ * [Output: HTTP](#output-http)
34
35
  * [Output: File](#output-file)
35
36
  * [Output types](#output-types)
36
37
  * [Advanced Configuration](#advanced-configuration)
@@ -70,13 +71,20 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen
70
71
  * IOSXR
71
72
  * NXOS
72
73
  * SMB (Nikola series)
74
+ * Citrix
75
+ * NetScaler (Virtual Applicance)
73
76
  * Cumulus
74
77
  * Linux
78
+ * DataCom
79
+ * DmSwitch 3000
75
80
  * DELL
76
81
  * PowerConnect
77
82
  * AOSW
83
+ * Ericsson/Redback
84
+ * IPOS (former SEOS)
78
85
  * Extreme Networks
79
86
  * XOS
87
+ * WM
80
88
  * F5
81
89
  * TMOS
82
90
  * Force10
@@ -94,8 +102,12 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen
94
102
  * ScreenOS (Netscreen)
95
103
  * Mikrotik
96
104
  * RouterOS
105
+ * Motorola
106
+ * RFS
97
107
  * MRV
98
108
  * MasterOS
109
+ * Netonix
110
+ * WISP Switch (As Netonix)
99
111
  * Opengear
100
112
  * Opengear
101
113
  * Palo Alto
@@ -121,7 +133,7 @@ gem install oxidized-script oxidized-web # if you don't install oxidized-web, ma
121
133
  ## CentOS, Oracle Linux, Red Hat Linux version 6
122
134
  Install Ruby 1.9.3 or greater (for Ruby 2.1.2 installation instructions see "Installing Ruby 2.1.2 using RVM"), then install Oxidized dependencies
123
135
  ```shell
124
- yum install cmake sqlite-devel openssl-devel
136
+ yum install cmake sqlite-devel openssl-devel libssh2-devel
125
137
  ```
126
138
 
127
139
  Now lets install oxidized via Rubygems:
@@ -136,6 +148,21 @@ Oxidized configuration is in YAML format. Configuration files are subsequently s
136
148
 
137
149
  To initialize a default configuration in your home directory ```~/.config/oxidized/config```, simply run ```oxidized``` once. If you don't further configure anything from the output and source sections, it'll extend the examples on a subsequent ```oxidized``` execution. This is useful to see what options for a specific source or output backend are available.
138
150
 
151
+ You can set the env variable `OXIDIZED_HOME` to change its home directory.
152
+
153
+ ```
154
+ OXIDIZED_HOME=/etc/oxidized
155
+
156
+ $ tree -L 1 /etc/oxidized
157
+ /etc/oxidized/
158
+ ├── config
159
+ ├── log-router-ssh
160
+ ├── log-router-telnet
161
+ ├── pid
162
+ ├── router.db
163
+ └── repository.git
164
+ ```
165
+
139
166
  ## Source
140
167
 
141
168
  Oxidized supports ```CSV```, ```SQLite``` and ```HTTP``` as source backends. The CSV backend reads nodes from a rancid compatible router.db file. The SQLite backend will fire queries against a database and map certain fields to model items. The HTTP backend will fire queries against a http/https url. Take a look at the [Cookbook](#cookbook) for more details.
@@ -181,7 +208,7 @@ Install Ruby 2.1.2 build dependencies
181
208
  ```
182
209
  yum install curl gcc-c++ patch readline readline-devel zlib zlib-devel
183
210
  yum install libyaml-devel libffi-devel openssl-devel make cmake
184
- yum install bzip2 autoconf automake libtool bison iconv-devel
211
+ yum install bzip2 autoconf automake libtool bison iconv-devel libssh2-devel
185
212
  ```
186
213
 
187
214
  Install RVM
@@ -283,7 +310,7 @@ source:
283
310
 
284
311
  ### SSH Proxy Command
285
312
 
286
- Oxidized can `ssh` through a proxy as well. To do so we just need to set `proxy` variable.
313
+ Oxidized can `ssh` through a proxy as well. To do so we just need to set `ssh_proxy` variable.
287
314
 
288
315
  ```
289
316
  ...
@@ -292,7 +319,7 @@ map:
292
319
  model: 1
293
320
  vars_map:
294
321
  enable: 2
295
- proxy: 3
322
+ ssh_proxy: 3
296
323
  ...
297
324
  ```
298
325
 
@@ -354,13 +381,53 @@ output:
354
381
 
355
382
  This uses the rugged/libgit2 interface. So you should remember that normal Git hooks will not be executed.
356
383
 
384
+
385
+ For a single repositories for all devices:
386
+
387
+ ``` yaml
388
+ output:
389
+ default: git
390
+ git:
391
+ user: Oxidized
392
+ email: o@example.com
393
+ repo: "/var/lib/oxidized/devices.git"
357
394
  ```
395
+
396
+ And for groups repositories:
397
+
398
+ ``` yaml
358
399
  output:
359
400
  default: git
360
401
  git:
361
402
  user: Oxidized
362
403
  email: o@example.com
404
+ repo:
405
+ first: "/var/lib/oxidized/first.git"
406
+ second: "/var/lib/oxidized/second.git"
407
+ ```
408
+
409
+ If you would like to use groups and a single repository, you can force this with the `single_repo` config.
410
+
411
+ ``` yaml
412
+ output:
413
+ default: git
414
+ git:
415
+ single_repo: true
363
416
  repo: "/var/lib/oxidized/devices.git"
417
+
418
+ ```
419
+
420
+ ### Output: Http
421
+
422
+ POST a config to the specified URL
423
+
424
+ ```
425
+ output:
426
+ default: http
427
+ http:
428
+ user: admin
429
+ password: changeit
430
+ url: "http://192.168.162.50:8080/db/coll"
364
431
  ```
365
432
 
366
433
  ### Output types
@@ -525,6 +592,42 @@ hooks:
525
592
  timeout: 120
526
593
  ```
527
594
 
595
+ ### githubrepo
596
+
597
+ This hook configures the repository `remote` and _push_ the code when the specified event is triggerd. If the `username` and `password` are not provided, the `Rugged::Credentials::SshKeyFromAgent` will be used.
598
+
599
+ `githubrepo` hook recognizes following configuration keys:
600
+
601
+ * `remote_repo`: the remote repository to be pushed to.
602
+ * `username`: username for repository auth.
603
+ * `password`: password for repository auth.
604
+ * `publickey`: publickey for repository auth.
605
+ * `privatekey`: privatekey for repository auth.
606
+
607
+ When using groups repositories, each group must have its own `remote` in the `remote_repo` config.
608
+
609
+ ``` yaml
610
+ hooks:
611
+ push_to_remote:
612
+ remote_repo:
613
+ routers: git@git.intranet:oxidized/routers.git
614
+ switches: git@git.intranet:oxidized/switches.git
615
+ firewalls: git@git.intranet:oxidized/firewalls.git
616
+ ```
617
+
618
+
619
+ ## Hook configuration example
620
+
621
+ ``` yaml
622
+ hooks:
623
+ push_to_remote:
624
+ type: githubrepo
625
+ events: [post_store]
626
+ remote_repo: git@git.intranet:oxidized/test.git
627
+ username: user
628
+ password: pass
629
+ ```
630
+
528
631
  # Ruby API
529
632
 
530
633
  The following objects exist in Oxidized.
@@ -0,0 +1,87 @@
1
+ #!/bin/sh
2
+ # chkconfig: - 99 01
3
+ # description: Oxidized - Network Device Configuration Backup Tool
4
+ # processname: /opt/ruby-2.1/bin/oxidized
5
+
6
+ # Source function library
7
+ . /etc/rc.d/init.d/functions
8
+
9
+ name="oxidized"
10
+ desc="Oxidized"
11
+ cmd=oxidized
12
+ args="--daemonize"
13
+ lockfile=/var/lock/subsys/$name
14
+ pidfile=/etc/oxidized/pid
15
+
16
+ export OXIDIZED_HOME=/etc/oxidized
17
+
18
+ # Source sysconfig configuration
19
+ [ -r /etc/sysconfig/$name ] && . /etc/sysconfig/$name
20
+
21
+ start() {
22
+ echo -n $"Starting $desc: "
23
+ daemon ${cmd} ${args}
24
+ retval=$?
25
+ if [ $retval = 0 ]
26
+ then
27
+ echo_success
28
+ touch $lockfile
29
+ else
30
+ echo_failure
31
+ fi
32
+ echo
33
+ return $retval
34
+ }
35
+
36
+ stop() {
37
+ echo -n $"Stopping $desc: "
38
+ killproc -p $pidfile
39
+ retval=$?
40
+ [ $retval -eq 0 ] && rm -f $lockfile
41
+ rm -f $pidfile
42
+ echo
43
+ return $retval
44
+ }
45
+
46
+ restart() {
47
+ stop
48
+ start
49
+ }
50
+
51
+ reload() {
52
+ echo -n $"Reloading config..."
53
+ curl -s http://localhost:8888/reload?format=json -O /dev/null
54
+ echo
55
+ }
56
+
57
+ rh_status() {
58
+ status -p $pidfile $cmd
59
+ }
60
+
61
+ rh_status_q() {
62
+ rh_status >/dev/null 2>&1
63
+ }
64
+
65
+ case "$1" in
66
+ start)
67
+ rh_status_q && exit 0
68
+ $1
69
+ ;;
70
+ stop)
71
+ rh_status_q || exit 0
72
+ $1
73
+ ;;
74
+ restart)
75
+ $1
76
+ ;;
77
+ reload)
78
+ rh_status_q || exit 0
79
+ $1
80
+ ;;
81
+ status)
82
+ rh_status
83
+ ;;
84
+ *)
85
+ echo $"Usage: $0 {start|stop|restart|reload|status}"
86
+ exit 2
87
+ esac
data/lib/oxidized.rb CHANGED
@@ -3,6 +3,7 @@ module Oxidized
3
3
 
4
4
  Directory = File.expand_path(File.join(File.dirname(__FILE__), '../'))
5
5
 
6
+ require 'oxidized/version'
6
7
  require 'oxidized/string'
7
8
  require 'oxidized/config'
8
9
  require 'oxidized/config/vars'
data/lib/oxidized/cli.rb CHANGED
@@ -43,6 +43,10 @@ module Oxidized
43
43
  opts = Slop.new(:help=>true) do
44
44
  on 'd', 'debug', 'turn on debugging'
45
45
  on 'daemonize', 'Daemonize/fork the process'
46
+ on 'v', 'version', 'show version' do
47
+ puts Oxidized::VERSION
48
+ Kernel.exit
49
+ end
46
50
  end
47
51
  [opts.parse!, opts]
48
52
  end
@@ -3,7 +3,7 @@ module Oxidized
3
3
  class NoConfig < OxidizedError; end
4
4
  class InvalidConfig < OxidizedError; end
5
5
  class Config
6
- Root = File.join ENV['HOME'], '.config', 'oxidized'
6
+ Root = ENV['OXIDIZED_HOME'] || File.join(ENV['HOME'], '.config', 'oxidized')
7
7
  Crash = File.join Root, 'crash'
8
8
  Log = File.join Root, 'log'
9
9
  InputDir = File.join Directory, %w(lib oxidized input)
@@ -27,7 +27,7 @@ module Oxidized
27
27
  asetus.default.timeout = 20
28
28
  asetus.default.retries = 3
29
29
  asetus.default.prompt = /^([\w.@-]+[#>]\s?)$/
30
- asetus.default.rest = '127.0.0.1:8888' # or false to disable
30
+ asetus.default.rest = '127.0.0.1:8888' # or false to disable
31
31
  asetus.default.vars = {} # could be 'enable'=>'enablePW'
32
32
  asetus.default.groups = {} # group level configuration
33
33
 
@@ -1,12 +1,12 @@
1
1
  class GithubRepo < Oxidized::Hook
2
2
  def validate_cfg!
3
- cfg.has_key?('remote_repo') or raise KeyError, 'remote_repo is required'
3
+ raise KeyError, 'hook.remote_repo is required' unless cfg.has_key?('remote_repo')
4
4
  end
5
5
 
6
6
  def run_hook(ctx)
7
- repo = Rugged::Repository.new(Oxidized.config.output.git.repo)
7
+ repo = Rugged::Repository.new(ctx.node.repo)
8
8
  log "Pushing local repository(#{repo.path})..."
9
- remote = repo.remotes['origin'] || repo.remotes.create('origin', cfg.remote_repo)
9
+ remote = repo.remotes['origin'] || repo.remotes.create('origin', remote_repo(ctx.node))
10
10
  log "to remote: #{remote.url}"
11
11
 
12
12
  fetch_and_merge_remote(repo)
@@ -49,9 +49,21 @@ class GithubRepo < Oxidized::Hook
49
49
  log "Using https auth", :debug
50
50
  Rugged::Credentials::UserPassword.new(username: cfg.username, password: cfg.password)
51
51
  else
52
- log "Using ssh auth", :debug
53
- Rugged::Credentials::SshKeyFromAgent.new(username: 'git')
52
+ if cfg.has_key?('publickey') && cfg.has_key?('privatekey')
53
+ log "Using ssh auth with key", :debug
54
+ Rugged::Credentials::SshKey.new(username: 'git', publickey: File.expand_path(cfg.publickey), privatekey: File.expand_path(cfg.privatekey))
55
+ else
56
+ log "Using ssh auth with agentforwarding", :debug
57
+ Rugged::Credentials::SshKeyFromAgent.new(username: 'git')
58
+ end
54
59
  end
55
60
  end
56
61
 
62
+ def remote_repo(node)
63
+ if node.group.nil? || cfg.remote_repo.is_a?(String)
64
+ cfg.remote_repo
65
+ else
66
+ cfg.remote_repo[node.group]
67
+ end
68
+ end
57
69
  end
@@ -23,15 +23,21 @@ module Oxidized
23
23
  secure = Oxidized.config.input.ssh.secure
24
24
  @log = File.open(Oxidized::Config::Log + "-#{@node.ip}-ssh", 'w') if Oxidized.config.input.debug?
25
25
  port = vars(:ssh_port) || 22
26
- if proxy_host = vars(:proxy)
27
- proxy = Net::SSH::Proxy::Command.new("ssh #{proxy_host} nc %h %p")
26
+ if proxy_host = vars(:ssh_proxy)
27
+ proxy = Net::SSH::Proxy::Command.new("ssh #{proxy_host} -W %h:%p")
28
28
  end
29
- @ssh = Net::SSH.start(@node.ip, @node.auth[:username], :port => port.to_i,
30
- :password => @node.auth[:password], :timeout => Oxidized.config.timeout,
31
- :paranoid => secure,
32
- :auth_methods => %w(none publickey password keyboard-interactive),
33
- :number_of_password_prompts => 0,
34
- :proxy => proxy)
29
+ ssh_opts = {
30
+ :port => port.to_i,
31
+ :password => @node.auth[:password], :timeout => Oxidized.config.timeout,
32
+ :paranoid => secure,
33
+ :auth_methods => %w(none publickey password keyboard-interactive),
34
+ :number_of_password_prompts => 0,
35
+ :proxy => proxy
36
+ }
37
+ ssh_opts[:kex] = vars(:ssh_kex).split(/,\s*/) if vars(:ssh_kex)
38
+ ssh_opts[:encryption] = vars(:ssh_encryption).split(/,\s*/) if vars(:ssh_encryption)
39
+
40
+ @ssh = Net::SSH.start(@node.ip, @node.auth[:username], ssh_opts)
35
41
  unless @exec
36
42
  shell_open @ssh
37
43
  begin
@@ -86,7 +92,7 @@ module Oxidized
86
92
  @output << data
87
93
  @output = @node.model.expects @output
88
94
  end
89
- ch.request_pty (opts={:term=>'vt100'}) do |_ch, success_pty|
95
+ ch.request_pty (_opts={:term=>'vt100'}) do |_ch, success_pty|
90
96
  raise NoShell, "Can't get PTY" unless success_pty
91
97
  ch.send_channel_request 'shell' do |_ch, success_shell|
92
98
  raise NoShell, "Can't get shell" unless success_shell
@@ -7,7 +7,7 @@ class Airos < Oxidized::Model
7
7
  cfg.split("\n").map { |line| "# #{line}" }.join("\n") + "\n"
8
8
  end
9
9
 
10
- cmd 'cat /tmp/system.cfg'
10
+ cmd 'sort /tmp/system.cfg'
11
11
 
12
12
  cmd :secret do |cfg|
13
13
  cfg.gsub! /^(users\.\d+\.password|snmp\.community)=.+/, "# \\1=<hidden>"
@@ -0,0 +1,33 @@
1
+ class DataCom < Oxidized::Model
2
+
3
+ comment '! '
4
+
5
+ expect /^--More--\s+$/ do |data, re|
6
+ send ' '
7
+ data.sub re, ''
8
+ end
9
+
10
+ cmd :all do |cfg|
11
+ cfg.each_line.to_a[1..-2].join
12
+ cfg.cut_head.cut_tail
13
+ end
14
+
15
+ cmd 'show firmware' do |cfg|
16
+ comment cfg
17
+ end
18
+
19
+ cmd 'show system' do |cfg|
20
+ comment cfg
21
+ end
22
+
23
+ cmd 'show running-config' do |cfg|
24
+ cfg.cut_head
25
+ end
26
+
27
+ cfg :telnet, :ssh do
28
+ username /login:\s$/
29
+ password /^Password:\s$/
30
+ pre_logout 'exit'
31
+ end
32
+
33
+ end
@@ -4,22 +4,29 @@ class EdgeSwitch < Oxidized::Model
4
4
 
5
5
  comment '!'
6
6
 
7
- prompt /[(]\w*\s\w*[)][\s#>]*[\s#>]/
7
+ prompt /\(.*\)\s[#>]/
8
8
 
9
9
  cmd 'show running-config' do |cfg|
10
- comment cfg.each_line.reject { |line| line.match /System Up Time.*/ or line.match /Current SNTP Synchronized Time.*/ }.join
10
+ cfg.each_line.to_a[2..-2].reject { |line| line.match /System Up Time.*/ or line.match /Current SNTP Synchronized Time.*/ }.join
11
11
  end
12
12
 
13
13
  cfg :telnet do
14
14
  username /Username:\s/
15
- passsword /^Password:\s/
15
+ password /^Password:\s/
16
16
  end
17
17
 
18
18
  cfg :telnet, :ssh do
19
- post_login 'enable'
20
- post_login 'terminal length 0'
21
- pre_logout 'exit'
22
- pre_logout 'exit'
19
+ post_login do
20
+ if vars :enable
21
+ send "enable\n"
22
+ cmd vars(:enable)
23
+ else
24
+ cmd 'enable'
25
+ end
26
+ cmd 'terminal length 0'
27
+ end
28
+ pre_logout 'quit'
29
+ pre_logout 'n'
23
30
  end
24
31
 
25
- end
32
+ end
@@ -2,11 +2,16 @@ class FortiOS < Oxidized::Model
2
2
 
3
3
  comment '# '
4
4
 
5
- prompt /^([-\w\.]+(\s[\(\w\-\.\)]+)?\~?\s?[#>]\s?)$/
5
+ prompt /^([-\w\.]+(\s[\(\w\-\.\)]+)?\~?\s?[#>$]\s?)$/
6
+
7
+ expect /^--More--\s$/ do |data, re|
8
+ send ' '
9
+ data.sub re, ''
10
+ end
6
11
 
7
12
  cmd :all do |cfg, cmdstring|
8
13
  new_cfg = comment "COMMAND: #{cmdstring}\n"
9
- new_cfg << cfg.each_line.to_a[1..-2].join
14
+ new_cfg << cfg.each_line.to_a[1..-2].map { |line| line.gsub(/(conf_file_ver=)(.*)/, '\1<stripped>\3') }.join
10
15
  end
11
16
 
12
17
  cmd 'get system status' do |cfg|
@@ -25,6 +25,10 @@ class IOS < Oxidized::Model
25
25
  cmd :secret do |cfg|
26
26
  cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
27
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>'
28
32
  cfg
29
33
  end
30
34
 
@@ -0,0 +1,61 @@
1
+ class IPOS < Oxidized::Model
2
+
3
+ # Ericsson SSR (IPOS)
4
+ # Redback SE (SEOS)
5
+
6
+ prompt /^([\[\]\w.@-]+[#>]\s?)$/
7
+ comment '! '
8
+
9
+ cmd 'show chassis' do |cfg|
10
+ comment cfg.each_line.to_a[0..-2].join
11
+ end
12
+
13
+ cmd 'show hardware' do |cfg|
14
+ comment cfg.each_line.to_a[0..-2].join
15
+ end
16
+
17
+ cmd 'show release' do |cfg|
18
+ comment cfg.each_line.to_a[0..-2].join
19
+ end
20
+
21
+ cmd 'show configuration' do |cfg|
22
+ # SEOS regularly adds some odd line breaks in random places
23
+ # when showing the config, triggering changes.
24
+ cfg.gsub! "\r\n", "\n"
25
+
26
+ cfg = cfg.each_line.to_a
27
+
28
+ # Keeps the issued command commented but removes the uncommented "Building configuration..."
29
+ # and "Current configuration:" lines as well as the last prompt at the end.
30
+ cfg = cfg[4..-2].unshift comment cfg[0]
31
+
32
+ # Later IPOS releases add this line in addition to the usual "last changed" line.
33
+ # It's touched regularly (as often as multiple times per minute) by the OS without actual visible config changes.
34
+ cfg = cfg.reject { |line| line.match "Configuration last changed by system user" }
35
+
36
+ # Earlier IPOS releases lack the "changed by system user" line and instead overwrite
37
+ # the single "last changed by user" line. Because the line has a timestamp it will
38
+ # trigger constant changes if not removed. By doing so there will only be a single
39
+ # extra change trigged after an actual config change by a user but still have the
40
+ # real user.
41
+ cfg = cfg.reject { |line| line.match "Configuration last changed by user '%LICM%' at" }
42
+ cfg = cfg.reject { |line| line.match "Configuration last changed by user '<NO USER>' at" }
43
+ cfg = cfg.reject { |line| line.match "Configuration last changed by user '' at" }
44
+
45
+ cfg.join
46
+ end
47
+
48
+ cfg :telnet do
49
+ username /^login:/
50
+ password /^\r*password:/
51
+ end
52
+
53
+ cfg :telnet, :ssh do
54
+ post_login 'terminal length 0'
55
+ pre_logout do
56
+ send "exit\n"
57
+ send "n\n"
58
+ end
59
+ end
60
+
61
+ end
@@ -30,6 +30,8 @@ class JunOS < Oxidized::Model
30
30
  case @model
31
31
  when 'mx960'
32
32
  out << cmd('show chassis fabric reachability') { |cfg| comment cfg }
33
+ when /^(ex22|ex33|ex4|ex8|qfx)/
34
+ out << cmd('show virtual-chassis') { |cfg| comment cfg }
33
35
  end
34
36
  out
35
37
  end
@@ -0,0 +1,37 @@
1
+ class Mtrlrfs < Oxidized::Model
2
+
3
+ # Motorola RFS/Extreme WM
4
+
5
+ comment '# '
6
+
7
+ cmd :all do |cfg|
8
+ # xos inserts leading \r characters and other trailing white space.
9
+ # this deletes extraneous \r and trailing white space.
10
+ cfg.each_line.to_a[1..-2].map{|line|line.delete("\r").rstrip}.join("\n") + "\n"
11
+ end
12
+
13
+ cmd 'show version' do |cfg|
14
+ comment cfg
15
+ end
16
+
17
+ cmd 'show licenses' do |cfg|
18
+ comment cfg
19
+ end
20
+
21
+ cmd 'show running-config'
22
+
23
+ cfg :telnet do
24
+ username /^login:/
25
+ password /^\r*password:/
26
+ end
27
+
28
+ cfg :telnet, :ssh do
29
+ post_login 'terminal length 0'
30
+ pre_logout do
31
+ send "exit\n"
32
+ send "n\n"
33
+ end
34
+ end
35
+
36
+ end
37
+
@@ -0,0 +1,15 @@
1
+ class Netonix < Oxidized::Model
2
+ prompt /^[\w\s.@_\/:-]+#/
3
+
4
+ cmd :all do |cfg|
5
+ cfg.each_line.to_a[1..-2].join
6
+ end
7
+
8
+ cmd 'cat config.json;echo'
9
+
10
+ cfg :ssh do
11
+ post_login 'cmdline'
12
+ pre_logout 'exit'
13
+ pre_logout 'exit'
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ class NetScaler < Oxidized::Model
2
+
3
+ prompt /^\>\s*$/
4
+ comment '# '
5
+
6
+ cmd :all do |cfg|
7
+ cfg.each_line.to_a[1..-3].join
8
+ end
9
+
10
+ cmd 'show version' do |cfg|
11
+ comment cfg
12
+ end
13
+
14
+ cmd 'show hardware' do |cfg|
15
+ comment cfg
16
+ end
17
+
18
+ cmd 'show ns ns.conf'
19
+
20
+ cfg :ssh do
21
+ pre_logout 'exit'
22
+ end
23
+
24
+ end
@@ -33,7 +33,7 @@ class NOS < Oxidized::Model
33
33
 
34
34
  cfg :telnet do
35
35
  username /^.* login: /
36
- username /^Password:/
36
+ password /^Password:/
37
37
  end
38
38
 
39
39
  cfg :telnet, :ssh do
@@ -1,36 +1,49 @@
1
1
  class Procurve < Oxidized::Model
2
2
 
3
- # FIXME: this is way too unsafe
4
- prompt /.*?(\w+# ).*/m
3
+ # some models start lines with \r
4
+ # previous command is repeated followed by "\eE", which sometimes ends up on last line
5
+ prompt /^\r?([\w -]+\eE)?([\w-]+# )$/
5
6
 
6
7
  comment '! '
7
8
 
9
+ # replace all used vt100 control sequences
10
+ expect /\e\[\??\d+(;\d+)*[A-Za-z]/ do |data, re|
11
+ data.gsub re, ''
12
+ end
13
+
8
14
  expect /Press any key to continue/ do
9
- send ' '
10
- ""
15
+ send ' '
16
+ ""
11
17
  end
12
18
 
13
19
  cmd :all do |cfg|
14
20
  cfg = cfg.each_line.to_a[1..-3].join
15
- cfg = cfg.gsub /\r/, ''
16
- new_cfg = ''
17
- cfg.each_line do |line|
18
- line.sub! /^\e.*(\e.*)/, '\1' #leave last escape
19
- line.sub! /\e\[24;1H/, '' #remove last escape, is it always this?
20
- new_cfg << line
21
- end
22
- new_cfg
21
+ cfg = cfg.gsub /^\r/, ''
22
+ end
23
+
24
+ cmd :secret do |cfg|
25
+ cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
26
+ cfg.gsub! /^(snmp-server host).*/, '\\1 <configuration removed>'
27
+ cfg.gsub! /^(radius-server host).*/, '\\1 <configuration removed>'
28
+ cfg
23
29
  end
24
30
 
25
31
  cmd 'show version' do |cfg|
26
32
  comment cfg
27
33
  end
28
34
 
35
+ # not supported on all models
29
36
  cmd 'show system-information' do |cfg|
30
37
  cfg = cfg.split("\n")[0..-8].join("\n")
31
38
  comment cfg
32
39
  end
33
40
 
41
+ # not supported on all models
42
+ cmd 'show system information' do |cfg|
43
+ cfg = cfg.split("\n")[0..-8].join("\n")
44
+ comment cfg
45
+ end
46
+
34
47
  cmd 'show running-config'
35
48
 
36
49
  cfg :telnet do
@@ -22,25 +22,27 @@ class TMOS < Oxidized::Model
22
22
 
23
23
  cmd('cat /config/bigip.license') { |cfg| comment cfg }
24
24
 
25
- cmd 'tmsh list' do |cfg|
26
- cfg.gsub!(/state (up|down)/, '')
25
+ cmd 'tmsh -q list' do |cfg|
26
+ cfg.gsub!(/state (up|down|checking|irule-down)/, '')
27
27
  cfg.gsub!(/errors (\d+)/, '')
28
28
  cfg
29
29
  end
30
30
 
31
- cmd('tmsh list net route all') { |cfg| comment cfg }
31
+ cmd('tmsh -q list net route all') { |cfg| comment cfg }
32
32
 
33
33
  cmd('/bin/ls --full-time --color=never /config/ssl/ssl.crt') { |cfg| comment cfg }
34
34
 
35
35
  cmd('/bin/ls --full-time --color=never /config/ssl/ssl.key') { |cfg| comment cfg }
36
36
 
37
- cmd 'tmsh show running-config sys db all-properties' do |cfg|
37
+ cmd 'tmsh -q show running-config sys db all-properties' do |cfg|
38
38
  cfg.gsub!(/sys db configsync.localconfigtime {[^}]+}/m, '')
39
39
  cfg.gsub!(/sys db gtm.configtime {[^}]+}/m, '')
40
40
  cfg.gsub!(/sys db ltm.configtime {[^}]+}/m, '')
41
41
  comment cfg
42
42
  end
43
43
 
44
+ cmd('cat /config/partitions/*/bigip.conf') { |cfg| comment cfg }
45
+
44
46
  cfg :ssh do
45
47
  exec true # don't run shell, run each command in exec channel
46
48
  end
@@ -36,8 +36,10 @@ class XOS < Oxidized::Model
36
36
 
37
37
  cfg :telnet, :ssh do
38
38
  post_login 'disable clipaging'
39
- pre_logout 'exit'
40
- pre_logout 'n'
39
+ pre_logout do
40
+ send "exit\n"
41
+ send "n\n"
42
+ end
41
43
  end
42
44
 
43
45
  end
data/lib/oxidized/node.rb CHANGED
@@ -24,7 +24,7 @@ module Oxidized
24
24
  @vars = opt[:vars]
25
25
  @stats = Stats.new
26
26
  @retry = 0
27
- @repo = Oxidized.config.output.git.repo
27
+ @repo = resolve_repo
28
28
 
29
29
  # model instance needs to access node instance
30
30
  @model.node = self
@@ -170,5 +170,15 @@ module Oxidized
170
170
  Oxidized.mgr.model[model].new
171
171
  end
172
172
 
173
+ def resolve_repo
174
+ remote_repo = Oxidized.config.output.git.repo
175
+
176
+ if Oxidized.config.output.git.single_repo? || @group.nil? || remote_repo.is_a?(String)
177
+ remote_repo
178
+ else
179
+ remote_repo[@group]
180
+ end
181
+ end
182
+
173
183
  end
174
184
  end
@@ -0,0 +1,58 @@
1
+ module Oxidized
2
+ class Http < Output
3
+ attr_reader :commitref
4
+ def initialize
5
+ @cfg = Oxidized.config.output.http
6
+ end
7
+
8
+ def setup
9
+ if @cfg.empty?
10
+ CFGS.user.output.http.user = 'Oxidized'
11
+ CFGS.user.output.http.pasword = 'secret'
12
+ CFGS.user.output.http.url = 'http://localhost/web-api/oxidized'
13
+ CFGS.save :user
14
+ raise NoConfig, 'no output http config, edit ~/.config/oxidized/config'
15
+ end
16
+ end
17
+ require "net/http"
18
+ require "uri"
19
+ require "json"
20
+ def store node, outputs, opt={}
21
+ @commitref = nil
22
+ json = JSON.pretty_generate(
23
+ {
24
+ 'msg' => opt[:msg],
25
+ 'user' => opt[:user],
26
+ 'email' => opt[:email],
27
+ 'group' => opt[:group],
28
+ 'node' => node,
29
+ 'config' => outputs.to_cfg,
30
+ # actually we need to also iterate outputs, for other types like in gitlab. But most people don't use 'type' functionality.
31
+ }
32
+ )
33
+ uri = URI.parse @cfg.url
34
+ http = Net::HTTP.new uri.host, uri.port
35
+ #http.use_ssl = true if uri.scheme = 'https'
36
+ req = Net::HTTP::Post.new(uri.request_uri, initheader = { 'Content-Type' => 'application/json'})
37
+ req.basic_auth @cfg.user, @cfg.password
38
+ req.body = json
39
+ response = http.request req
40
+
41
+ case response.code.to_i
42
+ when 200 || 201
43
+ Oxidized.logger.info "Configuration http backup complete for #{node}"
44
+ p [:success]
45
+ when (400..499)
46
+ Oxidized.logger.info "Configuration http backup for #{node} failed status: #{response.body}"
47
+ p [:bad_request]
48
+ when (500..599)
49
+ p [:server_problems]
50
+ Oxidized.logger.info "Configuration http backup for #{node} failed status: #{response.body}"
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+ end
57
+
58
+
@@ -1,3 +1,3 @@
1
1
  module Oxidized
2
- VERSION = '0.12.2'
2
+ VERSION = '0.13.0'
3
3
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oxidized
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.2
5
- prerelease:
4
+ version: 0.13.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Saku Ytti
@@ -11,162 +10,144 @@ authors:
11
10
  autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2016-02-06 00:00:00.000000000 Z
13
+ date: 2016-03-30 00:00:00.000000000 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: asetus
18
17
  requirement: !ruby/object:Gem::Requirement
19
- none: false
20
18
  requirements:
21
- - - ~>
19
+ - - "~>"
22
20
  - !ruby/object:Gem::Version
23
21
  version: '0.1'
24
22
  type: :runtime
25
23
  prerelease: false
26
24
  version_requirements: !ruby/object:Gem::Requirement
27
- none: false
28
25
  requirements:
29
- - - ~>
26
+ - - "~>"
30
27
  - !ruby/object:Gem::Version
31
28
  version: '0.1'
32
29
  - !ruby/object:Gem::Dependency
33
30
  name: slop
34
31
  requirement: !ruby/object:Gem::Requirement
35
- none: false
36
32
  requirements:
37
- - - ~>
33
+ - - "~>"
38
34
  - !ruby/object:Gem::Version
39
35
  version: '3.5'
40
36
  type: :runtime
41
37
  prerelease: false
42
38
  version_requirements: !ruby/object:Gem::Requirement
43
- none: false
44
39
  requirements:
45
- - - ~>
40
+ - - "~>"
46
41
  - !ruby/object:Gem::Version
47
42
  version: '3.5'
48
43
  - !ruby/object:Gem::Dependency
49
44
  name: net-ssh
50
45
  requirement: !ruby/object:Gem::Requirement
51
- none: false
52
46
  requirements:
53
- - - ~>
47
+ - - "~>"
54
48
  - !ruby/object:Gem::Version
55
49
  version: '3.0'
56
- - - ! '>='
50
+ - - ">="
57
51
  - !ruby/object:Gem::Version
58
52
  version: 3.0.2
59
53
  type: :runtime
60
54
  prerelease: false
61
55
  version_requirements: !ruby/object:Gem::Requirement
62
- none: false
63
56
  requirements:
64
- - - ~>
57
+ - - "~>"
65
58
  - !ruby/object:Gem::Version
66
59
  version: '3.0'
67
- - - ! '>='
60
+ - - ">="
68
61
  - !ruby/object:Gem::Version
69
62
  version: 3.0.2
70
63
  - !ruby/object:Gem::Dependency
71
64
  name: rugged
72
65
  requirement: !ruby/object:Gem::Requirement
73
- none: false
74
66
  requirements:
75
- - - ~>
67
+ - - "~>"
76
68
  - !ruby/object:Gem::Version
77
69
  version: '0.21'
78
- - - ! '>='
70
+ - - ">="
79
71
  - !ruby/object:Gem::Version
80
72
  version: 0.21.4
81
73
  type: :runtime
82
74
  prerelease: false
83
75
  version_requirements: !ruby/object:Gem::Requirement
84
- none: false
85
76
  requirements:
86
- - - ~>
77
+ - - "~>"
87
78
  - !ruby/object:Gem::Version
88
79
  version: '0.21'
89
- - - ! '>='
80
+ - - ">="
90
81
  - !ruby/object:Gem::Version
91
82
  version: 0.21.4
92
83
  - !ruby/object:Gem::Dependency
93
84
  name: pry
94
85
  requirement: !ruby/object:Gem::Requirement
95
- none: false
96
86
  requirements:
97
- - - ~>
87
+ - - "~>"
98
88
  - !ruby/object:Gem::Version
99
89
  version: '0'
100
90
  type: :development
101
91
  prerelease: false
102
92
  version_requirements: !ruby/object:Gem::Requirement
103
- none: false
104
93
  requirements:
105
- - - ~>
94
+ - - "~>"
106
95
  - !ruby/object:Gem::Version
107
96
  version: '0'
108
97
  - !ruby/object:Gem::Dependency
109
98
  name: bundler
110
99
  requirement: !ruby/object:Gem::Requirement
111
- none: false
112
100
  requirements:
113
- - - ~>
101
+ - - "~>"
114
102
  - !ruby/object:Gem::Version
115
103
  version: '1.10'
116
104
  type: :development
117
105
  prerelease: false
118
106
  version_requirements: !ruby/object:Gem::Requirement
119
- none: false
120
107
  requirements:
121
- - - ~>
108
+ - - "~>"
122
109
  - !ruby/object:Gem::Version
123
110
  version: '1.10'
124
111
  - !ruby/object:Gem::Dependency
125
112
  name: rake
126
113
  requirement: !ruby/object:Gem::Requirement
127
- none: false
128
114
  requirements:
129
- - - ~>
115
+ - - "~>"
130
116
  - !ruby/object:Gem::Version
131
117
  version: '10.0'
132
118
  type: :development
133
119
  prerelease: false
134
120
  version_requirements: !ruby/object:Gem::Requirement
135
- none: false
136
121
  requirements:
137
- - - ~>
122
+ - - "~>"
138
123
  - !ruby/object:Gem::Version
139
124
  version: '10.0'
140
125
  - !ruby/object:Gem::Dependency
141
126
  name: minitest
142
127
  requirement: !ruby/object:Gem::Requirement
143
- none: false
144
128
  requirements:
145
- - - ~>
129
+ - - "~>"
146
130
  - !ruby/object:Gem::Version
147
131
  version: '5.8'
148
132
  type: :development
149
133
  prerelease: false
150
134
  version_requirements: !ruby/object:Gem::Requirement
151
- none: false
152
135
  requirements:
153
- - - ~>
136
+ - - "~>"
154
137
  - !ruby/object:Gem::Version
155
138
  version: '5.8'
156
139
  - !ruby/object:Gem::Dependency
157
140
  name: mocha
158
141
  requirement: !ruby/object:Gem::Requirement
159
- none: false
160
142
  requirements:
161
- - - ~>
143
+ - - "~>"
162
144
  - !ruby/object:Gem::Version
163
145
  version: '1.1'
164
146
  type: :development
165
147
  prerelease: false
166
148
  version_requirements: !ruby/object:Gem::Requirement
167
- none: false
168
149
  requirements:
169
- - - ~>
150
+ - - "~>"
170
151
  - !ruby/object:Gem::Version
171
152
  version: '1.1'
172
153
  description: software to fetch configuration from network devices and store them
@@ -179,7 +160,7 @@ executables:
179
160
  extensions: []
180
161
  extra_rdoc_files: []
181
162
  files:
182
- - .travis.yml
163
+ - ".travis.yml"
183
164
  - CHANGELOG.md
184
165
  - Dockerfile
185
166
  - Gemfile
@@ -193,6 +174,7 @@ files:
193
174
  - extra/nagios_check_failing_nodes.rb
194
175
  - extra/oxidized-report-git-commits
195
176
  - extra/oxidized.init
177
+ - extra/oxidized.init.d
196
178
  - extra/oxidized.runit
197
179
  - extra/oxidized.service
198
180
  - extra/oxidized.supervisord
@@ -228,6 +210,7 @@ files:
228
210
  - lib/oxidized/model/ciscosmb.rb
229
211
  - lib/oxidized/model/comware.rb
230
212
  - lib/oxidized/model/cumulus.rb
213
+ - lib/oxidized/model/datacom.rb
231
214
  - lib/oxidized/model/dnos.rb
232
215
  - lib/oxidized/model/edgeos.rb
233
216
  - lib/oxidized/model/edgeswitch.rb
@@ -237,11 +220,15 @@ files:
237
220
  - lib/oxidized/model/ftos.rb
238
221
  - lib/oxidized/model/ios.rb
239
222
  - lib/oxidized/model/iosxr.rb
223
+ - lib/oxidized/model/ipos.rb
240
224
  - lib/oxidized/model/ironware.rb
241
225
  - lib/oxidized/model/isam.rb
242
226
  - lib/oxidized/model/junos.rb
243
227
  - lib/oxidized/model/masteros.rb
244
228
  - lib/oxidized/model/model.rb
229
+ - lib/oxidized/model/mtrlrfs.rb
230
+ - lib/oxidized/model/netonix.rb
231
+ - lib/oxidized/model/netscaler.rb
245
232
  - lib/oxidized/model/nos.rb
246
233
  - lib/oxidized/model/nxos.rb
247
234
  - lib/oxidized/model/opengear.rb
@@ -263,6 +250,7 @@ files:
263
250
  - lib/oxidized/nodes.rb
264
251
  - lib/oxidized/output/file.rb
265
252
  - lib/oxidized/output/git.rb
253
+ - lib/oxidized/output/http.rb
266
254
  - lib/oxidized/output/output.rb
267
255
  - lib/oxidized/source/csv.rb
268
256
  - lib/oxidized/source/http.rb
@@ -275,26 +263,25 @@ files:
275
263
  homepage: http://github.com/ytti/oxidized
276
264
  licenses:
277
265
  - Apache-2.0
266
+ metadata: {}
278
267
  post_install_message:
279
268
  rdoc_options: []
280
269
  require_paths:
281
270
  - lib
282
271
  required_ruby_version: !ruby/object:Gem::Requirement
283
- none: false
284
272
  requirements:
285
- - - ! '>='
273
+ - - ">="
286
274
  - !ruby/object:Gem::Version
287
275
  version: 2.0.0
288
276
  required_rubygems_version: !ruby/object:Gem::Requirement
289
- none: false
290
277
  requirements:
291
- - - ! '>='
278
+ - - ">="
292
279
  - !ruby/object:Gem::Version
293
280
  version: '0'
294
281
  requirements: []
295
282
  rubyforge_project: oxidized
296
- rubygems_version: 1.8.23
283
+ rubygems_version: 2.5.1
297
284
  signing_key:
298
- specification_version: 3
285
+ specification_version: 4
299
286
  summary: feeble attempt at rancid
300
287
  test_files: []