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-information", } } // 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)) var currentNeighbor *models.Neighbor for scanner.Scan() { line := scanner.Text() // 跳过空行和标题行 if strings.TrimSpace(line) == "" || strings.Contains(line, "LLDP neighbor information") || strings.Contains(line, "------") { continue } // 匹配邻居设备信息 - display lldp neighbor-information 输出格式: // NeighborIndex : 1 // ChassisID : 00e0-fc12-3456 // PortID : GigabitEthernet1/0/1 // SystemName : Switch-02 // ManagementAddress : 172.16.12.2 // LocalInterface : GigabitEthernet1/0/1 if strings.Contains(line, "NeighborIndex") { if currentNeighbor != nil && currentNeighbor.RemoteDevice != "" { neighbors = append(neighbors, *currentNeighbor) } currentNeighbor = &models.Neighbor{ Protocol: "LLDP", } } if currentNeighbor != nil { // 提取设备名称 if strings.Contains(line, "SystemName") { parts := strings.SplitN(line, ":", 2) if len(parts) == 2 { currentNeighbor.RemoteDevice = strings.TrimSpace(parts[1]) } } // 提取管理IP地址 if strings.Contains(line, "ManagementAddress") { parts := strings.SplitN(line, ":", 2) if len(parts) == 2 { currentNeighbor.RemoteIP = strings.TrimSpace(parts[1]) } } // 提取远程接口 if strings.Contains(line, "PortID") { parts := strings.SplitN(line, ":", 2) if len(parts) == 2 { currentNeighbor.RemoteInterface = strings.TrimSpace(parts[1]) } } // 提取本地接口 if strings.Contains(line, "LocalInterface") { parts := strings.SplitN(line, ":", 2) if len(parts) == 2 { currentNeighbor.LocalInterface = strings.TrimSpace(parts[1]) } } } } // 添加最后一个邻居 if currentNeighbor != nil && currentNeighbor.RemoteDevice != "" { neighbors = append(neighbors, *currentNeighbor) } return neighbors }