oxidized 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +41 -0
- data/README.md +64 -35
- data/Rakefile +7 -9
- data/bin/console +9 -0
- data/bin/oxidized +1 -1
- data/extra/nagios_check_failing_nodes.rb +4 -4
- data/extra/oxidized-report-git-commits +80 -0
- data/extra/rvm.oxidized.upstart +18 -0
- data/lib/oxidized.rb +45 -2
- data/lib/oxidized/cli.rb +54 -4
- data/lib/oxidized/config.rb +45 -39
- data/lib/oxidized/config/vars.rb +8 -3
- data/lib/oxidized/core.rb +5 -12
- data/lib/oxidized/hook.rb +4 -4
- data/lib/oxidized/hook/exec.rb +2 -0
- data/lib/oxidized/hook/githubrepo.rb +57 -0
- data/lib/oxidized/input/cli.rb +2 -1
- data/lib/oxidized/input/ftp.rb +3 -3
- data/lib/oxidized/input/ssh.rb +9 -9
- data/lib/oxidized/input/telnet.rb +3 -3
- data/lib/oxidized/job.rb +3 -3
- data/lib/oxidized/model/fortios.rb +1 -1
- data/lib/oxidized/model/junos.rb +8 -10
- data/lib/oxidized/model/model.rb +3 -2
- data/lib/oxidized/model/powerconnect.rb +11 -6
- data/lib/oxidized/model/saos.rb +24 -0
- data/lib/oxidized/node.rb +16 -16
- data/lib/oxidized/nodes.rb +12 -12
- data/lib/oxidized/output/file.rb +15 -3
- data/lib/oxidized/output/git.rb +10 -7
- data/lib/oxidized/source/csv.rb +7 -7
- data/lib/oxidized/source/http.rb +1 -1
- data/lib/oxidized/source/source.rb +1 -1
- data/lib/oxidized/source/sql.rb +7 -7
- data/lib/oxidized/string.rb +1 -1
- data/lib/oxidized/version.rb +3 -0
- data/lib/oxidized/worker.rb +11 -9
- data/oxidized.gemspec +12 -3
- metadata +75 -7
- data/lib/oxidized/log.rb +0 -22
- data/spec/nodes_spec.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f601ebdf3c7562322e2b76313f60e4128863968
|
4
|
+
data.tar.gz: c0151bcf8e6c02d53511321f198bdd7fd55ac1cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff1578ea27961bdf57d32433da245795a880f95e6698f1f2b37692617d4779467673c78a1e27318204c8fc5b0ef4bbb05c379bee870f1fe59365727bef7a8222
|
7
|
+
data.tar.gz: fde31a1ef6e58ceebe9b1bcc822efdcc37971c234b474f64daa679bb50c87f308e474c7aad132ac41f837be91e4034aaba8db346fed987cc3f3a6dea7846bc3d
|
data/.travis.yml
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# 0.10.0
|
2
|
+
- FEATURE: Various refactoring (by @ElvinEfendi)
|
3
|
+
- FEATURE: Ciena SOAS support (by @jgroom33)
|
4
|
+
- FEATURE: support group variables (by @supertylerc)
|
5
|
+
- BUGFIX: various ((orly)) (by @marnovdm, @danbaugher, @MrRJ45, @asynet, @nickhilliard)
|
6
|
+
|
1
7
|
# 0.9.0
|
2
8
|
- FEATURE: input log now uses devices name as file, instead of string from config (by @skoef)
|
3
9
|
- FEATURE: Dell Networkign OS (dnos) support (by @erefre)
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
oxidized (0.9.0)
|
5
|
+
asetus (~> 0.1)
|
6
|
+
net-ssh (~> 3.0, >= 3.0.2)
|
7
|
+
rugged (~> 0.21, >= 0.21.4)
|
8
|
+
slop (~> 3.5)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
asetus (0.3.0)
|
14
|
+
coderay (1.1.0)
|
15
|
+
metaclass (0.0.4)
|
16
|
+
method_source (0.8.2)
|
17
|
+
minitest (5.8.3)
|
18
|
+
mocha (1.1.0)
|
19
|
+
metaclass (~> 0.0.1)
|
20
|
+
net-ssh (3.0.2)
|
21
|
+
pry (0.10.3)
|
22
|
+
coderay (~> 1.1.0)
|
23
|
+
method_source (~> 0.8.1)
|
24
|
+
slop (~> 3.4)
|
25
|
+
rake (10.4.2)
|
26
|
+
rugged (0.23.3)
|
27
|
+
slop (3.6.0)
|
28
|
+
|
29
|
+
PLATFORMS
|
30
|
+
ruby
|
31
|
+
|
32
|
+
DEPENDENCIES
|
33
|
+
bundler (~> 1.10)
|
34
|
+
minitest (~> 5.8)
|
35
|
+
mocha (~> 1.1)
|
36
|
+
oxidized!
|
37
|
+
pry (~> 0)
|
38
|
+
rake (~> 10.0)
|
39
|
+
|
40
|
+
BUNDLED WITH
|
41
|
+
1.11.2
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Oxidized
|
1
|
+
# Oxidized [](https://travis-ci.org/Shopify/oxidized)
|
2
2
|
|
3
3
|
[](http://badge.fury.io/rb/oxidized)
|
4
4
|
|
@@ -42,39 +42,66 @@ Oxidized is a network device configuration backup tool. It's a RANCID replacemen
|
|
42
42
|
|
43
43
|
# Supported OS types
|
44
44
|
|
45
|
-
* A10 Networks
|
46
|
-
|
47
|
-
* Alcatel-Lucent
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
*
|
54
|
-
|
55
|
-
*
|
56
|
-
|
57
|
-
*
|
58
|
-
|
59
|
-
*
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
*
|
65
|
-
|
66
|
-
*
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
*
|
74
|
-
|
75
|
-
*
|
76
|
-
|
77
|
-
|
45
|
+
* A10 Networks
|
46
|
+
* ACOS
|
47
|
+
* Alcatel-Lucent
|
48
|
+
* ISAM
|
49
|
+
* AOS
|
50
|
+
* AOS7
|
51
|
+
* Wireless
|
52
|
+
* TiMOS
|
53
|
+
* Arista
|
54
|
+
* EOS
|
55
|
+
* Arris
|
56
|
+
* C4CMTS
|
57
|
+
* Aruba
|
58
|
+
* AOSW
|
59
|
+
* Brocade
|
60
|
+
* FabricOS
|
61
|
+
* Ironware
|
62
|
+
* NOS (Network Operating System)
|
63
|
+
* Vyatta
|
64
|
+
* Ciena
|
65
|
+
* SOAS
|
66
|
+
* Cisco
|
67
|
+
* AireOS
|
68
|
+
* ASA
|
69
|
+
* IOS
|
70
|
+
* IOSXR
|
71
|
+
* NXOS
|
72
|
+
* SMB (Nikola series)
|
73
|
+
* Cumulus
|
74
|
+
* Linux
|
75
|
+
* DELL
|
76
|
+
* PowerConnect
|
77
|
+
* AOSW
|
78
|
+
* Extreme Networks
|
79
|
+
* XOS
|
80
|
+
* Force10
|
81
|
+
* FTOS
|
82
|
+
* Force10
|
83
|
+
* DNOS
|
84
|
+
* FortiGate
|
85
|
+
* FortiOS
|
86
|
+
* HP
|
87
|
+
* Comware (HP A-series, H3C, 3Com)
|
88
|
+
* Procurve
|
89
|
+
* Huawei
|
90
|
+
* VRP
|
91
|
+
* Juniper
|
92
|
+
* JunOS
|
93
|
+
* ScreenOS (Netscreen)
|
94
|
+
* Mikrotik
|
95
|
+
* RouterOS
|
96
|
+
* MRV
|
97
|
+
* MasterOS
|
98
|
+
* Ubiquiti
|
99
|
+
* AirOS
|
100
|
+
* Edgeos
|
101
|
+
* Palo Alto
|
102
|
+
* PANOS
|
103
|
+
* Zyxel
|
104
|
+
* ZyNOS
|
78
105
|
|
79
106
|
|
80
107
|
# Installation
|
@@ -113,7 +140,7 @@ Oxidized supports ```CSV```, ```SQLite``` and ```HTTP``` as source backends. The
|
|
113
140
|
|
114
141
|
Possible outputs are either ```file``` or ```git```. The file backend takes a destination directory as argument and will keep a file per device, with most recent running version of a device. The GIT backend (recommended) will initialize an empty GIT repository in the specified path and create a new commit on every configuration change. Take a look at the [Cookbook](#cookbook) for more details.
|
115
142
|
|
116
|
-
Maps define how to map a model's fields to model [model fields](https://github.com/ytti/oxidized/tree/master/lib/oxidized/model). Most of the settings should be self explanatory, log is ignored if
|
143
|
+
Maps define how to map a model's fields to model [model fields](https://github.com/ytti/oxidized/tree/master/lib/oxidized/model). Most of the settings should be self explanatory, log is ignored if `use_syslog`(requires Ruby >= 2.0) is set to `true`.
|
117
144
|
|
118
145
|
First create the directory where the CSV ```output``` is going to store device configs and start Oxidized once.
|
119
146
|
```
|
@@ -444,6 +471,8 @@ OX_NODE_MSG
|
|
444
471
|
OX_NODE_GROUP
|
445
472
|
OX_JOB_STATUS
|
446
473
|
OX_JOB_TIME
|
474
|
+
OX_REPO_COMMITREF
|
475
|
+
OX_REPO_NAME
|
447
476
|
```
|
448
477
|
|
449
478
|
Exec hook recognizes following configuration keys:
|
data/Rakefile
CHANGED
@@ -1,10 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'bundler'
|
4
|
-
# Bundler.setup
|
5
|
-
rescue LoadError
|
6
|
-
warn 'bundler missing'
|
7
|
-
end
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
8
3
|
|
9
4
|
gemspec = eval(File.read(Dir['*.gemspec'].first))
|
10
5
|
file = [gemspec.name, gemspec.version].join('-') + '.gem'
|
@@ -17,8 +12,9 @@ end
|
|
17
12
|
desc 'Run minitest'
|
18
13
|
task :test do
|
19
14
|
Rake::TestTask.new do |t|
|
20
|
-
t.libs
|
21
|
-
t.test_files = FileList['spec
|
15
|
+
t.libs << 'spec'
|
16
|
+
t.test_files = FileList['spec/**/*_spec.rb']
|
17
|
+
t.warning = true
|
22
18
|
t.verbose = true
|
23
19
|
end
|
24
20
|
end
|
@@ -49,3 +45,5 @@ desc 'Push to rubygems'
|
|
49
45
|
task :push => :tag do
|
50
46
|
system "gem push gems/#{file}"
|
51
47
|
end
|
48
|
+
|
49
|
+
task default: :test
|
data/bin/console
ADDED
data/bin/oxidized
CHANGED
@@ -23,12 +23,12 @@ json.each do |node|
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
if
|
27
|
-
puts '[WARN] Pending backup: ' + pending_nodes.join(',')
|
28
|
-
exit 1
|
29
|
-
elsif critical
|
26
|
+
if critical
|
30
27
|
puts '[CRIT] Unable to backup: ' + critical_nodes.join(',')
|
31
28
|
exit 2
|
29
|
+
elsif pending
|
30
|
+
puts '[WARN] Pending backup: ' + pending_nodes.join(',')
|
31
|
+
exit 1
|
32
32
|
else
|
33
33
|
puts '[OK] Backup of all nodes completed successfully.'
|
34
34
|
exit 0
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#
|
3
|
+
# A script to maintain a local working copy of an oxidized configuration
|
4
|
+
# repository and mail out diffs for configuration changes
|
5
|
+
#
|
6
|
+
# Copyright 2016 Nick Hilliard <nick@foobar.org>, All Rights Reserved
|
7
|
+
#
|
8
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
9
|
+
# you may not use this file except in compliance with the License.
|
10
|
+
# You may obtain a copy of the License at
|
11
|
+
#
|
12
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
#
|
14
|
+
# Unless required by applicable law or agreed to in writing, software
|
15
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
16
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
17
|
+
# See the License for the specific language governing permissions and
|
18
|
+
# limitations under the License.
|
19
|
+
#
|
20
|
+
# usage: add the following hook to the oxidized config file:
|
21
|
+
#
|
22
|
+
# hooks:
|
23
|
+
# email_output:
|
24
|
+
# type: exec
|
25
|
+
# events: [post_store, node_fail]
|
26
|
+
# cmd: 'update-local-repo.sh ~/gitdir/ | mail -s "Oxidized updates for ${OX_NODE_NAME}" update-recipient@example.com'
|
27
|
+
# async: true
|
28
|
+
# timeout: 120
|
29
|
+
#
|
30
|
+
#
|
31
|
+
# The script takes a single argument, namely a git working directory name,
|
32
|
+
# e.g. "~/gitdir/". This is only used as a staging directory and should
|
33
|
+
# not be set to be the same as the git repo directory.
|
34
|
+
#
|
35
|
+
|
36
|
+
PATH=${PATH}:/usr/local/bin:/usr/local/sbin
|
37
|
+
export PATH
|
38
|
+
|
39
|
+
gitdir=$1
|
40
|
+
|
41
|
+
if [ X${OX_REPO_COMMITREF} = "X" ]; then
|
42
|
+
echo \$OX_REPO_COMMITREF not set
|
43
|
+
exit 64
|
44
|
+
fi
|
45
|
+
|
46
|
+
if [ X${OX_REPO_NAME} = "X" ]; then
|
47
|
+
echo \$OX_REPO_NAME not set
|
48
|
+
exit 64
|
49
|
+
fi
|
50
|
+
|
51
|
+
if [ ! -d ${gitdir}/.git ]; then
|
52
|
+
git clone -q ${OX_REPO_NAME} ${gitdir}
|
53
|
+
|
54
|
+
ret=$?
|
55
|
+
if [ X"${ret}" != X0 ] && [ X"${ret}" != X1 ]; then
|
56
|
+
echo git clone failed: aborting.
|
57
|
+
exit 128
|
58
|
+
fi
|
59
|
+
fi
|
60
|
+
|
61
|
+
cd ${gitdir}
|
62
|
+
|
63
|
+
git pull -q > /dev/null 2>&1
|
64
|
+
ret=$?
|
65
|
+
if [ X"${ret}" != X0 ] && [ X"${ret}" != X1 ]; then
|
66
|
+
echo git pull failed: aborting.
|
67
|
+
exit 128
|
68
|
+
fi
|
69
|
+
|
70
|
+
# Git is probably working at this stage, so safe to emit more info
|
71
|
+
|
72
|
+
echo "Node name: ${OX_NODE_NAME}"
|
73
|
+
echo "Group Name: ${OX_NODE_GROUP}"
|
74
|
+
echo "Job Time: ${OX_JOB_TIME}"
|
75
|
+
echo "Git Commit ID: ${OX_REPO_COMMITREF}"
|
76
|
+
echo "Git Repo: ${OX_REPO_NAME}"
|
77
|
+
echo "Local working dir: ${gitdir}"
|
78
|
+
echo ""
|
79
|
+
|
80
|
+
git diff --no-color ${OX_REPO_COMMITREF}~1..${OX_REPO_COMMITREF}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
start on started networking
|
2
|
+
|
3
|
+
respawn
|
4
|
+
|
5
|
+
setuid oxidized
|
6
|
+
setgid oxidized
|
7
|
+
|
8
|
+
chdir /home/oxidized
|
9
|
+
|
10
|
+
env HOME=/home/oxidized
|
11
|
+
|
12
|
+
pre-start script
|
13
|
+
test -x /usr/local/rvm/wrappers/ruby-2.1.2/oxidized || { stop; exit 0; }
|
14
|
+
end script
|
15
|
+
|
16
|
+
script
|
17
|
+
exec /usr/local/rvm/wrappers/ruby-2.1.2/oxidized
|
18
|
+
end script
|
data/lib/oxidized.rb
CHANGED
@@ -1,6 +1,49 @@
|
|
1
1
|
module Oxidized
|
2
2
|
class OxidizedError < StandardError; end
|
3
|
-
|
4
|
-
Directory = File.expand_path
|
3
|
+
|
4
|
+
Directory = File.expand_path(File.join(File.dirname(__FILE__), '../'))
|
5
|
+
|
6
|
+
require 'oxidized/string'
|
7
|
+
require 'oxidized/config'
|
8
|
+
require 'oxidized/config/vars'
|
9
|
+
require 'oxidized/worker'
|
10
|
+
require 'oxidized/nodes'
|
11
|
+
require 'oxidized/manager'
|
12
|
+
require 'oxidized/hook'
|
5
13
|
require 'oxidized/core'
|
14
|
+
|
15
|
+
def self.asetus
|
16
|
+
@@asetus
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.asetus=(val)
|
20
|
+
@@asetus = val
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.config
|
24
|
+
asetus.cfg
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.logger
|
28
|
+
@@logger
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.logger=(val)
|
32
|
+
@@logger = val
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.setup_logger
|
36
|
+
self.logger = if config.has_key?('use_syslog') && config.use_syslog
|
37
|
+
require 'syslog/logger'
|
38
|
+
Syslog::Logger.new('oxidized')
|
39
|
+
else
|
40
|
+
require 'logger'
|
41
|
+
if config.has_key?('log')
|
42
|
+
Logger.new(config.log)
|
43
|
+
else
|
44
|
+
Logger.new(STDERR)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
logger.level = Logger::INFO unless config.debug
|
48
|
+
end
|
6
49
|
end
|
data/lib/oxidized/cli.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
module Oxidized
|
2
2
|
class CLI
|
3
|
-
require 'oxidized'
|
4
3
|
require 'slop'
|
4
|
+
require 'oxidized'
|
5
5
|
|
6
6
|
def run
|
7
|
+
check_pid
|
7
8
|
Process.daemon if @opts[:daemonize]
|
9
|
+
write_pid
|
8
10
|
begin
|
11
|
+
Oxidized.logger.info "Oxidized starting, running as pid #{$$}"
|
9
12
|
Oxidized.new
|
10
13
|
rescue => error
|
11
14
|
crash error
|
@@ -16,13 +19,16 @@ module Oxidized
|
|
16
19
|
private
|
17
20
|
|
18
21
|
def initialize
|
19
|
-
Log.info "Oxidized starting, running as pid #{$$}"
|
20
22
|
_args, @opts = parse_opts
|
21
|
-
|
23
|
+
|
24
|
+
Config.load(@opts)
|
25
|
+
Oxidized.setup_logger
|
26
|
+
|
27
|
+
@pidfile = File.expand_path("pid")
|
22
28
|
end
|
23
29
|
|
24
30
|
def crash error
|
25
|
-
|
31
|
+
Oxidized.logger.fatal "Oxidized crashed, crashfile written in #{Config::Crash}"
|
26
32
|
open Config::Crash, 'w' do |file|
|
27
33
|
file.puts '-' * 50
|
28
34
|
file.puts Time.now.utc
|
@@ -40,5 +46,49 @@ module Oxidized
|
|
40
46
|
end
|
41
47
|
[opts.parse!, opts]
|
42
48
|
end
|
49
|
+
|
50
|
+
def pidfile
|
51
|
+
@pidfile
|
52
|
+
end
|
53
|
+
|
54
|
+
def pidfile?
|
55
|
+
!!pidfile
|
56
|
+
end
|
57
|
+
|
58
|
+
def write_pid
|
59
|
+
if pidfile?
|
60
|
+
begin
|
61
|
+
File.open(pidfile, ::File::CREAT | ::File::EXCL | ::File::WRONLY){|f| f.write("#{Process.pid}") }
|
62
|
+
at_exit { File.delete(pidfile) if File.exists?(pidfile) }
|
63
|
+
rescue Errno::EEXIST
|
64
|
+
check_pid
|
65
|
+
retry
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_pid
|
71
|
+
if pidfile?
|
72
|
+
case pid_status(pidfile)
|
73
|
+
when :running, :not_owned
|
74
|
+
puts "A server is already running. Check #{pidfile}"
|
75
|
+
exit(1)
|
76
|
+
when :dead
|
77
|
+
File.delete(pidfile)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def pid_status(pidfile)
|
83
|
+
return :exited unless File.exists?(pidfile)
|
84
|
+
pid = ::File.read(pidfile).to_i
|
85
|
+
return :dead if pid == 0
|
86
|
+
Process.kill(0, pid)
|
87
|
+
:running
|
88
|
+
rescue Errno::ESRCH
|
89
|
+
:dead
|
90
|
+
rescue Errno::EPERM
|
91
|
+
:not_owned
|
92
|
+
end
|
43
93
|
end
|
44
94
|
end
|