aio_elin 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/config.rb +32 -32
  3. data/lib/aio/base/toolkit/excel_wps.rb +1 -0
  4. data/lib/aio/base/toolkit/hash.rb +95 -0
  5. data/lib/aio/base/toolkit/myers.rb +161 -0
  6. data/lib/aio/base/toolkit.rb +2 -0
  7. data/lib/aio/core/device/cmd_switch.rb +1 -1
  8. data/lib/aio/core/device/h3c.rb +2 -0
  9. data/lib/aio/core/device/maipu.rb +8 -0
  10. data/lib/aio/core/device/methods.rb +230 -228
  11. data/lib/aio/core/device/parent_device.rb +270 -267
  12. data/lib/aio/core/device_manager.rb +255 -202
  13. data/lib/aio/core/module/cmd.rb +155 -150
  14. data/lib/aio/core/module/compare.rb +39 -0
  15. data/lib/aio/core/module/output_style.rb +2 -0
  16. data/lib/aio/core/module.rb +1 -0
  17. data/lib/aio/core/module_loader.rb +11 -0
  18. data/lib/aio/core/parse/file.rb +12 -14
  19. data/lib/aio/core/parse/parser.rb +99 -87
  20. data/lib/aio/core/parse/parser_machine/has_device_state.rb +42 -42
  21. data/lib/aio/core/parse/parser_machine.rb +44 -44
  22. data/lib/aio/core/text/block.rb +88 -0
  23. data/lib/aio/core/text/compare.rb +109 -0
  24. data/lib/aio/core/text/context.rb +206 -206
  25. data/lib/aio/core/text/line_string.rb +17 -62
  26. data/lib/aio/core/text/match_string_info.rb +73 -0
  27. data/lib/aio/core/text/warning.rb +175 -175
  28. data/lib/aio/core/text.rb +3 -0
  29. data/lib/aio/core/warning/warning_summarize.rb +246 -229
  30. data/lib/aio/core.rb +3 -0
  31. data/lib/aio/ui/logger.rb +38 -0
  32. data/lib/aio/ui/verbose.rb +6 -2
  33. data/lib/aio/ui.rb +135 -134
  34. data/lib/modules/cmd/cisco/show_version.rb +84 -84
  35. data/lib/modules/cmd/h3c/display_cpu.rb +41 -41
  36. data/lib/modules/cmd/h3c/display_version.rb +43 -43
  37. data/lib/modules/cmd/maipu/show_clock.rb +32 -0
  38. data/lib/modules/cmd/maipu/show_cpu.rb +36 -0
  39. data/lib/modules/cmd/maipu/show_ip_interface_brief.rb +44 -0
  40. data/lib/modules/cmd/maipu/show_memory.rb +22 -22
  41. data/lib/modules/cmd/maipu/show_version.rb +40 -40
  42. data/lib/modules/input/style/compare_xml.rb +73 -73
  43. data/lib/modules/output/style/cmds.rb +3 -3
  44. data/lib/modules/output/style/compare_diff.rb +23 -0
  45. data/lib/modules/output/style/excel_table_office.rb +1 -0
  46. data/lib/modules/output/style/excel_table_wps.rb +1 -0
  47. data/lib/modules/output/style/summary_report.rb +2 -1
  48. data/lib/modules/special/style/compare.rb +153 -103
  49. data/lib/modules/special/style/compare_old.rb +121 -0
  50. data/lib/modules/special/style/compare_with_device_manager.rb +227 -0
  51. metadata +16 -3
@@ -1,275 +1,278 @@
1
1
  #coding=utf-8
2
2
 
3
3
  module Aio::Device
