lib/hotwired/core.rb in hotwired-0.0.3 vs lib/hotwired/core.rb in hotwired-0.0.4

- old
+ new

@@ -19,11 +19,11 @@ Core.new opts end # 轮询 host 数据 def poll(opts = {}) - host = opts.delete :host + host = opts.delete(:host) raise HotwiredError, "'host' not given" unless host hotwire = new(opts) result = hotwire.poll Resolv.getaddress(host) # 数据转储 hotwire.make_record result if result @@ -39,92 +39,124 @@ end # 类对象外部调用函数入口 def run # 解析变量 - cidr = @opts.delete :cidr + cidr = @opts.delete(:cidr) # @output = @opts.delete :output # 设置缺省 logger 输出 # unless @output # @output = Logger.new $stdout # @output.formatter = proc { |_, _, _, msg| "#{msg}\n" } # end # 初始化变量及遍历 CIDR - poll, ignores = resolve_networks cidr + poll, ignores = resolve_networks(cidr) # 实例化线程和数据库联结 @mutex = Mutex.new @db = DB.new threads = [] # 线程遇到异常及时终止 - Thread.abort_on_exception = true + Thread.abort_on_exception = false # 遍历待轮询的 IPAddr poll.each do |net| net.to_range.each do |ip| # 检查当前地址是否需要被忽略 next if ignores.any? { |ignore| ignore.include? ip } # 清除空闲线程 while threads.size >= CFG.threads threads.delete_if { |thread| not thread.alive? } - sleep 0.01 + sleep 0.02 end # 线程不够则主动添加线程 threads << Thread.new do - result = poll ip + result = poll(ip) @mutex.synchronize { process result } if result end end end # 激活线程,开始干活 threads.each { |thread| thread.join } end + # 解析 cidr + def resolve_networks(cidr) + # 如未接收外部变量则使用缺省值 + cidr = cidr ? [cidr].flatten : CFG.poll + + # 从 CIDR 中剔除排除清单 + # 支持数组以及文本形式,数据返回包含2个数组对象的数组 + [cidr, CFG.ignore].map do |nets| + if nets.respond_to? :each + nets.map { |net| IPAddr.new net } + else + out = [] + File.read(nets).each_line do |net| + # 模糊的 IP 地址正则表达式 + net = net.match(/^([\d.\/]+)$/) + out << IPAddr.new(net[1]) if net + end + out + end + end + end + # 轮询单个 IP 设备信息 def poll(ip) result = nil # 实例化 SNMP 对象,批量获取相关监控数据 snmp = SNMP.new(ip.to_s, @community) + # 如有异常则返回 false oids = snmp.dbget if oids # 早期异常拦截 Log.debug "SNMP::NoSuchObject #{ip}" if oids[:sysDescr] == ::SNMP::NoSuchObject return nil if oids[:sysDescr] == ::SNMP::NoSuchObject # 初始化变量,并尝试刷新接口描述信息 result = { oids: oids, ip: ip, int: "n/a" } # 联机查询数据 index = snmp.ip2index(ip.to_s) - int = snmp.ifdescr(index) # 逻辑处理 - if index - if int - result[:int] = int.downcase - else + if index.nil? + Log.debug "no ifIndex for #{ip}" + else + int = snmp.ifdescr(index) + if int.nil? Log.debug "no ifDescr for #{index} at #{ip}" + else + result[:int] = int.downcase end - else - Log.debug "no ifIndex for #{ip}" end end # 关闭 SNMP 会话并返回结果 snmp.close result end + # 解析 IP 关联的主机名 + def ip2name(ip) + Resolv.getname ip rescue ip + end + # 新增表记录 def make_record(opt) + # 判断是否存在 sysObjectID,不存在则设置为 nil + sys_object_id = opt[:oids][:sysObjectID].empty? ? nil : opt[:oids][:sysObjectID].join(".") + + # 返回数据结构 { ip: opt[:ip].to_s, ptr: ip2name(opt[:ip].to_s), model: Model.map(opt[:oids][:sysDescr], opt[:oids][:sysObjectID]), oid_ifDescr: opt[:int], oid_sysName: opt[:oids][:sysName], oid_sysLocation: opt[:oids][:sysLocation], oid_sysDescr: opt[:oids][:sysDescr], - oid_sysObjectID: opt[:oids][:sysObjectID].join("."), + oid_sysObjectID: sys_object_id } end private def process(opt) @@ -203,35 +235,8 @@ # 序列化 opt 参数 def normalize_opt(opt) opt[:oids][:sysName].sub!(/-re[1-9]\./, "-re0.") opt - end - - # 解析 IP 关联的主机名 - def ip2name(ip) - Resolv.getname ip rescue ip - end - - # 解析 cidr - def resolve_networks(cidr) - # 如未接收外部变量则使用缺省值 - cidr = cidr ? [cidr].flatten : CFG.poll - - # 从 CIDR 中剔除排除清单 - # 支持数组以及文本形式,数据返回包含2个数组对象的数组 - [cidr, CFG.ignore].map do |nets| - if nets.respond_to? :each - nets.map { |net| IPAddr.new net } - else - out = [] - File.read(nets).each_line do |net| - # 模糊的 IP 地址正则表达式 - net = net.match(/^([\d.\/]+)$/) - out << IPAddr.new(net[1]) if net - end - out - end - end end end end