pkg/skoop/netstack/ipvs.go (129 lines of code) (raw):

package netstack import ( "flag" "fmt" "strconv" "strings" "github.com/alibaba/kubeskoop/pkg/skoop/model" "github.com/pkg/errors" ) type RealServer struct { Service string `json:"s,omitempty"` IP string `json:"ip"` Port uint16 `json:"p"` Masquerade bool `json:"m"` Weight int `json:"w"` } type IPVSService struct { Protocol model.Protocol `json:"pro"` IP string `json:"ip"` Port uint16 `json:"p"` Scheduler string `json:"s"` RS []RealServer `json:"r"` } func (s *IPVSService) Service() string { return fmt.Sprintf("%s:%s:%d", s.Protocol, s.IP, s.Port) } type IPVS struct { services map[string]*IPVSService } func (ipvs *IPVS) GetService(proto model.Protocol, ip string, port uint16) *IPVSService { key := fmt.Sprintf("%s:%s:%d", strings.ToLower(string(proto)), ip, port) return ipvs.services[key] } func parseOneLine(ipvs *IPVS, line string) error { var ( addService bool tcpService string udpService string scheduler string addServer bool realServer string masquerading bool weight string persistent string ) ipvsFlags := flag.NewFlagSet("ipvs", flag.ContinueOnError) ipvsFlags.BoolVar(&addService, "A", false, "") ipvsFlags.StringVar(&tcpService, "t", "", "") ipvsFlags.StringVar(&udpService, "u", "", "") ipvsFlags.StringVar(&scheduler, "s", "", "") ipvsFlags.BoolVar(&addServer, "a", false, "") ipvsFlags.StringVar(&realServer, "r", "", "") ipvsFlags.BoolVar(&masquerading, "m", false, "") ipvsFlags.StringVar(&weight, "w", "", "") ipvsFlags.StringVar(&persistent, "p", "", "") if err := ipvsFlags.Parse(strings.Fields(line)); err != nil { return errors.Wrapf(err, "error parse ipvs rule %s", line) } if !addServer && !addService { return fmt.Errorf("unknown ipvs action") } var protocol model.Protocol var service string if udpService != "" { protocol = model.UDP service = udpService } else { protocol = model.TCP service = tcpService } arr := strings.Split(service, ":") serviceIP := arr[0] servicePort, err := strconv.Atoi(arr[1]) if err != nil { return err } if addService { svc := &IPVSService{ Protocol: protocol, IP: serviceIP, Port: uint16(servicePort), Scheduler: scheduler, } ipvs.services[svc.Service()] = svc return nil } if addServer { weightInt, _ := strconv.Atoi(weight) arr := strings.Split(realServer, ":") serverIP := arr[0] serverPort, err := strconv.Atoi(arr[1]) if err != nil { return err } backend := RealServer{ IP: serverIP, Port: uint16(serverPort), Masquerade: masquerading, Weight: weightInt, } serviceName := fmt.Sprintf("%s:%s", protocol, service) svc, ok := ipvs.services[serviceName] if !ok { return fmt.Errorf("service not exists") } svc.RS = append(svc.RS, backend) return nil } return nil } func ParseIPVS(dump []string) (*IPVS, error) { ipvs := &IPVS{ services: make(map[string]*IPVSService), } for _, line := range dump { if line == "" { continue } if err := parseOneLine(ipvs, line); err != nil { return nil, err } } return ipvs, nil } func NewIPVS(services map[string]*IPVSService) *IPVS { return &IPVS{ services: services, } }