aio_elin 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +675 -0
- data/README.md +9 -0
- data/config.rb +39 -0
- data/lib/aio/base/debug.rb +30 -0
- data/lib/aio/base/toolkit/array.rb +24 -0
- data/lib/aio/base/toolkit/date.rb +46 -0
- data/lib/aio/base/toolkit/deep_clone.rb +10 -0
- data/lib/aio/base/toolkit/diff.rb +104 -0
- data/lib/aio/base/toolkit/excel_office.rb +421 -0
- data/lib/aio/base/toolkit/excel_wps.rb +437 -0
- data/lib/aio/base/toolkit/excel_wps.rb.bak +299 -0
- data/lib/aio/base/toolkit/ipaddr.rb +28 -0
- data/lib/aio/base/toolkit/os.rb +26 -0
- data/lib/aio/base/toolkit/regexp.rb +32 -0
- data/lib/aio/base/toolkit/string.rb +28 -0
- data/lib/aio/base/toolkit/table.rb +441 -0
- data/lib/aio/base/toolkit/test_diff.rb +9 -0
- data/lib/aio/base/toolkit/test_excel.rb +118 -0
- data/lib/aio/base/toolkit/test_word.rb +58 -0
- data/lib/aio/base/toolkit/word_wps.rb +492 -0
- data/lib/aio/base/toolkit.rb +18 -0
- data/lib/aio/base.rb +10 -0
- data/lib/aio/core/device/cisco.rb +13 -0
- data/lib/aio/core/device/cmd_switch.rb +113 -0
- data/lib/aio/core/device/h3c.rb +12 -0
- data/lib/aio/core/device/huawei.rb +10 -0
- data/lib/aio/core/device/juniper.rb +10 -0
- data/lib/aio/core/device/maipu.rb +11 -0
- data/lib/aio/core/device/methods.rb +233 -0
- data/lib/aio/core/device/methods.rb.bak +199 -0
- data/lib/aio/core/device/parent_device.rb +275 -0
- data/lib/aio/core/device.rb +15 -0
- data/lib/aio/core/device_manager.rb +207 -0
- data/lib/aio/core/module/cmd.rb +160 -0
- data/lib/aio/core/module/description.rb +67 -0
- data/lib/aio/core/module/input_style.rb +98 -0
- data/lib/aio/core/module/output_style.rb +80 -0
- data/lib/aio/core/module/platform.rb +30 -0
- data/lib/aio/core/module/ranking.rb +24 -0
- data/lib/aio/core/module/special_style.rb +30 -0
- data/lib/aio/core/module/template.rb +13 -0
- data/lib/aio/core/module.rb +15 -0
- data/lib/aio/core/module_loader.rb +161 -0
- data/lib/aio/core/module_loader.rb.bak +148 -0
- data/lib/aio/core/module_manager.rb +112 -0
- data/lib/aio/core/module_manager.rb.bak +78 -0
- data/lib/aio/core/parse/file.rb +19 -0
- data/lib/aio/core/parse/parser.rb +91 -0
- data/lib/aio/core/parse/parser_machine/bak/has_cmd_state.rb +14 -0
- data/lib/aio/core/parse/parser_machine/bak/has_context_state.rb +11 -0
- data/lib/aio/core/parse/parser_machine/bak/no_cmd_state.rb +11 -0
- data/lib/aio/core/parse/parser_machine/bak/no_context_state.rb +11 -0
- data/lib/aio/core/parse/parser_machine/full_state.rb +12 -0
- data/lib/aio/core/parse/parser_machine/has_device_state.rb +44 -0
- data/lib/aio/core/parse/parser_machine/no_device_state.rb +12 -0
- data/lib/aio/core/parse/parser_machine/parent_state.rb +26 -0
- data/lib/aio/core/parse/parser_machine.rb +47 -0
- data/lib/aio/core/parse.rb +6 -0
- data/lib/aio/core/text/context.rb +211 -0
- data/lib/aio/core/text/line_string.rb +74 -0
- data/lib/aio/core/text/warning.rb +179 -0
- data/lib/aio/core/text.rb +7 -0
- data/lib/aio/core/warning/description.rb +47 -0
- data/lib/aio/core/warning/warning_summarize.rb +232 -0
- data/lib/aio/core/warning.rb +6 -0
- data/lib/aio/core.rb +32 -0
- data/lib/aio/license.rb +687 -0
- data/lib/aio/resource/cover_picture.png +0 -0
- data/lib/aio/resource/line.png +0 -0
- data/lib/aio/resource/logo.png +0 -0
- data/lib/aio/ui/banner.rb +85 -0
- data/lib/aio/ui/readable_text.rb +75 -0
- data/lib/aio/ui/verbose.rb +29 -0
- data/lib/aio/ui/version.rb +9 -0
- data/lib/aio/ui.rb +138 -0
- data/lib/aio.rb +13 -0
- data/lib/modules/cmd/cisco/show_clock.rb +32 -0
- data/lib/modules/cmd/cisco/show_cpu.rb +32 -0
- data/lib/modules/cmd/cisco/show_env.rb +71 -0
- data/lib/modules/cmd/cisco/show_failover.rb +39 -0
- data/lib/modules/cmd/cisco/show_interface_ip_brief.rb +24 -0
- data/lib/modules/cmd/cisco/show_interfaces.rb +177 -0
- data/lib/modules/cmd/cisco/show_inv.rb +43 -0
- data/lib/modules/cmd/cisco/show_ip_interface_brief.rb +42 -0
- data/lib/modules/cmd/cisco/show_ip_ospf_nei.rb +38 -0
- data/lib/modules/cmd/cisco/show_ip_route_summary.rb +81 -0
- data/lib/modules/cmd/cisco/show_memory.rb +27 -0
- data/lib/modules/cmd/cisco/show_process_cpu.rb +35 -0
- data/lib/modules/cmd/cisco/show_process_memory.rb +63 -0
- data/lib/modules/cmd/cisco/show_version.rb +97 -0
- data/lib/modules/cmd/h3c/display_clock.rb +32 -0
- data/lib/modules/cmd/h3c/display_cpu.rb +51 -0
- data/lib/modules/cmd/h3c/display_device_manuinfo.rb +45 -0
- data/lib/modules/cmd/h3c/display_fan.rb +91 -0
- data/lib/modules/cmd/h3c/display_interface.rb +203 -0
- data/lib/modules/cmd/h3c/display_ip_interface_brief.rb +34 -0
- data/lib/modules/cmd/h3c/display_ip_routing.rb +68 -0
- data/lib/modules/cmd/h3c/display_ip_routing_stat.rb +90 -0
- data/lib/modules/cmd/h3c/display_memory.rb +35 -0
- data/lib/modules/cmd/h3c/display_ospf_peer.rb +38 -0
- data/lib/modules/cmd/h3c/display_power.rb +90 -0
- data/lib/modules/cmd/h3c/display_version.rb +54 -0
- data/lib/modules/cmd/h3c/display_vrrp_verbose.rb +86 -0
- data/lib/modules/cmd/maipu/show_env.rb +34 -0
- data/lib/modules/cmd/maipu/show_ip_route.rb +74 -0
- data/lib/modules/cmd/maipu/show_ip_route_statistic.rb +36 -0
- data/lib/modules/cmd/maipu/show_memory.rb +31 -0
- data/lib/modules/cmd/maipu/show_system_fan.rb +66 -0
- data/lib/modules/cmd/maipu/show_system_power.rb +66 -0
- data/lib/modules/cmd/maipu/show_version.rb +50 -0
- data/lib/modules/description/style/crc.rb +22 -0
- data/lib/modules/description/style/input_errors.rb +22 -0
- data/lib/modules/description/style/overrun.rb +22 -0
- data/lib/modules/description/style/proc_ratio.rb +22 -0
- data/lib/modules/description/style/protocol.rb +22 -0
- data/lib/modules/description/style/register.rb +22 -0
- data/lib/modules/description/style/runts.rb +22 -0
- data/lib/modules/description/style/template.rb +22 -0
- data/lib/modules/description/style/total_output_drops.rb +22 -0
- data/lib/modules/input/style/compare_xml.rb +89 -0
- data/lib/modules/input/style/console.rb +222 -0
- data/lib/modules/input/style/console.rb.bak +114 -0
- data/lib/modules/input/style/xinhua_nat.rb +70 -0
- data/lib/modules/output/style/boc_day.rb +223 -0
- data/lib/modules/output/style/cmds.rb +77 -0
- data/lib/modules/output/style/compare_json.rb +26 -0
- data/lib/modules/output/style/compare_report.rb +31 -0
- data/lib/modules/output/style/compare_xml.rb +86 -0
- data/lib/modules/output/style/excel_table_office.rb +407 -0
- data/lib/modules/output/style/excel_table_wps.rb +400 -0
- data/lib/modules/output/style/summary_report.rb +563 -0
- data/lib/modules/special/style/compare.rb +110 -0
- metadata +176 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#coding=utf-8
|
|
2
|
+
|
|
3
|
+
require "aio/core"
|
|
4
|
+
|
|
5
|
+
class Aio::Module::Description::TotalOutputDrops < Aio::Module::Description
|
|
6
|
+
include Aio::Module
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
super({
|
|
10
|
+
:author => "Elin",
|
|
11
|
+
:case => :total_output_drops,
|
|
12
|
+
:name => "出接口丢包",
|
|
13
|
+
:title => "出接口丢包检查",
|
|
14
|
+
:description => "出接口丢包检查"
|
|
15
|
+
})
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_s
|
|
19
|
+
"出接口丢包率不应该高出阈值。"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#coding=utf-8
|
|
2
|
+
|
|
3
|
+
require "aio/core"
|
|
4
|
+
require "rexml/document"
|
|
5
|
+
|
|
6
|
+
class Aio::Module::InputStyle::CompareXML < Aio::Module::InputStyle
|
|
7
|
+
include Aio::Module
|
|
8
|
+
include REXML
|
|
9
|
+
include Aio::Ui::Verbose
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
super({
|
|
13
|
+
:author => "Elin",
|
|
14
|
+
:description => "这个模块用于分析由output/out_compare_xml模块生成的xml文件",
|
|
15
|
+
:platform => "all",
|
|
16
|
+
:file_suffix => Regexp.new('\.xml$'),
|
|
17
|
+
:pass_file => [],
|
|
18
|
+
})
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def parse
|
|
22
|
+
# dir 为 Pathname 类
|
|
23
|
+
print_good "正在打开文件 #{self.input_file}"
|
|
24
|
+
file = File.open(self.input_file)
|
|
25
|
+
print_good "打开文件完成"
|
|
26
|
+
print_good "正在载入到XML模块..."
|
|
27
|
+
atime = Time.now
|
|
28
|
+
doc = Document.new(file)
|
|
29
|
+
root = doc.root
|
|
30
|
+
print_good "载入完成。载入用时 #{format("%.2fs", Time.now.to_f - atime.to_f)}"
|
|
31
|
+
device_hash = {}
|
|
32
|
+
|
|
33
|
+
index = 0
|
|
34
|
+
total = root.elements.size
|
|
35
|
+
|
|
36
|
+
print_good "开始比对分析..."
|
|
37
|
+
# 按每台设备解析XML
|
|
38
|
+
root.elements.each do |device|
|
|
39
|
+
index += 1
|
|
40
|
+
info = {}
|
|
41
|
+
device_name = device.attributes['device_name']
|
|
42
|
+
device_hash[device_name] = info
|
|
43
|
+
|
|
44
|
+
# 按照每个cmd解析XML
|
|
45
|
+
device.elements.each do |cmd|
|
|
46
|
+
i = {}
|
|
47
|
+
ch = cmd.name
|
|
48
|
+
cmd_name = cmd.attributes['cmd']
|
|
49
|
+
# 当同一个cmd有两个symbol时
|
|
50
|
+
if info[cmd_name].nil?
|
|
51
|
+
info[cmd_name] = {ch.to_sym => i}
|
|
52
|
+
else
|
|
53
|
+
info[cmd_name][ch.to_sym] = i
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# 进度条
|
|
57
|
+
progress_bar(total, index, device_name)
|
|
58
|
+
|
|
59
|
+
# 还有一种情况是当<attr cmd='show' val='var'/>
|
|
60
|
+
# 此时就可以直接将val填入
|
|
61
|
+
attr_val = cmd.attributes['val']
|
|
62
|
+
attr_val ? info[cmd_name][ch.to_sym] = attr_val : to_h(cmd, i)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
clear_line
|
|
67
|
+
return device_hash
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def to_h(xml, hash)
|
|
71
|
+
xml.elements.each do |e|
|
|
72
|
+
if e.has_elements?
|
|
73
|
+
son = {}
|
|
74
|
+
hash[convert(e.name)] = son
|
|
75
|
+
to_h(e, son)
|
|
76
|
+
else
|
|
77
|
+
hash[convert(e.name)] = e.attributes['val']
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# 转换恢复会出错字符串
|
|
83
|
+
def convert(e)
|
|
84
|
+
#/__/.match(e) ? e.gsub!('__', '/').to_sym : e.to_sym
|
|
85
|
+
e.gsub!('__', '/') if /__/.match(e)
|
|
86
|
+
e.gsub!(/^_i/, '') if /^_i/.match(e)
|
|
87
|
+
e.to_sym
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
#coding=utf-8
|
|
2
|
+
|
|
3
|
+
require "aio/core"
|
|
4
|
+
|
|
5
|
+
class Aio::Module::InputStyle::Console < Aio::Module::InputStyle
|
|
6
|
+
include Aio::Module
|
|
7
|
+
include Aio::Ui::Verbose
|
|
8
|
+
|
|
9
|
+
class Machine
|
|
10
|
+
|
|
11
|
+
attr_accessor :regs, :state
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@cmd_state = CmdState.new(self)
|
|
15
|
+
@context_state = ContextState.new(self)
|
|
16
|
+
@empty_state = EmptyState.new(self)
|
|
17
|
+
@cmd_context = CmdContext.new
|
|
18
|
+
|
|
19
|
+
@state = @empty_state
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def state
|
|
23
|
+
@state.class
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def cmd_context
|
|
27
|
+
@cmd_context
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_cmd_state
|
|
31
|
+
@state = @cmd_state
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_context_state
|
|
35
|
+
@state = @context_state
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_empty_state
|
|
39
|
+
@state = @empty_state
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def parse_line(line)
|
|
43
|
+
@state.parse_line(line)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class CmdContext
|
|
48
|
+
|
|
49
|
+
attr_accessor :device_name, :cmd, :context
|
|
50
|
+
|
|
51
|
+
# all_info = [[device_name, cmd, context] ... ]
|
|
52
|
+
attr_accessor :all_info
|
|
53
|
+
|
|
54
|
+
def initialize
|
|
55
|
+
@device_name = ""
|
|
56
|
+
@cmd = ""
|
|
57
|
+
@context = []
|
|
58
|
+
@all_info = []
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def done
|
|
62
|
+
# 当之前有cmd内容的时候,比较两个的长度
|
|
63
|
+
# 长的保留
|
|
64
|
+
info_idx = has_cmd?
|
|
65
|
+
if info_idx
|
|
66
|
+
if @all_info[info_idx][2].size < context.size
|
|
67
|
+
@all_info[info_idx][2] = context
|
|
68
|
+
end
|
|
69
|
+
else
|
|
70
|
+
|
|
71
|
+
# 如果都没有,那么就直接添加
|
|
72
|
+
@all_info << [device_name, cmd, context]
|
|
73
|
+
end
|
|
74
|
+
self.clear
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def has_cmd?
|
|
78
|
+
@all_info.each_with_index do |info, idx|
|
|
79
|
+
next unless info[1] == device_name
|
|
80
|
+
return idx if info[2] == cmd
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
return nil
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def clear
|
|
87
|
+
@device_name = ""
|
|
88
|
+
@cmd = ""
|
|
89
|
+
@context = []
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
class State
|
|
94
|
+
|
|
95
|
+
include Aio::Ui::Verbose
|
|
96
|
+
|
|
97
|
+
def initialize(machine)
|
|
98
|
+
@machine = machine
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def cmd_context
|
|
102
|
+
@machine.cmd_context
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
class EmptyState < State
|
|
107
|
+
def parse_line(line)
|
|
108
|
+
|
|
109
|
+
# 当前是空的状态
|
|
110
|
+
# 判断当前行有没有模块中的命令
|
|
111
|
+
line = Aio::Base::Toolkit::String.safe(line)
|
|
112
|
+
return unless @machine.regs.match(line)
|
|
113
|
+
|
|
114
|
+
@machine.to_cmd_state
|
|
115
|
+
@machine.parse_line(line)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
class CmdState < State
|
|
120
|
+
def parse_line(line)
|
|
121
|
+
# 判断是不是cmd命令行
|
|
122
|
+
res = /^[\[|<]?(?<name>.*)(#|>|\])(?<cmd>.*)/.match(line)
|
|
123
|
+
if res.nil?
|
|
124
|
+
@machine.to_empty_state
|
|
125
|
+
return
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# 当已经发现了是cmd行,那么紧接下来就是收集文本内容
|
|
129
|
+
cmd_context.device_name = res[:name]
|
|
130
|
+
cmd_context.cmd = res[:cmd]
|
|
131
|
+
@machine.to_context_state
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
class ContextState < State
|
|
136
|
+
|
|
137
|
+
def parse_line(line)
|
|
138
|
+
# 如果这行是命令行格式,那么就代表上一个cmd内容结束
|
|
139
|
+
tmp_reg = ::Regexp.new "^[\\[|<]?#{cmd_context.device_name}(#|>|\\])"
|
|
140
|
+
|
|
141
|
+
# 可能会出现UTF-8识别不出摄氏度符号的问题
|
|
142
|
+
# 已经通过安全字符解决
|
|
143
|
+
begin
|
|
144
|
+
if tmp_reg.match(line)
|
|
145
|
+
cmd_context.done
|
|
146
|
+
|
|
147
|
+
# 完成后将状态设置为空,并且重新分析这一行
|
|
148
|
+
# 毕竟如果这行也cmd行呢
|
|
149
|
+
@machine.to_empty_state
|
|
150
|
+
return @machine.parse_line(line)
|
|
151
|
+
end
|
|
152
|
+
rescue => e
|
|
153
|
+
print_error cmd_context.device_name + " 设备巡检信息编码出现问题"
|
|
154
|
+
print_error line + " : " + e.message
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
cmd_context.context << line
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def initialize
|
|
163
|
+
super({
|
|
164
|
+
:author => "Elin",
|
|
165
|
+
:description => "这个模块用于对命令行格式的输入处理",
|
|
166
|
+
:platform => "all",
|
|
167
|
+
})
|
|
168
|
+
@machine = Machine.new
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def parse
|
|
172
|
+
dir = self.input_file
|
|
173
|
+
dir_pn = Pathname.new(dir)
|
|
174
|
+
|
|
175
|
+
# 加载所有的cmd正则表达式
|
|
176
|
+
@machine.regs = merge_regs(ext_info[:cmds_reg])
|
|
177
|
+
|
|
178
|
+
# 如果是单个文件的话,直接进入文件解析模式
|
|
179
|
+
if dir_pn.file?
|
|
180
|
+
parse_file(dir_pn)
|
|
181
|
+
else
|
|
182
|
+
|
|
183
|
+
# 如果是文件夹的话,那么就对每个文件进行解析
|
|
184
|
+
Find.find(dir) do |file|
|
|
185
|
+
fn = Pathname.new(file)
|
|
186
|
+
parse_file(file) if fn.file?
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
@machine.cmd_context.all_info.each do |info|
|
|
191
|
+
yield info[0], info[1], info[2]
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def parse_file(file)
|
|
196
|
+
fo = File.open(file, "r+", :encoding => "utf-8")
|
|
197
|
+
|
|
198
|
+
fo.each_line do |line|
|
|
199
|
+
begin
|
|
200
|
+
line = Aio::Base::Toolkit::String.safe(line)
|
|
201
|
+
line = line.strip
|
|
202
|
+
rescue => e
|
|
203
|
+
print_error line + " : " + e.message
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
@machine.parse_line(line)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# 如果最后没有done结束,则手动结束
|
|
210
|
+
if @machine.state == ContextState
|
|
211
|
+
@machine.cmd_context.done
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def merge_regs(arr_regs)
|
|
216
|
+
regs = Aio::Base::Toolkit::Regexp.merge(arr_regs).to_s
|
|
217
|
+
regs.gsub!('(^', '(')
|
|
218
|
+
::Regexp.new(regs)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#coding=utf-8
|
|
2
|
+
|
|
3
|
+
require "aio/core"
|
|
4
|
+
|
|
5
|
+
class Aio::Module::InputStyle::Console < Aio::Module::InputStyle
|
|
6
|
+
include Aio::Module
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
super({
|
|
10
|
+
:author => "Elin",
|
|
11
|
+
:description => "这个模块用于对命令行格式的输入处理",
|
|
12
|
+
:platform => "all",
|
|
13
|
+
})
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def parse(&block)
|
|
17
|
+
dir = self.input_file
|
|
18
|
+
dir_pn = Pathname.new(dir)
|
|
19
|
+
|
|
20
|
+
# 如果是单个文件的话,直接进入文件解析模式
|
|
21
|
+
if dir_pn.file?
|
|
22
|
+
parse_file(file) do |info1, info2, info3, info4|
|
|
23
|
+
block.call(info1, info2, info3, info4)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# 如果是文件夹的话,那么就对每个文件进行解析
|
|
28
|
+
Find.find(dir) do |file|
|
|
29
|
+
fn = Pathname.new(file)
|
|
30
|
+
if fn.file?
|
|
31
|
+
parse_file(file) do |info1, info2, info3, info4|
|
|
32
|
+
block.call(info1, info2, info3, info4)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def parse_file(file)
|
|
39
|
+
fo = File.open(file)
|
|
40
|
+
regs = merge_regs(ext_info[:cmds_reg])
|
|
41
|
+
|
|
42
|
+
cmd = ""
|
|
43
|
+
context = []
|
|
44
|
+
device_name = ""
|
|
45
|
+
last_device_name = ""
|
|
46
|
+
# all_info = {cmd => [device_name, context]}
|
|
47
|
+
all_info = {}
|
|
48
|
+
|
|
49
|
+
fo_context = fo.each_line.to_a
|
|
50
|
+
fo_size = fo_context.size
|
|
51
|
+
fo_context.each_with_index do |line, idx|
|
|
52
|
+
line = line.strip
|
|
53
|
+
|
|
54
|
+
# 如果不是命令行,首先看下有有没有等待命令
|
|
55
|
+
# 如果有则将后续信息方法context中
|
|
56
|
+
unless regs.match(line)
|
|
57
|
+
|
|
58
|
+
# 只有当有设备名的时候才进行判断
|
|
59
|
+
if ! device_name.empty?
|
|
60
|
+
tmp_reg = ::Regexp.new "^[\\[|<]?#{device_name}(#|>|\\])"
|
|
61
|
+
# 保证是输入命令的line,而不是其他形式
|
|
62
|
+
if tmp_reg.match(line)
|
|
63
|
+
last_device_name = device_name
|
|
64
|
+
device_name = ""
|
|
65
|
+
else # 其他形式则作为文本输出
|
|
66
|
+
context << line if not cmd.empty?
|
|
67
|
+
if idx == fo_size and ! cmd.empty?
|
|
68
|
+
all_info[cmd] = [last_device_name, context]
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
next
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# 匹配devicename# cmd 的模式
|
|
77
|
+
res = /^[\[|<]?(?<name>.*)(#|>|\])(?<cmd>.*)/.match(line)
|
|
78
|
+
next if res.nil?
|
|
79
|
+
|
|
80
|
+
# 到这里的是line信息中包含了cmd信息以及设备名信息
|
|
81
|
+
if not cmd.empty? and not context.empty?
|
|
82
|
+
# 有一种情况是如果之前有了cmd,后面又出现同样的cmd
|
|
83
|
+
# 那么比较两个cmd的内容,内容行数多的保留
|
|
84
|
+
# 感觉有问题,会少一个cmd
|
|
85
|
+
if all_info.has_key?(cmd)
|
|
86
|
+
if all_info[cmd][1].size > context.size
|
|
87
|
+
device_name = ""
|
|
88
|
+
cmd = ""
|
|
89
|
+
context = []
|
|
90
|
+
next
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
all_info[cmd] = [last_device_name, context]
|
|
94
|
+
device_name = ""
|
|
95
|
+
cmd = ""
|
|
96
|
+
context = []
|
|
97
|
+
end
|
|
98
|
+
device_name = res[:name]
|
|
99
|
+
cmd = res[:cmd]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
all_info.each_pair do |cmd, info|
|
|
103
|
+
yield info[0], cmd, info[1], ""
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def merge_regs(arr_regs)
|
|
108
|
+
regs = Aio::Base::Toolkit::Regexp.merge(arr_regs).to_s
|
|
109
|
+
regs.gsub!('(^', '(')
|
|
110
|
+
::Regexp.new(regs)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#coding=utf-8
|
|
2
|
+
|
|
3
|
+
require "aio/core"
|
|
4
|
+
|
|
5
|
+
class Aio::Module::InputStyle::XinhuaNat < Aio::Module::InputStyle
|
|
6
|
+
include Aio::Module
|
|
7
|
+
|
|
8
|
+
Xinhua_Routing = /^------------------------------------------------------------$/
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
super({
|
|
12
|
+
:author => "Elin",
|
|
13
|
+
:description => "这个模块专门针对中行网络标准化管理NAT软件",
|
|
14
|
+
:platform => "ausware",
|
|
15
|
+
:file_suffix => Regexp.new('\.diag$'),
|
|
16
|
+
:pass_file => [
|
|
17
|
+
Regexp.new('RoutingTable.*'),
|
|
18
|
+
Regexp.new('路由状态'),
|
|
19
|
+
]
|
|
20
|
+
})
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def parse
|
|
24
|
+
# dir 为 Pathname 类
|
|
25
|
+
dir = self.input_file
|
|
26
|
+
|
|
27
|
+
# 分析第一层: 文件夹名称包含设备名称+管理IP
|
|
28
|
+
::Dir.foreach(dir) do |device_layer|
|
|
29
|
+
if device_layer.downcase == "." or device_layer.downcase == ".."
|
|
30
|
+
next
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
tmp = []
|
|
34
|
+
device_layer.reverse.split('_', 2).each do |res|
|
|
35
|
+
tmp << res.reverse
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
manager_ip = tmp[0]
|
|
39
|
+
device_name = tmp[1]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# 分析第二层:文件后缀为.diag,此外还有个HSRP文件夹,但是可有一次搞定
|
|
43
|
+
Find.find(File.join(dir, device_layer)) do |context_layer|
|
|
44
|
+
|
|
45
|
+
# 如果文件后缀名不是.diag则跳过
|
|
46
|
+
if ! self.file_suffix?(context_layer)
|
|
47
|
+
next
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# 检查是否是需要略过的文件
|
|
51
|
+
if self.pass_file?(context_layer)
|
|
52
|
+
next
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
fo = File.open(context_layer, "r+", :encoding => "utf-8")
|
|
56
|
+
context = fo.each_line.to_a
|
|
57
|
+
|
|
58
|
+
# 分割输出,在路由状态中会有这种情况
|
|
59
|
+
split(context, Xinhua_Routing).each do |cont|
|
|
60
|
+
cmd = cont.shift.strip
|
|
61
|
+
yield device_name, cmd, cont, manager_ip
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def split(array, pattern)
|
|
68
|
+
Aio::Base::Toolkit::Array.split(array, pattern)
|
|
69
|
+
end
|
|
70
|
+
end
|