oxidized 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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