aio_elin 0.0.1 → 1.0.0

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.
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
+