parser.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package device
  2. import (
  3. "fmt"
  4. "time"
  5. "network-topology-discovery/pkg/models"
  6. sshclient "network-topology-discovery/internal/ssh"
  7. )
  8. // Parser 设备解析器接口
  9. type Parser interface {
  10. // GetCommands 获取需要执行的命令列表
  11. GetCommands() []string
  12. // Parse 解析命令输出,填充设备信息
  13. Parse(device *models.Device, outputs []string) error
  14. // GetType 获取设备类型
  15. GetType() models.DeviceType
  16. }
  17. // BaseParser 基础解析器
  18. type BaseParser struct {
  19. DeviceType models.DeviceType
  20. }
  21. // GetType 获取设备类型
  22. func (b *BaseParser) GetType() models.DeviceType {
  23. return b.DeviceType
  24. }
  25. // DiscoverDevice 发现并采集设备信息
  26. func DiscoverDevice(ip string, deviceType models.DeviceType, username, password string) (*models.Device, error) {
  27. device := &models.Device{
  28. IP: ip,
  29. Type: deviceType,
  30. }
  31. // 创建SSH客户端 - 默认启用不安全加密算法以兼容老旧设备,增加超时时间
  32. client := sshclient.NewClient(sshclient.Config{
  33. Host: ip,
  34. Username: username,
  35. Password: password,
  36. Timeout: 30 * time.Second, // 增加到30秒,防止大输出超时
  37. InsecureCiphers: true, // 启用旧版加密算法支持
  38. })
  39. // 连接
  40. if err := client.Connect(); err != nil {
  41. device.ScanStatus = "failed"
  42. device.ErrorMessage = err.Error()
  43. return device, err
  44. }
  45. defer client.Close()
  46. // 获取对应的解析器
  47. var parser Parser
  48. switch deviceType {
  49. case models.DeviceTypeCisco:
  50. parser = &CiscoParser{}
  51. case models.DeviceTypeHuawei:
  52. parser = &HuaweiParser{}
  53. case models.DeviceTypeH3C:
  54. parser = &H3CParser{}
  55. case models.DeviceTypeASA:
  56. parser = &ASAParser{}
  57. case models.DeviceTypeLinux:
  58. parser = &LinuxParser{}
  59. case models.DeviceTypeWindows:
  60. parser = &WindowsParser{}
  61. default:
  62. device.ScanStatus = "failed"
  63. device.ErrorMessage = "unsupported device type"
  64. return device, nil
  65. }
  66. // 获取命令列表
  67. commands := parser.GetCommands()
  68. // 执行所有命令(使用Shell模式,在同一个会话中顺序执行)
  69. outputs, err := client.ExecuteCommands(commands)
  70. if err != nil {
  71. device.ScanStatus = "failed"
  72. device.ErrorMessage = err.Error()
  73. return device, err
  74. }
  75. // 打印调试信息
  76. for i, output := range outputs {
  77. fmt.Printf("[PARSER] Command %d/%d returned %d bytes\n", i+1, len(commands), len(output))
  78. }
  79. // 解析输出
  80. if err := parser.Parse(device, outputs); err != nil {
  81. device.ScanStatus = "failed"
  82. device.ErrorMessage = err.Error()
  83. return device, err
  84. }
  85. device.ScanStatus = "success"
  86. return device, nil
  87. }