Initial commit: 网络拓扑发现系统
- 支持Cisco、华为、H3C、ASA、Linux、Windows设备 - SSH远程采集设备信息 - 自动发现网络拓扑(LLDP/CDP) - Web可视化界面 - 支持旧版SSH加密算法兼容
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"network-topology-discovery/pkg/models"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// H3CParser H3C设备解析器
|
||||
type H3CParser struct {
|
||||
BaseParser
|
||||
}
|
||||
|
||||
// GetCommands 获取H3C设备命令列表
|
||||
func (p *H3CParser) GetCommands() []string {
|
||||
return []string{
|
||||
"display version",
|
||||
"display interface",
|
||||
"display ip interface brief",
|
||||
"display lldp neighbor-list",
|
||||
}
|
||||
}
|
||||
|
||||
// Parse 解析H3C设备输出
|
||||
func (p *H3CParser) Parse(device *models.Device, outputs []string) error {
|
||||
if len(outputs) < 4 {
|
||||
return fmt.Errorf("insufficient command outputs")
|
||||
}
|
||||
|
||||
p.parseVersion(device, outputs[0])
|
||||
device.Interfaces = p.parseInterfaces(outputs[1], outputs[2])
|
||||
device.Neighbors = p.parseNeighbors(outputs[3])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *H3CParser) parseVersion(device *models.Device, output string) {
|
||||
hostnameRegex := regexp.MustCompile(`<(\S+)>`)
|
||||
if matches := hostnameRegex.FindStringSubmatch(output); len(matches) > 1 {
|
||||
device.Hostname = matches[1]
|
||||
}
|
||||
|
||||
if strings.Contains(output, "Comware") {
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "Comware") {
|
||||
device.OSVersion = strings.TrimSpace(line)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uptimeRegex := regexp.MustCompile(`uptime is\s+(\d+\s+\S+)`)
|
||||
if matches := uptimeRegex.FindStringSubmatch(output); len(matches) > 1 {
|
||||
device.Uptime = matches[1]
|
||||
}
|
||||
}
|
||||
|
||||
func (p *H3CParser) parseInterfaces(interfaceOutput, briefOutput string) []models.Interface {
|
||||
var interfaces []models.Interface
|
||||
briefMap := p.parseInterfaceBrief(briefOutput)
|
||||
|
||||
scanner := bufio.NewScanner(strings.NewReader(interfaceOutput))
|
||||
var currentInterface *models.Interface
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
if nameRegex := regexp.MustCompile(`^(\S+)\s+current state:\s+(UP|DOWN)`); nameRegex.MatchString(line) {
|
||||
if currentInterface != nil {
|
||||
interfaces = append(interfaces, *currentInterface)
|
||||
}
|
||||
matches := nameRegex.FindStringSubmatch(line)
|
||||
currentInterface = &models.Interface{
|
||||
Name: matches[1],
|
||||
Status: strings.ToLower(matches[2]),
|
||||
}
|
||||
|
||||
if brief, ok := briefMap[currentInterface.Name]; ok {
|
||||
currentInterface.IP = brief.IP
|
||||
}
|
||||
}
|
||||
|
||||
if currentInterface != nil {
|
||||
if descRegex := regexp.MustCompile(`Description:\s+(.+)`); descRegex.MatchString(line) {
|
||||
currentInterface.Description = descRegex.FindStringSubmatch(line)[1]
|
||||
}
|
||||
|
||||
if macRegex := regexp.MustCompile(`Hardware address is\s+(\S+)`); macRegex.MatchString(line) {
|
||||
currentInterface.MAC = macRegex.FindStringSubmatch(line)[1]
|
||||
}
|
||||
|
||||
if ipRegex := regexp.MustCompile(`IP Address:\s+(\d+\.\d+\.\d+\.\d+)\s+Subnet Mask:\s+(\d+\.\d+\.\d+\.\d+)`); ipRegex.MatchString(line) {
|
||||
matches := ipRegex.FindStringSubmatch(line)
|
||||
currentInterface.IP = matches[1]
|
||||
currentInterface.Mask = matches[2]
|
||||
}
|
||||
|
||||
if speedRegex := regexp.MustCompile(`(\d+)\s+(Kbps|Mbps|Gbps)`); speedRegex.MatchString(line) {
|
||||
matches := speedRegex.FindStringSubmatch(line)
|
||||
currentInterface.Speed = matches[1] + " " + matches[2]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if currentInterface != nil {
|
||||
interfaces = append(interfaces, *currentInterface)
|
||||
}
|
||||
|
||||
return interfaces
|
||||
}
|
||||
|
||||
func (p *H3CParser) parseInterfaceBrief(output string) map[string]models.Interface {
|
||||
interfaces := make(map[string]models.Interface)
|
||||
lines := strings.Split(output, "\n")
|
||||
|
||||
for _, line := range lines {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) >= 4 {
|
||||
iface := models.Interface{
|
||||
Name: fields[0],
|
||||
IP: fields[1],
|
||||
Status: strings.ToLower(fields[3]),
|
||||
}
|
||||
interfaces[iface.Name] = iface
|
||||
}
|
||||
}
|
||||
|
||||
return interfaces
|
||||
}
|
||||
|
||||
func (p *H3CParser) parseNeighbors(output string) []models.Neighbor {
|
||||
var neighbors []models.Neighbor
|
||||
scanner := bufio.NewScanner(strings.NewReader(output))
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
if strings.Contains(line, "Local Interface") || strings.Contains(line, "-----") {
|
||||
continue
|
||||
}
|
||||
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) >= 5 {
|
||||
neighbor := models.Neighbor{
|
||||
LocalInterface: fields[0],
|
||||
RemoteDevice: fields[2],
|
||||
RemoteInterface: fields[4],
|
||||
Protocol: "LLDP",
|
||||
}
|
||||
neighbors = append(neighbors, neighbor)
|
||||
}
|
||||
}
|
||||
|
||||
return neighbors
|
||||
}
|
||||
Reference in New Issue
Block a user