oxidized 0.16.3 → 0.17.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cba5f31454c2e6512d70c1688f81885e82a97ad9
4
- data.tar.gz: 40b8dfe37843039c8fef5cedc443a7101c78ffa1
3
+ metadata.gz: 4293285f8095f28f9f3d38dc2d606a03a58d163b
4
+ data.tar.gz: f108592ebdce488d10f06d7ee0e5545e3e117e32
5
5
  SHA512:
6
- metadata.gz: 8ca49b2ed227d5526c2d2093c794fd67a796822f7aeb30966060ac7ff46d12446b7c54fc6438b9e54e57d442422d92dccfaf5483e71141de066dfeda5d2726cc
7
- data.tar.gz: 2df84d9068fcdebd9c633d627a189ea5eaf915c9e04dc00af03b372dfba944c5ad8e1e0508ab93968295136d69a892b9098dbcc0218e2880558bfccf04bbb119
6
+ metadata.gz: aed22b16c6223c5b27a6b68476e25aea4154fcafd104a8567f7f19c4de38c8dddcd3fe18e1fd0950bc6e01e927d6af2fed514dd8f966eb33670f2a3517c6285f
7
+ data.tar.gz: 62a21f8caa39a27c853d2d56b3b96d35f6320db5cf6743ea76dd0cb7c6562729a0b96b5cc9b83524ad6edaac960dfb07ab88c7bffa526b459248603ba0e71bfa
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ # 0 17.3
2
+ - FEATURE: "nil", "false" and "true" in source (e.g. router.db) are interpeted as nil, false, true. Empty is now always considered empty string, instead of in some cases nil and some cases empty string.
3
+ - FEATURE: support tftp as input model (@MajesticFalcon)
4
+ - FEATURE: add alvarion model (@MajesticFalcon)
5
+ - FEATURE: detect if ssh wants password terminal/CLI prompt or not
6
+ - FEATURE: node (group, model, username, password) resolution refactoring, supports wider range of use-cases
7
+ - BUGFIX: fetch for file output (@danilopopeye)
8
+ - BUGFIX: net-ssh version specification
9
+ - BUGFIX: routeros, catos, pfsense
10
+
1
11
  # 0.16.3
2
12
  - FEATURE: pfsense support (by @stokbaek)
3
13
  - BUGFIX: cumulus prompt not working with default switch configs (by @nertwork)
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.1 ruby2.1-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
7
7
 
8
8
  RUN gem install oxidized oxidized-web --no-ri --no-rdoc
9
9
 
data/Gemfile.lock CHANGED
@@ -1,9 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- oxidized (0.14.3)
4
+ oxidized (0.17.0)
5
5
  asetus (~> 0.1)
6
- net-ssh (>= 3.0.0, < 3.1)
6
+ net-ssh (~> 3.0.2)
7
+ net-telnet
7
8
  rugged (~> 0.21, >= 0.21.4)
8
9
  slop (~> 3.5)
9
10
 
@@ -14,16 +15,17 @@ GEM
14
15
  coderay (1.1.0)
15
16
  metaclass (0.0.4)
16
17
  method_source (0.8.2)
17
- minitest (5.8.3)
18
+ minitest (5.9.0)
18
19
  mocha (1.1.0)
19
20
  metaclass (~> 0.0.1)
20
21
  net-ssh (3.0.2)
22
+ net-telnet (0.1.1)
21
23
  pry (0.10.3)
22
24
  coderay (~> 1.1.0)
23
25
  method_source (~> 0.8.1)
24
26
  slop (~> 3.4)
25
- rake (10.4.2)
26
- rugged (0.24.0)
27
+ rake (10.5.0)
28
+ rugged (0.23.3)
27
29
  slop (3.6.0)
28
30
 
29
31
  PLATFORMS
@@ -38,4 +40,4 @@ DEPENDENCIES
38
40
  rake (~> 10.0)
39
41
 
40
42
  BUNDLED WITH
