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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -0
  3. data/CHANGELOG.md +6 -0
  4. data/Gemfile.lock +41 -0
  5. data/README.md +64 -35
  6. data/Rakefile +7 -9
  7. data/bin/console +9 -0
  8. data/bin/oxidized +1 -1
  9. data/extra/nagios_check_failing_nodes.rb +4 -4
  10. data/extra/oxidized-report-git-commits +80 -0
  11. data/extra/rvm.oxidized.upstart +18 -0
  12. data/lib/oxidized.rb +45 -2
  13. data/lib/oxidized/cli.rb +54 -4
  14. data/lib/oxidized/config.rb +45 -39
  15. data/lib/oxidized/config/vars.rb +8 -3
  16. data/lib/oxidized/core.rb +5 -12
  17. data/lib/oxidized/hook.rb +4 -4
  18. data/lib/oxidized/hook/exec.rb +2 -0
  19. data/lib/oxidized/hook/githubrepo.rb +57 -0
  20. data/lib/oxidized/input/cli.rb +2 -1
  21. data/lib/oxidized/input/ftp.rb +3 -3
  22. data/lib/oxidized/input/ssh.rb +9 -9
  23. data/lib/oxidized/input/telnet.rb +3 -3
  24. data/lib/oxidized/job.rb +3 -3
  25. data/lib/oxidized/model/fortios.rb +1 -1
  26. data/lib/oxidized/model/junos.rb +8 -10
  27. data/lib/oxidized/model/model.rb +3 -2
  28. data/lib/oxidized/model/powerconnect.rb +11 -6
  29. data/lib/oxidized/model/saos.rb +24 -0
  30. data/lib/oxidized/node.rb +16 -16
  31. data/lib/oxidized/nodes.rb +12 -12
  32. data/lib/oxidized/output/file.rb +15 -3
  33. data/lib/oxidized/output/git.rb +10 -7
  34. data/lib/oxidized/source/csv.rb +7 -7
  35. data/lib/oxidized/source/http.rb +1 -1
  36. data/lib/oxidized/source/source.rb +1 -1
  37. data/lib/oxidized/source/sql.rb +7 -7
  38. data/lib/oxidized/string.rb +1 -1
  39. data/lib/oxidized/version.rb +3 -0
  40. data/lib/oxidized/worker.rb +11 -9
  41. data/oxidized.gemspec +12 -3
  42. metadata +75 -7
  43. data/lib/oxidized/log.rb +0 -22
  44. data/spec/nodes_spec.rb +0 -46
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dd1e30df648aee0f0e1a19d7a55bb91879e0456b
4
- data.tar.gz: 239581a70a3709f67173cb59bf0288bcff6a4b7d
3
+ metadata.gz: 4f601ebdf3c7562322e2b76313f60e4128863968
4
+ data.tar.gz: c0151bcf8e6c02d53511321f198bdd7fd55ac1cf
5
5
  SHA512:
6
- metadata.gz: 98c9644577c24e064c415e985b09f501ef4ce9153a9ab3e7921fcb6093057e037cccc3157c8d2eca71660641501670e9840a57abd45d330ad5b482e8ec640148
7
- data.tar.gz: 4c9cfe10817d51454ceaca602e10d8dc08d283b8f7a1c850185064369840eb0c80f6479a513ffa2fcbcdbdad36b265eee92fcda278c8b0f10e5b7ad1dda7d2c0
6
+ metadata.gz: ff1578ea27961bdf57d32433da245795a880f95e6698f1f2b37692617d4779467673c78a1e27318204c8fc5b0ef4bbb05c379bee870f1fe59365727bef7a8222
7
+ data.tar.gz: fde31a1ef6e58ceebe9b1bcc822efdcc37971c234b474f64daa679bb50c87f308e474c7aad132ac41f837be91e4034aaba8db346fed987cc3f3a6dea7846bc3d
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.6
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 [![Build Status](https://travis-ci.org/Shopify/oxidized.svg)](https://travis-ci.org/Shopify/oxidized)
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/oxidized.svg)](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 ACOS
46
- * Alcatel-Lucent ISAM 7302/7330
47
- * Alcatel-Lucent Operating System AOS
48
- * Alcatel-Lucent Operating System AOS7
49
- * Alcatel-Lucent Operating System Wireless
50
- * Alcatel-Lucent TiMOS
51
- * Arista EOS
52
- * Brocade Fabric OS
53
- * Brocade Ironware
54
- * Brocade NOS (Network Operating System)
55
- * Brocade Vyatta
56
- * Cisco AireOS
57
- * Cisco ASA
58
- * Cisco IOS
59
- * Cisco IOS-XR
60
- * Cisco NXOS
61
- * Cisco SMB (Nikola series)
62
- * Cumulus Linux
63
- * DELL PowerConnect
64
- * Extreme Networks XOS
65
- * Force10 FTOS
66
- * Force10 NDOS
67
- * FortiGate FortiOS
68
- * HP Comware (HP A-series, H3C, 3Com)
69
- * HP ProCurve
70
- * Huawei VRP
71
- * Juniper JunOS
72
- * Juniper ScreenOS (Netscreen)
73
- * Mikrotik RouterOS
74
- * MRV Master-OS
75
- * Ubiquiti AirOS
76
- * Palo Alto PAN-OS
77
- * Zyxel ZyNOS
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 Syslog::Logger exists (>=2.0) and syslog is used instead.
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
- begin
2
- require 'rake/testtask'
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.push "lib"
21
- t.test_files = FileList['spec/*_spec.rb']
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
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'oxidized'
7
+ require 'pry'
8
+
9
+ Pry.start
data/bin/oxidized CHANGED
@@ -9,5 +9,5 @@ begin
9
9
  Oxidized::CLI.new.run
10
10
  rescue => error
11
11
  warn "#{error}"
12
- raise if Oxidized::CFG.debug
12
+ raise if Oxidized.config.debug
13
13
  end
@@ -23,12 +23,12 @@ json.each do |node|
23
23
  end
24
24
  end
25
25
 
26
- if pending
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
- Encoding.default_external = 'UTF-8'
4
- Directory = File.expand_path File.join File.dirname(__FILE__), '../'
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
- CFG.debug = true if @opts[:debug]
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
- Log.fatal "Oxidized crashed, crashfile written in #{Config::Crash}"
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