4
- class ParentDevice
5
-
6
- include Aio::Ui::Verbose
7
-
8
- attr_accessor :device_name
9
-
10
- # cmds_context = { "cmd_full_name" => [ {
11
- # device_type_1 => klass1,
12
- # device_type_2 => klass2},
13
- # context ] }
14
- attr_accessor :cmds_context
15
-
16
- # 管理IP
17
- attr_accessor :manager_ip
18
-
19
- # 设备的基本信息
20
- attr_accessor :device_info
21
-
22
- # 按cmd名称管理有用信息
23
- # Hash = { cmd_name => { :case => useful } }
24
- attr_accessor :cmds_useful
25
-
26
- # Warning信息模块
27
- attr_accessor :warning_klass
28
-
29
- # 设备类型
30
- #attr_reader :device_type
31
-
32
- InvalidInput = /Invalid input detected/
33
-
34
- Interface = {
35
- :geth => "GigabitEthernet",
36
- :feth => "FastEthernet",
37
- :eth => "Ethernet",
38
- :loopback => "Loopback",
39
- }
40
-
41
- def interface
42
- Interface
43
- end
44
-
45
- def initialize
46
- self.cmds_context = {}
47
- self.device_name = ""
48
- self.cmds_useful = {}
49
-
50
- @warning_klass = Aio::Text::Warning.new
51
- @device_type = ""
52
- @device_info = {}
53
- end
54
-
55
- def instance
56
- self
57
- end
58
-
59
- def inspect
60
- "#<#{self.class}>"
61
- end
62
-
63
- def device_type
64
- if @device_type.empty?
65
- return "other"
66
- end
67
-
68
- @device_type
69
- end
70
-
71
- # 判断是否有cmd的信息
72
- def has_cmd?(cmd)
73
- @cmds_useful.has_key?(cmd)
74
- end
75
-
76
- # 增加cmd
77
- # @Param klass_info 为Array
78
- # klass_info = ["maybe_device_type", cmd_klass]
79
- def add_cmd(klass_info)
80
- maybe_device_type = klass_info[0]
81
- cmd_klass = klass_info[1]
82
-
83
- cmd_full_name = cmd_klass.cmd_full
84
-
85
- # 有可能已经有了其他设备类型的模块
86
- # 那么通过Hash的方式存储所有的模块
87
- cmds_context[cmd_full_name] ||= []
88
- cmds_context[cmd_full_name][0] ||= {}
89
- cmds_context[cmd_full_name][0][maybe_device_type] = cmd_klass
90
- return cmd_full_name
91
- end
92
-
93
- # 两种用法:
94
- # 在有klass的时候可以添加为完整cmds_context
95
- # 当没有klass的话,也可以加。那么klass项为nil
96
- def add_cmd_context_by_cmd_name(cmd_full_name, context)
97
- cmds_context[cmd_full_name] ||= []
98
- cmds_context[cmd_full_name][1] = context
99
- end
100
-
101
- # 整合上面两个方法,成为一步
102
- def add_cmd_context_by_klass(klass_info, context)
103
- cmd_full_name = add_cmd(klass_info)
104
- add_cmd_context_by_cmd_name(cmd_full_name, context)
105
- return cmds_context[cmd_full_name]
106
- end
107
-
108
- # 最终解析的地方
109
- # 一定要确定设备类型,否则的话只能单一设备
110
- # cmds_context = { cmd_name => [ {
111
- # device_type_1 => klass1,
112
- # device_type_2 => klass2},
113
- # context ] }
114
- def parse
115
-
116
- # 做两次循环,第一次确定设备类型
117
- 2.times do |t|
118
- cmds_context.each_pair do |cmd_name, info|
119
- context = info[1]
120
-
121
- # 如果没有cmd模块, 那么就跳过
122
- next if info[0].nil?
123
-
124
- info[0].each_pair do |device_type, module_klass|
125
-
126
- #module_klass.clear_useful
127
-
128
- # 如果找到了设备类型
129
- # 那么之后就只对该类型进行解析,其他的跳过
130
- if ! @device_type.empty? and @device_type != device_type
131
- next
132
- end
133
-
134
- module_klass.context = context
135
- module_klass.warning_klass = @warning_klass
136
-
137
- # 循环模块对内容进行解析
138
- # 当是第一遍遍历的时候,只找可以决定是什么设备类型的命令
139
- # 一般都是通过show version 这类命令找到, 那么同时也能找到设备型号和软件版本
140
- if t == 0 and not module_klass.key_stand
141
- next
142
-
143
- elsif t == 0 and module_klass.key_stand
144
- module_klass.parse
145
- push_device_info(module_klass)
146
-
147
- module_klass.clear_useful
148
- # 当device_type 有内容时,确定为已知设备类型,那么进行下次循环遍历
149
- if @device_type.empty?
150
- next
151
- else
152
- @warning_klass.clear
153
- break
154
- end
155
- end
156
-
157
- begin
158
- # 当是第二遍的时候,则全部解析
159
- module_klass.clear_useful
160
- module_klass.device_info = device_info
161
- module_klass.ext_info = {:device_name => @device_name}
162
- module_klass.parse
163
- rescue Aio::Text::Context::OutLineError
164
- rescue NoMethodError
165
- print_error "未找到方法,请检查模块的方法名拼写"
166
- rescue Exception => e
167
- print_error "#{e.class} : #{module_klass.class}"
168
- print_error e.message
169
- ensure
170
- push_useful(module_klass, cmd_name)
171
- next
172
- end
173
- end
174
- end
175
- end
176
-
177
- # 当所有解析循环完成后,如果找到了设备类型
178
- # 就将此类转为对应子类
179
- # changeto
180
- if ! @device_type.empty?
181
- to = self.send("changeto_#{@device_type}")
182
- end
183
-
184
- return to ? to : self
185
- end
186
-
187
- # 存放设备基本信息
188
- def push_device_info(module_klass)
189
- @device_type = module_klass.useful[:device_type].to_s
190
- @device_info[:device_model] = module_klass.useful[:device_model].to_s
191
- @device_info[:device_version] = module_klass.useful[:device_version].to_s
192
- @device_info[:device_template] = module_klass.useful[:device_template].to_s
193
- end
194
-
195
- # 当一个模块解析完毕后,将有用信息放入cmds_useful
196
- # 当有用信息中device_type类为真时,
197
- # 就可以将此父类转变为具体的类型了
198
- # check
199
- def push_useful(module_klass, cmd_name)
200
-
201
- if Aio::Base::Debug.enable?
202
- puts "parent_device#push_useful"
203
- pp module_klass
204
- end
205
-
206
- # 将有用信息放入整体有用信息
207
- cmds_useful[cmd_name] = module_klass.useful
208
- end
4
+ class ParentDevice
5
+
6
+ include Aio::Ui::Verbose
7
+
8
+ attr_accessor :device_name
9
+
10
+ # cmds_context = { "cmd_full_name" => [ {
11
+ # device_type_1 => klass1,
12
+ # device_type_2 => klass2},
13
+ # context ] }
14
+ attr_accessor :cmds_context
15
+
16
+ # 管理IP
17
+ attr_accessor :manager_ip
18
+
19
+ # 设备的基本信息
20
+ attr_accessor :device_info
21
+
22
+ # 按cmd名称管理有用信息
23
+ # Hash = { cmd_name => { :case => useful } }
24
+ attr_accessor :cmds_useful
25
+
26
+ # Warning信息模块
27
+ attr_accessor :warning_klass
28
+
29
+ # 设备类型
30
+ #attr_reader :device_type
31
+
32
+ InvalidInput = /Invalid input detected/
33
+
34
+ Interface = {
35
+ geth: "GigabitEthernet",
36
+ feth: "FastEthernet",
37
+ eth: "Ethernet",
38
+ loopback: "Loopback",
39
+ vlan_if: "Vlan-interface"
40
+ }
41
+
42
+ # FIXME 无法获得正确的父类Interface
43
+ def interface
44
+ self.class::Interface
45
+ end
46
+
47
+ def initialize
48
+ self.cmds_context = {}
49
+ self.device_name = ""
50
+ self.cmds_useful = {}
51
+
52
+ @warning_klass = Aio::Text::Warning.new
53
+ @device_type = ""
54
+ @device_info = {}
55
+ end
56
+
57
+ def instance
58
+ self
59
+ end
60
+
61
+ def inspect
62
+ "#<#{self.class}>"
63
+ end
64
+
65
+ def device_type
66
+ if @device_type.empty?
67
+ return "other"
68
+ end
69
+
70
+ @device_type
71
+ end
72
+
73
+ # 判断是否有cmd的信息
74
+ def has_cmd?(cmd)
75
+ @cmds_useful.has_key?(cmd)
76
+ end
77
+
78
+ # 增加cmd
79
+ # @Param klass_info 为Array
80
+ # klass_info = ["maybe_device_type", cmd_klass]
81
+ def add_cmd(klass_info)
82
+ maybe_device_type = klass_info[0]
83
+ cmd_klass = klass_info[1]
84
+
85
+ cmd_full_name = cmd_klass.cmd_full
86
+
87
+ # 有可能已经有了其他设备类型的模块
88
+ # 那么通过Hash的方式存储所有的模块
89
+ cmds_context[cmd_full_name] ||= []
90
+ cmds_context[cmd_full_name][0] ||= {}
91
+ cmds_context[cmd_full_name][0][maybe_device_type] = cmd_klass
92
+ return cmd_full_name
93
+ end
94
+
95
+ # 两种用法:
96
+ # 在有klass的时候可以添加为完整cmds_context
97
+ # 当没有klass的话,也可以加。那么klass项为nil
98
+ def add_cmd_context_by_cmd_name(cmd_full_name, context)
99
+ cmds_context[cmd_full_name] ||= []
100
+ cmds_context[cmd_full_name][1] = context
101
+ end
102
+
103
+ # 整合上面两个方法,成为一步
104
+ def add_cmd_context_by_klass(klass_info, context)
105
+ cmd_full_name = add_cmd(klass_info)
106
+ add_cmd_context_by_cmd_name(cmd_full_name, context)
107
+ return cmds_context[cmd_full_name]
108
+ end
109
+
110
+ # 最终解析的地方
111
+ # 一定要确定设备类型,否则的话只能单一设备
112
+ # cmds_context = { cmd_name => [ {
113
+ # device_type_1 => klass1,
114
+ # device_type_2 => klass2},
115
+ # context ] }
116
+ def parse
117
+
118
+ # 做两次循环,第一次确定设备类型
119
+ 2.times do |t|
120
+ cmds_context.each_pair do |cmd_name, info|
121
+ context = info[1]
122
+
123
+ # 如果没有cmd模块, 那么就跳过
124
+ next if info[0].nil?
125
+
126
+ info[0].each_pair do |device_type, module_klass|
127
+
128
+ #module_klass.clear_useful
129
+
130
+ # 如果找到了设备类型
131
+ # 那么之后就只对该类型进行解析,其他的跳过
132
+ if ! @device_type.empty? and @device_type != device_type
133
+ next
134
+ end
135
+
136
+ module_klass.context = context
137
+ module_klass.warning_klass = @warning_klass
138
+
139
+ # 循环模块对内容进行解析
140
+ # 当是第一遍遍历的时候,只找可以决定是什么设备类型的命令
141
+ # 一般都是通过show version 这类命令找到, 那么同时也能找到设备型号和软件版本
142
+ if t == 0 and not module_klass.key_stand
143
+ next
144
+
145
+ elsif t == 0 and module_klass.key_stand
146
+ module_klass.parse
147
+ push_device_info(module_klass)
148
+
149
+ module_klass.clear_useful
150
+ # 当device_type 有内容时,确定为已知设备类型,那么进行下次循环遍历
151
+ if @device_type.empty?
152
+ next
153
+ else
154
+ @warning_klass.clear
155
+ break
156
+ end
157
+ end
158
+
159
+ begin
160
+ # 当是第二遍的时候,则全部解析
161
+ module_klass.clear_useful
162
+ module_klass.device_info = device_info
163
+ module_klass.ext_info = {:device_name => @device_name}
164
+ module_klass.parse
165
+ rescue Aio::Text::Context::OutLineError
166
+ rescue NoMethodError
167
+ print_error "未找到方法,请检查模块的方法名拼写"
168
+ rescue Exception => e
169
+ print_error "#{e.class} : #{module_klass.class}"
170
+ print_error e.message
171
+ ensure
172
+ push_useful(module_klass, cmd_name)
173
+ next
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ # 当所有解析循环完成后,如果找到了设备类型
180
+ # 就将此类转为对应子类
181
+ # changeto
182
+ if ! @device_type.empty?
183
+ to = self.send("changeto_#{@device_type}")
184
+ end
185
+
186
+ return to ? to : self
187
+ end
188
+
189
+ # 存放设备基本信息
190
+ def push_device_info(module_klass)
191
+ @device_type = module_klass.useful[:device_type].to_s
192
+ @device_info[:device_model] = module_klass.useful[:device_model].to_s
193
+ @device_info[:device_version] = module_klass.useful[:device_version].to_s
194
+ @device_info[:device_template] = module_klass.useful[:device_template].to_s
195
+ end
196
+
197
+ # 当一个模块解析完毕后,将有用信息放入cmds_useful
198
+ # 当有用信息中device_type类为真时,
199
+ # 就可以将此父类转变为具体的类型了
200
+ # check
201
+ def push_useful(module_klass, cmd_name)
202
+
203
+ if Aio::Base::Debug.enable?
204
+ puts "parent_device#push_useful"
205
+ pp module_klass
206
+ end
207
+
208
+ # 将有用信息放入整体有用信息
209
+ cmds_useful[cmd_name] = module_klass.useful
210
+ end
209
211
 
