summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/oxidized/cli.rb6
-rw-r--r--lib/oxidized/config.rb16
-rw-r--r--lib/oxidized/config/vars.rb6
-rw-r--r--lib/oxidized/core.rb6
-rw-r--r--lib/oxidized/hook.rb128
-rw-r--r--lib/oxidized/hook/awssns.rb5
-rw-r--r--lib/oxidized/hook/ciscosparkdiff.rb49
-rw-r--r--lib/oxidized/hook/exec.rb12
-rw-r--r--lib/oxidized/hook/githubrepo.rb34
-rw-r--r--lib/oxidized/hook/slackdiff.rb53
-rw-r--r--lib/oxidized/hook/xmppdiff.rb58
-rw-r--r--lib/oxidized/input/cli.rb11
-rw-r--r--lib/oxidized/input/ftp.rb15
-rw-r--r--lib/oxidized/input/ssh.rb39
-rw-r--r--lib/oxidized/input/telnet.rb50
-rw-r--r--lib/oxidized/jobs.rb7
-rw-r--r--lib/oxidized/manager.rb13
-rw-r--r--lib/oxidized/model/acos.rb31
-rw-r--r--lib/oxidized/model/acsw.rb62
-rw-r--r--lib/oxidized/model/aen.rb19
-rw-r--r--lib/oxidized/model/aireos.rb10
-rw-r--r--lib/oxidized/model/airos.rb13
-rw-r--r--lib/oxidized/model/alteonos.rb58
-rw-r--r--lib/oxidized/model/alvarion.rb6
-rw-r--r--lib/oxidized/model/aos.rb6
-rw-r--r--lib/oxidized/model/aos7.rb5
-rw-r--r--lib/oxidized/model/aosw.rb30
-rw-r--r--lib/oxidized/model/apc_aos.rb3
-rw-r--r--lib/oxidized/model/arbos.rb26
-rw-r--r--lib/oxidized/model/aricentiss.rb51
-rw-r--r--lib/oxidized/model/asa.rb78
-rw-r--r--lib/oxidized/model/asyncos.rb46
-rw-r--r--lib/oxidized/model/audiocodes.rb28
-rw-r--r--lib/oxidized/model/awplus.rb84
-rw-r--r--lib/oxidized/model/boss.rb75
-rw-r--r--lib/oxidized/model/br6910.rb88
-rw-r--r--lib/oxidized/model/c4cmts.rb8
-rw-r--r--lib/oxidized/model/catos.rb2
-rw-r--r--lib/oxidized/model/cisconga.rb17
-rw-r--r--lib/oxidized/model/ciscosma.rb42
-rw-r--r--lib/oxidized/model/ciscosmb.rb16
-rw-r--r--lib/oxidized/model/comware.rb24
-rw-r--r--lib/oxidized/model/coriant8600.rb8
-rw-r--r--lib/oxidized/model/coriantgroove.rb28
-rw-r--r--lib/oxidized/model/corianttmos.rb4
-rw-r--r--lib/oxidized/model/cumulus.rb60
-rw-r--r--lib/oxidized/model/datacom.rb2
-rw-r--r--lib/oxidized/model/dcnos.rb46
-rw-r--r--lib/oxidized/model/dlink.rb3
-rw-r--r--lib/oxidized/model/dnos.rb14
-rw-r--r--lib/oxidized/model/edgecos.rb45
-rw-r--r--lib/oxidized/model/edgeos.rb8
-rw-r--r--lib/oxidized/model/edgeswitch.rb4
-rw-r--r--lib/oxidized/model/enterasys.rb28
-rw-r--r--lib/oxidized/model/eos.rb14
-rw-r--r--lib/oxidized/model/fabricos.rb8
-rw-r--r--lib/oxidized/model/fiberdriver.rb2
-rw-r--r--lib/oxidized/model/firewareos.rb13
-rw-r--r--lib/oxidized/model/fortios.rb25
-rw-r--r--lib/oxidized/model/ftos.rb8
-rw-r--r--lib/oxidized/model/fujitsupy.rb6
-rw-r--r--lib/oxidized/model/gaiaos.rb16
-rw-r--r--lib/oxidized/model/gcombnps.rb82
-rw-r--r--lib/oxidized/model/hatteras.rb13
-rw-r--r--lib/oxidized/model/hirschmann.rb39
-rw-r--r--lib/oxidized/model/hpebladesystem.rb36
-rw-r--r--lib/oxidized/model/hpemsa.rb10
-rw-r--r--lib/oxidized/model/ios.rb106
-rw-r--r--lib/oxidized/model/iosxe.rb5
-rw-r--r--lib/oxidized/model/iosxr.rb5
-rw-r--r--lib/oxidized/model/ipos.rb10
-rw-r--r--lib/oxidized/model/ironware.rb38
-rw-r--r--lib/oxidized/model/isam.rb9
-rw-r--r--lib/oxidized/model/junos.rb16
-rw-r--r--lib/oxidized/model/masteros.rb4
-rw-r--r--lib/oxidized/model/mlnxos.rb13
-rw-r--r--lib/oxidized/model/model.rb22
-rw-r--r--lib/oxidized/model/mtrlrfs.rb5
-rw-r--r--lib/oxidized/model/ndms.rb24
-rw-r--r--lib/oxidized/model/netgear.rb39
-rw-r--r--lib/oxidized/model/netscaler.rb2
-rw-r--r--lib/oxidized/model/nos.rb4
-rw-r--r--lib/oxidized/model/nxos.rb12
-rw-r--r--lib/oxidized/model/oneos.rb56
-rw-r--r--lib/oxidized/model/opengear.rb6
-rw-r--r--lib/oxidized/model/opnsense.rb19
-rw-r--r--lib/oxidized/model/outputs.rb4
-rw-r--r--lib/oxidized/model/panos.rb5
-rw-r--r--lib/oxidized/model/pfsense.rb13
-rw-r--r--lib/oxidized/model/planet.rb21
-rw-r--r--lib/oxidized/model/powerconnect.rb17
-rw-r--r--lib/oxidized/model/procurve.rb39
-rw-r--r--lib/oxidized/model/quantaos.rb10
-rw-r--r--lib/oxidized/model/routeros.rb26
-rw-r--r--lib/oxidized/model/saos.rb5
-rw-r--r--lib/oxidized/model/screenos.rb8
-rw-r--r--lib/oxidized/model/sgos.rb45
-rw-r--r--lib/oxidized/model/siklu.rb17
-rw-r--r--lib/oxidized/model/slxos.rb59
-rw-r--r--lib/oxidized/model/sros.rb117
-rw-r--r--lib/oxidized/model/supermicro.rb47
-rw-r--r--lib/oxidized/model/timos.rb104
-rw-r--r--lib/oxidized/model/tmos.rb4
-rw-r--r--lib/oxidized/model/tplink.rb61
-rw-r--r--lib/oxidized/model/trango.rb13
-rw-r--r--lib/oxidized/model/ucs.rb30
-rw-r--r--lib/oxidized/model/voltaire.rb53
-rw-r--r--lib/oxidized/model/voss.rb41
-rw-r--r--lib/oxidized/model/vrp.rb15
-rw-r--r--lib/oxidized/model/vyatta.rb10
-rw-r--r--lib/oxidized/model/weos.rb20
-rw-r--r--lib/oxidized/model/xos.rb15
-rw-r--r--lib/oxidized/model/zhoneolt.rb4
-rw-r--r--lib/oxidized/model/zynos.rb4
-rw-r--r--lib/oxidized/model/zynoscli.rb36
-rw-r--r--lib/oxidized/node.rb65
-rw-r--r--lib/oxidized/node/stats.rb3
-rw-r--r--lib/oxidized/nodes.rb20
-rw-r--r--lib/oxidized/output/file.rb83
-rw-r--r--lib/oxidized/output/git.rb228
-rw-r--r--lib/oxidized/output/gitcrypt.rb243
-rw-r--r--lib/oxidized/output/http.rb50
-rw-r--r--lib/oxidized/output/output.rb3
-rw-r--r--lib/oxidized/source/csv.rb89
-rw-r--r--lib/oxidized/source/http.rb112
-rw-r--r--lib/oxidized/source/source.rb13
-rw-r--r--lib/oxidized/source/sql.rb106
-rw-r--r--lib/oxidized/string.rb5
-rw-r--r--lib/oxidized/version.rb18
-rw-r--r--lib/oxidized/worker.rb34
130 files changed, 3075 insertions, 1093 deletions
diff --git a/lib/oxidized/cli.rb b/lib/oxidized/cli.rb
index 9a09d41..23cc28c 100644
--- a/lib/oxidized/cli.rb
+++ b/lib/oxidized/cli.rb
@@ -40,11 +40,11 @@ module Oxidized
end
def parse_opts
- opts = Slop.new(:help=>true) do
+ opts = Slop.new(:help => true) do
on 'd', 'debug', 'turn on debugging'
on 'daemonize', 'Daemonize/fork the process'
on 'v', 'version', 'show version' do
- puts Oxidized::VERSION
+ puts Oxidized::VERSION_FULL
Kernel.exit
end
end
@@ -62,7 +62,7 @@ module Oxidized
def write_pid
if pidfile?
begin
- File.open(pidfile, ::File::CREAT | ::File::EXCL | ::File::WRONLY){|f| f.write("#{Process.pid}") }
+ File.open(pidfile, ::File::CREAT | ::File::EXCL | ::File::WRONLY) { |f| f.write("#{Process.pid}") }
at_exit { File.delete(pidfile) if File.exists?(pidfile) }
rescue Errno::EEXIST
check_pid
diff --git a/lib/oxidized/config.rb b/lib/oxidized/config.rb
index a92cea6..0a8fdfd 100644
--- a/lib/oxidized/config.rb
+++ b/lib/oxidized/config.rb
@@ -13,7 +13,7 @@ module Oxidized
HookDir = File.join Directory, %w(lib oxidized hook)
Sleep = 1
- def self.load(cmd_opts={})
+ def self.load(cmd_opts = {})
asetus = Asetus.new(name: 'oxidized', load: false, key_to_s: true)
Oxidized.asetus = asetus
@@ -29,13 +29,17 @@ module Oxidized
asetus.default.retries = 3
asetus.default.prompt = /^([\w.@-]+[#>]\s?)$/
asetus.default.rest = '127.0.0.1:8888' # or false to disable
- asetus.default.vars = {} # could be 'enable'=>'enablePW'
- asetus.default.groups = {} # group level configuration
+ asetus.default.next_adds_job = false # if true, /next adds job, so device is fetched immmeiately
+ asetus.default.vars = {} # could be 'enable'=>'enablePW'
+ asetus.default.groups = {} # group level configuration
+ asetus.default.models = {} # model level configuration
asetus.default.pid = File.join(Oxidized::Config::Root, 'pid')
- asetus.default.input.default = 'ssh, telnet'
- asetus.default.input.debug = false # or String for session log file
- asetus.default.input.ssh.secure = false # complain about changed certs
+ asetus.default.input.default = 'ssh, telnet'
+ asetus.default.input.debug = false # or String for session log file
+ asetus.default.input.ssh.secure = false # complain about changed certs
+ asetus.default.input.ftp.passive = true # ftp passive mode
+ asetus.default.input.utf8_encoded = true # configuration is utf8 encoded or ascii-8bit
asetus.default.output.default = 'file' # file, git
asetus.default.source.default = 'csv' # csv, sql
diff --git a/lib/oxidized/config/vars.rb b/lib/oxidized/config/vars.rb
index 09f9781..d926ee2 100644
--- a/lib/oxidized/config/vars.rb
+++ b/lib/oxidized/config/vars.rb
@@ -8,8 +8,12 @@ module Oxidized::Config::Vars
r ||= Oxidized.config.groups[@node.group].vars[name.to_s]
end
end
+ if Oxidized.config.models.has_key?(@node.model.class.name.to_s.downcase)
+ if Oxidized.config.models[@node.model.class.name.to_s.downcase].vars.has_key?(name.to_s)
+ r ||= Oxidized.config.models[@node.model.class.name.to_s.downcase].vars[name.to_s]
+ end
+ end
r ||= Oxidized.config.vars[name.to_s] if Oxidized.config.vars.has_key?(name.to_s)
r
end
end
-
diff --git a/lib/oxidized/core.rb b/lib/oxidized/core.rb
index e007c9d..440d8e2 100644
--- a/lib/oxidized/core.rb
+++ b/lib/oxidized/core.rb
@@ -11,9 +11,9 @@ module Oxidized
def initialize args
Oxidized.mgr = Manager.new
Oxidized.Hooks = HookManager.from_config(Oxidized.config)
- nodes = Nodes.new
+ nodes = Nodes.new
raise NoNodesFound, 'source returns no usable nodes' if nodes.size == 0
- @worker = Worker.new nodes
+ @worker = Worker.new nodes
trap('HUP') { nodes.load }
if Oxidized.config.rest?
begin
@@ -22,7 +22,7 @@ module Oxidized
raise OxidizedError, 'oxidized-web not found: sudo gem install oxidized-web - \
or disable web support by setting "rest: false" in your configuration'
end
- @rest = API::Web.new nodes, Oxidized.config.rest
+ @rest = API::Web.new nodes, Oxidized.config.rest
@rest.run
end
run
diff --git a/lib/oxidized/hook.rb b/lib/oxidized/hook.rb
index 029688d..915299b 100644
--- a/lib/oxidized/hook.rb
+++ b/lib/oxidized/hook.rb
@@ -1,88 +1,88 @@
module Oxidized
-class HookManager
- class << self
- def from_config cfg
- mgr = new
- cfg.hooks.each do |name,h_cfg|
- h_cfg.events.each do |event|
- mgr.register event.to_sym, name, h_cfg.type, h_cfg
+ class HookManager
+ class << self
+ def from_config cfg
+ mgr = new
+ cfg.hooks.each do |name, h_cfg|
+ h_cfg.events.each do |event|
+ mgr.register event.to_sym, name, h_cfg.type, h_cfg
+ end
end
+ mgr
end
- mgr
end
- end
-
- # HookContext is passed to each hook. It can contain anything related to the
- # event in question. At least it contains the event name
- class HookContext < OpenStruct; end
- # RegisteredHook is a container for a Hook instance
- class RegisteredHook < Struct.new(:name, :hook); end
+ # HookContext is passed to each hook. It can contain anything related to the
+ # event in question. At least it contains the event name
+ class HookContext < OpenStruct; end
- Events = [
- :node_success,
- :node_fail,
- :post_store,
- ]
- attr_reader :registered_hooks
+ # RegisteredHook is a container for a Hook instance
+ class RegisteredHook < Struct.new(:name, :hook); end
- def initialize
- @registered_hooks = Hash.new {|h,k| h[k] = []}
- end
+ Events = [
+ :node_success,
+ :node_fail,
+ :post_store,
+ :nodes_done
+ ]
+ attr_reader :registered_hooks
- def register event, name, hook_type, cfg
- unless Events.include? event
- raise ArgumentError,
- "unknown event #{event}, available: #{Events.join ','}"
+ def initialize
+ @registered_hooks = Hash.new { |h, k| h[k] = [] }
end
- Oxidized.mgr.add_hook hook_type
- begin
- hook = Oxidized.mgr.hook.fetch(hook_type).new
- rescue KeyError
- raise KeyError, "cannot find hook #{hook_type.inspect}"
- end
+ def register event, name, hook_type, cfg
+ unless Events.include? event
+ raise ArgumentError,
+ "unknown event #{event}, available: #{Events.join ','}"
+ end
- hook.cfg = cfg
+ Oxidized.mgr.add_hook hook_type
+ begin
+ hook = Oxidized.mgr.hook.fetch(hook_type).new
+ rescue KeyError
+ raise KeyError, "cannot find hook #{hook_type.inspect}"
+ end
- @registered_hooks[event] << RegisteredHook.new(name, hook)
- Oxidized.logger.debug "Hook #{name.inspect} registered #{hook.class} for event #{event.inspect}"
- end
+ hook.cfg = cfg
- def handle event, ctx_params={}
- ctx = HookContext.new ctx_params
- ctx.event = event
+ @registered_hooks[event] << RegisteredHook.new(name, hook)
+ Oxidized.logger.debug "Hook #{name.inspect} registered #{hook.class} for event #{event.inspect}"
+ end
- @registered_hooks[event].each do |r_hook|
- begin
- r_hook.hook.run_hook ctx
- rescue => e
- Oxidized.logger.error "Hook #{r_hook.name} (#{r_hook.hook}) failed " +
- "(#{e.inspect}) for event #{event.inspect}"
+ def handle event, ctx_params = {}
+ ctx = HookContext.new ctx_params
+ ctx.event = event
+
+ @registered_hooks[event].each do |r_hook|
+ begin
+ r_hook.hook.run_hook ctx
+ rescue => e
+ Oxidized.logger.error "Hook #{r_hook.name} (#{r_hook.hook}) failed " +
+ "(#{e.inspect}) for event #{event.inspect}"
+ end
end
end
end
-end
-# Hook abstract base class
-class Hook
- attr_reader :cfg
+ # Hook abstract base class
+ class Hook
+ attr_reader :cfg
- def initialize
- end
+ def initialize
+ end
- def cfg=(cfg)
- @cfg = cfg
- validate_cfg! if self.respond_to? :validate_cfg!
- end
+ def cfg=(cfg)
+ @cfg = cfg
+ validate_cfg! if self.respond_to? :validate_cfg!
+ end
- def run_hook ctx
- raise NotImplementedError
- end
+ def run_hook ctx
+ raise NotImplementedError
+ end
- def log(msg, level=:info)
- Oxidized.logger.send(level, "#{self.class.name}: #{msg}")
+ def log(msg, level = :info)
+ Oxidized.logger.send(level, "#{self.class.name}: #{msg}")
+ end
end
-
-end
end
diff --git a/lib/oxidized/hook/awssns.rb b/lib/oxidized/hook/awssns.rb
index dbc2d47..183cd2c 100644
--- a/lib/oxidized/hook/awssns.rb
+++ b/lib/oxidized/hook/awssns.rb
@@ -19,9 +19,8 @@ class AwsSns < Oxidized::Hook
:node => ctx.node.name.to_s
)
end
- topic.publish({
+ topic.publish(
message: message.to_json
- })
+ )
end
-
end
diff --git a/lib/oxidized/hook/ciscosparkdiff.rb b/lib/oxidized/hook/ciscosparkdiff.rb
new file mode 100644
index 0000000..e45d7c6
--- /dev/null
+++ b/lib/oxidized/hook/ciscosparkdiff.rb
@@ -0,0 +1,49 @@
+require 'cisco_spark'
+
+# defaults to posting a diff, if messageformat is supplied them a message will be posted too
+# diffenable defaults to true
+# Modified from slackdiff
+
+class CiscoSparkDiff < Oxidized::Hook
+ def validate_cfg!
+ raise KeyError, 'hook.accesskey is required' unless cfg.has_key?('accesskey')
+ raise KeyError, 'hook.space is required' unless cfg.has_key?('space')
+ end
+
+ def run_hook(ctx)
+ return unless ctx.node
+ return unless ctx.event.to_s == "post_store"
+ log "Connecting to Cisco Spark"
+ CiscoSpark.configure do |config|
+ config.api_key = cfg.accesskey
+ config.proxy = cfg.proxy if cfg.has_key?('proxy')
+ end
+ space = cfg.space
+ client = CiscoSpark::Room.new(id: space)
+ client.fetch
+ log "Connected"
+ diffenable = true
+ if cfg.has_key?('diff') == true
+ if cfg.diff == false
+ diffenable = false
+ end
+ end
+ if diffenable == true
+ gitoutput = ctx.node.output.new
+ diff = gitoutput.get_diff ctx.node, ctx.node.group, ctx.commitref, nil
+ title = ctx.node.name.to_s
+ log "Posting diff as snippet to #{cfg.space}"
+ message = CiscoSpark::Message.new(text: 'Device ' + title + ' modified:' + "\n" + diff[:patch].lines.to_a[4..-1].join)
+ room = CiscoSpark::Room.new(id: space)
+ room.send_message(message)
+ end
+ if cfg.has_key?('message') == true
+ log cfg.message
+ msg = cfg.message % { :node => ctx.node.name.to_s, :group => ctx.node.group.to_s, :commitref => ctx.commitref, :model => ctx.node.model.class.name.to_s.downcase }
+ log msg
+ log "Posting message to #{cfg.space}"
+ client.chat_postMessage(channel: cfg.channel, text: msg, as_user: true)
+ end
+ log "Finished"
+ end
+end
diff --git a/lib/oxidized/hook/exec.rb b/lib/oxidized/hook/exec.rb
index 58d6fd5..069b888 100644
--- a/lib/oxidized/hook/exec.rb
+++ b/lib/oxidized/hook/exec.rb
@@ -23,10 +23,9 @@ class Exec < Oxidized::Hook
@cmd = cfg.cmd
raise "invalid cmd value" unless @cmd.is_a?(String) || @cmd.is_a?(Array)
end
-
rescue RuntimeError => e
raise ArgumentError,
- "#{self.class.name}: configuration invalid: #{e.message}"
+ "#{self.class.name}: configuration invalid: #{e.message}"
end
def run_hook ctx
@@ -45,7 +44,7 @@ class Exec < Oxidized::Hook
def run_cmd! env
pid, status = nil, nil
Timeout.timeout(@timeout) do
- pid = spawn env, @cmd , :unsetenv_others => true
+ pid = spawn env, @cmd, :unsetenv_others => true
pid, status = wait2 pid
unless status.exitstatus.zero?
msg = "#{@cmd.inspect} failed with exit value #{status.exitstatus}"
@@ -53,11 +52,11 @@ class Exec < Oxidized::Hook
raise msg
end
end
- rescue TimeoutError
+ rescue Timeout::Error
kill "TERM", pid
msg = "#{@cmd} timed out"
log msg, :error
- raise TimeoutError, msg
+ raise Timeout::Error, msg
end
def make_env ctx
@@ -67,10 +66,11 @@ class Exec < Oxidized::Hook
if ctx.node
env.merge!(
"OX_NODE_NAME" => ctx.node.name.to_s,
+ "OX_NODE_IP" => ctx.node.ip.to_s,
"OX_NODE_FROM" => ctx.node.from.to_s,
"OX_NODE_MSG" => ctx.node.msg.to_s,
"OX_NODE_GROUP" => ctx.node.group.to_s,
- "OX_EVENT" => ctx.event.to_s,
+ "OX_NODE_MODEL" => ctx.node.model.class.name,
"OX_REPO_COMMITREF" => ctx.commitref.to_s,
"OX_REPO_NAME" => ctx.node.repo.to_s,
)
diff --git a/lib/oxidized/hook/githubrepo.rb b/lib/oxidized/hook/githubrepo.rb
index d33e54e..e077d5d 100644
--- a/lib/oxidized/hook/githubrepo.rb
+++ b/lib/oxidized/hook/githubrepo.rb
@@ -35,26 +35,32 @@ class GithubRepo < Oxidized::Hook
end
Rugged::Commit.create(repo, {
- parents: [repo.head.target, their_branch.target],
- tree: merge_index.write_tree(repo),
- message: "Merge remote-tracking branch '#{their_branch.name}'",
- update_ref: "HEAD"
- })
+ parents: [repo.head.target, their_branch.target],
+ tree: merge_index.write_tree(repo),
+ message: "Merge remote-tracking branch '#{their_branch.name}'",
+ update_ref: "HEAD"
+ })
end
private
def credentials
- @credentials ||= if cfg.has_key?('username') && cfg.has_key?('password')
- log "Using https auth", :debug
- Rugged::Credentials::UserPassword.new(username: cfg.username, password: cfg.password)
- else
- if cfg.has_key?('publickey') && cfg.has_key?('privatekey')
- log "Using ssh auth with key", :debug
- Rugged::Credentials::SshKey.new(username: 'git', publickey: File.expand_path(cfg.publickey), privatekey: File.expand_path(cfg.privatekey))
+ Proc.new do |url, username_from_url, allowed_types|
+ if cfg.has_key?('username')
+ git_user = cfg.username
+ else
+ git_user = username_from_url ? username_from_url : 'git'
+ end
+
+ if cfg.has_key?('password')
+ log "Authenticating using username and password as '#{git_user}'", :debug
+ Rugged::Credentials::UserPassword.new(username: git_user, password: cfg.password)
+ elsif cfg.has_key?('publickey') && cfg.has_key?('privatekey')
+ log "Authenticating using ssh keys as '#{git_user}'", :debug
+ Rugged::Credentials::SshKey.new(username: git_user, publickey: File.expand_path(cfg.publickey), privatekey: File.expand_path(cfg.privatekey), passphrase: ENV["OXIDIZED_SSH_PASSPHRASE"])
else
- log "Using ssh auth with agentforwarding", :debug
- Rugged::Credentials::SshKeyFromAgent.new(username: 'git')
+ log "Authenticating using ssh agent as '#{git_user}'", :debug
+ Rugged::Credentials::SshKeyFromAgent.new(username: git_user)
end
end
end
diff --git a/lib/oxidized/hook/slackdiff.rb b/lib/oxidized/hook/slackdiff.rb
new file mode 100644
index 0000000..baaf291
--- /dev/null
+++ b/lib/oxidized/hook/slackdiff.rb
@@ -0,0 +1,53 @@
+require 'slack'
+
+# defaults to posting a diff, if messageformat is supplied them a message will be posted too
+# diffenable defaults to true
+
+class SlackDiff < Oxidized::Hook
+ def validate_cfg!
+ raise KeyError, 'hook.token is required' unless cfg.has_key?('token')
+ raise KeyError, 'hook.channel is required' unless cfg.has_key?('channel')
+ end
+
+ def run_hook(ctx)
+ return unless ctx.node
+ return unless ctx.event.to_s == "post_store"
+ log "Connecting to slack"
+ Slack.configure do |config|
+ config.token = cfg.token
+ config.proxy = cfg.proxy if cfg.has_key?('proxy')
+ end
+ client = Slack::Client.new
+ client.auth_test
+ log "Connected"
+ # diff snippet - default
+ diffenable = true
+ if cfg.has_key?('diff') == true
+ if cfg.diff == false
+ diffenable = false
+ end
+ end
+ if diffenable == true
+ gitoutput = ctx.node.output.new
+ diff = gitoutput.get_diff ctx.node, ctx.node.group, ctx.commitref, nil
+ unless diff == "no diffs"
+ title = "#{ctx.node.name} #{ctx.node.group} #{ctx.node.model.class.name.to_s.downcase}"
+ log "Posting diff as snippet to #{cfg.channel}"
+ client.files_upload(channels: cfg.channel, as_user: true,
+ content: diff[:patch].lines.to_a[4..-1].join,
+ filetype: "diff",
+ title: title,
+ filename: "change")
+ end
+ end
+ # message custom formatted - optional
+ if cfg.has_key?('message') == true
+ log cfg.message
+ msg = cfg.message % { :node => ctx.node.name.to_s, :group => ctx.node.group.to_s, :commitref => ctx.commitref, :model => ctx.node.model.class.name.to_s.downcase }
+ log msg
+ log "Posting message to #{cfg.channel}"
+ client.chat_postMessage(channel: cfg.channel, text: msg, as_user: true)
+ end
+ log "Finished"
+ end
+end
diff --git a/lib/oxidized/hook/xmppdiff.rb b/lib/oxidized/hook/xmppdiff.rb
new file mode 100644
index 0000000..6acb172
--- /dev/null
+++ b/lib/oxidized/hook/xmppdiff.rb
@@ -0,0 +1,58 @@
+require 'xmpp4r'
+require 'xmpp4r/muc/helper/simplemucclient'
+
+class XMPPDiff < Oxidized::Hook
+ def validate_cfg!
+ raise KeyError, 'hook.jid is required' unless cfg.has_key?('jid')
+ raise KeyError, 'hook.password is required' unless cfg.has_key?('password')
+ raise KeyError, 'hook.channel is required' unless cfg.has_key?('channel')
+ raise KeyError, 'hook.nick is required' unless cfg.has_key?('nick')
+ end
+
+ def run_hook(ctx)
+ return unless ctx.node
+ return unless ctx.event.to_s == "post_store"
+ begin
+ Timeout.timeout(15) do
+ gitoutput = ctx.node.output.new
+ diff = gitoutput.get_diff ctx.node, ctx.node.group, ctx.commitref, nil
+
+ interesting = diff[:patch].lines.to_a[4..-1].any? do |line|
+ ["+", "-"].include?(line[0]) and not ["#", "!"].include?(line[1])
+ end
+ interesting &&= diff[:patch].lines.to_a[5..-1].any? { |line| line[0] == '-' }
+ interesting &&= diff[:patch].lines.to_a[5..-1].any? { |line| line[0] == '+' }
+
+ if interesting
+ log "Connecting to XMPP"
+ client = Jabber::Client.new(Jabber::JID.new(cfg.jid))
+ client.connect
+ sleep 1
+ client.auth(cfg.password)
+ sleep 1
+
+ log "Connected"
+
+ m = Jabber::MUC::SimpleMUCClient.new(client)
+ m.join(cfg.channel + "/" + cfg.nick)
+
+ log "Joined"
+
+ title = "#{ctx.node.name} #{ctx.node.group} #{ctx.node.model.class.name.to_s.downcase}"
+ log "Posting diff as snippet to #{cfg.channel}"
+
+ m.say(title + "\n\n" + diff[:patch].lines.to_a[4..-1].join)
+
+ sleep 1
+
+ client.close
+
+ log "Finished"
+
+ end
+ end
+ rescue Timeout::Error
+ log "timed out"
+ end
+ end
+end
diff --git a/lib/oxidized/input/cli.rb b/lib/oxidized/input/cli.rb
index 660e173..d434e33 100644
--- a/lib/oxidized/input/cli.rb
+++ b/lib/oxidized/input/cli.rb
@@ -32,26 +32,25 @@ module Oxidized
@pre_logout.each { |command, block| block ? block.call : (cmd command, nil) }
end
- def post_login _post_login=nil, &block
+ def post_login _post_login = nil, &block
unless @exec
@post_login << [_post_login, block]
end
end
- def pre_logout _pre_logout=nil, &block
+ def pre_logout _pre_logout = nil, &block
unless @exec
- @pre_logout << [_pre_logout, block]
+ @pre_logout << [_pre_logout, block]
end
end
- def username re=/^(Username|login)/
+ def username re = /^(Username|login)/
@username or @username = re
end
- def password re=/^Password/
+ def password re = /^Password/
@password or @password = re
end
-
end
end
end
diff --git a/lib/oxidized/input/ftp.rb b/lib/oxidized/input/ftp.rb
index 80de257..ebe50ef 100644
--- a/lib/oxidized/input/ftp.rb
+++ b/lib/oxidized/input/ftp.rb
@@ -6,20 +6,22 @@ module Oxidized
class FTP < Input
RescueFail = {
:debug => [
- #Net::SSH::Disconnect,
+ # Net::SSH::Disconnect,
],
:warn => [
- #RuntimeError,
- #Net::SSH::AuthenticationFailed,
+ # RuntimeError,
+ # Net::SSH::AuthenticationFailed,
],
}
include Input::CLI
def connect node
- @node = node
+ @node = node
@node.model.cfg['ftp'].each { |cb| instance_exec(&cb) }
@log = File.open(Oxidized::Config::Log + "/#{@node.ip}-ftp", 'w') if Oxidized.config.input.debug?
- @ftp = Net::FTP.new @node.ip, @node.auth[:username], @node.auth[:password]
+ @ftp = Net::FTP.new(@node.ip)
+ @ftp.passive = Oxidized.config.input.ftp.passive
+ @ftp.login @node.auth[:username], @node.auth[:password]
connected?
end
@@ -45,10 +47,9 @@ module Oxidized
def disconnect
@ftp.close
- #rescue Errno::ECONNRESET, IOError
+ # rescue Errno::ECONNRESET, IOError
ensure
@log.close if Oxidized.config.input.debug?
end
-
end
end
diff --git a/lib/oxidized/input/ssh.rb b/lib/oxidized/input/ssh.rb
index 9a5c508..6e86d13 100644
--- a/lib/oxidized/input/ssh.rb
+++ b/lib/oxidized/input/ssh.rb
@@ -24,17 +24,27 @@ module Oxidized
secure = Oxidized.config.input.ssh.secure
@log = File.open(Oxidized::Config::Log + "/#{@node.ip}-ssh", 'w') if Oxidized.config.input.debug?
port = vars(:ssh_port) || 22
- if proxy_host = vars(:ssh_proxy)
- proxy = Net::SSH::Proxy::Command.new("ssh #{proxy_host} -W %h:%p")
- end
+
ssh_opts = {
- :port => port.to_i,
- :password => @node.auth[:password], :timeout => Oxidized.config.timeout,
- :paranoid => secure,
- :auth_methods => %w(none publickey password keyboard-interactive),
- :number_of_password_prompts => 0,
- :proxy => proxy,
+ port: port.to_i,
+ paranoid: secure,
+ keepalive: true,
+ password: @node.auth[:password], :timeout => Oxidized.config.timeout,
+ number_of_password_prompts: 0,
}
+
+ auth_methods = vars(:auth_methods) || %w(none publickey password)
+ ssh_opts[:auth_methods] = auth_methods
+ Oxidized.logger.info "AUTH METHODS::#{auth_methods}"
+
+ if proxy_host = vars(:ssh_proxy)
+ proxy_command = "ssh "
+ proxy_command += "-o StrictHostKeyChecking=no " unless secure
+ proxy_command += "#{proxy_host} -W %h:%p"
+ proxy = Net::SSH::Proxy::Command.new(proxy_command)
+ ssh_opts[:proxy] = proxy
+ end
+
ssh_opts[:keys] = vars(:ssh_keys).is_a?(Array) ? vars(:ssh_keys) : [vars(:ssh_keys)] if vars(:ssh_keys)
ssh_opts[:kex] = vars(:ssh_kex).split(/,\s*/) if vars(:ssh_kex)
ssh_opts[:encryption] = vars(:ssh_encryption).split(/,\s*/) if vars(:ssh_encryption)
@@ -46,7 +56,7 @@ module Oxidized
begin
login
rescue Timeout::Error
- raise PromptUndetect, [ @output, 'not matching configured prompt', @node.prompt ].join(' ')
+ raise PromptUndetect, [@output, 'not matching configured prompt', @node.prompt].join(' ')
end
end
connected?
@@ -56,7 +66,7 @@ module Oxidized
@ssh and not @ssh.closed?
end
- def cmd cmd, expect=node.prompt
+ def cmd cmd, expect = node.prompt
Oxidized.logger.debug "lib/oxidized/input/ssh.rb #{cmd} @ #{node.name} with expect: #{expect.inspect}"
if @exec
@ssh.exec! cmd
@@ -94,7 +104,7 @@ module Oxidized
ch.on_data do |_ch, data|
if Oxidized.config.input.debug?
@log.print data
- @log.fsync
+ @log.flush
end
@output << data
@output = @node.model.expects @output
@@ -122,8 +132,8 @@ module Oxidized
end
end
- def exec state=nil
- state == nil ? @exec : (@exec=state) unless vars :ssh_no_exec
+ def exec state = nil
+ state == nil ? @exec : (@exec = state) unless vars :ssh_no_exec
end
def cmd_shell(cmd, expect_re)
@@ -146,6 +156,5 @@ module Oxidized
end
end
end
-
end
end
diff --git a/lib/oxidized/input/telnet.rb b/lib/oxidized/input/telnet.rb
index a5561b9..b1b3222 100644
--- a/lib/oxidized/input/telnet.rb
+++ b/lib/oxidized/input/telnet.rb
@@ -18,7 +18,7 @@ module Oxidized
'Model' => @node.model }
opt['Output_log'] = Oxidized::Config::Log + "/#{@node.ip}-telnet" if Oxidized.config.input.debug?
- @telnet = Net::Telnet.new opt
+ @telnet = Net::Telnet.new opt
if @node.auth[:username] and @node.auth[:username].length > 0
expect username
@telnet.puts @node.auth[:username]
@@ -28,7 +28,7 @@ module Oxidized
begin
expect @node.prompt
rescue Timeout::Error
- raise PromptUndetect, [ 'unable to detect prompt:', @node.prompt ].join(' ')
+ raise PromptUndetect, ['unable to detect prompt:', @node.prompt].join(' ')
end
end
@@ -36,7 +36,7 @@ module Oxidized
@telnet and not @telnet.sock.closed?
end
- def cmd cmd, expect=@node.prompt
+ def cmd cmd, expect = @node.prompt
Oxidized.logger.debug "Telnet: #{cmd} @#{@node.name}"
args = { 'String' => cmd }
args.merge!({ 'Match' => expect, 'Timeout' => @timeout }) if expect
@@ -64,11 +64,9 @@ module Oxidized
rescue Errno::ECONNRESET
end
end
-
end
end
-
class Net::Telnet
## FIXME: we just need 'line = model.expects line' to handle pager
## how to do this, without redefining the whole damn thing
@@ -86,7 +84,7 @@ class Net::Telnet
elsif options.has_key?("Prompt")
options["Prompt"]
elsif options.has_key?("String")
- Regexp.new( Regexp.quote(options["String"]) )
+ Regexp.new(Regexp.quote(options["String"]))
end
time_out = options["Timeout"] if options.has_key?("Timeout")
waittime = options["Waittime"] if options.has_key?("Waittime")
@@ -102,9 +100,9 @@ class Net::Telnet
line = ''
buf = ''
rest = ''
- until(prompt === line and not IO::select([@sock], nil, nil, waittime))
+ until prompt === line and not IO::select([@sock], nil, nil, waittime)
unless IO::select([@sock], nil, nil, time_out)
- raise TimeoutError, "timed out while waiting for more data"
+ raise Timeout::Error, "timed out while waiting for more data"
end
begin
c = @sock.readpartial(1024 * 1024)
@@ -114,30 +112,30 @@ class Net::Telnet
c = rest + c
if Integer(c.rindex(/#{IAC}#{SE}/no) || 0) <
Integer(c.rindex(/#{IAC}#{SB}/no) || 0)
- buf = preprocess(c[0 ... c.rindex(/#{IAC}#{SB}/no)])
- rest = c[c.rindex(/#{IAC}#{SB}/no) .. -1]
+ buf = preprocess(c[0...c.rindex(/#{IAC}#{SB}/no)])
+ rest = c[c.rindex(/#{IAC}#{SB}/no)..-1]
elsif pt = c.rindex(/#{IAC}[^#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]?\z/no) ||
c.rindex(/\r\z/no)
- buf = preprocess(c[0 ... pt])
- rest = c[pt .. -1]
+ buf = preprocess(c[0...pt])
+ rest = c[pt..-1]
else
buf = preprocess(c)
rest = ''
end
- else
- # Not Telnetmode.
- #
- # We cannot use preprocess() on this data, because that
- # method makes some Telnetmode-specific assumptions.
- buf = rest + c
- rest = ''
- unless @options["Binmode"]
- if pt = buf.rindex(/\r\z/no)
- buf = buf[0 ... pt]
- rest = buf[pt .. -1]
- end
- buf.gsub!(/#{EOL}/no, "\n")
- end
+ else
+ # Not Telnetmode.
+ #
+ # We cannot use preprocess() on this data, because that
+ # method makes some Telnetmode-specific assumptions.
+ buf = rest + c
+ rest = ''
+ unless @options["Binmode"]
+ if pt = buf.rindex(/\r\z/no)
+ buf = buf[0...pt]
+ rest = buf[pt..-1]
+ end
+ buf.gsub!(/#{EOL}/no, "\n")
+ end
end
@log.print(buf) if @options.has_key?("Output_log")
line += buf
diff --git a/lib/oxidized/jobs.rb b/lib/oxidized/jobs.rb
index c566778..fdc1cbf 100644
--- a/lib/oxidized/jobs.rb
+++ b/lib/oxidized/jobs.rb
@@ -6,7 +6,7 @@ module Oxidized
def initialize max, interval, nodes
@max = max
- # Set interval to 1 if interval is 0 (=disabled) so we don't break
+ # Set interval to 1 if interval is 0 (=disabled) so we don't break
# the 'ceil' function
@interval = interval == 0 ? 1 : interval
@nodes = nodes
@@ -28,7 +28,7 @@ module Oxidized
@durations.fill AVERAGE_DURATION, @durations.size...@nodes.size
end
@durations.push(last).shift
- @duration = @durations.inject(:+).to_f / @nodes.size #rolling average
+ @duration = @durations.inject(:+).to_f / @nodes.size # rolling average
new_count
end
@@ -45,9 +45,8 @@ module Oxidized
# and c) there is more than MAX_INTER_JOB_GAP since last one was started
# then we want one more thread (rationale is to fix hanging thread causing HOLB)
if @want <= size and @want < @nodes.size
- @want +=1 if (Time.now.utc - @last) > MAX_INTER_JOB_GAP
+ @want += 1 if (Time.now.utc - @last) > MAX_INTER_JOB_GAP
end
end
-
end
end
diff --git a/lib/oxidized/manager.rb b/lib/oxidized/manager.rb
index bf28ae7..c4523f3 100644
--- a/lib/oxidized/manager.rb
+++ b/lib/oxidized/manager.rb
@@ -7,11 +7,11 @@ module Oxidized
class << self
def load dir, file
begin
- require File.join dir, file+'.rb'
+ require File.join dir, file + '.rb'
klass = nil
[Oxidized, Object].each do |mod|
klass = mod.constants.find { |const| const.to_s.downcase == file.downcase }
- klass = mod.constants.find { |const| const.to_s.downcase == 'oxidized'+ file.downcase } unless klass
+ klass = mod.constants.find { |const| const.to_s.downcase == 'oxidized' + file.downcase } unless klass
klass = mod.const_get klass if klass
break if klass
end
@@ -31,16 +31,19 @@ module Oxidized
@source = {}
@hook = {}
end
+
def add_input method
method = Manager.load Config::InputDir, method
return false if method.empty?
@input.merge! method
end
+
def add_output method
method = Manager.load Config::OutputDir, method
return false if method.empty?
@output.merge! method
end
+
def add_model _model
name = _model
_model = Manager.load File.join(Config::Root, 'model'), name
@@ -48,14 +51,16 @@ module Oxidized
return false if _model.empty?
@model.merge! _model
end
+
def add_source _source
- return nil if @source.key? _source
+ return nil if @source.has_key? _source
_source = Manager.load Config::SourceDir, _source
return false if _source.empty?
@source.merge! _source
end
+
def add_hook _hook
- return nil if @hook.key? _hook
+ return nil if @hook.has_key? _hook
name = _hook
_hook = Manager.load File.join(Config::Root, 'hook'), name
_hook = Manager.load Config::HookDir, name if _hook.empty?
diff --git a/lib/oxidized/model/acos.rb b/lib/oxidized/model/acos.rb
index 47649a2..a2db89c 100644
--- a/lib/oxidized/model/acos.rb
+++ b/lib/oxidized/model/acos.rb
@@ -3,7 +3,7 @@ class ACOS < Oxidized::Model
comment '! '
- ##ACOS prompt changes depending on the state of the device
+ # ACOS prompt changes depending on the state of the device
prompt /^([-\w.\/:?\[\]\(\)]+[#>]\s?)$/
cmd :secret do |cfg|
@@ -30,19 +30,19 @@ class ACOS < Oxidized::Model
end
cmd 'show partition-config all' do |cfg|
- cfg.gsub! /(Current configuration).*/, '\\1 <removed>'
- cfg.gsub! /(Configuration last updated at).*/, '\\1 <removed>'
- cfg.gsub! /(Configuration last saved at).*/, '\\1 <removed>'
- cfg.gsub! /(Configuration last synchronized at).*/, '\\1 <removed>'
- cfg
- end
+ cfg.gsub! /(Current configuration).*/, '\\1 <removed>'
+ cfg.gsub! /(Configuration last updated at).*/, '\\1 <removed>'
+ cfg.gsub! /(Configuration last saved at).*/, '\\1 <removed>'
+ cfg.gsub! /(Configuration last synchronized at).*/, '\\1 <removed>'
+ cfg
+ end
cmd 'show running-config all-partitions' do |cfg|
- cfg.gsub! /(Current configuration).*/, '\\1 <removed>'
- cfg.gsub! /(Configuration last updated at).*/, '\\1 <removed>'
- cfg.gsub! /(Configuration last saved at).*/, '\\1 <removed>'
- cfg.gsub! /(Configuration last synchronized at).*/, '\\1 <removed>'
- cfg
+ cfg.gsub! /(Current configuration).*/, '\\1 <removed>'
+ cfg.gsub! /(Configuration last updated at).*/, '\\1 <removed>'
+ cfg.gsub! /(Configuration last saved at).*/, '\\1 <removed>'
+ cfg.gsub! /(Configuration last synchronized at).*/, '\\1 <removed>'
+ cfg
end
cmd 'show aflex all-partitions' do |cfg|
@@ -50,7 +50,7 @@ class ACOS < Oxidized::Model
end
cmd 'show aflex all-partitions' do |cfg|
- @partitions_aflex = cfg.lines.each_with_object({}) do |l,h|
+ @partitions_aflex = cfg.lines.each_with_object({}) do |l, h|
h[$1] = [] if l.match /partition: (.+)/
# only consider scripts that have passed syntax check
h[h.keys.last] << $1 if l.match /^([\w-]+) +Check/
@@ -66,7 +66,7 @@ class ACOS < Oxidized::Model
pre do
unless @partitions_aflex.empty?
out = []
- @partitions_aflex.each do |partition,arules|
+ @partitions_aflex.each do |partition, arules|
out << "! partition: #{partition}"
arules.each do |name|
cmd("show aflex #{name} partition #{partition}") do |cfg|
@@ -85,7 +85,7 @@ class ACOS < Oxidized::Model
username /login:/
password /^Password:/
end
-
+
cfg :telnet, :ssh do
# preferred way to handle additional passwords
post_login do
@@ -98,5 +98,4 @@ class ACOS < Oxidized::Model
post_login 'terminal width 0'
pre_logout "exit\nexit\nY\r\n"
end
-
end
diff --git a/lib/oxidized/model/acsw.rb b/lib/oxidized/model/acsw.rb
new file mode 100644
index 0000000..c0857b3
--- /dev/null
+++ b/lib/oxidized/model/acsw.rb
@@ -0,0 +1,62 @@
+class ACSW < Oxidized::Model
+ prompt /([\w.@()\/\\-]+[#>]\s?)/
+ comment '! '
+
+ cmd :all do |cfg|
+ cfg.gsub! /^% Invalid input detected at '\^' marker\.$|^\s+\^$/, ''
+ cfg.each_line.to_a[1..-2].join
+ end
+
+ cmd :secret do |cfg|
+ cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
+ cfg.gsub! /^(username \S+ privilege \d+) (\S+).*/, '\\1 <secret hidden>'
+ cfg.gsub! /^(username \S+ password \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(username \S+ secret \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(enable (password|secret) \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(\s+(?:password|secret)) (?:\d )?\S+/, '\\1 <secret hidden>'
+ cfg.gsub! /^(.*wpa-psk ascii \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(.*key 7) (.*)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(tacacs-server key \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(crypto isakmp key) (\S+) (.*)/, '\\1 <secret hidden> \\3'
+ cfg.gsub! /^(.*key 1 md5) (\d.+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(.*standby \d.+authentication).*/, '\\1 <secret hidden>'
+ cfg.gsub! /^(.*version 2c).*/, '\\1 <secret hidden>'
+ cfg
+ end
+
+ cmd 'show version' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show inventory' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show running-config' do |cfg|
+ cfg = cfg.each_line.to_a[3..-1]
+ cfg = cfg.reject { |line| line.match /^ntp clock-period / }.join
+ cfg.gsub! /^Current configuration : [^\n]*\n/, ''
+ cfg.gsub! /^\ tunnel\ mpls\ traffic-eng\ bandwidth[^\n]*\n*(
+ (?:\ [^\n]*\n*)*
+ tunnel\ mpls\ traffic-eng\ auto-bw)/mx, '\1'
+ cfg.gsub! /^([\s\t\!]*Last configuration change ).*/, ''
+ cfg.gsub! /^([\s\t\!]*NVRAM config last ).*/, ''
+ cfg
+ end
+
+ cfg :telnet do
+ username /.*login:/
+ password /^Password:/
+ end
+
+ cfg :telnet, :ssh do
+ if vars :enable
+ post_login do
+ send "enable\n"
+ cmd vars(:enable)
+ end
+ end
+ post_login 'terminal length 0'
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/aen.rb b/lib/oxidized/model/aen.rb
new file mode 100644
index 0000000..474e6d5
--- /dev/null
+++ b/lib/oxidized/model/aen.rb
@@ -0,0 +1,19 @@
+class AEN < Oxidized::Model
+ # Accedian
+
+ comment '# '
+
+ prompt /^([-\w.\/:?\[\]\(\)]+:\s?)$/
+
+ cmd 'configuration generate-script module all' do |cfg|
+ cfg
+ end
+
+ cmd :all do |cfg|
+ cfg.each_line.to_a[1..-2].join
+ end
+
+ cfg :ssh do
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/aireos.rb b/lib/oxidized/model/aireos.rb
index 7056e3f..a0378c7 100644
--- a/lib/oxidized/model/aireos.rb
+++ b/lib/oxidized/model/aireos.rb
@@ -1,17 +1,16 @@
class Aireos < Oxidized::Model
-
# AireOS (at least I think that is what it's called, hard to find data)
# Used in Cisco WLC 5500
- comment '# ' ## this complains too, can't find real comment char
+ comment '# ' # this complains too, can't find real comment char
prompt /^\([^\)]+\)\s>/
cmd :all do |cfg|
cfg.each_line.to_a[1..-2].join
end
- ##show sysinfo?
- ##show switchconfig?
+ # show sysinfo?
+ # show switchconfig?
cmd 'show udi' do |cfg|
cfg = comment clean cfg
@@ -44,12 +43,11 @@ class Aireos < Oxidized::Model
out = []
cfg.each_line do |line|
next if line.match /^\s*$/
- next if line.match /rogue (adhoc|client) alert [\da-f]{2}:/
+ next if line.match /rogue (adhoc|client) (alert|Unknown) [\da-f]{2}:/
line = line[1..-1] if line[0] == "\r"
out << line.strip
end
out = out.join "\n"
out << "\n"
end
-
end
diff --git a/lib/oxidized/model/airos.rb b/lib/oxidized/model/airos.rb
index 775005f..7d82956 100644
--- a/lib/oxidized/model/airos.rb
+++ b/lib/oxidized/model/airos.rb
@@ -1,14 +1,19 @@
class Airos < Oxidized::Model
# Ubiquiti AirOS circa 5.x
-
+
prompt /^[^#]+# /
-
+ comment '# '
+
cmd 'cat /etc/board.info' do |cfg|
cfg.split("\n").map { |line| "# #{line}" }.join("\n") + "\n"
end
-
+
+ cmd 'cat /etc/version' do |cfg|
+ comment "airos version: #{cfg}"
+ end
+
cmd 'sort /tmp/system.cfg'
-
+
cmd :secret do |cfg|
cfg.gsub! /^(users\.\d+\.password|snmp\.community)=.+/, "# \\1=<hidden>"
cfg
diff --git a/lib/oxidized/model/alteonos.rb b/lib/oxidized/model/alteonos.rb
new file mode 100644
index 0000000..dec4faf
--- /dev/null
+++ b/lib/oxidized/model/alteonos.rb
@@ -0,0 +1,58 @@
+class ALTEONOS < Oxidized::Model
+ prompt /^\(?.+\)?\s?[#>]/
+
+ comment '! '
+
+ cmd :secret do |cfg|
+ cfg.gsub!(/^([\s\t]*admpw ).*/, '\1 <password removed>')
+ cfg.gsub!(/^([\s\t]*pswd ).*/, '\1 <password removed>')
+ cfg.gsub!(/^([\s\t]*esecret ).*/, '\1 <password removed>')
+ cfg
+ end
+
+ ##############################################################################################
+ # Added to remove #
+ # #
+ # /* Configuration dump taken 14:10:20 Fri Jul 28, 2017 (DST) #
+ # /* Configuration last applied at 16:17:05 Fri Jul 14, 2017 #
+ # /* Configuration last save at 16:17:43 Fri Jul 14, 2017 #
+ # /* Version 29.0.3.12, vXXXXXXXX, Base MAC address XXXXXXXXXXX #
+ # /* To restore SSL Offloading configuration and management HTTPS access, #
+ # /* it is recommended to include the private keys in the dump. #
+ # OR #
+ # /* To restore SSL Offloading configuration and management HTTPS access,it is recommended #
+ # /* to include the private keys in the dump. #
+ # #
+ ##############################################################################################
+
+ cmd 'cfg/dump' do |cfg|
+ cfg.gsub! /^([\s\t\/*]*Configuration).*/, ''
+ cfg.gsub! /^([\s\t\/*]*Version).*/, ''
+ cfg.gsub! /^([\s\t\/*]*To restore ).*/, ''
+ cfg.gsub! /^([\s\t\/*]*it is recommended to include).*/, ''
+ cfg.gsub! /^([\s\t\/*]*to include ).*/, ''
+ cfg
+ end
+
+ # Answer for Dispay private keys
+ expect /^Display private keys\?\s?\[y\/n\]\: $/ do |data, re|
+ send "n\r"
+ data.sub re, ''
+ end
+
+ # Answer for sync to peer on exit
+ expect /^Confirm Sync to Peer\s?\[y\/n\]\: $/ do |data, re|
+ send "n\r"
+ data.sub re, ''
+ end
+
+ # Answer for Unsaved configuration
+ expect /^(WARNING: There are unsaved configuration changes).*/ do |data, re|
+ send "n\r"
+ data.sub re, ''
+ end
+
+ cfg :ssh do
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/alvarion.rb b/lib/oxidized/model/alvarion.rb
index 3c762de..8831f49 100644
--- a/lib/oxidized/model/alvarion.rb
+++ b/lib/oxidized/model/alvarion.rb
@@ -1,5 +1,4 @@
class Alvarion < Oxidized::Model
-
# Used in Alvarion wisp equipment
# Run this command as an instance of Model so we can access node
@@ -7,7 +6,6 @@ class Alvarion < Oxidized::Model
cmd "#{node.auth[:password]}.cfg"
end
-
- cfg :tftp {}
-
+ cfg :tftp do
+ end
end
diff --git a/lib/oxidized/model/aos.rb b/lib/oxidized/model/aos.rb
index ec73b92..fed78c8 100644
--- a/lib/oxidized/model/aos.rb
+++ b/lib/oxidized/model/aos.rb
@@ -1,8 +1,7 @@
class AOS < Oxidized::Model
-
# Alcatel-Lucent Operating System
# used in OmniSwitch
-
+
comment '! '
cmd :all do |cfg|
@@ -10,7 +9,7 @@ class AOS < Oxidized::Model
end
cmd 'show system' do |cfg|
- cfg = cfg.each_line.find{|line|line.match 'Description'}
+ cfg = cfg.each_line.find { |line| line.match 'Description' }
comment cfg.to_s.strip
end
@@ -34,5 +33,4 @@ class AOS < Oxidized::Model
cfg :telnet, :ssh do
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/aos7.rb b/lib/oxidized/model/aos7.rb
index 8d11066..00bee54 100644
--- a/lib/oxidized/model/aos7.rb
+++ b/lib/oxidized/model/aos7.rb
@@ -1,8 +1,7 @@
class AOS7 < Oxidized::Model
-
# Alcatel-Lucent Operating System Version 7 (Linux based)
# used in OmniSwitch 6900/10k
-
+
comment '! '
cmd :all do |cfg, cmdstring|
@@ -11,7 +10,7 @@ class AOS7 < Oxidized::Model
end
cmd 'show system' do |cfg|
- cfg = cfg.each_line.find{|line|line.match 'Description'}
+ cfg = cfg.each_line.find { |line| line.match 'Description' }
comment cfg.to_s.strip + "\n"
end
diff --git a/lib/oxidized/model/aosw.rb b/lib/oxidized/model/aosw.rb
index adf481b..7543353 100644
--- a/lib/oxidized/model/aosw.rb
+++ b/lib/oxidized/model/aosw.rb
@@ -1,47 +1,60 @@
class AOSW < Oxidized::Model
-
- # AOSW Aruba Wireless
+ # AOSW Aruba Wireless, IAP, Instant Controller and Mobility Access Switches
# Used in Alcatel OAW-4750 WLAN controller
# Also Dell controllers
+ # HPE Aruba Switches should use a different model as the software is based on the HP Procurve line.
+
+ # Support for IAP & Instant Controller tested with 115, 205, 215 & 325 running 6.4.4.8-4.2.4.5_57965
+ # Support for Mobility Access Switches tested with S2500-48P & S2500-24P running 7.4.1.4_54199 and S2500-24P running 7.4.1.7_57823
+ # All IAPs connected to a Instant Controller will have the same config output. Only the controller needs to be monitored.
+
comment '# '
- prompt /^\([^)]+\) [#>]/
+ prompt /^\(?.+\)?\s[#>]/
cmd :all do |cfg|
cfg.each_line.to_a[1..-2].join
end
cmd :secret do |cfg|
+ cfg.gsub!(/secret (\S+)$/, 'secret <secret removed>')
+ cfg.gsub!(/enable secret (\S+)$/, 'enable secret <secret removed>')
cfg.gsub!(/PRE-SHARE (\S+)$/, 'PRE-SHARE <secret removed>')
cfg.gsub!(/ipsec (\S+)$/, 'ipsec <secret removed>')
cfg.gsub!(/community (\S+)$/, 'community <secret removed>')
cfg.gsub!(/ sha (\S+)/, ' sha <secret removed>')
cfg.gsub!(/ des (\S+)/, ' des <secret removed>')
cfg.gsub!(/mobility-manager (\S+) user (\S+) (\S+)/, 'mobility-manager \1 user \2 <secret removed>')
- cfg.gsub!(/mgmt-user (\S+) (\S+) (\S+)$/, 'mgmt-user \1 \2 <secret removed>')
+ cfg.gsub!(/mgmt-user (\S+) (root|guest\-provisioning|network\-operations|read\-only|location\-api\-mgmt) (\S+)$/, 'mgmt-user \1 \2 <secret removed>') # MAS & Wireless Controler
+ cfg.gsub!(/mgmt-user (\S+) (\S+)( (read\-only|guest\-mgmt))?$/, 'mgmt-user \1 <secret removed> \3') # IAP
+ # MAS format: mgmt-user <username> <accesslevel> <password hash>
+ # IAP format (root user): mgmt-user <username> <password hash>
+ # IAP format: mgmt-user <username> <password hash> <access level>
cfg.gsub!(/key (\S+)$/, 'key <secret removed>')
- cfg.gsub!(/secret (\S+)$/, 'secret <secret removed>')
cfg.gsub!(/wpa-passphrase (\S+)$/, 'wpa-passphrase <secret removed>')
cfg.gsub!(/bkup-passwords (\S+)$/, 'bkup-passwords <secret removed>')
+ cfg.gsub!(/user (\S+) (\S+) (\S+)$/, 'user \1 <secret removed> \3')
+ cfg.gsub!(/virtual-controller-key (\S+)$/, 'virtual-controller-key <secret removed>')
cfg
end
cmd 'show version' do |cfg|
- cfg = cfg.each_line.select { |line| not line.match /Switch uptime/i }
+ cfg = cfg.each_line.reject { |line| line.match /(Switch|AP) uptime/i }
rstrip_cfg comment cfg.join
end
cmd 'show inventory' do |cfg|
+ cfg = "" if cfg.match /(Invalid input detected at '\^' marker|Parse error)/ # Don't show for unsupported devices (IAP and MAS)
rstrip_cfg clean cfg
end
cmd 'show slots' do |cfg|
- cfg = "" if cfg.match /Invalid input detected at '\^' marker/ #Don't show for unsupported devices
+ cfg = "" if cfg.match /(Invalid input detected at '\^' marker|Parse error)/ # Don't show for unsupported devices (IAP and MAS)
rstrip_cfg comment cfg
end
cmd 'show license' do |cfg|
- cfg = "" if cfg.match /Invalid input detected at '\^' marker/ #Don't show for unsupported devices
+ cfg = "" if cfg.match /(Invalid input detected at '\^' marker|Parse error)/ # Don't show for unsupported devices (IAP and MAS)
rstrip_cfg comment cfg
end
@@ -98,5 +111,4 @@ class AOSW < Oxidized::Model
out = comment out.join "\n"
out << "\n"
end
-
end
diff --git a/lib/oxidized/model/apc_aos.rb b/lib/oxidized/model/apc_aos.rb
index 530d436..5a4d232 100644
--- a/lib/oxidized/model/apc_aos.rb
+++ b/lib/oxidized/model/apc_aos.rb
@@ -1,11 +1,8 @@
class Apc_aos < Oxidized::Model
-
cmd 'config.ini' do |cfg|
cfg.gsub! /^; Configuration file\, generated on.*/, ''
end
cfg :ftp do
end
-
end
-
diff --git a/lib/oxidized/model/arbos.rb b/lib/oxidized/model/arbos.rb
new file mode 100644
index 0000000..51b269d
--- /dev/null
+++ b/lib/oxidized/model/arbos.rb
@@ -0,0 +1,26 @@
+class ARBOS < Oxidized::Model
+ # Arbor OS model #
+
+ prompt /^[\S\s]+\n([\w.@-]+[:\/#>]+)\s?$/
+ comment '# '
+
+ cmd 'system hardware' do |cfg|
+ cfg.gsub! /^Boot\ time\:\s.+/, '' # Remove boot timer
+ cfg.gsub! /^Load\ averages\:\s.+/, '' # Remove CPU load info
+ cfg = cfg.each_line.to_a[2..-1].join
+ comment cfg
+ end
+
+ cmd 'system version' do |cfg|
+ comment cfg
+ end
+
+ cmd 'config show' do |cfg|
+ cfg
+ end
+
+ cfg :ssh do
+ exec true
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/aricentiss.rb b/lib/oxidized/model/aricentiss.rb
new file mode 100644
index 0000000..77b78f4
--- /dev/null
+++ b/lib/oxidized/model/aricentiss.rb
@@ -0,0 +1,51 @@
+# Developed against:
+# #show version
+# Switch ID Hardware Version Firmware Version
+# 0 SSE-G48-TG4 (P2-01) 1.0.16-9
+
+class AricentISS < Oxidized::Model
+ prompt (/^(\e\[27m)?[ \r]*[\w-]+# ?$/)
+
+ cfg :ssh do
+ # "pagination" was misspelled in some (earlier) versions (at least 1.0.16-9)
+ # 1.0.18-15 is known to include the corrected spelling
+ post_login 'no cli pagination'
+ post_login 'no cli pagignation'
+ pre_logout 'exit'
+ end
+
+ cmd :all do |cfg|
+ # * Drop first line that contains the command, and the last line that
+ # contains a prompt
+ # * Strip carriage returns
+ cfg.delete("\r").each_line.to_a[1..-2].join
+ end
+
+ cmd :secret do |cfg|
+ cfg.gsub(/^(snmp community) .*/, '\1 <hidden>')
+ end
+
+ cmd 'show system information' do |cfg|
+ cfg.sub! /^Device Up Time.*\n/, ''
+ cfg.delete! "\r"
+ comment(cfg).gsub(/ +$/, '')
+ end
+
+ cmd 'show running-config' do |cfg|
+ comment_next = 0
+ cfg.each_line.map { |l|
+ next '' if l.match /^Building configuration/
+
+ if l.match /^Switch ID.*Hardware Version.*Firmware Version/ then
+ comment_next = 2
+ end
+
+ if comment_next > 0 then
+ comment_next -= 1
+ next comment(l)
+ end
+
+ l
+ }.join.gsub(/ +$/, '')
+ end
+end
diff --git a/lib/oxidized/model/asa.rb b/lib/oxidized/model/asa.rb
index df30059..dfd94b1 100644
--- a/lib/oxidized/model/asa.rb
+++ b/lib/oxidized/model/asa.rb
@@ -1,5 +1,4 @@
class ASA < Oxidized::Model
-
# Cisco ASA model #
# Only SSH supported for the sake of security
@@ -13,15 +12,21 @@ class ASA < Oxidized::Model
cmd :secret do |cfg|
cfg.gsub! /enable password (\S+) (.*)/, 'enable password <secret hidden> \2'
cfg.gsub! /username (\S+) password (\S+) (.*)/, 'username \1 password <secret hidden> \3'
- cfg.gsub! /ikev2 pre-shared-key (\S+)/, 'ikev2 pre-shared-key <secret hidden>'
- cfg.gsub! /ikev2 (remote|local)-authentication pre-shared-key (\S+)/, 'ikev2 \1-authentication pre-shared-key <secret hidden>'
+ cfg.gsub! /(ikev[12] ((remote|local)-authentication )?pre-shared-key) (\S+)/, '\1 <secret hidden>'
cfg.gsub! /^(aaa-server TACACS\+? \(\S+\) host.*\n\skey) \S+$/mi, '\1 <secret hidden>'
+ cfg.gsub! /ldap-login-password (\S+)/, 'ldap-login-password <secret hidden>'
+ cfg.gsub! /^snmp-server host (.*) community (\S+)/, 'snmp-server host \1 community <secret hidden>'
cfg
end
+ # check for multiple contexts
+ cmd 'show mode' do |cfg|
+ @is_multiple_context = cfg.include? 'multiple'
+ end
+
cmd 'show version' do |cfg|
# avoid commits due to uptime / ixo-router01 up 2 mins 28 secs / ixo-router01 up 1 days 2 hours
- cfg = cfg.each_line.select { |line| not line.match /(\s+up\s+\d+\s+)|(.*days.*)/ }
+ cfg = cfg.each_line.reject { |line| line.match /(\s+up\s+\d+\s+)|(.*days.*)/ }
cfg = cfg.join
comment cfg
end
@@ -30,25 +35,12 @@ class ASA < Oxidized::Model
comment cfg
end
- cmd 'more system:running-config' do |cfg|
- cfg = cfg.each_line.to_a[3..-1].join
- cfg.gsub! /^: [^\n]*\n/, ''
- # backup any xml referenced in the configuration.
- anyconnect_profiles = cfg.scan(Regexp.new('(\sdisk0:/.+\.xml)')).flatten
- anyconnect_profiles.each do |profile|
- cfg << (comment profile + "\n" )
- cmd ("more" + profile) do |xml|
- cfg << (comment xml)
- end
+ post do
+ if @is_multiple_context
+ multiple_context
+ else
+ single_context
end
- # if DAP is enabled, also backup dap.xml
- if cfg.rindex(/dynamic-access-policy-record\s(?!DfltAccessPolicy)/)
- cfg << (comment "disk0:/dap.xml\n")
- cmd "more disk0:/dap.xml" do |xml|
- cfg << (comment xml)
- end
- end
- cfg
end
cfg :ssh do
@@ -62,4 +54,46 @@ class ASA < Oxidized::Model
pre_logout 'exit'
end
+ def single_context
+ # Single context mode
+ cmd 'more system:running-config' do |cfg|
+ cfg = cfg.each_line.to_a[3..-1].join
+ cfg.gsub! /^: [^\n]*\n/, ''
+ # backup any xml referenced in the configuration.
+ anyconnect_profiles = cfg.scan(Regexp.new('(\sdisk0:/.+\.xml)')).flatten
+ anyconnect_profiles.each do |profile|
+ cfg << (comment profile + "\n")
+ cmd ("more" + profile) do |xml|
+ cfg << (comment xml)
+ end
+ end
+ # if DAP is enabled, also backup dap.xml
+ if cfg.rindex(/dynamic-access-policy-record\s(?!DfltAccessPolicy)/)
+ cfg << (comment "disk0:/dap.xml\n")
+ cmd "more disk0:/dap.xml" do |xml|
+ cfg << (comment xml)
+ end
+ end
+ cfg
+ end
+ end
+
+ def multiple_context
+ # Multiple context mode
+ cmd 'changeto system' do |cfg|
+ cmd 'show running-config' do |systemcfg|
+ allcfg = "\n\n" + systemcfg + "\n\n"
+ contexts = systemcfg.scan(/^context (\S+)$/)
+ files = systemcfg.scan(/config-url (\S+)$/)
+ contexts.each_with_index do |cont, i|
+ allcfg = allcfg + "\n\n----------========== [ CONTEXT " + cont.join(" ") + " FILE " + files[i].join(" ") + " ] ==========----------\n\n"
+ cmd "more " + files[i].join(" ") do |cfgcontext|
+ allcfg = allcfg + "\n\n" + cfgcontext
+ end
+ end
+ cfg = allcfg
+ end
+ cfg
+ end
+ end
end
diff --git a/lib/oxidized/model/asyncos.rb b/lib/oxidized/model/asyncos.rb
new file mode 100644
index 0000000..2857ef8
--- /dev/null
+++ b/lib/oxidized/model/asyncos.rb
@@ -0,0 +1,46 @@
+class AsyncOS < Oxidized::Model
+ # ESA prompt "(mail.example.com)> "
+ prompt /^\r*([(][\w. ]+[)][#>]\s+)$/
+ comment '! '
+
+ # Select passphrase display option
+ expect /\[\S+\]>\s/ do |data, re|
+ send "3\n"
+ data.sub re, ''
+ end
+
+ # handle paging
+ expect /-Press Any Key For More-+.*$/ do |data, re|
+ send " "
+ data.sub re, ''
+ end
+
+ cmd 'version' do |cfg|
+ comment cfg
+ end
+
+ cmd 'showconfig' do |cfg|
+ # Delete hour and date which change each run
+ # cfg.gsub! /\sCurrent Time: \S+\s\S+\s+\S+\s\S+\s\S+/, ' Current Time:'
+ # Delete select passphrase display option
+ cfg.gsub! /Choose the passphrase option:/, ''
+ cfg.gsub! /1. Mask passphrases \(Files with masked passphrases cannot be loaded using/, ''
+ cfg.gsub! /loadconfig command\)/, ''
+ cfg.gsub! /2. Encrypt passphrases/, ''
+ cfg.gsub! /3. Plain passphrases/, ''
+ cfg.gsub! /^3$/, ''
+ # Delete space
+ cfg.gsub! /\n\s{25,26}/, ''
+ # Delete after line
+ cfg.gsub! /([-\\\/,.\w><@]+)(\s{25,27})/, "\\1"
+ # Add a carriage return
+ cfg.gsub! /([-\\\/,.\w><@]+)(\s{6})([-\\\/,.\w><@]+)/, "\\1\n\\2\\3"
+ # Delete prompt
+ cfg.gsub! /^\r*([(][\w. ]+[)][#>]\s+)$/, ''
+ cfg
+ end
+
+ cfg :ssh do
+ pre_logout "exit"
+ end
+end
diff --git a/lib/oxidized/model/audiocodes.rb b/lib/oxidized/model/audiocodes.rb
new file mode 100644
index 0000000..2c77abb
--- /dev/null
+++ b/lib/oxidized/model/audiocodes.rb
@@ -0,0 +1,28 @@
+class AudioCodes < Oxidized::Model
+ # Pull config from AudioCodes Mediant devices from version > 7.0
+
+ prompt /^\r?([\w.@() -]+[#>]\s?)$/
+ comment '## '
+
+ expect /\s*--MORE--$/ do |data, re|
+ send ' '
+
+ data.sub re, ''
+ end
+
+ cmd 'show running-config' do |cfg|
+ cfg
+ end
+
+ cfg :ssh do
+ username /^login as:\s$/
+ password /^.+password:\s$/
+ pre_logout 'exit'
+ end
+
+ cfg :telnet do
+ username /^Username:\s$/
+ password /^Password:\s$/
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/awplus.rb b/lib/oxidized/model/awplus.rb
new file mode 100644
index 0000000..7c88d60
--- /dev/null
+++ b/lib/oxidized/model/awplus.rb
@@ -0,0 +1,84 @@
+class AWPlus < Oxidized::Model
+ # Allied Telesis Alliedware Plus Model#
+ # https://www.alliedtelesis.com/products/software/AlliedWare-Plus
+
+ prompt /^(\r?[\w.@:\/-]+[#>]\s?)$/
+ comment '! '
+
+ # Avoids needing "term length 0" to display full config file.
+ expect /--More--/ do |data, re|
+ send ' '
+ data.sub re, ''
+ end
+
+ # Removes gibberish pager output e.g. VT100 escape codes
+ cmd :all do |cfg|
+ cfg.gsub! /\e\[K/, '' # example how to handle pager - cleareol EL0
+ cfg.gsub! /\e\[7m\e\[m/, '' # example how to handle pager - Reverse SGR7
+ cfg.gsub! /\r/, '' # Filters rogue ^M - see issue #415
+ cfg.each_line.to_a[1..-2].join
+ end
+
+ # Remove passwords from config file.
+ # Add vars "remove_secret: true" to global oxidized config file to enable.
+
+ cmd :secret do |cfg|
+ cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
+ cfg.gsub! /^(username \S+ privilege \d+) (\S+).*/, '\\1 <secret hidden>'
+ cfg.gsub! /^(username \S+ password \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(username \S+ secret \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(enable (password|secret) \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(\s+(?:password|secret)) (?:\d )?\S+/, '\\1 <secret hidden>'
+ cfg.gsub! /^(tacacs-server key \d) (\S+)/, '\\1 <secret hidden>'
+ cfg
+ end
+
+ # Adds "Show system" output to start of config.
+
+ cmd 'Show System' do |cfg|
+ comment cfg.insert(0, "--------------------------------------------------------------------------------! \n")
+ # Unhash below to write a comment in the config file.
+ cfg.insert(0, "Starting: Show system cmd \n")
+ cfg << "\n \nEnding: show system cmd"
+ comment cfg << "\n--------------------------------------------------------------------------------! \n \n"
+ # Removes the following lines from "show system" in output file. This ensures oxidized diffs are meaningful.
+ comment cfg.each_line.reject { |line|
+ line.match /^$\n/ or # Remove blank lines in "sh sys"
+ line.match /System Status\s*.*/ or
+ line.match /RAM\s*:.*/ or
+ line.match /Uptime\s*:.*/ or
+ line.match /Flash\s*:.*/ or
+ line.match /Current software\s*:.*/ or
+ line.match /Software version\s*:.*/ or
+ line.match /Build date\s*:.*/
+ } .join
+ end
+
+ # Actually get the devices running config#
+ cmd 'show running-config' do |cfg|
+ cfg
+ end
+
+ # Config required for telnet to detect username prompt
+ cfg :telnet do
+ username /login:\s/
+ end
+
+ # Main login config
+ cfg :telnet, :ssh do
+ post_login do
+ if vars :enable
+ send "enable\n"
+ expect /^Password:\s/
+ cmd vars(:enable) + "\r\n"
+ else
+ cmd 'enable' # Required for Priv-Exec users without enable PW to be put into "enable mode".
+ end
+ # cmd 'terminal length 0' #set so the entire config is output without intervention.
+ end
+ pre_logout do
+ # cmd 'terminal no length' #Sets term length back to default on exit.
+ send "exit\r\n"
+ end
+ end
+end
diff --git a/lib/oxidized/model/boss.rb b/lib/oxidized/model/boss.rb
new file mode 100644
index 0000000..cf762ee
--- /dev/null
+++ b/lib/oxidized/model/boss.rb
@@ -0,0 +1,75 @@
+class Boss < Oxidized::Model
+ # Avaya Baystack Operating System Software(BOSS)
+ # Created by danielcoxman@gmail.com
+ # May 15, 2017
+ # This was tested on ers3510, ers5530, ers4850, ers5952
+ # ssh and telnet were tested with banner and without
+
+ comment '! '
+
+ prompt /^[^\s#>]+[#>]$/
+
+ # Handle the banner
+ # to disable the banner on BOSS the configuration parameter is "banner disabled"
+ expect /Enter Ctrl-Y to begin\./ do |data, re|
+ send "\cY"
+ data.sub re, ''
+ end
+
+ # Handle the Failed retries since last login
+ # no known way to disable other than to implement radius authentication
+ expect /Press ENTER to continue/ do |data, re|
+ send "\n"
+ data.sub re, ''
+ end
+
+ # Handle the menu on the older BOSS example ers55xx, ers56xx
+ # to disable them menu on BOSS the configuration parameter is "cmd-interface cli"
+ expect /ommand Line Interface\.\.\./ do |data, re|
+ send "c"
+ data.sub re, ''
+ end
+
+ # needed for proper formatting
+ cmd('') { |cfg| comment "#{cfg}\n" }
+
+ # Do a sys-info and check and see if it supports stack
+ cmd 'show sys-info' do |cfg|
+ @stack = true if cfg.match /Stack/
+ cfg.gsub! /(^((.*)sysUpTime(.*))$)/, 'removed sysUpTime'
+ cfg.gsub! /(^((.*)sysNtpTime(.*))$)/, 'removed sysNtpTime'
+ cfg.gsub! /(^((.*)sysRtcTime(.*))$)/, 'removed sysNtpTime'
+ # remove timestamp
+ cfg.gsub! /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} .*/, ''
+ comment "#{cfg}\n"
+ end
+
+ # if a stack then collect the stacking information
+ cmd 'show stack-info' do |cfg|
+ if @stack
+ # remove timestamp
+ cfg.gsub! /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} .*/, ''
+ comment "#{cfg}\n"
+ end
+ end
+
+ cmd 'show running-config' do |cfg|
+ cfg.gsub! /^show running-config/, '! show running-config'
+ # remove timestamp
+ cfg.gsub! /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} .*/, ''
+ cfg.gsub! /^[^\s#>]+[#>]$/, ''
+ cfg.gsub! /^! clock set.*/, '! removed clock set'
+ cfg
+ end
+
+ cfg :telnet do
+ username /Username: /
+ password /Password: /
+ end
+
+ cfg :telnet, :ssh do
+ pre_logout 'logout'
+ post_login 'terminal length 0'
+ post_login 'terminal width 132'
+ end
+end
diff --git a/lib/oxidized/model/br6910.rb b/lib/oxidized/model/br6910.rb
index b5c9bcf..1e79da3 100644
--- a/lib/oxidized/model/br6910.rb
+++ b/lib/oxidized/model/br6910.rb
@@ -1,45 +1,43 @@
-
-class BR6910 < Oxidized::Model
-
- prompt /^Vty-[0-9]\#$/
- comment '! '
-
- # not possible to disable paging prior to show running-config
- expect /^((.*)Others to exit ---(.*))$/ do |data, re|
- send 'a'
- data.sub re, ''
- end
-
- cmd :all do |cfg|
- # sometimes br6910s inserts arbitrary whitespace after commands are
- # issued on the CLI, from run to run. this normalises the output.
- cfg.each_line.to_a[1..-2].drop_while { |e| e.match /^\s+$/ }.join
- end
-
- cmd 'show version' do |cfg|
- comment cfg
- end
-
- # show flash is not possible on a brocade 6910, do dir instead
- # to see flash contents (includes config file names)
- cmd 'dir' do |cfg|
- comment cfg
- end
-
- cmd 'show running-config' do |cfg|
- arr = cfg.each_line.to_a
- arr[2..-1].join unless arr.length < 2
- end
-
- cfg :telnet do
- username /^Username:/
- password /^Password:/
- end
-
- # post login and post logout
- cfg :telnet, :ssh do
- post_login ''
- pre_logout 'exit'
- end
-
-end
+
+class BR6910 < Oxidized::Model
+ prompt /^([\w.@()-]+[#>]\s?)$/
+ comment '! '
+
+ # not possible to disable paging prior to show running-config
+ expect /^((.*)Others to exit ---(.*))$/ do |data, re|
+ send 'a'
+ data.sub re, ''
+ end
+
+ cmd :all do |cfg|
+ # sometimes br6910s inserts arbitrary whitespace after commands are
+ # issued on the CLI, from run to run. this normalises the output.
+ cfg.each_line.to_a[1..-2].drop_while { |e| e.match /^\s+$/ }.join
+ end
+
+ cmd 'show version' do |cfg|
+ comment cfg
+ end
+
+ # show flash is not possible on a brocade 6910, do dir instead
+ # to see flash contents (includes config file names)
+ cmd 'dir' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show running-config' do |cfg|
+ arr = cfg.each_line.to_a
+ arr[2..-1].join unless arr.length < 2
+ end
+
+ cfg :telnet do
+ username /^Username:/
+ password /^Password:/
+ end
+
+ # post login and post logout
+ cfg :telnet, :ssh do
+ post_login ''
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/c4cmts.rb b/lib/oxidized/model/c4cmts.rb
index 150029c..8ea27c6 100644
--- a/lib/oxidized/model/c4cmts.rb
+++ b/lib/oxidized/model/c4cmts.rb
@@ -1,15 +1,14 @@
class C4CMTS < Oxidized::Model
-
# Arris C4 CMTS
prompt /^([\w.@:\/-]+[#>]\s?)$/
comment '! '
cmd :all do |cfg|
- cfg.each_line.to_a[1..-2].map{|line|line.delete("\r").rstrip}.join("\n") + "\n"
+ cfg.each_line.to_a[1..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
end
- cmd :secret do |cfg|
+ cmd :secret do |cfg|
cfg.gsub! /(.+)\s+encrypted-password\s+\w+\s+(.*)/, '\\1 <secret hidden> \\2'
cfg.gsub! /(snmp-server community)\s+".*"\s+(.*)/, '\\1 <secret hidden> \\2'
cfg.gsub! /(tacacs.*\s+key)\s+".*"\s+(.*)/, '\\1 <secret hidden> \\2'
@@ -25,7 +24,7 @@ class C4CMTS < Oxidized::Model
cmd 'show version' do |cfg|
# remove uptime readings at char 55 and beyond
- cfg = cfg.each_line.map{|line|line.rstrip.slice(0..54)}.join("\n") + "\n"
+ cfg = cfg.each_line.map { |line| line.rstrip.slice(0..54) }.join("\n") + "\n"
comment cfg
end
@@ -48,5 +47,4 @@ class C4CMTS < Oxidized::Model
end
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/catos.rb b/lib/oxidized/model/catos.rb
index bac9eec..e97a0b6 100644
--- a/lib/oxidized/model/catos.rb
+++ b/lib/oxidized/model/catos.rb
@@ -1,5 +1,4 @@
class Catos < Oxidized::Model
-
prompt /^[\w.@-]+>\s?(\(enable\) )?$/
comment '# '
@@ -39,5 +38,4 @@ class Catos < Oxidized::Model
end
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/cisconga.rb b/lib/oxidized/model/cisconga.rb
new file mode 100644
index 0000000..9764351
--- /dev/null
+++ b/lib/oxidized/model/cisconga.rb
@@ -0,0 +1,17 @@
+class CiscoNGA < Oxidized::Model
+ comment '# '
+ prompt /([\w.@-]+[#>]\s?)$/
+
+ cmd 'show version' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show configuration' do |cfg|
+ cfg
+ end
+
+ cfg :ssh do
+ post_login 'terminal length 0'
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/ciscosma.rb b/lib/oxidized/model/ciscosma.rb
new file mode 100644
index 0000000..5a34f86
--- /dev/null
+++ b/lib/oxidized/model/ciscosma.rb
@@ -0,0 +1,42 @@
+class CiscoSMA < Oxidized::Model
+ # SMA prompt "mail.example.com> "
+ prompt /^\r*([-\w. ]+\.[-\w. ]+\.[-\w. ]+[#>]\s+)$/
+ comment '! '
+
+ # Select passphrase display option
+ expect /using loadconfig command\. \[Y\]\>/ do |data, re|
+ send "y\n"
+ data.sub re, ''
+ end
+
+ # handle paging
+ expect /-Press Any Key For More-+.*$/ do |data, re|
+ send " "
+ data.sub re, ''
+ end
+
+ cmd 'version' do |cfg|
+ comment cfg
+ end
+
+ cmd 'showconfig' do |cfg|
+ # Delete hour and date which change each run
+ # cfg.gsub! /\sCurrent Time: \S+\s\S+\s+\S+\s\S+\s\S+/, ' Current Time:'
+ # Delete select passphrase display option
+ cfg.gsub! /Do you want to mask the password\? Files with masked passwords cannot be loaded/, ''
+ cfg.gsub! /^\s+y/, ''
+ # Delete space
+ cfg.gsub! /\n\s{25}/, ''
+ # Delete after line
+ cfg.gsub! /([\/\-,.\w><@]+)(\s{27})/, "\\1"
+ # Add a carriage return
+ cfg.gsub! /([\/\-,.\w><@]+)(\s{6,8})([\/\-,.\w><@]+)/, "\\1\n\\2\\3"
+ # Delete prompt
+ cfg.gsub! /^\r*([-\w. ]+\.[-\w. ]+\.[-\w. ]+[#>]\s+)$/, ''
+ cfg
+ end
+
+ cfg :ssh do
+ pre_logout "exit"
+ end
+end
diff --git a/lib/oxidized/model/ciscosmb.rb b/lib/oxidized/model/ciscosmb.rb
index e5501d5..ef6f4e6 100644
--- a/lib/oxidized/model/ciscosmb.rb
+++ b/lib/oxidized/model/ciscosmb.rb
@@ -1,6 +1,5 @@
class CiscoSMB < Oxidized::Model
-
- # Cisco Small Business 200, 300, 500, and ESW2 series switches
+ # Cisco Small Business 300, 500, and ESW2 series switches
# http://www.cisco.com/c/en/us/support/switches/small-business-300-series-managed-switches/products-release-notes-list.html
prompt /^\r?([\w.@()-]+[#>]\s?)$/
@@ -16,6 +15,8 @@ class CiscoSMB < Oxidized::Model
cmd :secret do |cfg|
cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
cfg.gsub! /username (\S+) privilege (\d+) (\S+).*/, '<secret hidden>'
+ cfg.gsub! /^(encrypted radius-server key).*/, '\\1 <configuration removed>'
+ cfg.gsub! /System Up Time.*/, ''
cfg
end
@@ -23,6 +24,14 @@ class CiscoSMB < Oxidized::Model
comment cfg
end
+ cmd 'show system' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show bootvar' do |cfg|
+ comment cfg
+ end
+
cmd 'show running-config' do |cfg|
cfg = cfg.each_line.to_a[0..-1].join
cfg.gsub! /^Current configuration : [^\n]*\n/, ''
@@ -39,8 +48,7 @@ class CiscoSMB < Oxidized::Model
post_login 'terminal datadump' # Disable pager
post_login 'terminal width 0'
post_login 'terminal len 0'
- pre_logout 'exit' #exit returns to previous priv level, no way to quit from exec(#)
+ pre_logout 'exit' # exit returns to previous priv level, no way to quit from exec(#)
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/comware.rb b/lib/oxidized/model/comware.rb
index 27b70ae..f20cd4d 100644
--- a/lib/oxidized/model/comware.rb
+++ b/lib/oxidized/model/comware.rb
@@ -1,23 +1,29 @@
class Comware < Oxidized::Model
# HP (A-series)/H3C/3Com Comware
-
- # sometimes the prompt might have a leading nul
- prompt /^\0*(<[\w.-]+>)$/
+
+ # sometimes the prompt might have a leading nul or trailing ASCII Bell (^G)
+ prompt /^\0*(<[\w.-]+>).?$/
comment '# '
# example how to handle pager
- #expect /^\s*---- More ----$/ do |data, re|
+ # expect /^\s*---- More ----$/ do |data, re|
# send ' '
# data.sub re, ''
- #end
+ # end
cmd :all do |cfg|
- #cfg.gsub! /^.*\e\[42D/, '' # example how to handle pager
- #skip rogue ^M
+ # cfg.gsub! /^.*\e\[42D/, '' # example how to handle pager
+ # skip rogue ^M
cfg = cfg.gsub /\r/, ''
cfg.each_line.to_a[1..-2].join
end
-
+
+ cmd :secret do |cfg|
+ cfg.gsub! /^( snmp-agent community).*/, '\\1 <configuration removed>'
+ cfg.gsub! /^( password hash).*/, '\\1 <configuration removed>'
+ cfg
+ end
+
cfg :telnet do
username /^Username:$/
password /^Password:$/
@@ -41,7 +47,7 @@ class Comware < Oxidized::Model
end
cmd 'display version' do |cfg|
- cfg = cfg.each_line.select {|l| not l.match /uptime/i }.join
+ cfg = cfg.each_line.reject { |l| l.match /uptime/i }.join
comment cfg
end
diff --git a/lib/oxidized/model/coriant8600.rb b/lib/oxidized/model/coriant8600.rb
index a48ffa5..2e8bb76 100644
--- a/lib/oxidized/model/coriant8600.rb
+++ b/lib/oxidized/model/coriant8600.rb
@@ -1,7 +1,6 @@
class Coriant8600 < Oxidized::Model
-
comment '# '
-
+
prompt /^[^\s#>]+[#>]$/
cmd 'show hw-inventory' do |cfg|
@@ -11,7 +10,7 @@ class Coriant8600 < Oxidized::Model
cmd 'show flash' do |cfg|
comment cfg
end
-
+
cmd 'show run' do |cfg|
cfg
end
@@ -20,11 +19,10 @@ class Coriant8600 < Oxidized::Model
username /^user name:$/
password /^password:$/
end
-
+
cfg :telnet, :ssh do
pre_logout 'exit'
post_login 'enable'
post_login 'terminal more off'
end
-
end
diff --git a/lib/oxidized/model/coriantgroove.rb b/lib/oxidized/model/coriantgroove.rb
new file mode 100644
index 0000000..9d81e82
--- /dev/null
+++ b/lib/oxidized/model/coriantgroove.rb
@@ -0,0 +1,28 @@
+class CoriantGroove < Oxidized::Model
+ comment '# '
+
+ prompt /^(\w+@.*>\s*)$/
+
+ cmd :all do |cfg|
+ cfg.each_line.to_a[1..-3].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
+ end
+
+ cmd 'show inventory' do |cfg|
+ cfg = cfg.each_line.to_a[0..-2].join
+ comment cfg
+ end
+
+ cmd 'show softwareload' do |cfg|
+ cfg = cfg.each_line.to_a[0..-2].join
+ comment cfg
+ end
+
+ cmd 'show config | display commands' do |cfg|
+ cfg.each_line.to_a[1..-1].join
+ end
+
+ cfg :ssh do
+ post_login 'set -f cli-config cli-columns 65535'
+ pre_logout 'quit -f'
+ end
+end
diff --git a/lib/oxidized/model/corianttmos.rb b/lib/oxidized/model/corianttmos.rb
index 76603f6..bc9618e 100644
--- a/lib/oxidized/model/corianttmos.rb
+++ b/lib/oxidized/model/corianttmos.rb
@@ -1,7 +1,6 @@
class CoriantTmos < Oxidized::Model
-
comment '# '
-
+
prompt /^[^\s#]+#\s$/
cmd 'show node extensive' do |cfg|
@@ -21,5 +20,4 @@ class CoriantTmos < Oxidized::Model
pre_logout 'exit'
post_login 'enable config terminal length 0'
end
-
end
diff --git a/lib/oxidized/model/cumulus.rb b/lib/oxidized/model/cumulus.rb
index dc6792a..334e1e4 100644
--- a/lib/oxidized/model/cumulus.rb
+++ b/lib/oxidized/model/cumulus.rb
@@ -1,73 +1,81 @@
class Cumulus < Oxidized::Model
-
prompt /^((\w*)@(.*)):/
- comment '# '
-
-
- #add a comment in the final conf
+ comment '# '
+
+ # add a comment in the final conf
def add_comment comment
- "\n###### #{comment} ######\n"
+ "\n###### #{comment} ######\n"
end
cmd :all do |cfg|
cfg.each_line.to_a[1..-2].join
end
-
- #show the persistent configuration
+
+ # show the persistent configuration
pre do
cfg = add_comment 'THE HOSTNAME'
cfg += cmd 'cat /etc/hostname'
-
+
cfg += add_comment 'THE HOSTS'
cfg += cmd 'cat /etc/hosts'
-
+
cfg += add_comment 'THE INTERFACES'
cfg += cmd 'grep -r "" /etc/network/interface* | cut -d "/" -f 4-'
-
+
cfg += add_comment 'RESOLV.CONF'
cfg += cmd 'cat /etc/resolv.conf'
-
+
cfg += add_comment 'NTP.CONF'
cfg += cmd 'cat /etc/ntp.conf'
-
+
cfg += add_comment 'IP Routes'
cfg += cmd 'netstat -rn'
+ cfg += add_comment 'SNMP settings'
+ cfg += cmd 'cat /etc/snmp/snmpd.conf'
+
cfg += add_comment 'QUAGGA DAEMONS'
cfg += cmd 'cat /etc/quagga/daemons'
-
+
cfg += add_comment 'QUAGGA ZEBRA'
cfg += cmd 'cat /etc/quagga/zebra.conf'
-
+
cfg += add_comment 'QUAGGA BGP'
cfg += cmd 'cat /etc/quagga/bgpd.conf'
-
+
cfg += add_comment 'QUAGGA OSPF'
cfg += cmd 'cat /etc/quagga/ospfd.conf'
-
+
cfg += add_comment 'QUAGGA OSPF6'
cfg += cmd 'cat /etc/quagga/ospf6d.conf'
-
+
+ cfg += add_comment 'QUAGGA CONF'
+ cfg += cmd 'cat /etc/quagga/Quagga.conf'
+
cfg += add_comment 'MOTD'
cfg += cmd 'cat /etc/motd'
-
+
cfg += add_comment 'PASSWD'
cfg += cmd 'cat /etc/passwd'
-
- cfg += add_comment ' SWITCHD'
+
+ cfg += add_comment 'SWITCHD'
cfg += cmd 'cat /etc/cumulus/switchd.conf'
-
+
+ cfg += add_comment 'PORTS'
+ cfg += cmd 'cat /etc/cumulus/ports.conf'
+
+ cfg += add_comment 'TRAFFIC'
+ cfg += cmd 'cat /etc/cumulus/datapath/traffic.conf'
+
cfg += add_comment 'ACL'
cfg += cmd 'iptables -L -n'
-
+
cfg += add_comment 'VERSION'
cfg += cmd 'cat /etc/cumulus/etc.replace/os-release'
cfg += add_comment 'License'
cfg += cmd 'cl-license'
-
end
-
cfg :telnet do
username /^Username:/
@@ -77,6 +85,4 @@ class Cumulus < Oxidized::Model
cfg :telnet, :ssh do
pre_logout 'exit'
end
-
-
end
diff --git a/lib/oxidized/model/datacom.rb b/lib/oxidized/model/datacom.rb
index 5dbc080..5d5d220 100644
--- a/lib/oxidized/model/datacom.rb
+++ b/lib/oxidized/model/datacom.rb
@@ -1,5 +1,4 @@
class DataCom < Oxidized::Model
-
comment '! '
expect /^--More--\s+$/ do |data, re|
@@ -34,5 +33,4 @@ class DataCom < Oxidized::Model
password /^Password:\s$/
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/dcnos.rb b/lib/oxidized/model/dcnos.rb
new file mode 100644
index 0000000..59e6744
--- /dev/null
+++ b/lib/oxidized/model/dcnos.rb
@@ -0,0 +1,46 @@
+# DCNOS is a ZebOS derivative by DCN (http://www.dcnglobal.com/)
+# In addition to products by DCN (now Yunke China), this OS type
+# powers a number of re-branded OEM devices.
+
+# Developed against SNR S2950-24G 7.0.3.5
+
+class DCNOS < Oxidized::Model
+ comment '! '
+
+ cmd :all do |cfg|
+ cfg.each_line.to_a[1..-1].join
+ end
+
+ cmd 'show version' do |cfg|
+ cfg.gsub! /\s(Uptime is).*/, ''
+ comment cfg
+ end
+
+ cmd 'show boot-files' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show flash' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show running-config' do |cfg|
+ cfg
+ end
+
+ cfg :telnet do
+ username /^login:/i
+ password /^password:/i
+ end
+
+ cfg :telnet, :ssh do
+ if vars :enable
+ post_login do
+ send "enable\n"
+ cmd vars(:enable)
+ end
+ end
+ post_login 'terminal length 0'
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/dlink.rb b/lib/oxidized/model/dlink.rb
index 5756bad..6c604fb 100644
--- a/lib/oxidized/model/dlink.rb
+++ b/lib/oxidized/model/dlink.rb
@@ -11,10 +11,11 @@ class Dlink < Oxidized::Model
end
cmd :all do |cfg|
- cfg.each_line.to_a[2..-2].map{|line|line.delete("\r").rstrip}.join("\n") + "\n"
+ cfg.each_line.to_a[2..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
end
cmd 'show switch' do |cfg|
+ cfg.gsub! /^System\ Uptime\s.+/, '' # Omit constantly changing uptime info
comment cfg
end
diff --git a/lib/oxidized/model/dnos.rb b/lib/oxidized/model/dnos.rb
index a44630e..d8b1d96 100644
--- a/lib/oxidized/model/dnos.rb
+++ b/lib/oxidized/model/dnos.rb
@@ -1,14 +1,15 @@
-class DNOS < Oxidized::Model
-
+class DNOS < Oxidized::Model
# Force10 DNOS model #
comment '! '
cmd :all do |cfg|
+ cfg.gsub! /^% Invalid input detected at '\^' marker\.$|^\s+\^$/, ''
+ cfg.gsub! /^Dell Networking OS uptime is\s.+/, '' # Omit constantly changing uptime info
cfg.each_line.to_a[2..-2].join
end
- cmd :secret do |cfg|
+ cmd :secret do |cfg|
cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
cfg.gsub! /secret (\d+) (\S+).*/, '<secret hidden>'
cfg
@@ -22,6 +23,10 @@ class DNOS < Oxidized::Model
comment cfg
end
+ cmd 'show version' do |cfg|
+ comment cfg
+ end
+
cmd 'show running-config' do |cfg|
cfg = cfg.each_line.to_a[3..-1].join
cfg
@@ -42,7 +47,6 @@ class DNOS < Oxidized::Model
post_login 'terminal length 0'
post_login 'terminal width 0'
pre_logout 'exit'
- pre_logout 'exit'
+ pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/edgecos.rb b/lib/oxidized/model/edgecos.rb
new file mode 100644
index 0000000..3668769
--- /dev/null
+++ b/lib/oxidized/model/edgecos.rb
@@ -0,0 +1,45 @@
+class EdgeCOS < Oxidized::Model
+ comment '! '
+
+ cmd :secret do |cfg|
+ cfg.gsub!(/password \d+ (\S+).*/, '<secret removed>')
+ cfg.gsub!(/community (\S+)/, 'community <hidden>')
+ cfg
+ end
+
+ cmd :all do |cfg|
+ cfg.each_line.to_a[2..-2].join
+ end
+
+ cmd 'show running-config'
+
+ cmd 'show access-list tcam-utilization' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show memory' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show system' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show version' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show watchdog' do |cfg|
+ comment cfg
+ end
+
+ cfg :telnet do
+ username /^Username:/
+ password /^Password:/
+ end
+
+ cfg :telnet, :ssh do
+ post_login 'terminal length 0'
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/edgeos.rb b/lib/oxidized/model/edgeos.rb
index 2a8d663..a723904 100644
--- a/lib/oxidized/model/edgeos.rb
+++ b/lib/oxidized/model/edgeos.rb
@@ -1,5 +1,4 @@
class Edgeos < Oxidized::Model
-
# EdgeOS #
prompt /\@.*?\:~\$\s/
@@ -9,11 +8,15 @@ class Edgeos < Oxidized::Model
end
cmd :secret do |cfg|
+ cfg.gsub! /encrypted-password (\S+).*/, 'encrypted-password <secret removed>'
+ cfg.gsub! /plaintext-password (\S+).*/, 'plaintext-password <secret removed>'
+ cfg.gsub! /password (\S+).*/, 'password <secret removed>'
+ cfg.gsub! /pre-shared-secret (\S+).*/, 'pre-shared-secret <secret removed>'
cfg.gsub! /community (\S+) {/, 'community <hidden> {'
cfg
end
- cmd 'show configuration | no-more'
+ cmd 'show configuration commands | no-more'
cfg :telnet do
username /login:\s/
@@ -23,5 +26,4 @@ class Edgeos < Oxidized::Model
cfg :telnet, :ssh do
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/edgeswitch.rb b/lib/oxidized/model/edgeswitch.rb
index 7f5b1ea..36c0f9f 100644
--- a/lib/oxidized/model/edgeswitch.rb
+++ b/lib/oxidized/model/edgeswitch.rb
@@ -1,6 +1,5 @@
class EdgeSwitch < Oxidized::Model
-
-# Ubiquiti EdgeSwitch #
+ # Ubiquiti EdgeSwitch #
comment '!'
@@ -28,5 +27,4 @@ class EdgeSwitch < Oxidized::Model
pre_logout 'quit'
pre_logout 'n'
end
-
end
diff --git a/lib/oxidized/model/enterasys.rb b/lib/oxidized/model/enterasys.rb
new file mode 100644
index 0000000..40f676d
--- /dev/null
+++ b/lib/oxidized/model/enterasys.rb
@@ -0,0 +1,28 @@
+class Enterasys < Oxidized::Model
+ # Enterasys B3/C3 models #
+
+ prompt /^.+\w\(su\)->\s?$/
+
+ comment '!'
+
+ cmd :all do |cfg|
+ cfg.each_line.to_a[2..-3].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
+ end
+
+ cmd 'show system hardware' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show config' do |cfg|
+ cfg.gsub! /^This command shows non-default configurations only./, ''
+ cfg.gsub! /^Use 'show config all' to show both default and non-default configurations./, ''
+ cfg.gsub! /^!|#.*/, ''
+ cfg.gsub! /^$\n/, ''
+
+ cfg
+ end
+
+ cfg :ssh do
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/eos.rb b/lib/oxidized/model/eos.rb
index a9f3ff3..f29910c 100644
--- a/lib/oxidized/model/eos.rb
+++ b/lib/oxidized/model/eos.rb
@@ -1,5 +1,4 @@
class EOS < Oxidized::Model
-
# Arista EOS model #
prompt /^.+[#>]\s?$/
@@ -7,15 +6,15 @@ class EOS < Oxidized::Model
comment '! '
cmd :all do |cfg|
- cfg.each_line.to_a[1..-2].join
+ cfg.each_line.to_a[1..-2].join
end
cmd :secret do |cfg|
- cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
- cfg.gsub! /username (\S+) privilege (\d+) (\S+).*/, '<secret hidden>'
- cfg.gsub! /^(enable secret).*/, '\\1 <configuration removed>'
- cfg.gsub! /^(tacacs-server key \d+).*/, '\\1 <configuration removed>'
- cfg
+ cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
+ cfg.gsub! /username (\S+) privilege (\d+) (\S+).*/, '<secret hidden>'
+ cfg.gsub! /^(enable secret).*/, '\\1 <configuration removed>'
+ cfg.gsub! /^(tacacs-server key \d+).*/, '\\1 <configuration removed>'
+ cfg
end
cmd 'show inventory | no-more' do |cfg|
@@ -41,5 +40,4 @@ class EOS < Oxidized::Model
end
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/fabricos.rb b/lib/oxidized/model/fabricos.rb
index e6d921e..b150c51 100644
--- a/lib/oxidized/model/fabricos.rb
+++ b/lib/oxidized/model/fabricos.rb
@@ -1,22 +1,20 @@
class FabricOS < Oxidized::Model
-
# Brocade Fabric OS model #
## FIXME: Only ssh exec mode support, no telnet, no ssh screenscraping
prompt /^([\w]+:+[\w]+[>]\s)$/
- comment '# '
+ comment '# '
cmd 'chassisShow' do |cfg|
comment cfg.each_line.reject { |line| line.match /Time Awake:/ or line.match /Power Usage \(Watts\):/ or line.match /Time Alive:/ or line.match /Update:/ }.join
end
cmd 'configShow -all' do |cfg|
- cfg = cfg.each_line.reject { |line| line.match /date = /}.join
+ cfg = cfg.each_line.reject { |line| line.match /date = / }.join
cfg
end
cfg :ssh do
- exec true # don't run shell, run each command in exec channel
+ exec true # don't run shell, run each command in exec channel
end
-
end
diff --git a/lib/oxidized/model/fiberdriver.rb b/lib/oxidized/model/fiberdriver.rb
index abe8f68..7cfa847 100644
--- a/lib/oxidized/model/fiberdriver.rb
+++ b/lib/oxidized/model/fiberdriver.rb
@@ -13,7 +13,7 @@ class FiberDriver < Oxidized::Model
cfg.each_line.to_a[3..-1].join
cfg.gsub! /^Building configuration.*$/, ''
cfg.gsub! /^Current configuration:.*$$/, ''
- cfg.gsub! /^! Configuration saved on .*$/, ''
+ cfg.gsub! /^! Configuration (saved|generated) on .*$/, ''
cfg
end
diff --git a/lib/oxidized/model/firewareos.rb b/lib/oxidized/model/firewareos.rb
index f2bef4c..bd0008d 100644
--- a/lib/oxidized/model/firewareos.rb
+++ b/lib/oxidized/model/firewareos.rb
@@ -1,15 +1,20 @@
class FirewareOS < Oxidized::Model
-
- prompt /^\[?\w*\]?\w*<?\w*>?#\s*$/
+ prompt /^\[?\w*\]?\w*?(<\w*>)?(#|>)\s*$/
comment '-- '
cmd :all do |cfg|
cfg.each_line.to_a[1..-2].join
end
+ # Handle Logon Disclaimer added in XTM 11.9.3
+ expect /^I have read and accept the Logon Disclaimer message. \(yes or no\)\? $/ do |data, re|
+ send "yes\n"
+ data.sub re, ''
+ end
+
cmd 'show sysinfo' do |cfg|
# avoid commits due to uptime
- cfg = cfg.each_line.select { |line| not line.match /(.*time.*)|(.*memory.*)|(.*cpu.*)/ }
+ cfg = cfg.each_line.reject { |line| line.match /(.*time.*)|(.*memory.*)|(.*cpu.*)/ }
cfg = cfg.join
comment cfg
end
@@ -19,6 +24,4 @@ class FirewareOS < Oxidized::Model
cfg :ssh do
pre_logout 'exit'
end
-
end
-
diff --git a/lib/oxidized/model/fortios.rb b/lib/oxidized/model/fortios.rb
index cd379b7..bbbab89 100644
--- a/lib/oxidized/model/fortios.rb
+++ b/lib/oxidized/model/fortios.rb
@@ -1,6 +1,5 @@
class FortiOS < Oxidized::Model
-
- comment '# '
+ comment '# '
prompt /^([-\w\.\~]+(\s[\(\w\-\.\)]+)?\~?\s?[#>$]\s?)$/
@@ -14,6 +13,16 @@ class FortiOS < Oxidized::Model
new_cfg << cfg.each_line.to_a[1..-2].map { |line| line.gsub(/(conf_file_ver=)(.*)/, '\1<stripped>\3') }.join
end
+ cmd :secret do |cfg|
+ cfg.gsub! /(set (?:passwd|password|psksecret|secret|key|group-password|secondary-secret|tertiary-secret|auth-password-l1|auth-password-l2|rsso|history0|history1|inter-controller-key ENC|passphrase ENC|login-passwd ENC)).*/, '\\1 <configuration removed>'
+ cfg.gsub! /(set private-key).*-+END ENCRYPTED PRIVATE KEY-*"$/m, '\\1 <configuration removed>'
+ cfg.gsub! /(set ca ).*-+END CERTIFICATE-*"$/m, '\\1 <configuration removed>'
+ cfg.gsub! /(set csr ).*-+END CERTIFICATE REQUEST-*"$/m, '\\1 <configuration removed>'
+ cfg.gsub! /(Virus-DB|Extended DB|IPS-DB|IPS-ETDB|APP-DB|INDUSTRIAL-DB|Botnet DB|IPS Malicious URL Database).*/, '\\1 <configuration removed>'
+ cfg.gsub! /(Cluster uptime:).*/, '\\1 <configuration removed>'
+ cfg
+ end
+
cmd 'get system status' do |cfg|
@vdom_enabled = cfg.include? 'Virtual domain configuration: enable'
cfg.gsub!(/(System time: )(.*)/, '\1<stripped>\3')
@@ -28,13 +37,18 @@ class FortiOS < Oxidized::Model
comment cfg
end
- cfg << cmd('diagnose autoupdate version') do |cfg|
- comment cfg
+ # default behaviour: include autoupdate output (backwards compatibility)
+ # do not include if variable "show_autoupdate" is set to false
+ if defined?(vars(:fortios_autoupdate)).nil? || vars(:fortios_autoupdate)
+ cfg << cmd('diagnose autoupdate version') do |cfg|
+ cfg.gsub! /(FDS Address\n---------\n).*/, '\\1IP Address removed'
+ comment cfg.each_line.reject { |line| line.match /Last Update|Result/ }.join
+ end
end
cfg << cmd('end') if @vdom_enabled
- cfg << cmd('show')
+ cfg << cmd('show full-configuration | grep .')
cfg.join "\n"
end
@@ -46,5 +60,4 @@ class FortiOS < Oxidized::Model
cfg :telnet, :ssh do
pre_logout "exit\n"
end
-
end
diff --git a/lib/oxidized/model/ftos.rb b/lib/oxidized/model/ftos.rb
index b465271..3ef4de6 100644
--- a/lib/oxidized/model/ftos.rb
+++ b/lib/oxidized/model/ftos.rb
@@ -1,5 +1,4 @@
-class FTOS < Oxidized::Model
-
+class FTOS < Oxidized::Model
# Force10 FTOS model #
comment '! '
@@ -8,13 +7,15 @@ class FTOS < Oxidized::Model
cfg.each_line.to_a[2..-2].join
end
- cmd :secret do |cfg|
+ cmd :secret do |cfg|
cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
cfg.gsub! /secret (\d+) (\S+).*/, '<secret hidden>'
cfg
end
cmd 'show inventory' do |cfg|
+ # Old versions of FTOS can occasionally return data that triggers encoding errors.
+ cfg.encode!("UTF-8", :invalid => :replace, :undef => :replace, :replace => "")
comment cfg
end
@@ -43,5 +44,4 @@ class FTOS < Oxidized::Model
end
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/fujitsupy.rb b/lib/oxidized/model/fujitsupy.rb
index 20a78dd..a2db909 100644
--- a/lib/oxidized/model/fujitsupy.rb
+++ b/lib/oxidized/model/fujitsupy.rb
@@ -1,5 +1,4 @@
class FujitsuPY < Oxidized::Model
-
prompt /^(\([\w.-]*\)\s#|^\S+\#\s)$/
comment '! '
@@ -7,13 +6,13 @@ class FujitsuPY < Oxidized::Model
cfg.each_line.to_a[1..-2].join
end
-# 1Gbe switch
+ # 1Gbe switch
cmd 'show version' do |cfg|
cfg.gsub! /^(<ERROR> : 2 : format error)$/, ''
comment cfg
end
-# 10Gbe switch
+ # 10Gbe switch
cmd 'show system information' do |cfg|
cfg.gsub! /^Current-time : [\w\s:]*$/, ''
cfg.gsub! /^(\s{33}\^)$/, ''
@@ -38,5 +37,4 @@ class FujitsuPY < Oxidized::Model
send "n\n"
end
end
-
end
diff --git a/lib/oxidized/model/gaiaos.rb b/lib/oxidized/model/gaiaos.rb
index 434e774..8f13bcb 100644
--- a/lib/oxidized/model/gaiaos.rb
+++ b/lib/oxidized/model/gaiaos.rb
@@ -1,25 +1,23 @@
class GaiaOS < Oxidized::Model
-
# CheckPoint - Gaia OS Model
-
+
# Gaia Prompt
prompt /^([\[\]\w.@:-]+[#>]\s?)$/
# Comment tag
comment '# '
-
cmd :all do |cfg|
cfg = cfg.each_line.to_a[1..-2].join
end
cmd :secret do |cfg|
cfg.gsub! /^(set expert-password-hash ).*/, '\1<EXPERT PASSWORD REMOVED>'
- cfg.gsub! /^(set user \S+ password-hash ).*/,'\1<USER PASSWORD REMOVED>'
- cfg.gsub! /^(set ospf .* secret ).*/,'\1<OSPF KEY REMOVED>'
- cfg.gsub! /^(set snmp community )(.*)( read-only.*)/,'\1<SNMP COMMUNITY REMOVED>\3'
- cfg.gsub! /^(add snmp .* community )(.*)(\S?.*)/,'\1<SNMP COMMUNITY REMOVED>\3'
- cfg.gsub! /(auth|privacy)(-pass-phrase-hashed )(\S*)/,'\1-pass-phrase-hashed <SNMP PASS-PHRASE REMOVED>'
+ cfg.gsub! /^(set user \S+ password-hash ).*/, '\1<USER PASSWORD REMOVED>'
+ cfg.gsub! /^(set ospf .* secret ).*/, '\1<OSPF KEY REMOVED>'
+ cfg.gsub! /^(set snmp community )(.*)( read-only.*)/, '\1<SNMP COMMUNITY REMOVED>\3'
+ cfg.gsub! /^(add snmp .* community )(.*)(\S?.*)/, '\1<SNMP COMMUNITY REMOVED>\3'
+ cfg.gsub! /(auth|privacy)(-pass-phrase-hashed )(\S*)/, '\1-pass-phrase-hashed <SNMP PASS-PHRASE REMOVED>'
cfg
end
@@ -36,11 +34,9 @@ class GaiaOS < Oxidized::Model
cfg
end
-
cfg :ssh do
# User shell must be /etc/cli.sh
post_login 'set clienv rows 0'
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/gcombnps.rb b/lib/oxidized/model/gcombnps.rb
new file mode 100644
index 0000000..e92c7ba
--- /dev/null
+++ b/lib/oxidized/model/gcombnps.rb
@@ -0,0 +1,82 @@
+class GcomBNPS < Oxidized::Model
+ # For switches from GCOM Technologies Co.,Ltd. running the "Broadband Network Platform Software"
+ # Author: Frederik Kriewitz <frederik@kriewitz.eu>
+ #
+ # tested with:
+ # - S5330 (aka Fiberstore S3800)
+
+ prompt /^\r?([\w.@()-]+?(\(1-16 chars\))?[#>:]\s?)$/ # also match SSH password promt (post_login commands are sent after the first prompt)
+ comment '! '
+
+ # alternative to handle the SSH login, but this breaks telnet
+ # expect /^Password\(1-16 chars\):/ do |data|
+ # send @node.auth[:password] + "\n"
+ # ''
+ # end
+
+ # handle pager (can't be disabled?)
+ expect /^\.\.\.\.press ENTER to next line, CTRL_C to quit, other key to next page\.\.\.\.$/ do |data, re|
+ send ' '
+ data.sub re, ''
+ end
+
+ cmd :all do |cfg|
+ cfg = cfg.gsub " \e[73D\e[K", '' # remove garbage remaining from the pager
+ cfg.each_line.to_a[1..-2].join
+ end
+
+ cmd :secret do |cfg|
+ cfg.gsub! /^(snmp-server community)\s+[^\s]+\s+(.*)/, '\\1 <community hidden> \\2'
+ cfg
+ end
+
+ cmd 'show running-config' do |cfg|
+ cfg
+ end
+
+ cmd 'show interface sfp' do |cfg|
+ out = []
+ cfg.each_line do |line|
+ next if line.match /^ Temperature/
+ next if line.match /^ Voltage\(V\)/
+ next if line.match /^ Bias Current\(mA\)/
+ next if line.match /^ RX Power\(dBM\)/
+ next if line.match /^ TX Power\(dBM\)/
+ out << line
+ end
+
+ comment out.join
+ end
+
+ cmd 'show version' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show system' do |cfg|
+ out = []
+ cfg.each_line do |line|
+ next if line.match /^system run time :/
+ next if line.match /^switch temperature :/
+ out << line
+ end
+
+ comment out.join
+ end
+
+ cfg :telnet do
+ username /^Username\(1-32 chars\):/
+ password /^Password\(1-16 chars\):/
+ end
+
+ cfg :ssh do
+ # the switch blindy accepts the SSH connection without password validation and then spawns a telnet login prompt
+ # first thing we've to send is the password
+ post_login do
+ send @node.auth[:password] + "\n"
+ end
+ end
+
+ cfg :telnet, :ssh do
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/hatteras.rb b/lib/oxidized/model/hatteras.rb
index 4192cbc..7341cc4 100644
--- a/lib/oxidized/model/hatteras.rb
+++ b/lib/oxidized/model/hatteras.rb
@@ -9,7 +9,6 @@ class Hatteras < Oxidized::Model
data.sub re, ''
end
-
cmd :secret do |cfg|
cfg.gsub! /^(community) \S+/, '\\1 "<configuration removed>"'
cfg.gsub! /^(communityString) "\S+"/, '\\1 "<configuration removed>"'
@@ -22,14 +21,18 @@ class Hatteras < Oxidized::Model
end
cmd "show switch\r" do |cfg|
- cfg = cfg.each_line.reject { |line| line.match /Switch uptime|Switch temperature|Last reset reason/ or
- line.match /TermCpuUtil|^\s+\^$|ERROR: Bad command/ }.join
+ cfg = cfg.each_line.reject { |line|
+ line.match /Switch uptime|Switch temperature|Last reset reason/ or
+ line.match /TermCpuUtil|^\s+\^$|ERROR: Bad command/
+ } .join
comment cfg
end
cmd "show card\r" do |cfg|
- cfg = cfg.each_line.reject { |line| line.match /Card uptime|Card temperature|Last reset reason/ or
- line.match /TermCpuUtil|^\s+\^$|ERROR: Bad command/ }.join
+ cfg = cfg.each_line.reject { |line|
+ line.match /Card uptime|Card temperature|Last reset reason/ or
+ line.match /TermCpuUtil|^\s+\^$|ERROR: Bad command/
+ } .join
comment cfg
end
diff --git a/lib/oxidized/model/hirschmann.rb b/lib/oxidized/model/hirschmann.rb
new file mode 100644
index 0000000..858b198
--- /dev/null
+++ b/lib/oxidized/model/hirschmann.rb
@@ -0,0 +1,39 @@
+class Hirschmann < Oxidized::Model
+ prompt /^[\(\w\s\w\)]+\s[>|#]+?$/
+
+ comment '## '
+
+ # Handle pager
+ expect /^--More--.*$/ do |data, re|
+ send 'a'
+ data.sub re, ''
+ end
+
+ cmd :all do |cfg|
+ cfg.each_line.to_a[1..-2].join
+ end
+
+ cmd 'show sysinfo' do |cfg|
+ cfg.gsub! /^System Up Time.*\n/, ""
+ cfg.gsub! /^System Date and Time.*\n/, ""
+ cfg.gsub! /^CPU Utilization.*\n/, ""
+ cfg.gsub! /^Memory.*\n/, ""
+ cfg.gsub! /^Average CPU Utilization.*\n/, ""
+ comment cfg
+ end
+
+ cmd 'show running-config' do |cfg|
+ cfg.gsub! /^users.*\n/, ""
+ cfg
+ end
+
+ cfg :telnet do
+ username /^User:/
+ password /^Password:/
+ end
+
+ cfg :telnet, :ssh do
+ post_login 'enable'
+ pre_logout 'logout'
+ end
+end
diff --git a/lib/oxidized/model/hpebladesystem.rb b/lib/oxidized/model/hpebladesystem.rb
index 5e34de8..75d2dbf 100644
--- a/lib/oxidized/model/hpebladesystem.rb
+++ b/lib/oxidized/model/hpebladesystem.rb
@@ -4,13 +4,13 @@ class HPEBladeSystem < Oxidized::Model
prompt /.*> /
comment '# '
- expect /^\s*--More--\s+.*$/ do |data, re|
- send ' '
- data.sub re, ''
- end
+ # expect /^\s*--More--\s+.*$/ do |data, re|
+ # send ' '
+ # data.sub re, ''
+ # end
cmd :all do |cfg|
- cfg = cfg.delete("\r").each_line.to_a[0..-1].map{|line|line.rstrip}.join("\n") + "\n"
+ cfg = cfg.delete("\r").each_line.to_a[0..-1].map { |line| line.rstrip }.join("\n") + "\n"
cfg.each_line.to_a[0..-2].join
end
@@ -22,7 +22,7 @@ class HPEBladeSystem < Oxidized::Model
cmd 'show oa info' do |cfg|
comment cfg
end
-
+
cmd 'show oa network' do |cfg|
comment cfg
end
@@ -30,16 +30,17 @@ class HPEBladeSystem < Oxidized::Model
cmd 'show oa certificate' do |cfg|
comment cfg
end
-
+
cmd 'show sshfingerprint' do |cfg|
comment cfg
end
-
+
cmd 'show fru' do |cfg|
comment cfg
end
-
+
cmd 'show network' do |cfg|
+ cfg.gsub! /Last Update:.*$/i, ''
comment cfg
end
@@ -54,15 +55,15 @@ class HPEBladeSystem < Oxidized::Model
cmd 'show server list' do |cfg|
comment cfg
end
-
+
cmd 'show server names' do |cfg|
comment cfg
end
-
+
cmd 'show server port map all' do |cfg|
comment cfg
end
-
+
cmd 'show server info all' do |cfg|
comment cfg
end
@@ -71,13 +72,14 @@ class HPEBladeSystem < Oxidized::Model
cfg.gsub! /^#(Generated on:) .*$/, '\\1 <removed>'
cfg.gsub /^\s+/, ''
end
-
+
cfg :telnet do
username /\slogin:/
password /^Password: /
end
-
- cfg :telnet, :ssh do
- pre_logout "exit"
- end
+
+ cfg :telnet, :ssh do
+ post_login "set script mode on"
+ pre_logout "exit"
+ end
end
diff --git a/lib/oxidized/model/hpemsa.rb b/lib/oxidized/model/hpemsa.rb
new file mode 100644
index 0000000..68485a1
--- /dev/null
+++ b/lib/oxidized/model/hpemsa.rb
@@ -0,0 +1,10 @@
+class HpeMsa < Oxidized::Model
+ prompt /^#\s?$/
+
+ cmd 'show configuration'
+
+ cfg :ssh do
+ post_login 'set cli-parameters pager disabled'
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/ios.rb b/lib/oxidized/model/ios.rb
index c8b0ef3..8069f83 100644
--- a/lib/oxidized/model/ios.rb
+++ b/lib/oxidized/model/ios.rb
@@ -1,41 +1,114 @@
class IOS < Oxidized::Model
-
prompt /^([\w.@()-]+[#>]\s?)$/
comment '! '
# example how to handle pager
- #expect /^\s--More--\s+.*$/ do |data, re|
+ # expect /^\s--More--\s+.*$/ do |data, re|
# send ' '
# data.sub re, ''
- #end
+ # end
# non-preferred way to handle additional PW prompt
- #expect /^[\w.]+>$/ do |data|
+ # expect /^[\w.]+>$/ do |data|
# send "enable\n"
# send vars(:enable) + "\n"
# data
- #end
+ # end
cmd :all do |cfg|
- #cfg.gsub! /\cH+\s{8}/, '' # example how to handle pager
- #cfg.gsub! /\cH+/, '' # example how to handle pager
+ # cfg.gsub! /\cH+\s{8}/, '' # example how to handle pager
+ # cfg.gsub! /\cH+/, '' # example how to handle pager
+ # get rid of errors for commands that don't work on some devices
+ cfg.gsub! /^% Invalid input detected at '\^' marker\.$|^\s+\^$/, ''
cfg.each_line.to_a[1..-2].join
end
cmd :secret do |cfg|
cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
- cfg.gsub! /username (\S+) privilege (\d+) (\S+).*/, '<secret hidden>'
- cfg.gsub! /^username \S+ password \d \S+/, '<secret hidden>'
- cfg.gsub! /^username \S+ secret \d \S+/, '<secret hidden>'
- cfg.gsub! /^enable (password|secret) \d \S+/, '<secret hidden>'
+ cfg.gsub! /^(snmp-server host \S+( vrf \S+)?( version (1|2c|3))?)\s+\S+((\s+\S*)*)\s*/, '\\1 <secret hidden> \\5'
+ cfg.gsub! /^(username \S+ privilege \d+) (\S+).*/, '\\1 <secret hidden>'
+ cfg.gsub! /^(username \S+ password \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(username \S+ secret \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(enable (password|secret) \d) (\S+)/, '\\1 <secret hidden>'
cfg.gsub! /^(\s+(?:password|secret)) (?:\d )?\S+/, '\\1 <secret hidden>'
- cfg.gsub! /wpa-psk ascii \d \S+/, '<secret hidden>'
- cfg.gsub! /^tacacs-server key \d \S+/, '<secret hidden>'
+ cfg.gsub! /^(.*wpa-psk ascii \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(.*key 7) (\d.+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(tacacs-server key \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(crypto isakmp key) (\S+) (.*)/, '\\1 <secret hidden> \\3'
cfg
end
cmd 'show version' do |cfg|
- comment cfg.lines.first
+ comments = []
+ comments << cfg.lines.first
+ lines = cfg.lines
+ lines.each_with_index do |line, i|
+ slave = ''
+ slaveslot = ''
+
+ if line.match /^Slave in slot (\d+) is running/
+ slave = " Slave:";
+ slaveslot = ", slot #{$1}";
+ end
+
+ if line.match /^Compiled (.*)$/
+ comments << "Image:#{slave} Compiled: #{$1}"
+ end
+
+ if line.match /^(?:Cisco )?IOS .* Software,? \(([A-Za-z0-9_-]*)\), .*Version\s+(.*)$/
+ comments << "Image:#{slave} Software: #{$1}, #{$2}"
+ end
+
+ if line.match /^ROM: (IOS \S+ )?(System )?Bootstrap.*(Version.*)$/
+ comments << "ROM Bootstrap: #{$3}"
+ end
+
+ if line.match /^BOOTFLASH: .*(Version.*)$/
+ comments << "BOOTFLASH: #{$1}"
+ end
+
+ if line.match /^(\d+[kK]) bytes of (non-volatile|NVRAM)/
+ comments << "Memory: nvram #{$1}"
+ end
+
+ if line.match /^(\d+[kK]) bytes of (flash memory|flash internal|processor board System flash|ATA CompactFlash)/i
+ comments << "Memory: flash #{$1}"
+ end
+
+ if line.match (/^(\d+[kK]) bytes of (Flash|ATA)?.*PCMCIA .*(slot|disk) ?(\d)/i)
+ comments << "Memory: pcmcia #{$2} #{$3}#{$4} #{$1}";
+ end
+
+ if line.match /(\S+(?:\sseries)?)\s+(?:\((\S+)\)\s+processor|\(revision[^)]+\)).*\s+with (\S+k) bytes/i
+ sproc = $1
+ cpu = $2
+ mem = $3
+ cpuxtra = ''
+ comments << "Chassis type:#{slave} #{sproc}";
+ comments << "Memory:#{slave} main #{mem}";
+ # check the next two lines for more CPU info
+ if cfg.lines[i + 1].match /processor board id (\S+)/i
+ comments << "Processor ID: #{$1}";
+ end
+ if cfg.lines[i + 2].match /(cpu at |processor: |#{cpu} processor,)/i
+ # change implementation to impl and prepend comma
+ cpuxtra = cfg.lines[i + 2].gsub(/implementation/, 'impl').gsub(/^/, ', ').chomp;
+ end
+ comments << "CPU:#{slave} #{cpu}#{cpuxtra}#{slaveslot}";
+ end
+
+ if line.match /^System image file is "([^\"]*)"$/
+ comments << "Image: #{$1}"
+ end
+ end
+ comments << "\n"
+ comment comments.join "\n"
+ end
+
+ cmd 'show vtp status' do |cfg|
+ cfg.gsub! /^$\n/, ''
+ cfg.gsub! /^/, 'VTP: ' if (!cfg.empty?)
+ comment "#{cfg}\n"
end
cmd 'show inventory' do |cfg|
@@ -53,8 +126,8 @@ class IOS < Oxidized::Model
end
cfg :telnet do
- username /^Username:/
- password /^Password:/
+ username /^Username:/i
+ password /^Password:/i
end
cfg :telnet, :ssh do
@@ -69,5 +142,4 @@ class IOS < Oxidized::Model
post_login 'terminal width 0'
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/iosxe.rb b/lib/oxidized/model/iosxe.rb
new file mode 100644
index 0000000..1945e11
--- /dev/null
+++ b/lib/oxidized/model/iosxe.rb
@@ -0,0 +1,5 @@
+# IOS parser should work here
+
+require_relative 'ios.rb'
+
+IOSXE = IOS
diff --git a/lib/oxidized/model/iosxr.rb b/lib/oxidized/model/iosxr.rb
index bf01140..1635e57 100644
--- a/lib/oxidized/model/iosxr.rb
+++ b/lib/oxidized/model/iosxr.rb
@@ -1,5 +1,4 @@
class IOSXR < Oxidized::Model
-
# IOS XR model #
prompt /^(\r?[\w.@:\/-]+[#>]\s?)$/
@@ -9,7 +8,7 @@ class IOSXR < Oxidized::Model
cfg.each_line.to_a[2..-2].join
end
- cmd :secret do |cfg|
+ cmd :secret do |cfg|
cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
cfg.gsub! /secret (\d+) (\S+).*/, '<secret hidden>'
cfg
@@ -36,6 +35,7 @@ class IOSXR < Oxidized::Model
cfg :telnet, :ssh do
post_login 'terminal length 0'
post_login 'terminal width 0'
+ post_login 'terminal exec prompt no-timestamp'
if vars :enable
post_login do
send "enable\n"
@@ -44,5 +44,4 @@ class IOSXR < Oxidized::Model
end
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/ipos.rb b/lib/oxidized/model/ipos.rb
index 5efd831..753c6b1 100644
--- a/lib/oxidized/model/ipos.rb
+++ b/lib/oxidized/model/ipos.rb
@@ -1,9 +1,8 @@
class IPOS < Oxidized::Model
-
# Ericsson SSR (IPOS)
# Redback SE (SEOS)
- prompt /^([\[\]\w.@-]+[#>]\s?)$/
+ prompt /^([\[\]\w.@-]+[#:>]\s?)$/
comment '! '
cmd 'show chassis' do |cfg|
@@ -52,10 +51,15 @@ class IPOS < Oxidized::Model
cfg :telnet, :ssh do
post_login 'terminal length 0'
+ if vars :enable
+ post_login do
+ cmd "enable"
+ cmd vars(:enable)
+ end
+ end
pre_logout do
send "exit\n"
send "n\n"
end
end
-
end
diff --git a/lib/oxidized/model/ironware.rb b/lib/oxidized/model/ironware.rb
index 5b58f22..32dbf47 100644
--- a/lib/oxidized/model/ironware.rb
+++ b/lib/oxidized/model/ironware.rb
@@ -1,19 +1,17 @@
class IronWare < Oxidized::Model
-
prompt /^.*(telnet|ssh)\@.+[>#]\s?$/i
comment '! '
- #to handle pager without enable
- #expect /^((.*)--More--(.*))$/ do |data, re|
+ # to handle pager without enable
+ # expect /^((.*)--More--(.*))$/ do |data, re|
# send ' '
# data.sub re, ''
- #end
-
+ # end
- #to remove backspace (if handle pager without enable)
- #expect /^((.*)[\b](.*))$/ do |data, re|
+ # to remove backspace (if handle pager without enable)
+ # expect /^((.*)[\b](.*))$/ do |data, re|
# data.sub re, ''
- #end
+ # end
cmd :all do |cfg|
# sometimes ironware inserts arbitrary whitespace after commands are
@@ -22,18 +20,20 @@ class IronWare < Oxidized::Model
end
cmd 'show version' do |cfg|
- cfg.gsub! /(^((.*)[Ss]ystem uptime(.*))$)/, '' #remove unwanted line system uptime
+ cfg.gsub! /(^((.*)[Ss]ystem uptime(.*))$)/, '' # remove unwanted line system uptime
cfg.gsub! /(^((.*)[Tt]he system started at(.*))$)/, ''
- cfg.gsub! /[Uu]p\s?[Tt]ime is .*/,''
+ cfg.gsub! /[Uu]p\s?[Tt]ime is .*/, ''
comment cfg
end
cmd 'show chassis' do |cfg|
- cfg.encode!("UTF-8", :invalid => :replace, :undef => :replace) #sometimes ironware returns broken encoding
- cfg.gsub! /(^((.*)Current temp(.*))$)/, '' #remove unwanted lines current temperature
- cfg.gsub! /Speed = [A-Z-]{2,6} \(\d{2,3}\%\)/, '' #remove unwanted lines Speed Fans
+ cfg.encode!("UTF-8", :invalid => :replace, :undef => :replace) # sometimes ironware returns broken encoding
+ cfg.gsub! /(^((.*)Current temp(.*))$)/, '' # remove unwanted lines current temperature
+ cfg.gsub! /Speed = [A-Z-]{2,6} \(\d{2,3}\%\)/, '' # remove unwanted lines Speed Fans
cfg.gsub! /current speed is [A-Z]{2,6} \(\d{2,3}\%\)/, ''
+ cfg.gsub! /Fan \d* - STATUS: OK \D*\d*./, '' # Fix for ADX Fan speed reporting
+ cfg.gsub! /\d* deg C/, '' # Fix for ADX temperature reporting
cfg.gsub! /([\[]*)1([\]]*)<->([\[]*)2([\]]*)(<->([\[]*)3([\]]*))*/, ''
cfg.gsub! /\d{2}\.\d deg-C/, 'XX.X deg-C'
if cfg.include? "TEMPERATURE"
@@ -50,6 +50,7 @@ class IronWare < Oxidized::Model
end
cmd 'show flash' do |cfg|
+ cfg.gsub! /(\d+) bytes/, '' # Fix for ADX flash size
comment cfg
end
@@ -67,23 +68,20 @@ class IronWare < Oxidized::Model
# match expected prompts on both older and newer
# versions of IronWare
username /^(Please Enter Login Name|Username):/
- password /^(Please Enter )Password:/
+ password /^(Please Enter Password ?|Password):/
end
- #handle pager with enable
+ # handle pager with enable
cfg :telnet, :ssh do
if vars :enable
post_login do
- send "enable\r\n"
+ send "enable\n"
cmd vars(:enable)
end
end
post_login ''
post_login 'skip-page-display'
post_login 'terminal length 0'
- pre_logout 'logout'
- pre_logout 'exit'
- pre_logout 'exit'
+ pre_logout "logout\nexit\nexit\n"
end
-
end
diff --git a/lib/oxidized/model/isam.rb b/lib/oxidized/model/isam.rb
index 1709500..8b8b5d5 100644
--- a/lib/oxidized/model/isam.rb
+++ b/lib/oxidized/model/isam.rb
@@ -1,6 +1,6 @@
class ISAM < Oxidized::Model
- #Alcatel ISAM 7302/7330 FTTN
-
+ # Alcatel ISAM 7302/7330 FTTN
+
prompt /^([\w.:@-]+>#\s)$/
comment '# '
@@ -8,7 +8,7 @@ class ISAM < Oxidized::Model
cfg.each_line.to_a[1..-2].join
end
- cfg :telnet do
+ cfg :telnet do
username /^login:\s*/
password /^password:\s*/
end
@@ -19,7 +19,7 @@ class ISAM < Oxidized::Model
post_login 'environment inhibit-alarms print no-more'
pre_logout 'logout'
end
-
+
cmd 'show software-mngt oswp detail' do |cfg|
comment cfg
end
@@ -31,5 +31,4 @@ class ISAM < Oxidized::Model
cmd 'info configure flat' do |cfg|
cfg
end
-
end
diff --git a/lib/oxidized/model/junos.rb b/lib/oxidized/model/junos.rb
index 058e3cf..737a000 100644
--- a/lib/oxidized/model/junos.rb
+++ b/lib/oxidized/model/junos.rb
@@ -1,6 +1,5 @@
class JunOS < Oxidized::Model
-
- comment '# '
+ comment '# '
def telnet
@input.class.to_s.match(/Telnet/)
@@ -8,11 +7,15 @@ class JunOS < Oxidized::Model
cmd :all do |cfg|
cfg = cfg.lines.to_a[1..-2].join if screenscrape
+ cfg.gsub!(/ scale-subscriber (\s+)(\d+)/, ' scale-subscriber <count>')
cfg.lines.map { |line| line.rstrip }.join("\n") + "\n"
end
cmd :secret do |cfg|
- cfg.gsub!(/encrypted-password (\S+).*/, '<secret removed>')
+ cfg.gsub!(/encrypted-password (\S+).*/, 'encrypted-password <secret removed>')
+ cfg.gsub!(/pre-shared-key ascii-text (\S+).*/, 'pre-shared-key ascii-text <secret removed>')
+ cfg.gsub!(/pre-shared-key hexadecimal (\S+).*/, 'pre-shared-key hexadecimal <secret removed>')
+ cfg.gsub!(/authentication-key (\S+).*/, 'authentication-key <secret removed>')
cfg.gsub!(/community (\S+) {/, 'community <hidden> {')
cfg
end
@@ -28,7 +31,7 @@ class JunOS < Oxidized::Model
out = ''
case @model
when 'mx960'
- out << cmd('show chassis fabric reachability') { |cfg| comment cfg }
+ out << cmd('show chassis fabric reachability') { |cfg| comment cfg }
when /^(ex22|ex33|ex4|ex8|qfx)/
out << cmd('show virtual-chassis') { |cfg| comment cfg }
end
@@ -36,6 +39,8 @@ class JunOS < Oxidized::Model
end
cmd('show chassis hardware') { |cfg| comment cfg }
+ cmd('show system license') { |cfg| comment cfg }
+ cmd('show system license keys') { |cfg| comment cfg }
cfg :telnet do
username(/^login:/)
@@ -43,7 +48,7 @@ class JunOS < Oxidized::Model
end
cfg :ssh do
- exec true # don't run shell, run each command in exec channel
+ exec true # don't run shell, run each command in exec channel
end
cfg :telnet, :ssh do
@@ -51,5 +56,4 @@ class JunOS < Oxidized::Model
post_login 'set cli screen-width 0'
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/masteros.rb b/lib/oxidized/model/masteros.rb
index 587fdc4..c03beb1 100644
--- a/lib/oxidized/model/masteros.rb
+++ b/lib/oxidized/model/masteros.rb
@@ -1,8 +1,7 @@
class MasterOS < Oxidized::Model
-
# MRV MasterOS model #
-comment '!'
+ comment '!'
cmd :secret do |cfg|
cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
@@ -43,5 +42,4 @@ comment '!'
end
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/mlnxos.rb b/lib/oxidized/model/mlnxos.rb
index 9542c88..990417d 100644
--- a/lib/oxidized/model/mlnxos.rb
+++ b/lib/oxidized/model/mlnxos.rb
@@ -1,8 +1,7 @@
class MLNXOS < Oxidized::Model
-
prompt /([\w.@()-\[:\s\]]+[#>]\s)$/
- comment '## '
-
+ comment '## '
+
# Pager Handling
expect /.+lines\s\d+\-\d+([\s]|\/\d+\s\(END\)\s).+$/ do |data, re|
send ' '
@@ -11,8 +10,12 @@ class MLNXOS < Oxidized::Model
cmd :all do |cfg|
cfg.gsub! /\[\?1h=\r/, '' # Pager Handling
- cfg.gsub! /\r\[K/,'' # Pager Handling
+ cfg.gsub! /\r\[K/, '' # Pager Handling
cfg.gsub! /\s/, '' # Linebreak Handling
+ cfg.gsub! /^CPU\ load\ averages\:\s.+/, '' # Omit constantly changing CPU info
+ cfg.gsub! /^System\ memory\:\s.+/, '' # Omit constantly changing memory info
+ cfg.gsub! /^Uptime\:\s.+/, '' # Omit constantly changing uptime info
+ cfg.gsub! /.+Generated\ at\s\d+.+/, '' # Omit constantly changing generation time info
cfg = cfg.lines.to_a[2..-3].join
end
@@ -38,6 +41,6 @@ class MLNXOS < Oxidized::Model
cfg :ssh do
password /^Password:\s*/
- pre_logout 'exit'
+ pre_logout "\nexit"
end
end
diff --git a/lib/oxidized/model/model.rb b/lib/oxidized/model/model.rb
index a2a71cb..438357f 100644
--- a/lib/oxidized/model/model.rb
+++ b/lib/oxidized/model/model.rb
@@ -7,29 +7,34 @@ module Oxidized
class << self
def inherited klass
- klass.instance_variable_set '@cmd', Hash.new { |h,k| h[k] = [] }
- klass.instance_variable_set '@cfg', Hash.new { |h,k| h[k] = [] }
- klass.instance_variable_set '@procs', Hash.new { |h,k| h[k] = [] }
+ klass.instance_variable_set '@cmd', Hash.new { |h, k| h[k] = [] }
+ klass.instance_variable_set '@cfg', Hash.new { |h, k| h[k] = [] }
+ klass.instance_variable_set '@procs', Hash.new { |h, k| h[k] = [] }
klass.instance_variable_set '@expect', []
klass.instance_variable_set '@comment', nil
klass.instance_variable_set '@prompt', nil
end
- def comment _comment='# '
+
+ def comment _comment = '# '
return @comment if @comment
@comment = block_given? ? yield : _comment
end
- def prompt _prompt=nil
+
+ def prompt _prompt = nil
@prompt or @prompt = _prompt
end
+
def cfg *methods, &block
[methods].flatten.each do |method|
@cfg[method.to_s] << block
end
end
+
def cfgs
@cfg
end
- def cmd _cmd=nil, &block
+
+ def cmd _cmd = nil, &block
if _cmd.class == Symbol
@cmd[_cmd] << block
else
@@ -37,12 +42,15 @@ module Oxidized
end
Oxidized.logger.debug "lib/oxidized/model/model.rb Added #{_cmd} to the commands list"
end
+
def cmds
@cmd
end
+
def expect re, &block
@expect << [re, block]
end
+
def expects
@expect
end
@@ -83,6 +91,7 @@ module Oxidized
Oxidized.logger.debug "lib/oxidized/model/model.rb Executing #{string}"
out = @input.cmd(string)
return false unless out
+ out = out.b unless Oxidized.config.input.utf8_encoded?
self.class.cmds[:all].each do |all_block|
out = instance_exec Oxidized::String.new(out), string, &all_block
end
@@ -166,6 +175,5 @@ module Oxidized
output.set_cmd(name)
output
end
-
end
end
diff --git a/lib/oxidized/model/mtrlrfs.rb b/lib/oxidized/model/mtrlrfs.rb
index 8baa4e9..31b4f22 100644
--- a/lib/oxidized/model/mtrlrfs.rb
+++ b/lib/oxidized/model/mtrlrfs.rb
@@ -1,5 +1,4 @@
class Mtrlrfs < Oxidized::Model
-
# Motorola RFS/Extreme WM
comment '# '
@@ -7,7 +6,7 @@ class Mtrlrfs < Oxidized::Model
cmd :all do |cfg|
# xos inserts leading \r characters and other trailing white space.
# this deletes extraneous \r and trailing white space.
- cfg.each_line.to_a[1..-2].map{|line|line.delete("\r").rstrip}.join("\n") + "\n"
+ cfg.each_line.to_a[1..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
end
cmd 'show version' do |cfg|
@@ -32,6 +31,4 @@ class Mtrlrfs < Oxidized::Model
send "n\n"
end
end
-
end
-
diff --git a/lib/oxidized/model/ndms.rb b/lib/oxidized/model/ndms.rb
new file mode 100644
index 0000000..1947f91
--- /dev/null
+++ b/lib/oxidized/model/ndms.rb
@@ -0,0 +1,24 @@
+class NDMS < Oxidized::Model
+ # Pull config from Zyxel Keenetic devices from version NDMS >= 2.0
+
+ comment '! '
+
+ prompt /^([\w.@()-]+[#>]\s?)/m
+
+ cmd 'show version' do |cfg|
+ cfg = cfg.each_line.to_a[1..-3].join
+ comment cfg
+ end
+
+ cmd 'show running-config' do |cfg|
+ cfg = cfg.each_line.to_a[1..-2]
+ cfg = cfg.reject { |line| line.match /(clock date|checksum)/ }.join
+ cfg
+ end
+
+ cfg :telnet do
+ username /^Login:/
+ password /^Password:/
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/netgear.rb b/lib/oxidized/model/netgear.rb
new file mode 100644
index 0000000..40b0924
--- /dev/null
+++ b/lib/oxidized/model/netgear.rb
@@ -0,0 +1,39 @@
+class Netgear < Oxidized::Model
+ comment '!'
+ prompt /^(\([\w\s\-.]+\)\s[#>])$/
+
+ cmd :secret do |cfg|
+ cfg.gsub!(/password (\S+)/, 'password <hidden>')
+ cfg.gsub!(/encrypted (\S+)/, 'encrypted <hidden>')
+ cfg
+ end
+
+ cfg :telnet do
+ username /^(User:|Applying Interface configuration, please wait ...)/
+ end
+
+ cfg :telnet, :ssh do
+ if vars :enable
+ post_login do
+ send "enable\n"
+ # Interpret enable: true as meaning we won't be prompted for a password
+ unless vars(:enable).is_a? TrueClass
+ expect /[pP]assword:\s?$/
+ send vars(:enable) + "\n"
+ end
+ expect /^.+[#]$/
+ end
+ end
+ post_login 'terminal length 0'
+ # quit / logout will sometimes prompt the user:
+ #
+ # The system has unsaved changes.
+ # Would you like to save them now? (y/n)
+ #
+ # So it is safer simply to disconnect and not issue a pre_logout command
+ end
+
+ cmd 'show running-config' do |cfg|
+ cfg.gsub! /^(!.*Time).*$/, '\1'
+ end
+end
diff --git a/lib/oxidized/model/netscaler.rb b/lib/oxidized/model/netscaler.rb
index 9ca66b6..00d1b71 100644
--- a/lib/oxidized/model/netscaler.rb
+++ b/lib/oxidized/model/netscaler.rb
@@ -1,5 +1,4 @@
class NetScaler < Oxidized::Model
-
prompt /^\>\s*$/
comment '# '
@@ -20,5 +19,4 @@ class NetScaler < Oxidized::Model
cfg :ssh do
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/nos.rb b/lib/oxidized/model/nos.rb
index ec7c818..4049aa5 100644
--- a/lib/oxidized/model/nos.rb
+++ b/lib/oxidized/model/nos.rb
@@ -1,5 +1,4 @@
class NOS < Oxidized::Model
-
# Brocade Network Operating System
prompt /^(?:\e\[..h)?[\w.-]+# $/
@@ -38,8 +37,7 @@ class NOS < Oxidized::Model
cfg :telnet, :ssh do
post_login 'terminal length 0'
- #post_login 'terminal width 0'
+ # post_login 'terminal width 0'
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/nxos.rb b/lib/oxidized/model/nxos.rb
index fbe772d..d1449dd 100644
--- a/lib/oxidized/model/nxos.rb
+++ b/lib/oxidized/model/nxos.rb
@@ -1,8 +1,15 @@
class NXOS < Oxidized::Model
-
prompt /^(\r?[\w.@_()-]+[#]\s?)$/
comment '! '
+ cmd :secret do |cfg|
+ cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
+ cfg.gsub! /^(snmp-server user (\S+) (\S+) auth (\S+)) (\S+) (priv) (\S+)/, '\\1 <configuration removed> '
+ cfg.gsub! /^(username \S+ password \d) (\S+)/, '\\1 <secret hidden>'
+ cfg.gsub! /^(radius-server key).*/, '\\1 <secret hidden>'
+ cfg
+ end
+
cmd 'show version' do |cfg|
cfg = cfg.each_line.take_while { |line| not line.match(/uptime/i) }
comment cfg.join ""
@@ -10,10 +17,11 @@ class NXOS < Oxidized::Model
cmd 'show inventory' do |cfg|
comment cfg
- end
+ end
cmd 'show running-config' do |cfg|
cfg.gsub! /^!Time:[^\n]*\n/, ''
+ cfg
end
cfg :ssh, :telnet do
diff --git a/lib/oxidized/model/oneos.rb b/lib/oxidized/model/oneos.rb
new file mode 100644
index 0000000..35332c8
--- /dev/null
+++ b/lib/oxidized/model/oneos.rb
@@ -0,0 +1,56 @@
+class OneOS < Oxidized::Model
+ prompt /^([\w.@()-]+#\s?)$/
+ comment '! '
+
+ # example how to handle pager
+ # expect /^\s--More--\s+.*$/ do |data, re|
+ # send ' '
+ # data.sub re, ''
+ # end
+
+ # non-preferred way to handle additional PW prompt
+ # expect /^[\w.]+>$/ do |data|
+ # send "enable\n"
+ # send vars(:enable) + "\n"
+ # data
+ # end
+
+ cmd :all do |cfg|
+ # cfg.gsub! /\cH+\s{8}/, '' # example how to handle pager
+ # cfg.gsub! /\cH+/, '' # example how to handle pager
+ cfg.each_line.to_a[1..-2].join
+ end
+
+ cmd :secret do |cfg|
+ cfg.gsub! /^(snmp set-read-community ").*+?(".*)$/, '\\1<secret hidden>\\2'
+ cfg
+ end
+
+ cmd 'show version' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show running-config' do |cfg|
+ cfg = cfg.each_line.to_a[0..-1].join
+ cfg.gsub! /^Building configuration...\s*[^\n]*\n/, ''
+ cfg.gsub! /^Current configuration :\s*[^\n]*\n/, ''
+ cfg
+ end
+
+ cfg :telnet do
+ username /^Username:/
+ password /^Password:/
+ end
+
+ cfg :telnet, :ssh do
+ # preferred way to handle additional passwords
+ if vars :enable
+ post_login do
+ send "enable\n"
+ cmd vars(:enable)
+ end
+ end
+ post_login 'term len 0'
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/opengear.rb b/lib/oxidized/model/opengear.rb
index 7f801f8..e0d4c0a 100644
--- a/lib/oxidized/model/opengear.rb
+++ b/lib/oxidized/model/opengear.rb
@@ -1,6 +1,7 @@
class OpenGear < Oxidized::Model
+ comment '# '
- comment '# '
+ prompt /^(\$\s)?$/
cmd :secret do |cfg|
cfg.gsub!(/password (\S+)/, 'password <secret removed>')
@@ -13,7 +14,6 @@ class OpenGear < Oxidized::Model
cmd 'config -g config'
cfg :ssh do
- exec true # don't run shell, run each command in exec channel
+ exec true # don't run shell, run each command in exec channel
end
-
end
diff --git a/lib/oxidized/model/opnsense.rb b/lib/oxidized/model/opnsense.rb
new file mode 100644
index 0000000..a8f7a47
--- /dev/null
+++ b/lib/oxidized/model/opnsense.rb
@@ -0,0 +1,19 @@
+class OpnSense < Oxidized::Model
+ # minimum required permissions: "System: Shell account access"
+ # must enable SSH and password-based SSH access
+
+ cmd :all do |cfg|
+ cfg.each_line.to_a[1..-1].join
+ end
+
+ cmd 'cat /conf/config.xml' do |cfg|
+ cfg.gsub! /\s<revision>\s*<time>\d*<\/time>\s*.*\s*.*\s*<\/revision>/, ''
+ cfg.gsub! /\s<last_rule_upd_time>\d*<\/last_rule_upd_time>/, ''
+ cfg
+ end
+
+ cfg :ssh do
+ exec true
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/outputs.rb b/lib/oxidized/model/outputs.rb
index a668e9d..23a37f5 100644
--- a/lib/oxidized/model/outputs.rb
+++ b/lib/oxidized/model/outputs.rb
@@ -1,7 +1,6 @@
module Oxidized
class Model
class Outputs
-
def to_cfg
type_to_str(nil)
end
@@ -23,7 +22,7 @@ module Oxidized
end
def type type
- @outputs.select { |out| out.type==type }
+ @outputs.select { |out| out.type == type }
end
def types
@@ -35,7 +34,6 @@ module Oxidized
def initialize
@outputs = []
end
-
end
end
end
diff --git a/lib/oxidized/model/panos.rb b/lib/oxidized/model/panos.rb
index 68d80c3..422a9fe 100644
--- a/lib/oxidized/model/panos.rb
+++ b/lib/oxidized/model/panos.rb
@@ -1,8 +1,7 @@
class PanOS < Oxidized::Model
-
# PaloAlto PAN-OS model #
- comment '! '
+ comment '! '
prompt /^[\w.\@:\(\)-]+>\s?$/
@@ -28,6 +27,6 @@ class PanOS < Oxidized::Model
cfg :ssh do
post_login 'set cli pager off'
- pre_logout 'exit'
+ pre_logout 'quit'
end
end
diff --git a/lib/oxidized/model/pfsense.rb b/lib/oxidized/model/pfsense.rb
index c02c0d0..278a126 100644
--- a/lib/oxidized/model/pfsense.rb
+++ b/lib/oxidized/model/pfsense.rb
@@ -1,19 +1,18 @@
class PfSense < Oxidized::Model
-
# use other use than 'admin' user, 'admin' user cannot get ssh/exec. See issue #535
-
+
cmd :all do |cfg|
- cfg.each_line.to_a[1..-2].join
+ cfg.each_line.to_a[1..-1].join
end
-
+
cmd 'cat /cf/conf/config.xml' do |cfg|
- cfg.gsub! /\s<revision>\s*.*\s*<time>\d*<\/time>\s*.*\s*<\/revision>/, ''
+ cfg.gsub! /\s<revision>\s*<time>\d*<\/time>\s*.*\s*.*\s*<\/revision>/, ''
+ cfg.gsub! /\s<last_rule_upd_time>\d*<\/last_rule_upd_time>/, ''
cfg
end
-
+
cfg :ssh do
exec true
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/planet.rb b/lib/oxidized/model/planet.rb
index 05a369a..56e688c 100644
--- a/lib/oxidized/model/planet.rb
+++ b/lib/oxidized/model/planet.rb
@@ -1,24 +1,23 @@
class Planet < Oxidized::Model
-
prompt /^\r?([\w.@()-]+[#>]\s?)$/
comment '! '
# example how to handle pager
- #expect /^\s--More--\s+.*$/ do |data, re|
+ # expect /^\s--More--\s+.*$/ do |data, re|
# send ' '
# data.sub re, ''
- #end
+ # end
# non-preferred way to handle additional PW prompt
- #expect /^[\w.]+>$/ do |data|
+ # expect /^[\w.]+>$/ do |data|
# send "enable\n"
# send vars(:enable) + "\n"
# data
- #end
+ # end
cmd :all do |cfg|
- #cfg.gsub! /\cH+\s{8}/, '' # example how to handle pager
- #cfg.gsub! /\cH+/, '' # example how to handle pager
+ # cfg.gsub! /\cH+\s{8}/, '' # example how to handle pager
+ # cfg.gsub! /\cH+/, '' # example how to handle pager
cfg.each_line.to_a[1..-2].join
end
@@ -39,20 +38,20 @@ class Planet < Oxidized::Model
cfg = cfg.each_line.to_a[0...-2]
- # Strip system time and system uptime from planet gs switches
+ # Strip system (up)time and temperature
cfg = cfg.reject { |line| line.match /System Time\s*:.*/ }
cfg = cfg.reject { |line| line.match /System Uptime\s*:.*/ }
+ cfg = cfg.reject { |line| line.match /Temperature\s*:.*/ }
comment cfg.join
end
-
cmd 'show running-config' do |cfg|
cfg.gsub! "\n\r", "\n"
cfg = cfg.each_line.to_a
cfg = cfg.reject { |line| line.match "Building configuration..." }
-
+
if @planetsgs
cfg << cmd('show transceiver detail | include transceiver detail information|found|Type|length|Nominal|wavelength|Base information') do |cfg|
comment cfg
@@ -61,7 +60,6 @@ class Planet < Oxidized::Model
cfg.join
end
-
cfg :telnet do
username /^Username:/
@@ -79,5 +77,4 @@ class Planet < Oxidized::Model
end
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/powerconnect.rb b/lib/oxidized/model/powerconnect.rb
index ac36c26..bf36f65 100644
--- a/lib/oxidized/model/powerconnect.rb
+++ b/lib/oxidized/model/powerconnect.rb
@@ -1,23 +1,27 @@
class PowerConnect < Oxidized::Model
-
prompt /^([\w\s.@-]+[#>]\s?)$/ # allow spaces in hostname..dell does not limit it.. #
- comment '! '
+ comment '! '
expect /^\s*--More--\s+.*$/ do |data, re|
- send ' '
- data.sub re, ''
+ send ' '
+ data.sub re, ''
end
cmd :all do |cfg|
cfg.each_line.to_a[1..-3].join
end
+ cmd :secret do |cfg|
+ cfg.gsub! /^(username \S+ password (?:encrypted )?)\S+(.*)/, '\1<hidden>\2'
+ cfg
+ end
+
cmd 'show version' do |cfg|
if (@stackable.nil?)
@stackable = true if cfg.match /(U|u)nit\s/
end
- cfg = cfg.split("\n").select { |line| not line[/Up\sTime/] }
+ cfg = cfg.split("\n").reject { |line| line[/Up\sTime/] }
comment cfg.join("\n") + "\n"
end
@@ -47,7 +51,6 @@ class PowerConnect < Oxidized::Model
post_login "terminal length 0"
pre_logout "logout"
pre_logout "exit"
-
end
def clean cfg
@@ -67,8 +70,8 @@ class PowerConnect < Oxidized::Model
end
out << line.strip
end
+ out = out.reject { |line| line[/Up\sTime/] }
out = comment out.join "\n"
out << "\n"
end
-
end
diff --git a/lib/oxidized/model/procurve.rb b/lib/oxidized/model/procurve.rb
index c117df3..930dc53 100644
--- a/lib/oxidized/model/procurve.rb
+++ b/lib/oxidized/model/procurve.rb
@@ -1,10 +1,14 @@
class Procurve < Oxidized::Model
-
- # some models start lines with \r
+ # some models start lines with \r
# previous command is repeated followed by "\eE", which sometimes ends up on last line
- prompt /^\r?([\w -]+\eE)?([\w.-]+# )$/
+ prompt /^\r?([\w.-]+# )$/
+
+ comment '! '
- comment '! '
+ # replace next line control sequence with a new line
+ expect /(\e\[1M\e\[\??\d+(;\d+)*[A-Za-z]\e\[1L)|(\eE)/ do |data, re|
+ data.gsub re, "\n"
+ end
# replace all used vt100 control sequences
expect /\e\[\??\d+(;\d+)*[A-Za-z]/ do |data, re|
@@ -16,8 +20,13 @@ class Procurve < Oxidized::Model
""
end
+ expect /Enter switch number/ do
+ send "\n"
+ ""
+ end
+
cmd :all do |cfg|
- cfg = cfg.each_line.to_a[1..-3].join
+ cfg = cfg.each_line.to_a[1..-2].join
cfg = cfg.gsub /^\r/, ''
end
@@ -25,6 +34,7 @@ class Procurve < Oxidized::Model
cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
cfg.gsub! /^(snmp-server host).*/, '\\1 <configuration removed>'
cfg.gsub! /^(radius-server host).*/, '\\1 <configuration removed>'
+ cfg.gsub! /^(radius-server key).*/, '\\1 <configuration removed>'
cfg
end
@@ -32,6 +42,22 @@ class Procurve < Oxidized::Model
comment cfg
end
+ cmd 'show modules' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show system power-supply' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show interfaces transceiver' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show flash' do |cfg|
+ comment cfg
+ end
+
# not supported on all models
cmd 'show system-information' do |cfg|
cfg = cfg.split("\n")[0..-8].join("\n")
@@ -40,7 +66,7 @@ class Procurve < Oxidized::Model
# not supported on all models
cmd 'show system information' do |cfg|
- cfg = cfg.each_line.select { |line| not line.match /(.*CPU.*)|(.*Up Time.*)|(.*Total.*)|(.*Free.*)|(.*Lowest.*)|(.*Missed.*)/ }
+ cfg = cfg.each_line.reject { |line| line.match /(.*CPU.*)|(.*Up Time.*)|(.*Total.*)|(.*Free.*)|(.*Lowest.*)|(.*Missed.*)/ }
cfg = cfg.join
comment cfg
end
@@ -60,5 +86,4 @@ class Procurve < Oxidized::Model
cfg :ssh do
pty_options({ chars_wide: 1000 })
end
-
end
diff --git a/lib/oxidized/model/quantaos.rb b/lib/oxidized/model/quantaos.rb
index 274440d..8dbdf3b 100644
--- a/lib/oxidized/model/quantaos.rb
+++ b/lib/oxidized/model/quantaos.rb
@@ -1,18 +1,17 @@
class QuantaOS < Oxidized::Model
-
prompt /^\((\w|\S)+\) (>|#)$/
comment '! '
-
+
cmd 'show run' do |cfg|
cfg.each_line.select do |line|
not line.match /^!.*$/ and
- not line.match /^\((\w|\S)+\) (>|#)$/ and
- not line.match /^show run$/
+ not line.match /^\((\w|\S)+\) (>|#)$/ and
+ not line.match /^show run$/
end.join
end
cfg :telnet do
- username /^Username:/
+ username /^User(name)?:/
password /^Password:/
end
@@ -31,5 +30,4 @@ class QuantaOS < Oxidized::Model
send "n\n"
end
end
-
end
diff --git a/lib/oxidized/model/routeros.rb b/lib/oxidized/model/routeros.rb
index a92ad5e..c729126 100644
--- a/lib/oxidized/model/routeros.rb
+++ b/lib/oxidized/model/routeros.rb
@@ -6,11 +6,23 @@ class RouterOS < Oxidized::Model
comment cfg
end
- cmd '/export' do |cfg|
- cfg.gsub! /\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]/, '' # strip ANSI colours
- cfg.gsub! /\\\r\n\s+/, '' # strip new line
- cfg = cfg.split("\n").select { |line| not line[/^\#\s\w{3}\/\d{2}\/\d{4}.*$/] }
- cfg.join("\n") + "\n"
+ cmd '/system package update print' do |cfg|
+ comment cfg
+ end
+
+ cmd '/system history print' do |cfg|
+ comment cfg
+ end
+
+ post do
+ run_cmd = vars(:remove_secret) ? '/export hide-sensitive' : '/export'
+ cmd run_cmd do |cfg|
+ cfg.gsub! /\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]/, '' # strip ANSI colours
+ cfg.gsub! /\\\r\n\s+/, '' # strip new line
+ cfg.gsub! /# inactive time\r\n/, '' # Remove time based system comment
+ cfg = cfg.split("\n").reject { |line| line[/^\#\s\w{3}\/\d{2}\/\d{4}.*$/] }
+ cfg.join("\n") + "\n"
+ end
end
cfg :telnet do
@@ -18,6 +30,10 @@ class RouterOS < Oxidized::Model
password /^Password:/
end
+ cfg :telnet, :ssh do
+ pre_logout 'quit'
+ end
+
cfg :ssh do
exec true
end
diff --git a/lib/oxidized/model/saos.rb b/lib/oxidized/model/saos.rb
index 5d460cf..97547b5 100644
--- a/lib/oxidized/model/saos.rb
+++ b/lib/oxidized/model/saos.rb
@@ -1,8 +1,7 @@
class SAOS < Oxidized::Model
-
# Ciena SAOS switch
# used for 6.x devices
-
+
comment '! '
cmd :all do |cfg|
@@ -10,6 +9,8 @@ class SAOS < Oxidized::Model
end
cmd 'configuration show' do |cfg|
+ cfg.gsub! /^! Created: [^\n]*\n/, ''
+ cfg.gsub! /^! On terminal: [^\n]*\n/, ''
cfg
end
diff --git a/lib/oxidized/model/screenos.rb b/lib/oxidized/model/screenos.rb
index 0258898..9b52f9f 100644
--- a/lib/oxidized/model/screenos.rb
+++ b/lib/oxidized/model/screenos.rb
@@ -1,8 +1,7 @@
-class ScreenOS < Oxidized::Model
-
+class ScreenOS < Oxidized::Model
# Netscreen ScreenOS model #
- comment '! '
+ comment '! '
prompt /^[\w.:\(\)-]+->\s?$/
@@ -10,7 +9,7 @@ class ScreenOS < Oxidized::Model
cfg.each_line.to_a[2..-2].join
end
- cmd :secret do |cfg|
+ cmd :secret do |cfg|
cfg.gsub! /^(set admin name) .*|^(set admin password) .*/, '\\1 <removed>'
cfg.gsub! /^(set admin user .* password) .* (.*)/, '\\1 <removed> \\2'
cfg.gsub! /(secret|password|preshare) .*/, '\\1 <secret hidden>'
@@ -41,5 +40,4 @@ class ScreenOS < Oxidized::Model
send "n"
end
end
-
end
diff --git a/lib/oxidized/model/sgos.rb b/lib/oxidized/model/sgos.rb
new file mode 100644
index 0000000..894e042
--- /dev/null
+++ b/lib/oxidized/model/sgos.rb
@@ -0,0 +1,45 @@
+class SGOS < Oxidized::Model
+ comment '!- '
+ prompt /\w+>|#/
+
+ expect /--More--/ do |data, re|
+ send ' '
+ data.sub re, ''
+ end
+
+ cmd :all do |cfg|
+ cfg.each_line.to_a[1..-3].join
+ end
+
+ cmd 'show licenses' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show general' do |cfg|
+ comment cfg
+ end
+
+ cmd :secret do |cfg|
+ cfg.gsub! /^(security hashed-enable-password).*/, '\\1 <secret hidden>'
+ cfg.gsub! /^(security hashed-password).*/, '\\1 <secret hidden>'
+ cfg
+ end
+
+ cmd 'show configuration expanded noprompts with-keyrings unencrypted' do |cfg|
+ cfg.gsub! /^(!- Local time).*/, ""
+ cfg.gsub! /^(archive-configuration encrypted-password).*/, ""
+ cfg.gsub! /^(download encrypted-password).*/, ""
+ cfg
+ end
+
+ cfg :telnet, :ssh do
+ # preferred way to handle additional passwords
+ if vars :enable
+ post_login do
+ send "enable\n"
+ cmd vars(:enable)
+ end
+ end
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/siklu.rb b/lib/oxidized/model/siklu.rb
new file mode 100644
index 0000000..2203bda
--- /dev/null
+++ b/lib/oxidized/model/siklu.rb
@@ -0,0 +1,17 @@
+class Siklu < Oxidized::Model
+ # Siklu EtherHaul #
+
+ prompt /^[\w-]+>$/
+
+ cmd 'copy startup-configuration display' do |cfg|
+ cfg.each_line.to_a[2..2].join
+ end
+
+ cmd 'copy running-configuration display' do |cfg|
+ cfg.each_line.to_a[3..-2].join
+ end
+
+ cfg :ssh do
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/slxos.rb b/lib/oxidized/model/slxos.rb
new file mode 100644
index 0000000..1afc8b1
--- /dev/null
+++ b/lib/oxidized/model/slxos.rb
@@ -0,0 +1,59 @@
+class SLXOS < Oxidized::Model
+ prompt /^.*[>#]\s?$/i
+ comment '! '
+
+ cmd 'show version' do |cfg|
+ cfg.gsub! /(^((.*)[Ss]ystem [Uu]ptime(.*))$)/, '' # remove unwanted line system uptime
+ cfg.gsub! /[Uu]p\s?[Tt]ime is .*/, ''
+
+ comment cfg
+ end
+
+ cmd 'show chassis' do |cfg|
+ cfg.encode!("UTF-8", :invalid => :replace, :undef => :replace) # sometimes ironware returns broken encoding
+ cfg.gsub! /.*Power Usage.*/, '' # remove unwanted lines power usage
+ cfg.gsub! /Time A(live|wake).*/, '' # remove unwanted lines time alive/awake
+ cfg.gsub! /([\[]*)1([\]]*)<->([\[]*)2([\]]*)(<->([\[]*)3([\]]*))*/, ''
+
+ comment cfg
+ end
+
+ cmd 'show system' do |cfg|
+ cfg.gsub! /Up Time.*/, '' # removes uptime line
+ cfg.gsub! /Current Time.*/, '' # remove current time line
+ cfg.gsub! /.*speed is.*/, '' # removes fan speed lines
+
+ comment cfg
+ end
+
+ cmd 'show slots' do |cfg|
+ cfg.gsub! /^-*^$/, '' # some slx devices are fixed config
+ cfg.gsub! /syntax error: element does not exist/, '' # same as above
+
+ comment cfg
+ end
+
+ cmd 'show running-config' do |cfg|
+ arr = cfg.each_line.to_a
+ arr[2..-1].join unless arr.length < 2
+ end
+
+ cfg :telnet do
+ # match expected prompts
+ username /^(Please Enter Login Name|Username):/
+ password /^(Please Enter Password ?|Password):/
+ end
+
+ # handle pager with enable
+ cfg :telnet, :ssh do
+ if vars :enable
+ post_login do
+ send "enable\n"
+ cmd vars(:enable)
+ end
+ end
+ post_login ''
+ post_login 'terminal length 0'
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/sros.rb b/lib/oxidized/model/sros.rb
new file mode 100644
index 0000000..d809147
--- /dev/null
+++ b/lib/oxidized/model/sros.rb
@@ -0,0 +1,117 @@
+class SROS < Oxidized::Model
+ #
+ # Nokia SR OS (TiMOS) (formerly TiMetra, Alcatel, Alcatel-Lucent).
+ # Used in 7705 SAR, 7210 SAS, 7450 ESS, 7750 SR, 7950 XRS, and NSP.
+ #
+
+ comment '# '
+
+ prompt /^([-\w\.:>\*]+\s?[#>]\s?)$/
+
+ cmd :all do |cfg, cmdstring|
+ new_cfg = comment "COMMAND: #{cmdstring}\n"
+ new_cfg << cfg.each_line.to_a[1..-2].join
+ end
+
+ #
+ # Show the boot options file.
+ #
+ cmd 'show bof' do |cfg|
+ cfg.gsub! /# Finished .*/, ''
+ cfg.gsub! /# Generated .*/, ''
+ comment cfg
+ end
+
+ #
+ # Show the system information.
+ #
+ cmd 'show system information' do |cfg|
+ #
+ # Strip uptime.
+ #
+ cfg.sub! /^System Up Time.*\n/, ''
+ cfg.gsub! /# Finished .*/, ''
+ cfg.gsub! /# Generated .*/, ''
+ comment cfg
+ end
+
+ #
+ # Show the card state.
+ #
+ cmd 'show card state' do |cfg|
+ cfg.gsub! /# Finished .*/, ''
+ cfg.gsub! /# Generated .*/, ''
+ comment cfg
+ end
+
+ #
+ # Show the boot log.
+ #
+ cmd 'file type bootlog.txt' do |cfg|
+ #
+ # Strip carriage returns and backspaces.
+ #
+ cfg.gsub! /\r/, ''
+ cfg.gsub! /[\b][\b][\b]/, "\n"
+ cfg.gsub! /# Finished .*/, ''
+ cfg.gsub! /# Generated .*/, ''
+ comment cfg
+ end
+
+ #
+ # Show the running debug configuration.
+ #
+ cmd 'show debug' do |cfg|
+ cfg.gsub! /# Finished .*/, ''
+ cfg.gsub! /# Generated .*/, ''
+ comment cfg
+ end
+
+ #
+ # Show the saved debug configuration (admin debug-save).
+ #
+ cmd 'file type config.dbg' do |cfg|
+ #
+ # Strip carriage returns.
+ #
+ cfg.gsub! /\r/, ''
+ cfg.gsub! /# Finished .*/, ''
+ cfg.gsub! /# Generated .*/, ''
+ comment cfg
+ end
+
+ #
+ # Show the running persistent indices.
+ #
+ cmd 'admin display-config index' do |cfg|
+ #
+ # Strip carriage returns.
+ #
+ cfg.gsub! /\r/, ''
+ cfg.gsub! /# Finished .*/, ''
+ cfg.gsub! /# Generated .*/, ''
+ comment cfg
+ end
+
+ #
+ # Show the running configuration.
+ #
+ cmd 'admin display-config' do |cfg|
+ #
+ # Strip carriage returns.
+ #
+ cfg.gsub! /\r/, ''
+ cfg.gsub! /# Finished .*/, ''
+ cfg.gsub! /# Generated .*/, ''
+ end
+
+ cfg :telnet do
+ username /^Login: /
+ password /^Password: /
+ end
+
+ cfg :telnet, :ssh do
+ post_login 'environment no more'
+ pre_logout 'logout'
+ end
+end
diff --git a/lib/oxidized/model/supermicro.rb b/lib/oxidized/model/supermicro.rb
index 361244c..56d5ef6 100644
--- a/lib/oxidized/model/supermicro.rb
+++ b/lib/oxidized/model/supermicro.rb
@@ -1,45 +1,10 @@
-class Supermicro < Oxidized::Model
- comment '! '
+# Backward compatibility shim for deprecated model `supermicro`.
+# Migrate your source from `supermicro` to `edgecos`.
- cmd :secret do |cfg|
- cfg.gsub!(/password \d+ (\S+).*/, '<secret removed>')
- cfg.gsub!(/community (\S+)/, 'community <hidden>')
- cfg
- end
+require_relative 'edgecos.rb'
- cmd :all do |cfg|
- cfg.each_line.to_a[2..-2].join
- end
+Supermicro = EdgeCOS
- cmd 'show running-config'
+Oxidized.logger.warn "Using deprecated model supermicro, use edgecos instead."
- cmd 'show access-list tcam-utilization' do |cfg|
- comment cfg
- end
-
- cmd 'show memory' do |cfg|
- comment cfg
- end
-
- cmd 'show system' do |cfg|
- comment cfg
- end
-
- cmd 'show version' do |cfg|
- comment cfg
- end
-
- cmd 'show watchdog' do |cfg|
- comment cfg
- end
-
- cfg :telnet do
- username /^Username:/
- password /^Password:/
- end
-
- cfg :telnet, :ssh do
- post_login 'terminal length 0'
- pre_logout 'exit'
- end
-end \ No newline at end of file
+# Deprecated
diff --git a/lib/oxidized/model/timos.rb b/lib/oxidized/model/timos.rb
index d40e845..e454630 100644
--- a/lib/oxidized/model/timos.rb
+++ b/lib/oxidized/model/timos.rb
@@ -1,102 +1,10 @@
-class TiMOS < Oxidized::Model
+# Backward compatibility shim for deprecated model `timos`.
+# Migrate your source from `timos` to `sros`.
- #
- # Nokia SR OS (TiMOS) (formerly TiMetra, Alcatel, Alcatel-Lucent).
- # Used in 7705 SAR, 7210 SAS, 7450 ESS, 7750 SR, 7950 XRS, and NSP.
- #
+require_relative 'sros.rb'
- comment '# '
+TiMOS = SROS
- prompt /^([-\w\.:>\*]+\s?[#>]\s?)$/
+Oxidized.logger.warn "Using deprecated model timos, use sros instead."
- cmd :all do |cfg, cmdstring|
- new_cfg = comment "COMMAND: #{cmdstring}\n"
- new_cfg << cfg.each_line.to_a[1..-2].join
- end
-
- #
- # Show the boot options file.
- #
- cmd 'show bof' do |cfg|
- comment cfg
- end
-
- #
- # Show the system information.
- #
- cmd 'show system information' do |cfg|
- #
- # Strip uptime.
- #
- cfg.sub! /^System Up Time.*\n/, ''
- comment cfg
- end
-
- #
- # Show the card state.
- #
- cmd 'show card state' do |cfg|
- comment cfg
- end
-
- #
- # Show the boot log.
- #
- cmd 'file type bootlog.txt' do |cfg|
- #
- # Strip carriage returns and backspaces.
- #
- cfg.gsub! /\r/, ''
- cfg.gsub! /[\b][\b][\b]/, "\n"
- comment cfg
- end
-
- #
- # Show the running debug configuration.
- #
- cmd 'show debug' do |cfg|
- comment cfg
- end
-
- #
- # Show the saved debug configuration (admin debug-save).
- #
- cmd 'file type config.dbg' do |cfg|
- #
- # Strip carriage returns.
- #
- cfg.gsub! /\r/, ''
- comment cfg
- end
-
- #
- # Show the running persistent indices.
- #
- cmd 'admin display-config index' do |cfg|
- #
- # Strip carriage returns.
- #
- cfg.gsub! /\r/, ''
- comment cfg
- end
-
- #
- # Show the running configuration.
- #
- cmd 'admin display-config' do |cfg|
- #
- # Strip carriage returns.
- #
- cfg.gsub! /\r/, ''
- end
-
- cfg :telnet do
- username /^Login: /
- password /^Password: /
- end
-
- cfg :telnet, :ssh do
- post_login 'environment no more'
- pre_logout 'logout'
- end
-end
+# Deprecated
diff --git a/lib/oxidized/model/tmos.rb b/lib/oxidized/model/tmos.rb
index 390046d..69b0e1b 100644
--- a/lib/oxidized/model/tmos.rb
+++ b/lib/oxidized/model/tmos.rb
@@ -1,5 +1,4 @@
class TMOS < Oxidized::Model
-
comment '# '
cmd :secret do |cfg|
@@ -46,7 +45,6 @@ class TMOS < Oxidized::Model
cmd('cat /config/partitions/*/bigip.conf') { |cfg| comment cfg }
cfg :ssh do
- exec true # don't run shell, run each command in exec channel
+ exec true # don't run shell, run each command in exec channel
end
-
end
diff --git a/lib/oxidized/model/tplink.rb b/lib/oxidized/model/tplink.rb
new file mode 100644
index 0000000..2a61fa5
--- /dev/null
+++ b/lib/oxidized/model/tplink.rb
@@ -0,0 +1,61 @@
+class TPLink < Oxidized::Model
+ # tp-link prompt
+ prompt /^\r?([\w.@()-]+[#>]\s?)$/
+ comment '! '
+
+ # handle paging
+ # workaround for sometimes missing whitespaces with "\s?"
+ expect /Press\s?any\s?key\s?to\s?continue\s?\(Q\s?to\s?quit\)/ do |data, re|
+ send ' '
+ data.sub re, ''
+ end
+
+ # send carriage return because \n with the command is not enough
+ # checks if line ends with prompt >,# or \r,\nm otherwise send \r
+ expect /[^>#\r\n]$/ do |data, re|
+ send "\r"
+ data.sub re, ''
+ end
+
+ cmd :all do |cfg|
+ # normalize linefeeds
+ cfg.gsub! /(\r|\r\n|\n\r)/, "\n"
+ # remove empty lines
+ cfg.each_line.reject { |line| line.match /^[\r\n\s\u0000#]+$/ }.join
+ end
+
+ cmd :secret do |cfg|
+ cfg.gsub! /^(snmp-server community).*/, '\\1 <configuration removed>'
+ cfg.gsub! /secret (\d+) (\S+).*/, '<secret hidden>'
+ cfg
+ end
+
+ cmd 'show system-info' do |cfg|
+ comment cfg.each_line.to_a[3..-3].join
+ end
+
+ cmd 'show running-config' do |cfg|
+ lines = cfg.each_line.to_a[1..-1]
+ # cut config after "end"
+ lines[0..lines.index("end\n")].join
+ end
+
+ cfg :telnet, :ssh do
+ username /^User ?[nN]ame:/
+ password /^\r?Password:/
+ end
+
+ cfg :telnet, :ssh do
+ if vars :enable
+ post_login do
+ send "enable\r"
+ cmd vars(:enable)
+ end
+ end
+
+ pre_logout do
+ send "exit\r"
+ send "logout\r"
+ end
+ end
+end
diff --git a/lib/oxidized/model/trango.rb b/lib/oxidized/model/trango.rb
index b2aa1e7..b55b277 100644
--- a/lib/oxidized/model/trango.rb
+++ b/lib/oxidized/model/trango.rb
@@ -1,8 +1,8 @@
class Trango < Oxidized::Model
# take a Trangolink sysinfo output and turn it into a configuration file
-
+
prompt /^#>\s?/
- comment '# '
+ comment '# '
cmd 'sysinfo' do |cfg|
out = []
@@ -47,16 +47,15 @@ class Trango < Oxidized::Model
end
if line.match /\[IP\] (\S+) \[Subnet Mask\] (\S+) \[Gateway\] (\S+)/
out << "ipconfig " + Regexp.last_match[1] + ' ' +
- Regexp.last_match[2] + ' ' +
- Regexp.last_match[3]
+ Regexp.last_match[2] + ' ' +
+ Regexp.last_match[3]
end
- end
+ end
comments.push(*out).join "\n"
- end
+ end
cfg :telnet do
password /Password:/
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/ucs.rb b/lib/oxidized/model/ucs.rb
new file mode 100644
index 0000000..4418b68
--- /dev/null
+++ b/lib/oxidized/model/ucs.rb
@@ -0,0 +1,30 @@
+class UCS < Oxidized::Model
+ prompt /^(\r?[\w.@_()-]+[#]\s?)$/
+ comment '! '
+
+ cmd 'show version brief' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show chassis detail' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show fabric-interconnect detail' do |cfg|
+ comment cfg
+ end
+
+ cmd 'show configuration all | no-more' do |cfg|
+ cfg
+ end
+
+ cfg :ssh, :telnet do
+ post_login 'terminal length 0'
+ pre_logout 'exit'
+ end
+
+ cfg :telnet do
+ username /^login:/
+ password /^Password:/
+ end
+end
diff --git a/lib/oxidized/model/voltaire.rb b/lib/oxidized/model/voltaire.rb
new file mode 100644
index 0000000..62a62e5
--- /dev/null
+++ b/lib/oxidized/model/voltaire.rb
@@ -0,0 +1,53 @@
+class VOLTAIRE < Oxidized::Model
+ prompt /([\w.@()-\[:\s\]]+[#>]\s|(One or more tests have failed.*))$/
+ comment '## '
+
+ # Pager Handling
+ expect /.+lines\s\d+\-\d+([\s]|\/\d+\s\(END\)\s).+$/ do |data, re|
+ send ' '
+ data.sub re, ''
+ end
+
+ cmd :all do |cfg|
+ cfg.gsub! /\[\?1h=\r/, '' # Pager Handling
+ cfg.gsub! /\r\[K/, '' # Pager Handling
+ cfg.gsub! /\s/, '' # Linebreak Handling
+ cfg.gsub! /^CPU\ load\ averages\:\s.+/, '' # Omit constantly changing CPU info
+ cfg.gsub! /^System\ memory\:\s.+/, '' # Omit constantly changing memory info
+ cfg.gsub! /^Uptime\:\s.+/, '' # Omit constantly changing uptime info
+ cfg.gsub! /.+Generated\ at\s\d+.+/, '' # Omit constantly changing generation time info
+ cfg = cfg.lines.to_a[2..-3].join
+ end
+
+ cmd :secret do |cfg|
+ cfg.gsub! /(snmp-server community).*/, ' <snmp-server community configuration removed>'
+ cfg.gsub! /username (\S+) password (\d+) (\S+).*/, '<secret hidden>'
+ cfg
+ end
+
+ cmd 'version show' do |cfg|
+ comment cfg
+ end
+
+ cmd 'firmware-version show' do |cfg|
+ comment cfg
+ end
+
+ cmd 'remote show' do |cfg|
+ cfg
+ end
+
+ cmd 'sm-info show' do |cfg|
+ cfg
+ end
+
+ cmd ' show' do |cfg|
+ cfg
+ end
+
+ cfg :ssh do
+ post_login "no\n"
+ password /^Password:\s*/
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/model/voss.rb b/lib/oxidized/model/voss.rb
new file mode 100644
index 0000000..32958ce
--- /dev/null
+++ b/lib/oxidized/model/voss.rb
@@ -0,0 +1,41 @@
+class Voss < Oxidized::Model
+ # Avaya VSP Operating System Software(VOSS)
+ # Created by danielcoxman@gmail.com
+ # May 25, 2017
+ # This was tested on vsp4k and vsp8k
+
+ comment '# '
+
+ prompt /^[^\s#>]+[#>]$/
+
+ # needed for proper formatting after post_login
+ cmd('') { |cfg| comment "#{cfg}\n" }
+
+ # Get sys-info and remove information that changes such has temperature and power
+ cmd 'show sys-info' do |cfg|
+ cfg.gsub! /(^((.*)SysUpTime(.*))$)/, 'removed SysUpTime'
+ cfg.gsub! /^((.*)Temperature Info \:(.*\r?\n){4})/, 'removed Temperature Info and 3 more lines'
+ cfg.gsub! /(^((.*)AmbientTemperature(.*)\:(.*))$)/, 'removed AmbientTemperature'
+ cfg.gsub! /(^((.*)Temperature(.*)\:(.*))$)/, 'removed Temperature'
+ cfg.gsub! /(^((.*)Total Power Usage(.*)\:(.*))$)/, 'removed Total Power Usage'
+ comment "#{cfg}\n"
+ end
+
+ # more the config rather than doing a show run
+ cmd 'more config.cfg' do |cfg|
+ cfg
+ cfg.gsub! /^[^\s#>]+[#>]$/, ''
+ cfg.gsub! /^more config.cfg/, '# more config.cfg'
+ end
+
+ cfg :telnet do
+ username /Login: $/
+ password /Password: $/
+ end
+
+ cfg :telnet, :ssh do
+ pre_logout 'exit'
+ post_login 'enable'
+ post_login 'terminal more disable'
+ end
+end
diff --git a/lib/oxidized/model/vrp.rb b/lib/oxidized/model/vrp.rb
index 12a9ca3..42762c2 100644
--- a/lib/oxidized/model/vrp.rb
+++ b/lib/oxidized/model/vrp.rb
@@ -1,25 +1,31 @@
class VRP < Oxidized::Model
# Huawei VRP
-
+
prompt /^(<[\w.-]+>)$/
comment '# '
+ cmd :secret do |cfg|
+ cfg.gsub! /(pin verify (?:auto|)).*/, '\\1 <PIN hidden>'
+ cfg.gsub! /(%\^%#.*%\^%#)/, '<secret hidden>'
+ cfg
+ end
+
cmd :all do |cfg|
cfg.each_line.to_a[1..-2].join
end
-
+
cfg :telnet do
username /^Username:$/
password /^Password:$/
end
- cfg :telnet, :ssh do
+ cfg :telnet, :ssh do
post_login 'screen-length 0 temporary'
pre_logout 'quit'
end
cmd 'display version' do |cfg|
- cfg = cfg.each_line.select {|l| not l.match /uptime/ }.join
+ cfg = cfg.each_line.reject { |l| l.match /uptime/ }.join
comment cfg
end
@@ -30,5 +36,4 @@ class VRP < Oxidized::Model
cmd 'display current-configuration all' do |cfg|
cfg
end
-
end
diff --git a/lib/oxidized/model/vyatta.rb b/lib/oxidized/model/vyatta.rb
index 8d977aa..fb6b0d1 100644
--- a/lib/oxidized/model/vyatta.rb
+++ b/lib/oxidized/model/vyatta.rb
@@ -1,7 +1,6 @@
class Vyatta < Oxidized::Model
-
# Brocade Vyatta / VyOS model #
-
+
prompt /\@.*?\:~\$\s/
cmd :all do |cfg|
@@ -9,11 +8,15 @@ class Vyatta < Oxidized::Model
end
cmd :secret do |cfg|
+ cfg.gsub! /encrypted-password (\S+).*/, 'encrypted-password <secret removed>'
+ cfg.gsub! /plaintext-password (\S+).*/, 'plaintext-password <secret removed>'
+ cfg.gsub! /password (\S+).*/, 'password <secret removed>'
+ cfg.gsub! /pre-shared-secret (\S+).*/, 'pre-shared-secret <secret removed>'
cfg.gsub! /community (\S+) {/, 'community <hidden> {'
cfg
end
- cmd 'show configuration | no-more'
+ cmd 'show configuration commands | no-more'
cfg :telnet do
username /login:\s/
@@ -23,5 +26,4 @@ class Vyatta < Oxidized::Model
cfg :telnet, :ssh do
pre_logout 'exit'
end
-
end
diff --git a/lib/oxidized/model/weos.rb b/lib/oxidized/model/weos.rb
new file mode 100644
index 0000000..2856666
--- /dev/null
+++ b/lib/oxidized/model/weos.rb
@@ -0,0 +1,20 @@
+class WEOS < Oxidized::Model
+ # Westell WEOS, works with Westell 8178G, Westell 8266G
+
+ prompt /^(\s[\w.@-]+[#>]\s?)$/
+
+ cmd :all do |cfg|
+ cfg.each_line.to_a[1..-2].join
+ end
+
+ cmd 'show running-config' do |cfg|
+ cfg
+ end
+
+ cfg :telnet do
+ username /login:/
+ password /assword:/
+ post_login 'cli more disable'
+ pre_logout 'logout'
+ end
+end
diff --git a/lib/oxidized/model/xos.rb b/lib/oxidized/model/xos.rb
index 6f1323f..5ce8017 100644
--- a/lib/oxidized/model/xos.rb
+++ b/lib/oxidized/model/xos.rb
@@ -1,5 +1,4 @@
class XOS < Oxidized::Model
-
# Extreme Networks XOS
prompt /^*?[\w .-]+# $/
@@ -8,7 +7,7 @@ class XOS < Oxidized::Model
cmd :all do |cfg|
# xos inserts leading \r characters and other trailing white space.
# this deletes extraneous \r and trailing white space.
- cfg.each_line.to_a[1..-2].map{|line|line.delete("\r").rstrip}.join("\n") + "\n"
+ cfg.each_line.to_a[1..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
end
cmd 'show version' do |cfg|
@@ -23,11 +22,18 @@ class XOS < Oxidized::Model
comment cfg
end
- cmd 'show switch'do |cfg|
+ cmd 'show switch' do |cfg|
comment cfg.each_line.reject { |line| line.match /Time:/ or line.match /boot/i }.join
end
- cmd 'show configuration'
+ cmd 'show configuration' do |cfg|
+ cfg = cfg.each_line.reject { |line| line.match /^#(\s[\w]+\s)(Configuration generated)/ }.join
+ cfg
+ end
+
+ cmd 'show policy detail' do |cfg|
+ comment cfg
+ end
cfg :telnet do
username /^login:/
@@ -41,5 +47,4 @@ class XOS < Oxidized::Model
send "n\n"
end
end
-
end
diff --git a/lib/oxidized/model/zhoneolt.rb b/lib/oxidized/model/zhoneolt.rb
index b60edb2..ce6df29 100644
--- a/lib/oxidized/model/zhoneolt.rb
+++ b/lib/oxidized/model/zhoneolt.rb
@@ -18,7 +18,7 @@ class ZhoneOLT < Oxidized::Model
end
cmd :all do |cfg|
- cfg.each_line.to_a[1..-2].map{|line|line.delete("\r").rstrip}.join("\n") + "\n"
+ cfg.each_line.to_a[1..-2].map { |line| line.delete("\r").rstrip }.join("\n") + "\n"
end
cmd 'swversion' do |cfg|
@@ -39,7 +39,7 @@ class ZhoneOLT < Oxidized::Model
end
cmd 'dump console' do |cfg|
- cfg = cfg.each_line.select { |line| not line.match /To Abort the operation enter Ctrl-C/ }.join
+ cfg = cfg.each_line.reject { |line| line.match /To Abort the operation enter Ctrl-C/ }.join
end
# zhone technically supports ssh, but it locks up a ton. Especially when
diff --git a/lib/oxidized/model/zynos.rb b/lib/oxidized/model/zynos.rb
index 89be8af..581d405 100644
--- a/lib/oxidized/model/zynos.rb
+++ b/lib/oxidized/model/zynos.rb
@@ -1,12 +1,10 @@
class ZyNOS < Oxidized::Model
-
# Used in Zyxel DSLAMs, such as SAM1316
- comment '! '
+ comment '! '
cmd 'config-0'
cfg :ftp do
end
-
end
diff --git a/lib/oxidized/model/zynoscli.rb b/lib/oxidized/model/zynoscli.rb
new file mode 100644
index 0000000..ae64b04
--- /dev/null
+++ b/lib/oxidized/model/zynoscli.rb
@@ -0,0 +1,36 @@
+class ZyNOSCLI < Oxidized::Model
+ # Used in Zyxel DSLAMs, such as SAM1316
+
+ # Typical prompt "XGS4600#"
+ prompt /^([\w.@()-]+[#>]\s\e7)$/
+ comment ';; '
+
+ cmd :all do |cfg|
+ cfg.gsub! /^.*\e7/, ''
+ end
+ cmd 'show stacking'
+
+ cmd 'show version'
+
+ cmd 'show running-config'
+
+ cfg :telnet do
+ username /^User name:/i
+ password /^Password:/i
+ end
+
+ cfg :telnet, :ssh do
+ if vars :enable
+ post_login do
+ send "enable\n"
+ # Interpret enable: true as meaning we won't be prompted for a password
+ unless vars(:enable).is_a? TrueClass
+ expect /[pP]assword:\s?$/
+ send vars(:enable) + "\n"
+ end
+ expect /^.+[#]$/
+ end
+ end
+ pre_logout 'exit'
+ end
+end
diff --git a/lib/oxidized/node.rb b/lib/oxidized/node.rb
index 7201a73..4105da0 100644
--- a/lib/oxidized/node.rb
+++ b/lib/oxidized/node.rb
@@ -6,8 +6,9 @@ module Oxidized
class ModelNotFound < OxidizedError; end
class Node
attr_reader :name, :ip, :model, :input, :output, :group, :auth, :prompt, :vars, :last, :repo
- attr_accessor :running, :user, :msg, :from, :stats, :retry
+ attr_accessor :running, :user, :email, :msg, :from, :stats, :retry
alias :running? :running
+
def initialize opt
Oxidized.logger.debug 'resolving DNS for %s...' % opt[:name]
# remove the prefix if an IP Address is provided with one as IPAddr converts it to a network address.
@@ -39,7 +40,7 @@ module Oxidized
cfg_name = input.to_s.split('::').last.downcase
next unless @model.cfg[cfg_name] and not @model.cfg[cfg_name].empty?
@model.input = input = input.new
- if config=run_input(input)
+ if config = run_input(input)
Oxidized.logger.debug "lib/oxidized/node.rb: #{input.class.name} ran for #{name} successfully"
status = :success
break
@@ -55,7 +56,7 @@ module Oxidized
def run_input input
rescue_fail = {}
[input.class::RescueFail, input.class.superclass::RescueFail].each do |hash|
- hash.each do |level,errors|
+ hash.each do |level, errors|
errors.each do |err|
rescue_fail[err] = level
end
@@ -64,9 +65,9 @@ module Oxidized
begin
input.connect(self) and input.get
rescue *rescue_fail.keys => err
- resc = ''
+ resc = ''
if not level = rescue_fail[err.class]
- resc = err.class.ancestors.find{|e|rescue_fail.keys.include? e}
+ resc = err.class.ancestors.find { |e| rescue_fail.keys.include? e }
level = rescue_fail[resc]
resc = " (rescued #{resc})"
end
@@ -121,7 +122,7 @@ module Oxidized
end
def reset
- @user = @msg = @from = nil
+ @user = @email = @msg = @from = nil
@retry = 0
end
@@ -167,35 +168,49 @@ module Oxidized
end
def resolve_repo opt
- return unless is_git? opt
-
- remote_repo = Oxidized.config.output.git.repo
-
- if remote_repo.is_a?(::String)
- if Oxidized.config.output.git.single_repo? || @group.nil?
- remote_repo
+ if is_git? opt
+ remote_repo = Oxidized.config.output.git.repo
+
+ if remote_repo.is_a?(::String)
+ if Oxidized.config.output.git.single_repo? || @group.nil?
+ remote_repo
+ else
+ File.join(File.dirname(remote_repo), @group + '.git')
+ end
else
- File.join(File.dirname(remote_repo), @group + '.git')
+ remote_repo[@group]
+ end
+ elsif is_gitcrypt? opt
+ remote_repo = Oxidized.config.output.gitcrypt.repo
+
+ if remote_repo.is_a?(::String)
+ if Oxidized.config.output.gitcrypt.single_repo? || @group.nil?
+ remote_repo
+ else
+ File.join(File.dirname(remote_repo), @group + '.git')
+ end
+ else
+ remote_repo[@group]
end
else
- remote_repo[@group]
+ return
end
end
- def resolve_key key, opt, global=nil
+ def resolve_key key, opt, global = nil
# resolve key, first get global, then get group then get node config
key_sym = key.to_sym
key_str = key.to_s
value = global
Oxidized.logger.debug "node.rb: resolving node key '#{key}', with passed global value of '#{value}' and node value '#{opt[key_sym]}'"
- #global
+ # global
if not value and Oxidized.config.has_key?(key_str)
value = Oxidized.config[key_str]
Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from global"
end
- #group
+ # group
if Oxidized.config.groups.has_key?(@group)
if Oxidized.config.groups[@group].has_key?(key_str)
value = Oxidized.config.groups[@group][key_str]
@@ -203,7 +218,16 @@ module Oxidized
end
end
- #node
+ # model
+ # FIXME: warning: instance variable @model not initialized
+ if Oxidized.config.models.has_key?(@model.class.name.to_s.downcase)
+ if Oxidized.config.models[@model.class.name.to_s.downcase].has_key?(key_str)
+ value = Oxidized.config.models[@model.class.name.to_s.downcase][key_str]
+ Oxidized.logger.debug "node.rb: setting node key '#{key}' to value '#{value}' from model"
+ end
+ end
+
+ # node
value = opt[key_sym] || value
Oxidized.logger.debug "node.rb: returning node key '#{key}' with value '#{value}'"
value
@@ -213,5 +237,8 @@ module Oxidized
(opt[:output] || Oxidized.config.output.default) == 'git'
end
+ def is_gitcrypt? opt
+ (opt[:output] || Oxidized.config.output.default) == 'gitcrypt'
+ end
end
end
diff --git a/lib/oxidized/node/stats.rb b/lib/oxidized/node/stats.rb
index 6b5719c..2c04a60 100644
--- a/lib/oxidized/node/stats.rb
+++ b/lib/oxidized/node/stats.rb
@@ -18,7 +18,7 @@ module Oxidized
# @param [Symbol] status stats for specific status
# @return [Hash,Array] Hash of stats for every status or Array of stats for specific status
- def get status=nil
+ def get status = nil
status ? @stats[status] : @stats
end
@@ -27,7 +27,6 @@ module Oxidized
def initialize
@stats = {}
end
-
end
end
end
diff --git a/lib/oxidized/nodes.rb b/lib/oxidized/nodes.rb
index f5a1ad0..a159b48 100644
--- a/lib/oxidized/nodes.rb
+++ b/lib/oxidized/nodes.rb
@@ -4,15 +4,16 @@ module Oxidized
class Oxidized::NotSupported < OxidizedError; end
class Oxidized::NodeNotFound < OxidizedError; end
class Nodes < Array
- attr_accessor :source
+ attr_accessor :source, :jobs
alias :put :unshift
- def load node_want=nil
+ def load node_want = nil
with_lock do
new = []
@source = Oxidized.config.source.default
Oxidized.mgr.add_source @source
Oxidized.logger.info "lib/oxidized/nodes.rb: Loading nodes"
- Oxidized.mgr.source[@source].new.load.each do |node|
+ nodes = Oxidized.mgr.source[@source].new.load node_want
+ nodes.each do |node|
# we want to load specific node(s), not all of them
next unless node_want? node_want, node
begin
@@ -42,7 +43,6 @@ module Oxidized
end
end
-
def list
with_lock do
map { |e| e.serialize }
@@ -63,16 +63,18 @@ module Oxidized
end
# @param node [String] name of the node moved into the head of array
- def next node, opt={}
+ def next node, opt = {}
if waiting.find_node_index(node)
with_lock do
n = del node
n.user = opt['user']
+ n.email = opt['email']
n.msg = opt['msg']
n.from = opt['from']
# set last job to nil so that the node is picked for immediate update
n.last = nil
put n
+ jobs.want += 1 if Oxidized.config.next_adds_job?
end
end
end
@@ -111,10 +113,10 @@ module Oxidized
private
- def initialize opts={}
+ def initialize opts = {}
super()
node = opts.delete :node
- @mutex= Mutex.new # we compete for the nodes with webapi thread
+ @mutex = Mutex.new # we compete for the nodes with webapi thread
if nodes = opts.delete(:nodes)
replace nodes
else
@@ -127,7 +129,7 @@ module Oxidized
end
def find_index node
- index { |e| e.name == node or e.ip == node}
+ index { |e| e.name == node or e.ip == node }
end
# @param node node which is removed from nodes list
@@ -160,7 +162,7 @@ module Oxidized
node.stats = old[i].stats
node.last = old[i].last
end
- rescue Oxidized::NodeNotFound
+ rescue Oxidized::NodeNotFound
end
end
sort_by! { |x| x.last.nil? ? Time.new(0) : x.last.end }
diff --git a/lib/oxidized/output/file.rb b/lib/oxidized/output/file.rb
index 45f72e1..bad1b6a 100644
--- a/lib/oxidized/output/file.rb
+++ b/lib/oxidized/output/file.rb
@@ -1,59 +1,58 @@
module Oxidized
-class OxidizedFile < Output
- require 'fileutils'
+ class OxidizedFile < Output
+ require 'fileutils'
- attr_reader :commitref
+ attr_reader :commitref
- def initialize
- @cfg = Oxidized.config.output.file
- end
+ def initialize
+ @cfg = Oxidized.config.output.file
+ end
- def setup
- if @cfg.empty?
- Oxidized.asetus.user.output.file.directory = File.join(Config::Root, 'configs')
- Oxidized.asetus.save :user
- raise NoConfig, 'no output file config, edit ~/.config/oxidized/config'
+ def setup
+ if @cfg.empty?
+ Oxidized.asetus.user.output.file.directory = File.join(Config::Root, 'configs')
+ Oxidized.asetus.save :user
+ raise NoConfig, 'no output file config, edit ~/.config/oxidized/config'
+ end
end
- end
- def store node, outputs, opt={}
- file = File.expand_path @cfg.directory
- if opt[:group]
- file = File.join File.dirname(file), opt[:group]
+ def store node, outputs, opt = {}
+ file = File.expand_path @cfg.directory
+ if opt[:group]
+ file = File.join File.dirname(file), opt[:group]
+ end
+ FileUtils.mkdir_p file
+ file = File.join file, node
+ open(file, 'w') { |fh| fh.write outputs.to_cfg }
+ @commitref = file
end
- FileUtils.mkdir_p file
- file = File.join file, node
- open(file, 'w') { |fh| fh.write outputs.to_cfg }
- @commitref = file
- end
- def fetch node, group
- cfg_dir = File.expand_path @cfg.directory
- node_name = node.name
+ def fetch node, group
+ cfg_dir = File.expand_path @cfg.directory
+ node_name = node.name
- if group # group is explicitly defined by user
- cfg_dir = File.join File.dirname(cfg_dir), group
- File.read File.join(cfg_dir, node_name)
- else
- if File.exists? File.join(cfg_dir, node_name) # node configuration file is stored on base directory
+ if group # group is explicitly defined by user
+ cfg_dir = File.join File.dirname(cfg_dir), group
File.read File.join(cfg_dir, node_name)
else
- path = Dir.glob(File.join(File.dirname(cfg_dir), '**', node_name)).first # fetch node in all groups
- File.read path
+ if File.exists? File.join(cfg_dir, node_name) # node configuration file is stored on base directory
+ File.read File.join(cfg_dir, node_name)
+ else
+ path = Dir.glob(File.join(File.dirname(cfg_dir), '**', node_name)).first # fetch node in all groups
+ File.read path
+ end
end
+ rescue Errno::ENOENT
+ return nil
end
- rescue Errno::ENOENT
- return nil
- end
- def version node, group
- # not supported
- []
- end
+ def version node, group
+ # not supported
+ []
+ end
- def get_version node, group, oid
- 'not supported'
+ def get_version node, group, oid
+ 'not supported'
+ end
end
-
-end
end
diff --git a/lib/oxidized/output/git.rb b/lib/oxidized/output/git.rb
index fee0ab6..8acfd46 100644
--- a/lib/oxidized/output/git.rb
+++ b/lib/oxidized/output/git.rb
@@ -1,74 +1,73 @@
module Oxidized
-class Git < Output
- class GitError < OxidizedError; end
- begin
- require 'rugged'
- rescue LoadError
- raise OxidizedError, 'rugged not found: sudo gem install rugged'
- end
-
- attr_reader :commitref
+ class Git < Output
+ class GitError < OxidizedError; end
+ begin
+ require 'rugged'
+ rescue LoadError
+ raise OxidizedError, 'rugged not found: sudo gem install rugged'
+ end
- def initialize
- @cfg = Oxidized.config.output.git
- end
+ attr_reader :commitref
- def setup
- if @cfg.empty?
- Oxidized.asetus.user.output.git.user = 'Oxidized'
- Oxidized.asetus.user.output.git.email = 'o@example.com'
- Oxidized.asetus.user.output.git.repo = File.join(Config::Root, 'oxidized.git')
- Oxidized.asetus.save :user
- raise NoConfig, 'no output git config, edit ~/.config/oxidized/config'
+ def initialize
+ @cfg = Oxidized.config.output.git
end
- if @cfg.repo.respond_to?(:each)
- @cfg.repo.each do |group, repo|
- @cfg.repo["#{group}="] = File.expand_path repo
+ def setup
+ if @cfg.empty?
+ Oxidized.asetus.user.output.git.user = 'Oxidized'
+ Oxidized.asetus.user.output.git.email = 'o@example.com'
+ Oxidized.asetus.user.output.git.repo = File.join(Config::Root, 'oxidized.git')
+ Oxidized.asetus.save :user
+ raise NoConfig, 'no output git config, edit ~/.config/oxidized/config'
end
- else
- @cfg.repo = File.expand_path @cfg.repo
- end
- end
- def store file, outputs, opt={}
- @msg = opt[:msg]
- @user = (opt[:user] or @cfg.user)
- @email = (opt[:email] or @cfg.email)
- @opt = opt
- @commitref = nil
- repo = @cfg.repo
-
- outputs.types.each do |type|
- type_cfg = ''
- type_repo = File.join(File.dirname(repo), type + '.git')
- outputs.type(type).each do |output|
- (type_cfg << output; next) if not output.name
- type_file = file + '--' + output.name
- if @cfg.type_as_directory?
- type_file = type + '/' + type_file
- type_repo = repo
+ if @cfg.repo.respond_to?(:each)
+ @cfg.repo.each do |group, repo|
+ @cfg.repo["#{group}="] = File.expand_path repo
end
- update type_repo, type_file, output
+ else
+ @cfg.repo = File.expand_path @cfg.repo
end
- update type_repo, file, type_cfg
end
- update repo, file, outputs.to_cfg
- end
+ def store file, outputs, opt = {}
+ @msg = opt[:msg]
+ @user = (opt[:user] or @cfg.user)
+ @email = (opt[:email] or @cfg.email)
+ @opt = opt
+ @commitref = nil
+ repo = @cfg.repo
+
+ outputs.types.each do |type|
+ type_cfg = ''
+ type_repo = File.join(File.dirname(repo), type + '.git')
+ outputs.type(type).each do |output|
+ (type_cfg << output; next) if not output.name
+ type_file = file + '--' + output.name
+ if @cfg.type_as_directory?
+ type_file = type + '/' + type_file
+ type_repo = repo
+ end
+ update type_repo, type_file, output
+ end
+ update type_repo, file, type_cfg
+ end
+ update repo, file, outputs.to_cfg
+ end
- def fetch node, group
- begin
- repo, path = yield_repo_and_path(node, group)
- repo = Rugged::Repository.new repo
- index = repo.index
- index.read_tree repo.head.target.tree unless repo.empty?
- repo.read(index.get(path)[:oid]).data
- rescue
- 'node not found'
+ def fetch node, group
+ begin
+ repo, path = yield_repo_and_path(node, group)
+ repo = Rugged::Repository.new repo
+ index = repo.index
+ index.read_tree repo.head.target.tree unless repo.empty?
+ repo.read(index.get(path)[:oid]).data
+ rescue
+ 'node not found'
+ end
end
- end
# give a hash of all oid revision for the given node, and the date of the commit
def version node, group
@@ -80,7 +79,7 @@ class Git < Output
walker.sorting(Rugged::SORT_DATE)
walker.push(repo.head.target)
i = -1
- tab = []
+ tab = []
walker.each do |commit|
if commit.diff(paths: [path]).size > 0
hash = {}
@@ -98,18 +97,18 @@ class Git < Output
end
end
- #give the blob of a specific revision
+ # give the blob of a specific revision
def get_version node, group, oid
begin
repo, path = yield_repo_and_path(node, group)
repo = Rugged::Repository.new repo
- repo.blob_at(oid,path).content
+ repo.blob_at(oid, path).content
rescue
'version not found'
end
end
- #give a hash with the patch of a diff between 2 revision and the stats (added and deleted lines)
+ # give a hash with the patch of a diff between 2 revision and the stats (added and deleted lines)
def get_diff node, group, oid1, oid2
begin
diff_commits = nil
@@ -122,15 +121,15 @@ class Git < Output
diff = repo.diff(commit_old, commit)
diff.each do |patch|
if /#{node.name}\s+/.match(patch.to_s.lines.first)
- diff_commits = {:patch => patch.to_s, :stat => patch.stat}
+ diff_commits = { :patch => patch.to_s, :stat => patch.stat }
break
end
end
else
stat = commit.parents[0].diff(commit).stat
- stat = [stat[1],stat[2]]
+ stat = [stat[1], stat[2]]
patch = commit.parents[0].diff(commit).patch
- diff_commits = {:patch => patch, :stat => stat}
+ diff_commits = { :patch => patch, :stat => stat }
end
diff_commits
@@ -139,68 +138,67 @@ class Git < Output
end
end
- private
+ private
- def yield_repo_and_path(node, group)
- repo, path = node.repo, node.name
+ def yield_repo_and_path(node, group)
+ repo, path = node.repo, node.name
- if group and @cfg.single_repo?
- path = "#{group}/#{node.name}"
- end
+ if group and @cfg.single_repo?
+ path = "#{group}/#{node.name}"
+ end
- [repo, path]
- end
+ [repo, path]
+ end
- def update repo, file, data
- return if data.empty?
+ def update repo, file, data
+ return if data.empty?
- if @opt[:group]
- if @cfg.single_repo?
- file = File.join @opt[:group], file
- else
- repo = if repo.is_a?(::String)
- File.join File.dirname(repo), @opt[:group] + '.git'
- else
- repo[@opt[:group]]
- end
+ if @opt[:group]
+ if @cfg.single_repo?
+ file = File.join @opt[:group], file
+ else
+ repo = if repo.is_a?(::String)
+ File.join File.dirname(repo), @opt[:group] + '.git'
+ else
+ repo[@opt[:group]]
+ end
+ end
end
- end
- begin
- repo = Rugged::Repository.new repo
- update_repo repo, file, data, @msg, @user, @email
- rescue Rugged::OSError, Rugged::RepositoryError => open_error
begin
- Rugged::Repository.init_at repo, :bare
- rescue => create_error
- raise GitError, "first '#{open_error.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
+ repo = Rugged::Repository.new repo
+ update_repo repo, file, data, @msg, @user, @email
+ rescue Rugged::OSError, Rugged::RepositoryError => open_error
+ begin
+ Rugged::Repository.init_at repo, :bare
+ rescue => create_error
+ raise GitError, "first '#{open_error.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
+ end
+ retry
end
- retry
end
- end
- def update_repo repo, file, data, msg, user, email
- oid = repo.write data, :blob
- index = repo.index
- index.read_tree repo.head.target.tree unless repo.empty?
-
- tree_old = index.write_tree repo
- index.add :path=>file, :oid=>oid, :mode=>0100644
- tree_new = index.write_tree repo
-
- if tree_old != tree_new
- repo.config['user.name'] = user
- repo.config['user.email'] = email
- @commitref = Rugged::Commit.create(repo,
- :tree => index.write_tree(repo),
- :message => msg,
- :parents => repo.empty? ? [] : [repo.head.target].compact,
- :update_ref => 'HEAD',
- )
-
- index.write
- true
+ def update_repo repo, file, data, msg, user, email
+ oid = repo.write data, :blob
+ index = repo.index
+ index.read_tree repo.head.target.tree unless repo.empty?
+
+ tree_old = index.write_tree repo
+ index.add :path => file, :oid => oid, :mode => 0100644
+ tree_new = index.write_tree repo
+
+ if tree_old != tree_new
+ repo.config['user.name'] = user
+ repo.config['user.email'] = email
+ @commitref = Rugged::Commit.create(repo,
+ :tree => index.write_tree(repo),
+ :message => msg,
+ :parents => repo.empty? ? [] : [repo.head.target].compact,
+ :update_ref => 'HEAD',)
+
+ index.write
+ true
+ end
end
end
end
-end
diff --git a/lib/oxidized/output/gitcrypt.rb b/lib/oxidized/output/gitcrypt.rb
new file mode 100644
index 0000000..2da0179
--- /dev/null
+++ b/lib/oxidized/output/gitcrypt.rb
@@ -0,0 +1,243 @@
+module Oxidized
+ class GitCrypt < Output
+ class GitCryptError < OxidizedError; end
+ begin
+ require 'git'
+ rescue LoadError
+ raise OxidizedError, 'git not found: sudo gem install ruby-git'
+ end
+
+ attr_reader :commitref
+
+ def initialize
+ @cfg = Oxidized.config.output.gitcrypt
+ @gitcrypt_cmd = "/usr/bin/git-crypt"
+ @gitcrypt_init = @gitcrypt_cmd + " init"
+ @gitcrypt_unlock = @gitcrypt_cmd + " unlock"
+ @gitcrypt_lock = @gitcrypt_cmd + " lock"
+ @gitcrypt_adduser = @gitcrypt_cmd + " add-gpg-user --trusted "
+ end
+
+ def setup
+ if @cfg.empty?
+ Oxidized.asetus.user.output.gitcrypt.user = 'Oxidized'
+ Oxidized.asetus.user.output.gitcrypt.email = 'o@example.com'
+ Oxidized.asetus.user.output.gitcrypt.repo = File.join(Config::Root, 'oxidized.git')
+ Oxidized.asetus.save :user
+ raise NoConfig, 'no output git config, edit ~/.config/oxidized/config'
+ end
+
+ if @cfg.repo.respond_to?(:each)
+ @cfg.repo.each do |group, repo|
+ @cfg.repo["#{group}="] = File.expand_path repo
+ end
+ else
+ @cfg.repo = File.expand_path @cfg.repo
+ end
+ end
+
+ def crypt_init repo
+ repo.chdir do
+ system(@gitcrypt_init)
+ @cfg.users.each do |user|
+ system("#{@gitcrypt_adduser} #{user}")
+ end
+ File.write(".gitattributes", "* filter=git-crypt diff=git-crypt\n.gitattributes !filter !diff")
+ repo.add(".gitattributes")
+ repo.commit("Initial commit: crypt all config files")
+ end
+ end
+
+ def lock repo
+ repo.chdir do
+ system(@gitcrypt_lock)
+ end
+ end
+
+ def unlock repo
+ repo.chdir do
+ system(@gitcrypt_unlock)
+ end
+ end
+
+ def store file, outputs, opt = {}
+ @msg = opt[:msg]
+ @user = (opt[:user] or @cfg.user)
+ @email = (opt[:email] or @cfg.email)
+ @opt = opt
+ @commitref = nil
+ repo = @cfg.repo
+
+ outputs.types.each do |type|
+ type_cfg = ''
+ type_repo = File.join(File.dirname(repo), type + '.git')
+ outputs.type(type).each do |output|
+ (type_cfg << output; next) if not output.name
+ type_file = file + '--' + output.name
+ if @cfg.type_as_directory?
+ type_file = type + '/' + type_file
+ type_repo = repo
+ end
+ update type_repo, type_file, output
+ end
+ update type_repo, file, type_cfg
+ end
+
+ update repo, file, outputs.to_cfg
+ end
+
+ def fetch node, group
+ begin
+ repo, path = yield_repo_and_path(node, group)
+ repo = Git.open repo
+ unlock repo
+ index = repo.index
+ # Empty repo ?
+ empty = File.exists? index.path
+ if empty
+ raise 'Empty git repo'
+ else
+ File.read path
+ end
+ lock repo
+ rescue
+ 'node not found'
+ end
+ end
+
+ # give a hash of all oid revision for the given node, and the date of the commit
+ def version node, group
+ begin
+ repo, path = yield_repo_and_path(node, group)
+
+ repo = Git.open repo
+ unlock repo
+ walker = repo.log.path(path)
+ i = -1
+ tab = []
+ walker.each do |commit|
+ hash = {}
+ hash[:date] = commit.date.to_s
+ hash[:oid] = commit.objectish
+ hash[:author] = commit.author
+ hash[:message] = commit.message
+ tab[i += 1] = hash
+ end
+ walker.reset
+ tab
+ rescue
+ 'node not found'
+ end
+ end
+
+ # give the blob of a specific revision
+ def get_version node, group, oid
+ begin
+ repo, path = yield_repo_and_path(node, group)
+ repo = Git.open repo
+ unlock repo
+ repo.gtree(oid).files[path].contents
+ rescue
+ 'version not found'
+ ensure
+ lock repo
+ end
+ end
+
+ # give a hash with the patch of a diff between 2 revision and the stats (added and deleted lines)
+ def get_diff node, group, oid1, oid2
+ begin
+ diff_commits = nil
+ repo, path = yield_repo_and_path(node, group)
+ repo = Git.open repo
+ unlock repo
+ commit = repo.gcommit(oid1)
+
+ if oid2
+ commit_old = repo.gcommit(oid2)
+ diff = repo.diff(commit_old, commit)
+ stats = [diff.stats[:files][node.name][:insertions], diff.stats[:files][node.name][:deletions]]
+ diff.each do |patch|
+ if /#{node.name}\s+/.match(patch.patch.to_s.lines.first)
+ diff_commits = { :patch => patch.patch.to_s, :stat => stats }
+ break
+ end
+ end
+ else
+ stat = commit.parents[0].diff(commit).stats
+ stat = [stat[:files][node.name][:insertions], stat[:files][node.name][:deletions]]
+ patch = commit.parents[0].diff(commit).patch
+ diff_commits = { :patch => patch, :stat => stat }
+ end
+ lock repo
+ diff_commits
+ rescue
+ 'no diffs'
+ ensure
+ lock repo
+ end
+ end
+
+ private
+
+ def yield_repo_and_path(node, group)
+ repo, path = node.repo, node.name
+
+ if group and @cfg.single_repo?
+ path = "#{group}/#{node.name}"
+ end
+
+ [repo, path]
+ end
+
+ def update repo, file, data
+ return if data.empty?
+
+ if @opt[:group]
+ if @cfg.single_repo?
+ file = File.join @opt[:group], file
+ else
+ repo = if repo.is_a?(::String)
+ File.join File.dirname(repo), @opt[:group] + '.git'
+ else
+ repo[@opt[:group]]
+ end
+ end
+ end
+
+ begin
+ update_repo repo, file, data, @msg, @user, @email
+ rescue Git::GitExecuteError, ArgumentError => open_error
+ Oxidized.logger.debug "open_error #{open_error} #{file}"
+ begin
+ grepo = Git.init repo
+ crypt_init grepo
+ rescue => create_error
+ raise GitCryptError, "first '#{open_error.message}' was raised while opening git repo, then '#{create_error.message}' was while trying to create git repo"
+ end
+ retry
+ end
+ end
+
+ def update_repo repo, file, data, msg, user, email
+ grepo = Git.open repo
+ grepo.config('user.name', user)
+ grepo.config('user.email', email)
+ grepo.chdir do
+ unlock grepo
+ File.write(file, data)
+ grepo.add(file)
+ if grepo.status[file].nil?
+ grepo.commit(msg)
+ @commitref = grepo.log(1).first.objectish
+ true
+ elsif !grepo.status[file].type.nil?
+ grepo.commit(msg)
+ @commitref = grepo.log(1).first.objectish
+ true
+ end
+ lock grepo
+ end
+ end
+ end
+end
diff --git a/lib/oxidized/output/http.rb b/lib/oxidized/output/http.rb
index 13ba300..0467261 100644
--- a/lib/oxidized/output/http.rb
+++ b/lib/oxidized/output/http.rb
@@ -7,9 +7,9 @@ module Oxidized
def setup
if @cfg.empty?
- CFGS.user.output.http.user = 'Oxidized'
+ CFGS.user.output.http.user = 'Oxidized'
CFGS.user.output.http.pasword = 'secret'
- CFGS.user.output.http.url = 'http://localhost/web-api/oxidized'
+ CFGS.user.output.http.url = 'http://localhost/web-api/oxidized'
CFGS.save :user
raise NoConfig, 'no output http config, edit ~/.config/oxidized/config'
end
@@ -17,42 +17,38 @@ module Oxidized
require "net/http"
require "uri"
require "json"
- def store node, outputs, opt={}
+ def store node, outputs, opt = {}
@commitref = nil
json = JSON.pretty_generate(
- {
- 'msg' => opt[:msg],
- 'user' => opt[:user],
- 'email' => opt[:email],
- 'group' => opt[:group],
- 'node' => node,
- 'config' => outputs.to_cfg,
- # actually we need to also iterate outputs, for other types like in gitlab. But most people don't use 'type' functionality.
- }
+ {
+ 'msg' => opt[:msg],
+ 'user' => opt[:user],
+ 'email' => opt[:email],
+ 'group' => opt[:group],
+ 'node' => node,
+ 'config' => outputs.to_cfg,
+ # actually we need to also iterate outputs, for other types like in gitlab. But most people don't use 'type' functionality.
+ }
)
uri = URI.parse @cfg.url
http = Net::HTTP.new uri.host, uri.port
- #http.use_ssl = true if uri.scheme = 'https'
- req = Net::HTTP::Post.new(uri.request_uri, initheader = { 'Content-Type' => 'application/json'})
+ # http.use_ssl = true if uri.scheme = 'https'
+ req = Net::HTTP::Post.new(uri.request_uri, initheader = { 'Content-Type' => 'application/json' })
req.basic_auth @cfg.user, @cfg.password
req.body = json
response = http.request req
case response.code.to_i
- when 200 || 201
- Oxidized.logger.info "Configuration http backup complete for #{node}"
- p [:success]
- when (400..499)
- Oxidized.logger.info "Configuration http backup for #{node} failed status: #{response.body}"
- p [:bad_request]
- when (500..599)
- p [:server_problems]
- Oxidized.logger.info "Configuration http backup for #{node} failed status: #{response.body}"
+ when 200 || 201
+ Oxidized.logger.info "Configuration http backup complete for #{node}"
+ p [:success]
+ when (400..499)
+ Oxidized.logger.info "Configuration http backup for #{node} failed status: #{response.body}"
+ p [:bad_request]
+ when (500..599)
+ p [:server_problems]
+ Oxidized.logger.info "Configuration http backup for #{node} failed status: #{response.body}"
end
-
end
-
end
end
-
-
diff --git a/lib/oxidized/output/output.rb b/lib/oxidized/output/output.rb
index 1355d03..9fae7b0 100644
--- a/lib/oxidized/output/output.rb
+++ b/lib/oxidized/output/output.rb
@@ -3,8 +3,7 @@ module Oxidized
class NoConfig < OxidizedError; end
def cfg_to_str cfg
- cfg.select{ |h| h[:type]=='cfg' }.map{ |h| h[:data] }.join
+ cfg.select { |h| h[:type] == 'cfg' }.map { |h| h[:data] }.join
end
-
end
end
diff --git a/lib/oxidized/source/csv.rb b/lib/oxidized/source/csv.rb
index c1e310a..ae1c0a9 100644
--- a/lib/oxidized/source/csv.rb
+++ b/lib/oxidized/source/csv.rb
@@ -1,54 +1,53 @@
module Oxidized
-class CSV < Source
- def initialize
- @cfg = Oxidized.config.source.csv
- super
- end
-
- def setup
- if @cfg.empty?
- Oxidized.asetus.user.source.csv.file = File.join(Config::Root, 'router.db')
- Oxidized.asetus.user.source.csv.delimiter = /:/
- Oxidized.asetus.user.source.csv.map.name = 0
- Oxidized.asetus.user.source.csv.map.model = 1
- Oxidized.asetus.user.source.csv.gpg = false
- Oxidized.asetus.save :user
- raise NoConfig, 'no source csv config, edit ~/.config/oxidized/config'
+ class CSV < Source
+ def initialize
+ @cfg = Oxidized.config.source.csv
+ super
end
- require 'gpgme' if @cfg.gpg?
- end
- def load
- nodes = []
- file = File.expand_path(@cfg.file)
- file = if @cfg.gpg?
- crypto = GPGME::Crypto.new password: @cfg.gpg_password
- crypto.decrypt(file).to_s
- else
- open(file)
- end
- file.each_line do |line|
- next if line.match(/^\s*#/)
- data = line.chomp.split(@cfg.delimiter, -1)
- next if data.empty?
- # map node parameters
- keys = {}
- @cfg.map.each do |key, position|
- keys[key.to_sym] = node_var_interpolate data[position]
+ def setup
+ if @cfg.empty?
+ Oxidized.asetus.user.source.csv.file = File.join(Config::Root, 'router.db')
+ Oxidized.asetus.user.source.csv.delimiter = /:/
+ Oxidized.asetus.user.source.csv.map.name = 0
+ Oxidized.asetus.user.source.csv.map.model = 1
+ Oxidized.asetus.user.source.csv.gpg = false
+ Oxidized.asetus.save :user
+ raise NoConfig, 'no source csv config, edit ~/.config/oxidized/config'
end
- keys[:model] = map_model keys[:model] if keys.key? :model
+ require 'gpgme' if @cfg.gpg?
+ end
- # map node specific vars
- vars = {}
- @cfg.vars_map.each do |key, position|
- vars[key.to_sym] = node_var_interpolate data[position]
- end
- keys[:vars] = vars unless vars.empty?
+ def load
+ nodes = []
+ file = File.expand_path(@cfg.file)
+ file = if @cfg.gpg?
+ crypto = GPGME::Crypto.new password: @cfg.gpg_password
+ file = crypto.decrypt(File.open(file)).to_s
+ else
+ open(file)
+ end
+ file.each_line do |line|
+ next if line.match(/^\s*#/)
+ data = line.chomp.split(@cfg.delimiter, -1)
+ next if data.empty?
+ # map node parameters
+ keys = {}
+ @cfg.map.each do |key, position|
+ keys[key.to_sym] = node_var_interpolate data[position]
+ end
+ keys[:model] = map_model keys[:model] if keys.has_key? :model
- nodes << keys
+ # map node specific vars
+ vars = {}
+ @cfg.vars_map.each do |key, position|
+ vars[key.to_sym] = node_var_interpolate data[position]
+ end
+ keys[:vars] = vars unless vars.empty?
+
+ nodes << keys
+ end
+ nodes
end
- nodes
end
-
-end
end
diff --git a/lib/oxidized/source/http.rb b/lib/oxidized/source/http.rb
index 4fd388b..55dcd4c 100644
--- a/lib/oxidized/source/http.rb
+++ b/lib/oxidized/source/http.rb
@@ -1,60 +1,80 @@
module Oxidized
-class HTTP < Source
- def initialize
- @cfg = Oxidized.config.source.http
- super
- end
-
- def setup
- if @cfg.url.empty?
- raise NoConfig, 'no source http url config, edit ~/.config/oxidized/config'
+ class HTTP < Source
+ def initialize
+ @cfg = Oxidized.config.source.http
+ super
end
- end
- require "net/http"
- require "uri"
- require "json"
-
- def load
- nodes = []
- uri = URI.parse(@cfg.url)
- http = Net::HTTP.new(uri.host, uri.port)
- http.use_ssl = true if uri.scheme == 'https'
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @cfg.secure
-
- # map headers
- headers = {}
- @cfg.headers.each do |header, value|
- headers[header] = value
+ def setup
+ if @cfg.url.empty?
+ raise NoConfig, 'no source http url config, edit ~/.config/oxidized/config'
+ end
end
- request = Net::HTTP::Get.new(uri.request_uri, headers)
- if (@cfg.user && @cfg.pass)
- request.basic_auth(@cfg.user,@cfg.pass)
- end
+ require "net/http"
+ require "uri"
+ require "json"
+
+ def load node_want = nil
+ nodes = []
+ uri = URI.parse(@cfg.url)
+ http = Net::HTTP.new(uri.host, uri.port)
+ http.use_ssl = true if uri.scheme == 'https'
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @cfg.secure
- response = http.request(request)
- data = JSON.parse(response.body)
- data.each do |line|
- next if line.empty?
- # map node parameters
- keys = {}
- @cfg.map.each do |key, position|
- keys[key.to_sym] = node_var_interpolate line[position]
+ # map headers
+ headers = {}
+ @cfg.headers.each do |header, value|
+ headers[header] = value
end
- keys[:model] = map_model keys[:model] if keys.key? :model
- # map node specific vars
- vars = {}
- @cfg.vars_map.each do |key, position|
- vars[key.to_sym] = node_var_interpolate line[position]
+ req_uri = uri.request_uri
+ if node_want
+ req_uri = "#{req_uri}/#{node_want}"
end
- keys[:vars] = vars unless vars.empty?
+ request = Net::HTTP::Get.new(req_uri, headers)
+ if (@cfg.user? && @cfg.pass?)
+ request.basic_auth(@cfg.user, @cfg.pass)
+ end
+
+ response = http.request(request)
+ data = JSON.parse(response.body)
+ data.each do |node|
+ next if node.empty?
+ # map node parameters
+ keys = {}
+ @cfg.map.each do |key, want_position|
+ want_positions = want_position.split('.')
+ keys[key.to_sym] = node_var_interpolate node.dig(*want_positions)
+ end
+ keys[:model] = map_model keys[:model] if keys.has_key? :model
- nodes << keys
+ # map node specific vars
+ vars = {}
+ @cfg.vars_map.each do |key, want_position|
+ want_positions = want_position.split('.')
+ vars[key.to_sym] = node_var_interpolate node.dig(*want_positions)
+ end
+ keys[:vars] = vars unless vars.empty?
+
+ nodes << keys
+ end
+ nodes
end
- nodes
end
-
end
+
+if RUBY_VERSION < '2.3'
+ class Hash
+ def dig(key, *rest)
+ value = self[key]
+ if value.nil? || rest.empty?
+ value
+ elsif value.respond_to?(:dig)
+ value.dig(*rest)
+ else # foo.bar.baz (bar exist but is not hash)
+ return nil
+ end
+ end
+ end
end
diff --git a/lib/oxidized/source/source.rb b/lib/oxidized/source/source.rb
index 9b8bc94..3bae0f6 100644
--- a/lib/oxidized/source/source.rb
+++ b/lib/oxidized/source/source.rb
@@ -11,13 +11,12 @@ module Oxidized
end
def node_var_interpolate var
- case var
- when "nil" then nil
- when "false" then false
- when "true" then true
- else var
- end
+ case var
+ when "nil" then nil
+ when "false" then false
+ when "true" then true
+ else var
+ end
end
-
end
end
diff --git a/lib/oxidized/source/sql.rb b/lib/oxidized/source/sql.rb
index 13fc39b..c5fe650 100644
--- a/lib/oxidized/source/sql.rb
+++ b/lib/oxidized/source/sql.rb
@@ -1,63 +1,67 @@
module Oxidized
-class SQL < Source
- begin
- require 'sequel'
- rescue LoadError
- raise OxidizedError, 'sequel not found: sudo gem install sequel'
- end
+ class SQL < Source
+ begin
+ require 'sequel'
+ rescue LoadError
+ raise OxidizedError, 'sequel not found: sudo gem install sequel'
+ end
- def setup
- if @cfg.empty?
- Oxidized.asetus.user.source.sql.adapter = 'sqlite'
- Oxidized.asetus.user.source.sql.database = File.join(Config::Root, 'sqlite.db')
- Oxidized.asetus.user.source.sql.table = 'devices'
- Oxidized.asetus.user.source.sql.map.name = 'name'
- Oxidized.asetus.user.source.sql.map.model = 'rancid'
- Oxidized.asetus.save :user
- raise NoConfig, 'no source sql config, edit ~/.config/oxidized/config'
+ def setup
+ if @cfg.empty?
+ Oxidized.asetus.user.source.sql.adapter = 'sqlite'
+ Oxidized.asetus.user.source.sql.database = File.join(Config::Root, 'sqlite.db')
+ Oxidized.asetus.user.source.sql.table = 'devices'
+ Oxidized.asetus.user.source.sql.map.name = 'name'
+ Oxidized.asetus.user.source.sql.map.model = 'rancid'
+ Oxidized.asetus.save :user
+ raise NoConfig, 'no source sql config, edit ~/.config/oxidized/config'
+ end
end
- end
- def load
- nodes = []
- db = connect
- query = db[@cfg.table.to_sym]
- query = query.with_sql(@cfg.query) if @cfg.query?
- query.each do |node|
- # map node parameters
- keys = {}
- @cfg.map.each { |key, sql_column| keys[key.to_sym] = node_var_interpolate node[sql_column.to_sym] }
- keys[:model] = map_model keys[:model] if keys.key? :model
-
- # map node specific vars
- vars = {}
- @cfg.vars_map.each do |key, sql_column|
- vars[key.to_sym] = node_var_interpolate node[sql_column.to_sym]
+ def load node_want = nil
+ nodes = []
+ db = connect
+ query = db[@cfg.table.to_sym]
+ query = query.with_sql(@cfg.query) if @cfg.query?
+
+ if node_want
+ query = query.where(@cfg.map.name.to_sym => node_want)
end
- keys[:vars] = vars unless vars.empty?
- nodes << keys
+ query.each do |node|
+ # map node parameters
+ keys = {}
+ @cfg.map.each { |key, sql_column| keys[key.to_sym] = node_var_interpolate node[sql_column.to_sym] }
+ keys[:model] = map_model keys[:model] if keys.has_key? :model
+
+ # map node specific vars
+ vars = {}
+ @cfg.vars_map.each do |key, sql_column|
+ vars[key.to_sym] = node_var_interpolate node[sql_column.to_sym]
+ end
+ keys[:vars] = vars unless vars.empty?
+
+ nodes << keys
+ end
+ db.disconnect
+ nodes
end
- db.disconnect
- nodes
- end
- private
+ private
- def initialize
- super
- @cfg = Oxidized.config.source.sql
- end
+ def initialize
+ super
+ @cfg = Oxidized.config.source.sql
+ end
- def connect
- Sequel.connect(:adapter => @cfg.adapter,
- :host => @cfg.host?,
- :user => @cfg.user?,
- :password => @cfg.password?,
- :database => @cfg.database)
- rescue Sequel::AdapterNotFound => error
- raise OxidizedError, "SQL adapter gem not installed: " + error.message
+ def connect
+ Sequel.connect(:adapter => @cfg.adapter,
+ :host => @cfg.host?,
+ :user => @cfg.user?,
+ :password => @cfg.password?,
+ :database => @cfg.database)
+ rescue Sequel::AdapterNotFound => error
+ raise OxidizedError, "SQL adapter gem not installed: " + error.message
+ end
end
-
-end
end
diff --git a/lib/oxidized/string.rb b/lib/oxidized/string.rb
index 8bcb082..ca4862d 100644
--- a/lib/oxidized/string.rb
+++ b/lib/oxidized/string.rb
@@ -15,11 +15,11 @@ module Oxidized
# sets @cmd and @name unless @name is already set
def set_cmd command
- @cmd = command
+ @cmd = command
@name ||= @cmd.strip.gsub(/\s+/, '_')
end
- def initialize str=''
+ def initialize str = ''
super
if str.class == Oxidized::String
@cmd = str.cmd
@@ -27,6 +27,5 @@ module Oxidized
@type = str.type
end
end
-
end
end
diff --git a/lib/oxidized/version.rb b/lib/oxidized/version.rb
index 073aae9..b607e12 100644
--- a/lib/oxidized/version.rb
+++ b/lib/oxidized/version.rb
@@ -1,3 +1,19 @@
module Oxidized
- VERSION = '0.19.0'
+ VERSION = '0.21.0'
+ VERSION_FULL = '0.21.0-180-g9691008'
+ def self.version_set
+ version_full = %x(git describe --tags).chop rescue ""
+ version = %x(git describe --tags --abbrev=0).chop rescue ""
+
+ return false unless [version, version_full].none?(&:empty?)
+
+ Oxidized.send(:remove_const, :VERSION)
+ Oxidized.send(:remove_const, :VERSION_FULL)
+ const_set(:VERSION, version)
+ const_set(:VERSION_FULL, version_full)
+ file = File.readlines(__FILE__)
+ file[1] = " VERSION = '%s'\n" % VERSION
+ file[2] = " VERSION_FULL = '%s'\n" % VERSION_FULL
+ File.write(__FILE__, file.join)
+ end
end
diff --git a/lib/oxidized/worker.rb b/lib/oxidized/worker.rb
index 1952d01..692b060 100644
--- a/lib/oxidized/worker.rb
+++ b/lib/oxidized/worker.rb
@@ -3,8 +3,10 @@ module Oxidized
require 'oxidized/jobs'
class Worker
def initialize nodes
- @nodes = nodes
- @jobs = Jobs.new(Oxidized.config.threads, Oxidized.config.interval, @nodes)
+ @jobs_done = 0
+ @nodes = nodes
+ @jobs = Jobs.new(Oxidized.config.threads, Oxidized.config.interval, @nodes)
+ @nodes.jobs = @jobs
Thread.abort_on_exception = true
end
@@ -13,8 +15,9 @@ module Oxidized
@jobs.delete_if { |job| ended << job if not job.alive? }
ended.each { |job| process job }
@jobs.work
+
while @jobs.size < @jobs.want
- Oxidized.logger.debug "lib/oxidized/worker.rb: Jobs #{@jobs.size}, Want: #{@jobs.want}"
+ Oxidized.logger.debug "lib/oxidized/worker.rb: Jobs running: #{@jobs.size} of #{@jobs.want} - ended: #{@jobs_done} of #{@nodes.size}"
# ask for next node in queue non destructive way
nextnode = @nodes.first
unless nextnode.last.nil?
@@ -28,6 +31,8 @@ module Oxidized
@jobs.push Job.new node
Oxidized.logger.debug "lib/oxidized/worker.rb: Added #{node.name} to the job queue"
end
+
+ run_done_hook if is_cycle_finished?
Oxidized.logger.debug("lib/oxidized/worker.rb: #{@jobs.size} jobs running in parallel") unless @jobs.empty?
end
@@ -37,6 +42,8 @@ module Oxidized
node.stats.add job
@jobs.duration job.time
node.running = false
+ @jobs_done += 1 # needed for worker_done event
+
if job.status == :success
Oxidized.Hooks.handle :node_success, :node => node,
:job => job
@@ -45,7 +52,7 @@ module Oxidized
msg += " with message '#{node.msg}'" if node.msg
output = node.output.new
if output.store node.name, job.config,
- :msg => msg, :user => node.user, :group => node.group
+ :msg => msg, :email => node.email, :user => node.user, :group => node.group
Oxidized.logger.info "Configuration updated for #{node.group}/#{node.name}"
Oxidized.Hooks.handle :post_store, :node => node,
:job => job,
@@ -70,5 +77,24 @@ module Oxidized
Oxidized.logger.warn "#{node.name} not found, removed while collecting?"
end
+ private
+
+ def is_cycle_finished?
+ if @jobs_done > @nodes.count
+ true
+ else
+ @jobs_done > 0 && @jobs_done % @nodes.count == 0
+ end
+ end
+
+ def run_done_hook
+ Oxidized.logger.debug "lib/oxidized/worker.rb: Running :nodes_done hook"
+ Oxidized.Hooks.handle :nodes_done
+ rescue => e
+ # swallow the hook erros and continue as normal
+ Oxidized.logger.error "lib/oxidized/worker.rb: #{e.message}"
+ ensure
+ @jobs_done = 0
+ end
end
end