41
- 1.12.4
43
+ 1.11.2
data/README.md CHANGED
@@ -27,13 +27,16 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen
27
27
  * [Privileged mode](#privileged-mode)
28
28
  * [Disabling SSH exec channels](#disabling-ssh-exec-channels)
29
29
  * [Source: CSV](#source-csv)
30
- * [Source: SQLite](#source-sqlite)
30
+ * [Source: SQL](#source-sql)
31
+ * [Source: SQLite](#source-sqlite)
32
+ * [Source: Mysql](#source-mysql)
31
33
  * [Source: HTTP](#source-http)
32
34
  * [Output: GIT](#output-git)
33
35
  * [Output: HTTP](#output-http)
34
36
  * [Output: File](#output-file)
35
37
  * [Output types](#output-types)
36
38
  * [Advanced Configuration](#advanced-configuration)
39
+ * [Advanced Group Configuration](#advanced-group-configuration)
37
40
  7. [Ruby API](#ruby-api)
38
41
  * [Input](#input)
39
42
  * [Output](#output)
@@ -41,99 +44,103 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen
41
44
  * [Model](#model)
42
45
 
43
46
  # Supported OS types
47
+ * Vendor
48
+ * OS - model_name
44
49
 
45
50
  * A10 Networks
46
- * ACOS
51
+ * ACOS - acos
47
52
  * Alcatel-Lucent
48
- * AOS
49
- * AOS7
50
- * ISAM
53
+ * AOS - aos
54
+ * AOS7 - aos7
55
+ * ISAM - isam
51
56
  * Wireless
57
+ * Alvarion
58
+ * BreezeACCESS - alvarion
52
59
  * Arista
53
- * EOS
60
+ * EOS - eos
54
61
  * Arris
55
- * C4CMTS
62
+ * C4CMTS - c4cmts
56
63
  * Aruba
57
- * AOSW
64
+ * AOSW - aosw
58
65
  * Brocade
59
- * FabricOS
60
- * Ironware
61
- * NOS (Network Operating System)
62
- * Vyatta
63
- * 6910
66
+ * FabricOS - fabricos
67
+ * Ironware - ironware
68
+ * NOS (Network Operating System) - nos
69
+ * Vyatta - vyatta
70
+ * 6910 - br6910
64
71
  * Check Point
65
- * GaiaOS
72
+ * GaiaOS - gaiaos
66
73
  * Ciena
67
- * SOAS
74
+ * SOAS - saos
68
75
  * Cisco
69
- * AireOS
70
- * ASA
71
- * CatOS
72
- * IOS
73
- * IOSXR
74
- * NXOS
75
- * SMB (Nikola series)
76
+ * AireOS - aireos
77
+ * ASA - asa
78
+ * CatOS - catos
79
+ * IOS - ios
80
+ * IOSXR - iosxr
81
+ * NXOS - nxos
82
+ * SMB (Nikola series)
76
83
  * Citrix
77
- * NetScaler (Virtual Applicance)
84
+ * NetScaler (Virtual Applicance) - netscaler
78
85
  * Coriant (former Tellabs)
79
- * TMOS (8800)
80
- * 8600
86
+ * TMOS (8800) - tmos
87
+ * 8600 -
81
88
  * Cumulus
82
89
  * Linux
83
90
  * DataCom
84
91
  * DmSwitch 3000
85
92
  * DELL
86
- * PowerConnect
87
- * AOSW
93
+ * PowerConnect - powerconnect
94
+ * AOSW - aosw
88
95
  * Ericsson/Redback
89
- * IPOS (former SEOS)
96
+ * IPOS (former SEOS) - ipos
90
97
  * Extreme Networks
91
- * XOS
98
+ * XOS - xos
92
99
  * WM
93
100
  * F5
94
101
  * TMOS
95
102
  * Force10
96
- * DNOS
97
- * FTOS
103
+ * DNOS - dnos
104
+ * FTOS - ftos
98
105
  * FortiGate
99
- * FortiOS
106
+ * FortiOS - fortios
100
107
  * HP
101
- * Comware (HP A-series, H3C, 3Com)
102
- * Procurve
108
+ * Comware (HP A-series, H3C, 3Com) - comware
109
+ * Procurve - procurve
103
110
  * Huawei
104
111
  * VRP
105
112
  * Juniper
106
113
  * JunOS
107
114
  * ScreenOS (Netscreen)
108
115
  * Mellanox
109
- * MLNX-OS
116
+ * MLNX-OS - mlnxos
110
117
  * Mikrotik
111
- * RouterOS
118
+ * RouterOS - routeros
112
119
  * Motorola
113
120
  * RFS
114
121
  * MRV
115
- * MasterOS
122
+ * MasterOS - masteros
116
123
  * Netonix
117
- * WISP Switch (As Netonix)
124
+ * WISP Switch (As Netonix) - netonix
118
125
  * Nokia (formerly TiMetra, Alcatel, Alcatel-Lucent)
119
- * SR OS (TiMOS)
126
+ * SR OS (TiMOS) - timos
120
127
  * Opengear
121
- * Opengear
128
+ * Opengear - opengear
122
129
  * Palo Alto
123
- * PANOS
124
- * pfSense
130
+ * PANOS - panos
131
+ * pfSense - pfsense
125
132
  * Quanta
126
- * Quanta / VxWorks 6.6 (1.1.0.8)
133
+ * Quanta / VxWorks 6.6 (1.1.0.8) - quantaos
127
134
  * Supermicro
128
- * Supermicro
135
+ * Supermicro - supermicro
129
136
  * Ubiquiti
130
- * AirOS
131
- * Edgeos
132
- * EdgeSwitch
137
+ * AirOS - airos
138
+ * Edgeos - edgeos
139
+ * EdgeSwitch - edgeswitch
133
140
  * Watchguard
134
- * Fireware OS
141
+ * Fireware OS - firewareos
135
142
  * Zyxel
136
- * ZyNOS
143
+ * ZyNOS - zynos
137
144
 
138
145
 
139
146
  # Installation
@@ -147,7 +154,7 @@ gem install oxidized-script oxidized-web # if you don't install oxidized-web, ma
147
154
  ```
148
155
 
149
156
  ## CentOS, Oracle Linux, Red Hat Linux
150
- On CentOS 6 / RHEL 6, 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
157
+ On CentOS 6 / RHEL 6, install Ruby greater than 1.9.3 (for Ruby 2.1.2 installation instructions see "Installing Ruby 2.1.2 using RVM"), then install Oxidized dependencies
151
158
  ```shell
152
159
  yum install cmake sqlite-devel openssl-devel libssh2-devel
153
160
  ```
@@ -254,46 +261,54 @@ rvm use --default 2.1.2
254
261
  ```
255
262
 
256
263
  # Running with Docker
257
- 1. clone git repo:
264
+
265
+ clone git repo:
258
266
 
259
267
  ```
260
- root@bla:~# git clone https://github.com/ytti/oxidized
261
- ```
262
- 2. build container locally:
268
+ git clone https://github.com/ytti/oxidized
263
269
  ```
264
- root@bla:~# docker build -q -t oxidized/oxidized:latest oxidized/
270
+
271
+ build container locally:
272
+
265
273
  ```
266
- 3. create config directory in main system:
274
+ docker build -q -t oxidized/oxidized:latest oxidized/
267
275
  ```
268
- root@bla~:# mkdir /etc/oxidized
276
+
277
+ create config directory in main system:
278
+
269
279
  ```
270
- 4. run container the first time:
280
+ mkdir /etc/oxidized
271
281
  ```
272
- root@bla:~# docker run -v /etc/oxidized:/root/.config/oxidized -p 8888:8888/tcp -t oxidized/oxidized:latest oxidized
282
+
283
+ run container the first time:
284
+ _Note: this step in only needed for creating Oxidized's configuration file and can be skipped if you already have it
285
+
273
286
  ```
274
- 5. add 'router.db' to /etc/oxidized:
287
+ docker run --rm -v /etc/oxidized:/root/.config/oxidized -p 8888:8888/tcp -t oxidized/oxidized:latest oxidized
275
288
  ```
276
- root@bla:~# vim /etc/oxidized/router.db
277
- [ ... ]
278
- root@bla:~#
289
+
290
+ create the `/etc/oxidized/router.db`
291
+
279
292
  ```
280
- 6. run container again:
293
+ vim /etc/oxidized/router.db
281
294
  ```
282
- root@bla:~# docker run -v /etc/oxidized:/root/.config/oxidized -p 8888:8888/tcp -t oxidized/oxidized:latest
283
- oxidized[1]: Oxidized starting, running as pid 1
284
- oxidized[1]: Loaded 1 nodes
285
- Puma 2.13.4 starting...
286
- * Min threads: 0, max threads: 16
287
- * Environment: development
288
- * Listening on tcp://0.0.0.0:8888
289
- ^C
290
295
 
291
- root@bla:~#
296
+ run container again:
297
+
298
+ ```
299
+ docker run -v /etc/oxidized:/root/.config/oxidized -p 8888:8888/tcp -t oxidized/oxidized:latest
300
+ oxidized[1]: Oxidized starting, running as pid 1
301
+ oxidized[1]: Loaded 1 nodes
302
+ Puma 2.13.4 starting...
303
+ * Min threads: 0, max threads: 16
304
+ * Environment: development
305
+ * Listening on tcp://0.0.0.0:8888
292
306
  ```
293
307
 
294
308
  If you want to have the config automatically reloaded (e.g. when using a http source that changes)
309
+
295
310
  ```
296
- root@bla:~# docker run -v /etc/oxidized:/root/.config/oxidized -p 8888:8888/tcp -e CONFIG_RELOAD_INTERVAL=3600 -t oxidized/oxidized:latest
311
+ docker run -v /etc/oxidized:/root/.config/oxidized -p 8888:8888/tcp -e CONFIG_RELOAD_INTERVAL=3600 -t oxidized/oxidized:latest
297
312
  ```
298
313
 
299
314
  ## Cookbook
@@ -386,6 +401,31 @@ vars_map:
386
401
  ssh_proxy: 3
387
402
  ...
388
403
  ```
404
+ ### Source: SQL
405
+ Oxidized uses the `sequel` ruby gem. You can use a variety of databases that aren't explicitly listed. For more information visit https://github.com/jeremyevans/sequel Make sure you have the correct adapter!
406
+ ### Source: MYSQL
407
+
408
+ ```sudo apt-get install libmysqlclient-dev```
409
+
410
+ The values correspond to your fields in the DB such that ip, model, etc are field names in the DB
411
+
412
+ ```
413
+ source:
414
+ default: sql
415
+ sql:
416
+ adapter: mysql2
417
+ database: oxidized
418
+ table: nodes
419
+ username: root
420
+ password: rootpass
421
+ map:
422
+ name: ip
423
+ model: model
424
+ username: username
425
+ password: password
426
+ vars_map:
427
+ enable: enable
428
+ ```
389
429
 
390
430
  ### Source: SQLite
391
431
 
@@ -572,7 +612,7 @@ rest: 10.0.0.1:8000/oxidized
572
612
 
573
613
  ### Advanced Configuration
574
614
 
575
- Below is an advanced example configuration. You will be able to (optinally) override options per device. The router.db format used is ```hostname:model:username:password:enable_password```. Hostname and model will be the only required options, all others override the global configuration sections.
615
+ Below is an advanced example configuration. You will be able to (optionally) override options per device. The router.db format used is ```hostname:model:username:password:enable_password```. Hostname and model will be the only required options, all others override the global configuration sections.
576
616
 
577
617
  ```
578
618
  ---
@@ -617,6 +657,28 @@ source:
617
657
  model_map:
618
658
  cisco: ios
619
659
  juniper: junos
660
+
661
+ ```
662
+
663
+ ### Advanced Group Configuration
664
+
665
+ For group specific credentials
666
+
667
+ ```
668
+ groups:
669
+ mikrotik:
670
+ username: admin
671
+ password: blank
672
+ ubiquiti:
673
+ username: ubnt
674
+ password: ubnt
675
+ ```
676
+ and add group mapping
677
+ ```
678
+ map:
679
+ model: 0
680
+ name: 1
681
+ group: 2
620
682
  ```
621
683
 
622
684
  # Hooks
@@ -716,7 +778,7 @@ The following objects exist in Oxidized.
716
778
  ## Input
717
779
  * gets config from nodes
718
780
  * must implement 'connect', 'get', 'cmd'
719
- * 'ssh' and 'telnet' implemented
781
+ * 'ssh', 'telnet, ftp, and tftp' implemented
720
782
 
721
783
  ## Output
722
784
  * stores config
data/Rakefile CHANGED
@@ -19,10 +19,10 @@ task :test do
19
19
  end
20
20
  end
21
21
 
22
- desc 'Install gem'
23
- task :install => :build do
24
- system "sudo -Es sh -c \'umask 022; gem install gems/#{file}\'"
25
- end
22
+ ## desc 'Install gem'
23
+ ## task :install => :build do
24
+ ## system "sudo -Es sh -c \'umask 022; gem install gems/#{file}\'"
25
+ ## end
26
26
 
27
27
  desc 'Remove gems'
28
28
  task :clean do
data/extra/rest_client.rb CHANGED
@@ -2,8 +2,30 @@ module Oxidized
2
2
  class RestClient
3
3
  require 'net/http'
4
4
  require 'json'
5
- HOST = 'localhost'
6
- PORT = 8888
5
+ require 'uri'
6
+ require 'asetus'
7
+
8
+ class Config
9
+ Root = Root = ENV['OXIDIZED_HOME'] || File.join(ENV['HOME'], '.config', 'oxidized')
10
+ end
11
+
12
+ CFGS = Asetus.new :name=>'oxidized', :load=>false, :key_to_s=>true
13
+ CFGS.default.rest = '127.0.0.1:8888'
14
+
15
+ begin
16
+ CFGS.load
17
+ rescue => error
18
+ raise InvalidConfig, "Error loading config: #{error.message}"
19
+ end
20
+
21
+ restcfg = CFGS.cfg.rest
22
+ unless restcfg.match(/^http:\/\//)
23
+ restcfg.insert(0, 'http://')
24
+ end
25
+
26
+ HOST = URI(restcfg).host
27
+ PORT = URI(restcfg).port
28
+ PATH = URI(restcfg).path
7
29
 
8
30
  class << self
9
31
  def next opt={}, host=HOST, port=PORT
@@ -18,7 +40,7 @@ module Oxidized
18
40
 
19
41
  def next opt
20
42
  data = JSON.dump opt
21
- @web.put '/node/next/' + opt[:name].to_s, data
43
+ @web.put PATH + '/node/next/' + opt[:name].to_s, data
22
44
  end
23
45
 
24
46
  end
@@ -42,7 +42,7 @@ module Oxidized
42
42
  unless @exec
43
43
  shell_open @ssh
44
44
  begin
45
- @username ? shell_login : expect(@node.prompt)
45
+ login
46
46
  rescue Timeout::Error
47
47
  raise PromptUndetect, [ @output, 'not matching configured prompt', @node.prompt ].join(' ')
48
48
  end
@@ -102,13 +102,18 @@ module Oxidized
102
102
  end
103
103
  end
104
104
 
105
- # Cisco WCS has extremely dubious SSH implementation, SSH auth is always
106
- # success, it always opens shell and then run auth in shell. I guess
107
- # they'll never support exec() :)
108
- def shell_login
109
- expect username
110
- cmd @node.auth[:username], password
111
- cmd @node.auth[:password]
105
+ # some models have SSH auth or terminal auth based on version of code
106
+ # if SSH is configured for terminal auth, we'll still try to detect prompt
107
+ def login
108
+ if @username
109
+ match = expect username, @node.prompt
110
+ if match == username
111
+ cmd @node.auth[:username], password
112
+ cmd @node.auth[:password]
113
+ end
114
+ else
115
+ expect @node.prompt
116
+ end
112
117
  end
113
118
 
114
119
  def exec state=nil
@@ -123,14 +128,18 @@ module Oxidized
123
128
  @output
124
129
  end
125
130
 
126
- def expect regexp
127
- Oxidized.logger.debug "lib/oxidized/input/ssh.rb: expecting #{regexp.inspect} at #{node.name}"
131
+ def expect *regexps
132
+ regexps = [regexps].flatten
133
+ Oxidized.logger.debug "lib/oxidized/input/ssh.rb: expecting #{regexps.inspect} at #{node.name}"
128
134
  Timeout::timeout(Oxidized.config.timeout) do
129
135
  @ssh.loop(0.1) do
130
136
  sleep 0.1
131
- not @output.match regexp
137
+ match = regexps.find { |regexp| @output.match regexp }
138
+ return match if match
139
+ true
132
140
  end
133
141
  end
134
142
  end
143
+
135
144
  end
136
145
  end
@@ -0,0 +1,41 @@
1
+ module Oxidized
2
+ require 'stringio'
3
+ require_relative 'cli'
4
+
5
+ begin
6
+ require 'net/tftp'
7
+ rescue LoadError
8
+ raise OxidizedError, 'net/tftp not found: sudo gem install net-tftp'
9
+ end
10
+
11
+ class TFTP < Input
12
+
13
+ include Input::CLI
14
+
15
+ # TFTP utilizes UDP, there is not a connection. We simply specify an IP and send/receive data.
16
+ def connect node
17
+ @node = node
18
+
19
+ @node.model.cfg['tftp'].each { |cb| instance_exec(&cb) }
20
+ @log = File.open(Oxidized::Config::Log + "/#{@node.ip}-tftp", 'w') if Oxidized.config.input.debug?
21
+ @tftp = Net::TFTP.new @node.ip
22
+ end
23
+
24
+ def cmd file
25
+ Oxidized.logger.debug "TFTP: #{file} @ #{@node.name}"
26
+ config = StringIO.new
27
+ @tftp.getbinary file, config
28
+ config.rewind
29
+ config.read
30
+ end
31
+
32
+ private
33
+
34
+ def disconnect
35
+ # TFTP uses UDP, there is no connection to close
36
+ ensure
37
+ @log.close if Oxidized.config.input.debug?
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,13 @@
1
+ class Alvarion < Oxidized::Model
2
+
3
+ # Used in Alvarion wisp equipment
4
+
5
+ # Run this command as an instance of Model so we can access node
6
+ pre do
7
+ cmd "#{node.auth[:password]}.cfg"
8
+ end
9
+
10
+
11
+ cfg :tftp {}
12
+
13
+ end
@@ -1,6 +1,6 @@
1
1
  class Catos < Oxidized::Model
2
2
 
3
- prompt /^[\w.@-]+> \(enable\) $/
3
+ prompt /^[\w.@-]+>\s?(\(enable\) )?$/
4
4
  comment '# '
5
5
 
6
6
  cmd :all do |cfg|
@@ -28,8 +28,15 @@ class Catos < Oxidized::Model
28
28
  password /^Password:/
29
29
  end
30
30
 
31
- cfg :ssh, :telnet do
31
+ cfg :telnet, :ssh do
32
32
  post_login 'set length 0'
33
+ # preferred way to handle additional passwords
34
+ if vars :enable
35
+ post_login do
36
+ send "enable\n"
37
+ cmd vars(:enable)
38
+ end
39
+ end
33
40
  pre_logout 'exit'
34
41
  end
35
42
 
@@ -2,21 +2,12 @@ class PfSense < Oxidized::Model
2
2
 
3
3
  # use other use than 'admin' user, 'admin' user cannot get ssh/exec. See issue #535
4
4
 
5
- comment '# '
6
-
7
- #add a comment in the final conf
8
- def add_comment comment
9
- "\n###### #{comment} ######\n"
10
- end
11
-
12
5
  cmd :all do |cfg|
13
6
  cfg.each_line.to_a[1..-2].join
14
7
  end
15
8
 
16
- #show the persistent configuration
17
- pre do
18
- cfg = add_comment 'Configuration'
19
- cfg += cmd 'cat /cf/conf/config.xml'
9
+ cmd 'cat /cf/conf/config.xml' do |cfg|
10
+ cfg.gsub! /\s<revision>\s*<time>\d*<\/time>\s*.*\s*.*\s*<\/revision>/, ''
20
11
  end
21
12
 
22
13
  cfg :ssh do
@@ -1,5 +1,5 @@
1
1
  class RouterOS < Oxidized::Model
2
- prompt /\[\w+@\S+\]\s?>\s?$/
2
+ prompt /\[\w+@\S+(\s?\S+)*\]\s?>\s?$/
3
3
  comment "# "
4
4
 
5
5
  cmd '/system routerboard print' do |cfg|
@@ -8,6 +8,7 @@ class RouterOS < Oxidized::Model
8
8
 
9
9
  cmd '/export' do |cfg|
10
10
  cfg.gsub! /\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]/, '' # strip ANSI colours
11
+ cfg.gsub! /\\\r\n\s+/, '' # strip new line
11
12
  cfg = cfg.split("\n").select { |line| not line[/^\#\s\w{3}\/\d{2}\/\d{4}.*$/] }
12
13
  cfg.join("\n") + "\n"
13
14
  end
data/lib/oxidized/node.rb CHANGED
@@ -128,24 +128,15 @@ module Oxidized
128
128
  end
129
129
 
130
130
  def resolve_auth opt
131
- # Resolve configured username/password, give priority to group level configuration
132
- # TODO: refactor to use revised behaviour of Asetus
133
- cfg_username, cfg_password =
134
- if Oxidized.config.groups.has_key?(@group) and ['username', 'password'].all? {|e| Oxidized.config.groups[@group].has_key?(e)}
135
- [Oxidized.config.groups[@group].username, Oxidized.config.groups[@group].password]
136
- elsif ['username', 'password'].all? {|e| Oxidized.config.has_key?(e)}
137
- [Oxidized.config.username, Oxidized.config.password]
138
- else
139
- [nil, nil]
140
- end
141
- auth = {}
142
- auth[:username] = (opt[:username] or cfg_username)
143
- auth[:password] = (opt[:password] or cfg_password)
144
- auth
131
+ # Resolve configured username/password
132
+ {
133
+ username: resolve_key(:username, opt),
134
+ password: resolve_key(:password, opt),
135
+ }
145
136
  end
146
137
 
147
138
  def resolve_input opt
148
- inputs = (opt[:input] or Oxidized.config.input.default)
139
+ inputs = resolve_key :input, opt, Oxidized.config.input.default
149
140
  inputs.split(/\s*,\s*/).map do |input|
150
141
  if not Oxidized.mgr.input[input]
151
142
  Oxidized.mgr.add_input input or raise MethodNotFound, "#{input} not found for node #{ip}"
@@ -155,7 +146,7 @@ module Oxidized
155
146
  end
156
147
 
157
148
  def resolve_output opt
158
- output = (opt[:output] or Oxidized.config.output.default)
149
+ output = resolve_key :output, opt, Oxidized.config.output.default
159
150
  if not Oxidized.mgr.output[output]
160
151
  Oxidized.mgr.add_output output or raise MethodNotFound, "#{output} not found for node #{ip}"
161
152
  end
@@ -163,7 +154,7 @@ module Oxidized
163
154
  end
164
155
 
165
156
  def resolve_model opt
166
- model = (opt[:model] or Oxidized.config.model)
157
+ model = resolve_key :model, opt
167
158
  if not Oxidized.mgr.model[model]
168
159
  Oxidized.logger.debug "lib/oxidized/node.rb: Loading model #{model.inspect}"
169
160
  Oxidized.mgr.add_model model or raise ModelNotFound, "#{model} not found for node #{ip}"
@@ -187,6 +178,33 @@ module Oxidized
187
178
  end
188
179
  end
189
180
 
181
+ def resolve_key key, opt, global=nil
182
+ # resolve key, first get global, then get group then get node config
183
+ key_sym = key.to_sym
184
+ key_str = key.to_s
185
+ value = global
186
+ Oxidized.logger.debug "node.rb: resolving node key '#{key}', with passed global value of '#{value}' and node value '#{opt[key_sym]}'"
187
+
188
+ #global
189
+ if not value and Oxidized.config.has_key?(key_str)
190
+ value = Oxidized.config[key_str]
191
+ Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from global"
192
+ end
193
+
194
+ #group
195
+ if Oxidized.config.groups.has_key?(@group)
196
+ if Oxidized.config.groups[@group].has_key?(key_str)
197
+ value = Oxidized.config.groups[@group][key_str]
198
+ Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from group"
199
+ end
200
+ end
201
+
202
+ #node
203
+ value = opt[key_sym] || value
204
+ Oxidized.logger.debug "node.rb: returning node key '#{key}' with value '#{value}'"
205
+ value
206
+ end
207
+
190
208
  def is_git? opt
191
209
  (opt[:output] || Oxidized.config.output.default) == 'git'
192
210
  end
@@ -17,7 +17,7 @@ class OxidizedFile < Output
17
17
  end
18
18
 
19
19
  def store node, outputs, opt={}
20
- file = @cfg.directory
20
+ file = File.expand_path @cfg.directory
21
21
  if opt[:group]
22
22
  file = File.join File.dirname(file), opt[:group]
23
23
  end
@@ -28,14 +28,16 @@ class OxidizedFile < Output
28
28
  end
29
29
 
30
30
  def fetch node, group
31
- cfg_dir = @cfg.directory
31
+ cfg_dir = File.expand_path @cfg.directory
32
+ node_name = node.name
33
+
32
34
  if group # group is explicitly defined by user
33
- IO.readlines File.join(cfg_dir, group, node)
35
+ IO.readlines File.join(cfg_dir, group, node_name)
34
36
  else
35
- if File.exists? File.join(cfg_dir, node) # node configuration file is stored on base directory
36
- IO.readlines File.join(cfg_dir, node)
37
+ if File.exists? File.join(cfg_dir, node_name) # node configuration file is stored on base directory
38
+ IO.readlines File.join(cfg_dir, node_name)
37
39
  else
38
- path = Dir.glob File.join(cfg_dir, '**', node) # fetch node in all groups
40
+ path = Dir.glob File.join(cfg_dir, '**', node_name) # fetch node in all groups
39
41
  return nil if path[0].nil?
40
42
  open(path[0], 'r').readlines
41
43
  end
@@ -20,7 +20,7 @@ class CSV < Source
20
20
  nodes = []
21
21
  open(File.expand_path @cfg.file).each_line do |line|
22
22
  next if line.match(/^\s*#/)
23
- data = line.chomp.split @cfg.delimiter
23
+ data = line.chomp.split(@cfg.delimiter, -1)
24
24
  next if data.empty?
25
25
  # map node parameters
26
26
  keys = {}
@@ -29,9 +29,11 @@ class CSV < Source
29
29
  end
30
30
  keys[:model] = map_model keys[:model] if keys.key? :model
31
31
 
32
- # map node specific vars, empty value is considered as nil
32
+ # map node specific vars
33
33
  vars = {}
34
- @cfg.vars_map.each { |key, position| vars[key.to_sym] = data[position].to_s.empty? ? nil : data[position] }
34
+ @cfg.vars_map.each do |key, position|
35
+ vars[key.to_sym] = node_var_interpolate data[position]
36
+ end
35
37
  keys[:vars] = vars unless vars.empty?
36
38
 
37
39
  nodes << keys
@@ -43,9 +43,11 @@ class HTTP < Source
43
43
  end
44
44
  keys[:model] = map_model keys[:model] if keys.key? :model
45
45
 
46
- # map node specific vars, empty value is considered as nil
46
+ # map node specific vars
47
47
  vars = {}
48
- @cfg.vars_map.each { |key, position| vars[key.to_sym] = line[position].to_s.empty? ? nil : line[position] }
48
+ @cfg.vars_map.each do |key, position|
49
+ vars[key.to_sym] = node_var_interpolate line[position]
50
+ end
49
51
  keys[:vars] = vars unless vars.empty?
50
52
 
51
53
  nodes << keys
@@ -1,11 +1,23 @@
1
1
  module Oxidized
2
2
  class Source
3
3
  class NoConfig < OxidizedError; end
4
+
4
5
  def initialize
5
6
  @map = (Oxidized.config.model_map or {})
6
7
  end
8
+
7
9
  def map_model model
8
10
  @map.has_key?(model) ? @map[model] : model
9
11
  end
12
+
13
+ def node_var_interpolate var
14
+ case var
15
+ when "nil" then nil
16
+ when "false" then false
17
+ when "true" then true
18
+ else var
19
+ end
20
+ end
21
+
10
22
  end
11
23
  end
@@ -31,7 +31,9 @@ class SQL < Source
31
31
 
32
32
  # map node specific vars
33
33
  vars = {}
34
- @cfg.vars_map.each { |key, sql_column| vars[key.to_sym] = node[sql_column.to_sym] }
34
+ @cfg.vars_map.each do |key, sql_column|
35
+ vars[key.to_sym] = node_var_interpolate node[sql_column.to_sym]
36
+ end
35
37
  keys[:vars] = vars unless vars.empty?
36
38
 
37
39
  nodes << keys
@@ -1,3 +1,3 @@
1
1
  module Oxidized
2
- VERSION = '0.16.3'
2
+ VERSION = '0.17.0'
3
3
  end
data/oxidized.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
21
21
  s.required_ruby_version = '>= 2.0.0'
22
22
  s.add_runtime_dependency 'asetus', '~> 0.1'
23
23
  s.add_runtime_dependency 'slop', '~> 3.5'
24
- s.add_runtime_dependency 'net-ssh', '>= 3.0.0', '<3.1'
24
+ s.add_runtime_dependency 'net-ssh', '~> 3.0.2'
25
25
  s.add_runtime_dependency 'rugged', '~> 0.21', '>= 0.21.4'
26
26
 
27
27
  if defined?(RUBY_VERSION) && RUBY_VERSION > '2.3'
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.16.3
4
+ version: 0.17.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-08-25 00:00:00.000000000 Z
13
+ date: 2016-09-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: asetus
@@ -44,22 +44,16 @@ dependencies:
44
44
  name: net-ssh
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 3.0.0
50
- - - "<"
47
+ - - "~>"
51
48
  - !ruby/object:Gem::Version
52
- version: '3.1'
49
+ version: 3.0.2
53
50
  type: :runtime
54
51
  prerelease: false
55
52
  version_requirements: !ruby/object:Gem::Requirement
56
53
  requirements:
57
- - - ">="
58
- - !ruby/object:Gem::Version
59
- version: 3.0.0
60
- - - "<"
54
+ - - "~>"
61
55
  - !ruby/object:Gem::Version
62
- version: '3.1'
56
+ version: 3.0.2
63
57
  - !ruby/object:Gem::Dependency
64
58
  name: rugged
65
59
  requirement: !ruby/object:Gem::Requirement
@@ -211,12 +205,14 @@ files:
211
205
  - lib/oxidized/input/input.rb
212
206
  - lib/oxidized/input/ssh.rb
213
207
  - lib/oxidized/input/telnet.rb
208
+ - lib/oxidized/input/tftp.rb
214
209
  - lib/oxidized/job.rb
215
210
  - lib/oxidized/jobs.rb
216
211
  - lib/oxidized/manager.rb
217
212
  - lib/oxidized/model/acos.rb
218
213
  - lib/oxidized/model/aireos.rb
219
214
  - lib/oxidized/model/airos.rb
215
+ - lib/oxidized/model/alvarion
220
216
  - lib/oxidized/model/aos.rb
221
217
  - lib/oxidized/model/aos7.rb
222
218
  - lib/oxidized/model/aosw.rb