210
212
  =begin
211
- def warning_info
212
- warning_klass.warning_info
213
- end
214
-
215
- def warning_info_serious
216
- warning_klass.warning_info_serious
217
- end
218
-
219
- def warning_info_ordinary
220
- warning_klass.warning_info_ordinary
221
- end
222
-
223
- def warning_info_compare
224
- warning_klass.warning_info_compare
225
- end
213
+ # 通过 method_missing, 注释掉的命令可以直接使用
214
+ def warning_info
215
+ warning_klass.warning_info
216
+ end
217
+
218
+ def warning_info_serious
219
+ warning_klass.warning_info_serious
220
+ end
221
+
222
+ def warning_info_ordinary
223
+ warning_klass.warning_info_ordinary
224
+ end
225
+
226
+ def warning_info_compare
227
+ warning_klass.warning_info_compare
228
+ end
226
229
  =end
227
230
 
228
- # 1.导向命令方法模块
229
- # 2.导向Warning类
230
- def method_missing(m, *args, &block)
231
- if Aio::Device::Methods.respond_to?(m)
232
- Aio::Device::Methods.klass = self
233
- Aio::Device::Methods.send(m)
234
-
235
- elsif Aio::Text::Warning.instance_methods(false).include?(m.to_sym)
236
- warning_klass.send(m, *args)
237
- else
238
- super
239
- end
240
- end
241
-
242
- private
243
-
244
- def changeto_cisco
245
- to = Cisco.new
246
- clone(to)
247
- end
248
-
249
- def changeto_huawei
250
- to = Huawei.new
251
- clone(to)
252
- end
253
-
254
- def changeto_maipu
255
- to = Maipu.new
256
- clone(to)
257
- end
258
-
259
- def changeto_h3c
260
- to = H3C.new
261
- clone(to)
262
- end
263
-
264
- def clone(to)
265
- to.device_name = Aio::Base::Toolkit::DeepClone.clone(self.device_name)
266
- to.cmds_context = Aio::Base::Toolkit::DeepClone.clone(self.cmds_context)
267
- to.manager_ip = Aio::Base::Toolkit::DeepClone.clone(self.manager_ip)
268
- to.device_info = Aio::Base::Toolkit::DeepClone.clone(self.device_info)
269
- to.cmds_useful = Aio::Base::Toolkit::DeepClone.clone(self.cmds_useful)
270
- to.warning_klass = Aio::Base::Toolkit::DeepClone.clone(self.warning_klass)
271
- to
272
- end
273
- end
231
+ # 1.导向命令方法模块
232
+ # 2.导向Warning类
233
+ def method_missing(m, *args, &block)
234
+ if Aio::Device::Methods.respond_to?(m)
235
+ Aio::Device::Methods.klass = self
236
+ Aio::Device::Methods.send(m)
237
+
238
+ elsif Aio::Text::Warning.instance_methods(false).include?(m.to_sym)
239
+ warning_klass.send(m, *args)
240
+ else
241
+ super
242
+ end
243
+ end
244
+
245
+ private
246
+
247
+ def changeto_cisco
248
+ to = Cisco.new
249
+ clone(to)
250
+ end
251
+
252
+ def changeto_huawei
253
+ to = Huawei.new
254
+ clone(to)
255
+ end
256
+
257
+ def changeto_maipu
258
+ to = Maipu.new
259
+ clone(to)
260
+ end
261
+
262
+ def changeto_h3c
263
+ to = H3C.new
264
+ clone(to)
265
+ end
266
+
267
+ def clone(to)
268
+ to.device_name = Aio::Base::Toolkit::DeepClone.clone(self.device_name)
269
+ to.cmds_context = Aio::Base::Toolkit::DeepClone.clone(self.cmds_context)
270
+ to.manager_ip = Aio::Base::Toolkit::DeepClone.clone(self.manager_ip)
271
+ to.device_info = Aio::Base::Toolkit::DeepClone.clone(self.device_info)
272
+ to.cmds_useful = Aio::Base::Toolkit::DeepClone.clone(self.cmds_useful)
273
+ to.warning_klass = Aio::Base::Toolkit::DeepClone.clone(self.warning_klass)
274
+ to
275
+ end
276
+ end
274
277
  end
275
-
278
+