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,28 @@
|
|
|
1
|
+
module Aio::Base::Toolkit::IPAddr
|
|
2
|
+
class << self
|
|
3
|
+
|
|
4
|
+
# 子网掩码从点分十进制转换为数值
|
|
5
|
+
# 255.255.255.0 => 24
|
|
6
|
+
def mask_dotted_to_i(mask)
|
|
7
|
+
arr = mask.split(".")
|
|
8
|
+
binary = ""
|
|
9
|
+
arr.each do |m|
|
|
10
|
+
binary << m.to_i.to_s(2)
|
|
11
|
+
end
|
|
12
|
+
return binary.scan(/1/).size
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# 子网掩码从十进制到点分十进制
|
|
16
|
+
# 24 => 255.255.255.0
|
|
17
|
+
def mask_i_to_dotted(int)
|
|
18
|
+
int = int.to_i
|
|
19
|
+
arr = [nil, nil, nil, nil]
|
|
20
|
+
binary = (2 ** int - 1) << (32 - int)
|
|
21
|
+
4.times do |t|
|
|
22
|
+
arr[3-t] = (binary & 255).to_s
|
|
23
|
+
binary = binary >> 8
|
|
24
|
+
end
|
|
25
|
+
return arr.join(".")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Aio::Base::Toolkit
|
|
2
|
+
module OS
|
|
3
|
+
class << self
|
|
4
|
+
def os_family
|
|
5
|
+
case RUBY_PLATFORM
|
|
6
|
+
when /ix/i, /ux/i, /gnu/i,
|
|
7
|
+
/sysv/i, /solaris/i,
|
|
8
|
+
/sunos/i, /bsd/i
|
|
9
|
+
"unix"
|
|
10
|
+
when /win/i, /ming/i
|
|
11
|
+
"windows"
|
|
12
|
+
else
|
|
13
|
+
"other"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def windows?
|
|
18
|
+
self.os_family == "windows" ? true : false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def linux?
|
|
22
|
+
self.os_family == "unix" ? true : false
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Aio::Base::Toolkit
|
|
2
|
+
module Regexp
|
|
3
|
+
class << self
|
|
4
|
+
def to_reg(cmd)
|
|
5
|
+
res = cmd.gsub(' ', '([^\s]*)\s+')
|
|
6
|
+
res.insert(0, '^')
|
|
7
|
+
res.insert(-1, '([^\s]*)$')
|
|
8
|
+
return ::Regexp.new(res)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def blank
|
|
12
|
+
return /^[\t]*$/
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# 产生一个安全的正则表达式
|
|
16
|
+
def safe(reg)
|
|
17
|
+
res = reg.to_s.gsub(' ', '\s+')
|
|
18
|
+
return ::Regexp.new(res)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# 将一个数组的正则表达式合并成为一个正则表达式
|
|
22
|
+
def merge(arr_regs)
|
|
23
|
+
str_arr = []
|
|
24
|
+
arr_regs.each {|x| str_arr << x.to_s}
|
|
25
|
+
new_reg = str_arr.join("|").gsub("?-mix:", "")
|
|
26
|
+
new_reg = ::Regexp.new(new_reg)
|
|
27
|
+
return new_reg
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Aio::Base::Toolkit::String
|
|
2
|
+
class << self
|
|
3
|
+
|
|
4
|
+
# 终极解决方案
|
|
5
|
+
# 遇到了 invalid byte sequence in UTF-8 (ArgumentError) 问题
|
|
6
|
+
# 解决办法参考 https://stackoverflow.com/questions/29877310/invalid-byte-sequence-in-utf-8-argumenterror
|
|
7
|
+
def safe(str)
|
|
8
|
+
case Aio::Base::Toolkit::OS.os_family
|
|
9
|
+
when "unix"
|
|
10
|
+
if ! str.valid_encoding?
|
|
11
|
+
str = str.encode("UTF-16be", :invalid=>:replace, :replace=>"?").encode('UTF-8')
|
|
12
|
+
end
|
|
13
|
+
when "windows"
|
|
14
|
+
#str = str.force_encoding("UTF-8")
|
|
15
|
+
str = str.encode("UTF-16be", :invalid=>:replace, :replace=>"?").encode('UTF-8')
|
|
16
|
+
end
|
|
17
|
+
return str
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# 改写成安全的Windows书写方式
|
|
21
|
+
def safe_path(path)
|
|
22
|
+
if Aio::Base::Toolkit::OS.windows?
|
|
23
|
+
path.gsub!("/", "\\")
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
# -*- coding: binary -*-
|
|
2
|
+
require 'ipaddr'
|
|
3
|
+
|
|
4
|
+
module Aio::Base::Toolkit
|
|
5
|
+
|
|
6
|
+
###
|
|
7
|
+
#
|
|
8
|
+
# Prints text in a tablized format. Pretty lame at the moment, but
|
|
9
|
+
# whatever.
|
|
10
|
+
# 经过修改增加了对中文字体格式的支持 by Elin
|
|
11
|
+
#
|
|
12
|
+
###
|
|
13
|
+
class Table
|
|
14
|
+
|
|
15
|
+
#
|
|
16
|
+
# Initializes a text table instance using the supplied properties. The
|
|
17
|
+
# Table class supports the following hash attributes:
|
|
18
|
+
#
|
|
19
|
+
# Header
|
|
20
|
+
#
|
|
21
|
+
# The string to display as a heading above the table. If none is
|
|
22
|
+
# specified, no header will be displayed.
|
|
23
|
+
#
|
|
24
|
+
# HeaderIndent
|
|
25
|
+
#
|
|
26
|
+
# The amount of space to indent the header. The default is zero.
|
|
27
|
+
#
|
|
28
|
+
# Columns
|
|
29
|
+
#
|
|
30
|
+
# The array of columns that will exist within the table.
|
|
31
|
+
#
|
|
32
|
+
# Rows
|
|
33
|
+
#
|
|
34
|
+
# The array of rows that will exist.
|
|
35
|
+
#
|
|
36
|
+
# Width
|
|
37
|
+
#
|
|
38
|
+
# The maximum width of the table in characters.
|
|
39
|
+
#
|
|
40
|
+
# Indent
|
|
41
|
+
#
|
|
42
|
+
# The number of characters to indent the table.
|
|
43
|
+
#
|
|
44
|
+
# CellPad
|
|
45
|
+
#
|
|
46
|
+
# The number of characters to put between each horizontal cell.
|
|
47
|
+
#
|
|
48
|
+
# Prefix
|
|
49
|
+
#
|
|
50
|
+
# The text to prefix before the table.
|
|
51
|
+
#
|
|
52
|
+
# Postfix
|
|
53
|
+
#
|
|
54
|
+
# The text to affix to the end of the table.
|
|
55
|
+
#
|
|
56
|
+
# Sortindex
|
|
57
|
+
#
|
|
58
|
+
# The column to sort the table on, -1 disables sorting.
|
|
59
|
+
#
|
|
60
|
+
def initialize(opts = {})
|
|
61
|
+
self.header = opts['Header']
|
|
62
|
+
self.headeri = opts['HeaderIndent'] || 0
|
|
63
|
+
self.columns = opts['Columns'] || []
|
|
64
|
+
# updated below if we got a "Rows" option
|
|
65
|
+
self.rows = []
|
|
66
|
+
|
|
67
|
+
self.width = opts['Width'] || 80
|
|
68
|
+
self.indent = opts['Indent'] || 0
|
|
69
|
+
self.cellpad = opts['CellPad'] || 2
|
|
70
|
+
self.prefix = opts['Prefix'] || ''
|
|
71
|
+
self.postfix = opts['Postfix'] || ''
|
|
72
|
+
self.colprops = []
|
|
73
|
+
self.scterm = /#{opts['SearchTerm']}/mi if opts['SearchTerm']
|
|
74
|
+
|
|
75
|
+
self.sort_index = opts['SortIndex'] || 0
|
|
76
|
+
self.sort_order = opts['SortOrder'] || :forward
|
|
77
|
+
|
|
78
|
+
# Default column properties
|
|
79
|
+
self.columns.length.times { |idx|
|
|
80
|
+
self.colprops[idx] = {}
|
|
81
|
+
self.colprops[idx]['MaxWidth'] = self.columns[idx].length + ch_num(self.columns[idx])
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# ensure all our internal state gets updated with the given rows by
|
|
85
|
+
# using add_row instead of just adding them to self.rows. See #3825.
|
|
86
|
+
opts['Rows'].each { |row| add_row(row) } if opts['Rows']
|
|
87
|
+
|
|
88
|
+
# Merge in options
|
|
89
|
+
if (opts['ColProps'])
|
|
90
|
+
opts['ColProps'].each_key { |col|
|
|
91
|
+
idx = self.columns.index(col)
|
|
92
|
+
|
|
93
|
+
if (idx)
|
|
94
|
+
self.colprops[idx].merge!(opts['ColProps'][col])
|
|
95
|
+
end
|
|
96
|
+
}
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
#
|
|
102
|
+
# Converts table contents to a string.
|
|
103
|
+
#
|
|
104
|
+
def to_s
|
|
105
|
+
str = prefix.dup
|
|
106
|
+
str << header_to_s || ''
|
|
107
|
+
str << columns_to_s || ''
|
|
108
|
+
str << hr_to_s || ''
|
|
109
|
+
|
|
110
|
+
sort_rows
|
|
111
|
+
rows.each { |row|
|
|
112
|
+
if (is_hr(row))
|
|
113
|
+
str << hr_to_s
|
|
114
|
+
else
|
|
115
|
+
str << row_to_s(row) if row_visible(row)
|
|
116
|
+
end
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
str << postfix
|
|
120
|
+
|
|
121
|
+
return str
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
#
|
|
125
|
+
# Converts table contents to a csv
|
|
126
|
+
#
|
|
127
|
+
def to_csv
|
|
128
|
+
str = ''
|
|
129
|
+
str << ( columns.join(",") + "\n" )
|
|
130
|
+
rows.each { |row|
|
|
131
|
+
next if is_hr(row) || !row_visible(row)
|
|
132
|
+
str << ( row.map{|x|
|
|
133
|
+
x = x.to_s
|
|
134
|
+
x.gsub(/[\r\n]/, ' ').gsub(/\s+/, ' ').gsub('"', '""')
|
|
135
|
+
}.map{|x| "\"#{x}\"" }.join(",") + "\n" )
|
|
136
|
+
}
|
|
137
|
+
str
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
#
|
|
141
|
+
#
|
|
142
|
+
# Returns the header string.
|
|
143
|
+
#
|
|
144
|
+
def header_to_s # :nodoc:
|
|
145
|
+
if (header)
|
|
146
|
+
pad = " " * headeri
|
|
147
|
+
|
|
148
|
+
return pad + header + "\n" + pad + "=" * (header.length + ch_num(header)) + "\n\n"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
return ''
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
#
|
|
155
|
+
# Prints the contents of the table.
|
|
156
|
+
#
|
|
157
|
+
def print
|
|
158
|
+
puts to_s
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
#
|
|
162
|
+
# Adds a row using the supplied fields.
|
|
163
|
+
#
|
|
164
|
+
def <<(fields)
|
|
165
|
+
add_row(fields)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
#
|
|
169
|
+
# Adds a row with the supplied fields.
|
|
170
|
+
#
|
|
171
|
+
def add_row(fields = [])
|
|
172
|
+
if fields.length != self.columns.length
|
|
173
|
+
raise RuntimeError, 'Invalid number of columns!'
|
|
174
|
+
end
|
|
175
|
+
fields.each_with_index { |field, idx|
|
|
176
|
+
# Remove whitespace and ensure String format
|
|
177
|
+
field = field.to_s.strip
|
|
178
|
+
field_length = field.to_s.length + ch_num(field.to_s)
|
|
179
|
+
if (colprops[idx]['MaxWidth'] < field_length)
|
|
180
|
+
old = colprops[idx]['MaxWidth']
|
|
181
|
+
colprops[idx]['MaxWidth'] = field_length
|
|
182
|
+
end
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
rows << fields
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def ip_cmp(a, b)
|
|
189
|
+
begin
|
|
190
|
+
a = ::IPAddr.new(a.to_s)
|
|
191
|
+
b = ::IPAddr.new(b.to_s)
|
|
192
|
+
return 1 if a.ipv6? && b.ipv4?
|
|
193
|
+
return -1 if a.ipv4? && b.ipv6?
|
|
194
|
+
a <=> b
|
|
195
|
+
rescue ::IPAddr::Error
|
|
196
|
+
nil
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
#
|
|
201
|
+
# Sorts the rows based on the supplied index of sub-arrays
|
|
202
|
+
# If the supplied index is an IPv4 address, handle it differently, but
|
|
203
|
+
# avoid actually resolving domain names.
|
|
204
|
+
#
|
|
205
|
+
def sort_rows(index = sort_index, order = sort_order)
|
|
206
|
+
return if index == -1
|
|
207
|
+
return unless rows
|
|
208
|
+
rows.sort! do |a,b|
|
|
209
|
+
if a[index].nil?
|
|
210
|
+
cmp = -1
|
|
211
|
+
elsif b[index].nil?
|
|
212
|
+
cmp = 1
|
|
213
|
+
elsif a[index] =~ /^[0-9]+$/ and b[index] =~ /^[0-9]+$/
|
|
214
|
+
cmp = a[index].to_i <=> b[index].to_i
|
|
215
|
+
elsif (cmp = ip_cmp(a[index], b[index])) != nil
|
|
216
|
+
else
|
|
217
|
+
cmp = a[index] <=> b[index] # assumes otherwise comparable.
|
|
218
|
+
end
|
|
219
|
+
cmp ||= 0
|
|
220
|
+
order == :forward ? cmp : -cmp
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
#
|
|
225
|
+
# Adds a horizontal line.
|
|
226
|
+
#
|
|
227
|
+
def add_hr
|
|
228
|
+
rows << '__hr__'
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
#
|
|
232
|
+
# Returns new sub-table with headers and rows maching column names submitted
|
|
233
|
+
#
|
|
234
|
+
#
|
|
235
|
+
# Flips table 90 degrees left
|
|
236
|
+
#
|
|
237
|
+
def drop_left
|
|
238
|
+
tbl = self.class.new(
|
|
239
|
+
'Columns' => Array.new(self.rows.count+1,' '),
|
|
240
|
+
'Header' => self.header,
|
|
241
|
+
'Indent' => self.indent)
|
|
242
|
+
(self.columns.count+1).times do |ti|
|
|
243
|
+
row = self.rows.map {|r| r[ti]}.unshift(self.columns[ti]).flatten
|
|
244
|
+
# insert our col|row break. kind of hackish
|
|
245
|
+
row[1] = "| #{row[1]}" unless row.all? {|e| e.nil? || e.empty?}
|
|
246
|
+
tbl << row
|
|
247
|
+
end
|
|
248
|
+
return tbl
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def valid_ip?(value)
|
|
252
|
+
begin
|
|
253
|
+
::IPAddr.new value
|
|
254
|
+
true
|
|
255
|
+
rescue ::IPAddr::Error
|
|
256
|
+
false
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
#
|
|
261
|
+
# Build table from CSV dump
|
|
262
|
+
#
|
|
263
|
+
def self.new_from_csv(csv)
|
|
264
|
+
# Read in or keep data, get CSV or die
|
|
265
|
+
if csv.is_a?(String)
|
|
266
|
+
csv = File.file?(csv) ? CSV.read(csv) : CSV.parse(csv)
|
|
267
|
+
end
|
|
268
|
+
# Adjust for skew
|
|
269
|
+
if csv.first == ["Keys", "Values"]
|
|
270
|
+
csv.shift # drop marker
|
|
271
|
+
cols = []
|
|
272
|
+
rows = []
|
|
273
|
+
csv.each do |row|
|
|
274
|
+
cols << row.shift
|
|
275
|
+
rows << row
|
|
276
|
+
end
|
|
277
|
+
tbl = self.new('Columns' => cols)
|
|
278
|
+
rows.in_groups_of(cols.count) {|r| tbl << r.flatten}
|
|
279
|
+
else
|
|
280
|
+
tbl = self.new('Columns' => csv.shift)
|
|
281
|
+
while !csv.empty? do
|
|
282
|
+
tbl << csv.shift
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
return tbl
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def [](*col_names)
|
|
289
|
+
tbl = self.class.new('Indent' => self.indent,
|
|
290
|
+
'Header' => self.header,
|
|
291
|
+
'Columns' => col_names)
|
|
292
|
+
indexes = []
|
|
293
|
+
|
|
294
|
+
col_names.each do |col_name|
|
|
295
|
+
index = self.columns.index(col_name)
|
|
296
|
+
raise RuntimeError, "Invalid column name #{col_name}" if index.nil?
|
|
297
|
+
indexes << index
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
self.rows.each do |old_row|
|
|
301
|
+
new_row = []
|
|
302
|
+
indexes.map {|i| new_row << old_row[i]}
|
|
303
|
+
tbl << new_row
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
return tbl
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
alias p print
|
|
311
|
+
|
|
312
|
+
attr_accessor :header, :headeri # :nodoc:
|
|
313
|
+
attr_accessor :columns, :rows, :colprops # :nodoc:
|
|
314
|
+
attr_accessor :width, :indent, :cellpad # :nodoc:
|
|
315
|
+
attr_accessor :prefix, :postfix # :nodoc:
|
|
316
|
+
attr_accessor :sort_index, :sort_order, :scterm # :nodoc:
|
|
317
|
+
|
|
318
|
+
protected
|
|
319
|
+
|
|
320
|
+
#
|
|
321
|
+
# Returns if a row should be visible or not
|
|
322
|
+
#
|
|
323
|
+
def row_visible(row)
|
|
324
|
+
return true if self.scterm.nil?
|
|
325
|
+
row_to_s(row).match(self.scterm)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
#
|
|
329
|
+
# Defaults cell widths and alignments.
|
|
330
|
+
#
|
|
331
|
+
def defaults # :nodoc:
|
|
332
|
+
self.columns.length.times { |idx|
|
|
333
|
+
}
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
#
|
|
337
|
+
# Checks to see if the row is an hr.
|
|
338
|
+
#
|
|
339
|
+
def is_hr(row) # :nodoc:
|
|
340
|
+
return ((row.kind_of?(String)) && (row == '__hr__'))
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
#
|
|
344
|
+
# Converts the columns to a string.
|
|
345
|
+
#
|
|
346
|
+
def columns_to_s # :nodoc:
|
|
347
|
+
nameline = ' ' * indent
|
|
348
|
+
barline = nameline.dup
|
|
349
|
+
last_col = nil
|
|
350
|
+
last_idx = nil
|
|
351
|
+
columns.each_with_index { |col,idx|
|
|
352
|
+
if (last_col)
|
|
353
|
+
# This produces clean to_s output without truncation
|
|
354
|
+
# Preserves full string in cells for to_csv output
|
|
355
|
+
padding = pad(' ', last_col, last_idx)
|
|
356
|
+
nameline << padding
|
|
357
|
+
remainder = padding.length - cellpad
|
|
358
|
+
remainder = 0 if remainder < 0
|
|
359
|
+
barline << (' ' * (cellpad + remainder))
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
nameline << col
|
|
363
|
+
barline << ('-' * (col.length + ch_num(col)))
|
|
364
|
+
|
|
365
|
+
last_col = col
|
|
366
|
+
last_idx = idx
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return "#{nameline}\n#{barline}"
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
#
|
|
373
|
+
# Converts an hr to a string.
|
|
374
|
+
#
|
|
375
|
+
def hr_to_s # :nodoc:
|
|
376
|
+
return "\n"
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
#
|
|
380
|
+
# Converts a row to a string.
|
|
381
|
+
#
|
|
382
|
+
def row_to_s(row) # :nodoc:
|
|
383
|
+
line = ' ' * indent
|
|
384
|
+
last_cell = nil
|
|
385
|
+
last_idx = nil
|
|
386
|
+
row.each_with_index { |cell, idx|
|
|
387
|
+
if (idx != 0)
|
|
388
|
+
line << pad(' ', last_cell.to_s, last_idx)
|
|
389
|
+
end
|
|
390
|
+
# Limit wide cells
|
|
391
|
+
if colprops[idx]['MaxChar']
|
|
392
|
+
last_cell = cell.to_s[0..colprops[idx]['MaxChar'].to_i]
|
|
393
|
+
line << last_cell
|
|
394
|
+
else
|
|
395
|
+
line << cell.to_s
|
|
396
|
+
last_cell = cell
|
|
397
|
+
end
|
|
398
|
+
last_idx = idx
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return line + "\n"
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
#
|
|
405
|
+
# Pads out with the supplied character for the remainder of the space given
|
|
406
|
+
# some text and a column index.
|
|
407
|
+
#
|
|
408
|
+
def pad(chr, buf, colidx, use_cell_pad = true) # :nodoc:
|
|
409
|
+
# Ensure we pad the minimum required amount
|
|
410
|
+
max = colprops[colidx]['MaxChar'] || colprops[colidx]['MaxWidth']
|
|
411
|
+
max = colprops[colidx]['MaxWidth'] if max.to_i > colprops[colidx]['MaxWidth'].to_i
|
|
412
|
+
encoding = buf.encoding.name
|
|
413
|
+
if not ["UTF-8", "ASCII-8BIT", "US-ASCII", "GBK"].include? encoding
|
|
414
|
+
warn '**WARNING** In file ' << __FILE__ << '::' <<\
|
|
415
|
+
__method__.to_s << ': String with unsupported encoding caught!'
|
|
416
|
+
end
|
|
417
|
+
utf8_buf = buf.dup.force_encoding("UTF-8")
|
|
418
|
+
|
|
419
|
+
utf8_buf_length = utf8_buf.size + ch_num(utf8_buf)
|
|
420
|
+
|
|
421
|
+
remainder = max - utf8_buf_length
|
|
422
|
+
remainder = 0 if remainder < 0
|
|
423
|
+
val = chr * remainder
|
|
424
|
+
|
|
425
|
+
if (use_cell_pad)
|
|
426
|
+
val << ' ' * cellpad
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
return val
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def ch_num(str)
|
|
433
|
+
s = str.dup
|
|
434
|
+
s.size-s.gsub(/[\u4e00-\u9fa5]/,'').size
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
cwd = File.expand_path(File.dirname(__FILE__))
|
|
2
|
+
load "#{cwd}/excel.rb"
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
include Aio::Base::Toolkit::Excel
|
|
6
|
+
|
|
7
|
+
excel = WorkBook.new
|
|
8
|
+
excel.show
|
|
9
|
+
worksheet = excel.add_worksheet("sheet")
|
|
10
|
+
=begin
|
|
11
|
+
worksheet.add_title("title")
|
|
12
|
+
row = worksheet.add_row
|
|
13
|
+
row << ["elin", 1]
|
|
14
|
+
row.height = 20
|
|
15
|
+
=end
|
|
16
|
+
|
|
17
|
+
worksheet.width("a", 15)
|
|
18
|
+
worksheet.width("b", 10)
|
|
19
|
+
worksheet.width("c", 15)
|
|
20
|
+
worksheet.width("d", 15)
|
|
21
|
+
worksheet.width("e", 14)
|
|
22
|
+
worksheet.width("f", 7)
|
|
23
|
+
worksheet.width("g", 12)
|
|
24
|
+
|
|
25
|
+
row = worksheet.add_row
|
|
26
|
+
row.merge("a", "g")
|
|
27
|
+
row << "湖北中行现场巡检报告"
|
|
28
|
+
row.set_style("a", "TitleStyle")
|
|
29
|
+
row = worksheet.add_row
|
|
30
|
+
row.merge("b", "g")
|
|
31
|
+
row << ["巡检命令", "1.基本信息"]
|
|
32
|
+
row.set_style("a", "BoldStyle")
|
|
33
|
+
row.set_style("b", "BoldStyle")
|
|
34
|
+
|
|
35
|
+
#========== show version
|
|
36
|
+
row = worksheet.add_row
|
|
37
|
+
row.merge("c", "d")
|
|
38
|
+
row.merge("f", "g")
|
|
39
|
+
row << ["show version", "设备名称", "A_HBWHA_COR_CS01", "设备型号", "WS-C6506-E"]
|
|
40
|
+
row.set_style("a", "BoldStyle")
|
|
41
|
+
row = worksheet.add_row
|
|
42
|
+
row.merge("c", "d")
|
|
43
|
+
row.merge("f", "g")
|
|
44
|
+
row << ["show version", "IP", "30.48.1.248", "FLASH(MB)", "512"]
|
|
45
|
+
row = worksheet.add_row
|
|
46
|
+
row.merge("c", "g")
|
|
47
|
+
row << ["show version", "运行时间", "26 weeks, 5 days, 5 hours, 44 minutes"]
|
|
48
|
+
row = worksheet.add_row
|
|
49
|
+
row << [
|
|
50
|
+
"show version",
|
|
51
|
+
"内存", "512",
|
|
52
|
+
"IOS版本", "12.2(33)SXI4a",
|
|
53
|
+
"紧急版本", "12.2(17r)SX7" ]
|
|
54
|
+
row = worksheet.add_row
|
|
55
|
+
row.merge("c", "g")
|
|
56
|
+
row << [
|
|
57
|
+
"show version",
|
|
58
|
+
"IOS特性集", "s72033-ipservicesk9-mz.122-33.SXI4a"]
|
|
59
|
+
|
|
60
|
+
worksheet.merge("a3","a7")
|
|
61
|
+
|
|
62
|
+
#========= show inventory
|
|
63
|
+
row = worksheet.add_row
|
|
64
|
+
row.merge("e", "g")
|
|
65
|
+
row << [
|
|
66
|
+
"show inventory", "硬件信息", "接口卡型号","序列号",
|
|
67
|
+
"RMA历史记录(年/月/日)"]
|
|
68
|
+
row.style("a", "BoldStyle")
|
|
69
|
+
row = worksheet.add_row
|
|
70
|
+
row << ["show inventory",
|
|
71
|
+
"机箱", "WS-C6506-E", "SAL1439URLY", "", "", ""]
|
|
72
|
+
row = worksheet.add_row
|
|
73
|
+
row << ["show inventory",
|
|
74
|
+
"插槽1", "WS-C6506-E", "SAL1439URLY", "", "", ""]
|
|
75
|
+
row = worksheet.add_row
|
|
76
|
+
row << ["show inventory",
|
|
77
|
+
"插槽2", "WS-C6506-E", "SAL1439URLY", "", "", ""]
|
|
78
|
+
row = worksheet.add_row
|
|
79
|
+
row << ["show inventory",
|
|
80
|
+
"插槽3", "WS-C6506-E", "SAL1439URLY", "", "", ""]
|
|
81
|
+
row = worksheet.add_row
|
|
82
|
+
row << ["show inventory",
|
|
83
|
+
"插槽4", "WS-C6506-E", "SAL1439URLY", "", "", ""]
|
|
84
|
+
worksheet.merge("a8", "a13")
|
|
85
|
+
#=========
|
|
86
|
+
row = worksheet.add_row
|
|
87
|
+
row.merge("b", "g")
|
|
88
|
+
row << ["", "2.运行状态巡检信息采集"]
|
|
89
|
+
row.style("b", "BoldStyle")
|
|
90
|
+
row = worksheet.add_row
|
|
91
|
+
row.merge("d", "f")
|
|
92
|
+
row << ["", "项目", "内容", "结果", "备注"]
|
|
93
|
+
row.style("b", "BoldStyle")
|
|
94
|
+
row.style("c", "BoldStyle")
|
|
95
|
+
row.style("d", "BoldStyle")
|
|
96
|
+
row.style("g", "BoldStyle")
|
|
97
|
+
#========= show process cpu
|
|
98
|
+
row = worksheet.add_row
|
|
99
|
+
row.merge("d", "f")
|
|
100
|
+
row << ["show process cpu", "路由状态",
|
|
101
|
+
"cpu利用率(%)", "five minutes: 10%", ""]
|
|
102
|
+
row.style("a", "BoldStyle")
|
|
103
|
+
row = worksheet.add_row
|
|
104
|
+
row.merge("d", "f")
|
|
105
|
+
row << ["show process mem", "路由状态",
|
|
106
|
+
"内存利用率(%)", "24.00", ""]
|
|
107
|
+
row.style("a", "BoldStyle")
|
|
108
|
+
row = worksheet.add_row
|
|
109
|
+
row.merge("d", "f")
|
|
110
|
+
row << ["show environment", "路由状态",
|
|
111
|
+
"温度", "√", ""]
|
|
112
|
+
row.style("a", "BoldStyle")
|
|
113
|
+
row = worksheet.add_row
|
|
114
|
+
row.merge("d", "f")
|
|
115
|
+
row << ["show environment", "路由状态",
|
|
116
|
+
"电源", "正常√ 不正常□", ""]
|
|
117
|
+
|
|
118
|
+
|