package swClient import ( "errors" "strings" "sync" "time" "github.rackspace.com/gorax/clients/unipede" "github.rackspace.com/gorax/libs/switchlib/swModels" ) type ( SwConfig struct { IntConfig []*swModels.IntConfig `json:"interfaces_configuration"` IntStatus *swModels.InterfacesStatus `json:"interfaces_status"` Routes *swModels.IPRoutes `json:"routes"` Vlans []*swModels.VlanConfig `json:"vlans"` Monitors []*swModels.MonitorSession `json:"monitor_sessions"` AccessLists []*swModels.AccessList `json:"access_lists"` } SwPortData struct { SwitchName string `json:"switch_name"` Ports map[int]*PortData `json:"ports"` } PortData struct { Port *swModels.IntConfig Po *swModels.IntConfig } ) func (s *Switch) Pull(unipede bool, refresh *int) error { if unipede { if err := s.UnipedeSwitchConfig(refresh); err != nil { return errors.New(*s.Name + ": " + err.Error()) } return nil } config, err := s.DirectSwitchConfig() if err != nil { return errors.New(*s.Name + ": " + err.Error()) } //log.Println(*s.Name, *config) s.ParseConfigItems(config) return nil } func (s *Switch) ParseConfigItems(config *string) { var ic swModels.InterfaceConfig ic.Parse(config) s.Config.IntConfig = ic.InterfaceConfig var vl swModels.VlanDB vl.Parse(config) s.Config.Vlans = vl.Vlans var ms swModels.MonitorSessions ms.Parse(config) s.Config.Monitors = ms.Monitors var acl swModels.AccessLists acl.Parse(config) s.Config.AccessLists = acl.AccessLists } func (s *Switch) Status() error { status, err := s.DirectIntStatus() if err != nil { return err } s.Config.IntStatus.Parse(status) return nil } func (s *Switch) FullMACTable() ([]*swModels.MACAddress, error) { macs, err := s.DirectFullMAC() if err != nil { return nil, err } var mt swModels.MACAddressTable mt.Parse(macs) return mt.MACAddress, nil } func (s *Switch) VlanMACTable(vlan string) ([]*swModels.MACAddress, error) { macs, err := s.DirectMACVlan(vlan) if err != nil { return nil, err } var mt swModels.MACAddressTable mt.Parse(macs) return mt.MACAddress, nil } func (s *Switch) PortMACTable(port string) ([]*swModels.MACAddress, error) { macs, err := s.DirectMACPort(port) if err != nil { return nil, err } var mt swModels.MACAddressTable mt.Parse(macs) return mt.MACAddress, nil } func appendError(errList *[]string, err error) { if err != nil { *errList = append(*errList, err.Error()) } } // function to create unique list of switches and initiate the switch client based on data method. func CreateSwitchMap(switchList *[]string, apiKey *string, uni bool) (map[string]*Switch, []error) { swConfigs := make(map[string]*Switch) var errList []error for _, sw := range *switchList { if sw == "" { continue } sw = strings.ToLower(sw) if _, ok := swConfigs[sw]; !ok { if uni { u, err := unipede.New("", "", *apiKey) if err != nil { errList = append(errList, err) continue } nSw, err := New(u, "", sw) if err != nil { errList = append(errList, err) continue } swConfigs[sw] = nSw continue } nSw, err := New(nil, *apiKey, sw) if err != nil { errList = append(errList, err) continue } swConfigs[sw] = nSw } } return swConfigs, errList } // Function to gather switch configuration for a list of switches, requires a core token func SwitchConfigDirect(switchList []string, coreToken string) (map[string]*Switch, []error) { swConfigs, errList := CreateSwitchMap(&switchList, &coreToken, false) errList = append(errList, SwitchPool(swConfigs, false)...) return swConfigs, errList } // Function to gather switch configuration from unipede, required unipede token and refresh value func SwitchConfigUnipede(switchList []string, uniAPI string, refresh bool) (map[string]*Switch, []error) { swConfigs, errList := CreateSwitchMap(&switchList, &uniAPI, true) errList = append(errList, SwitchPool(swConfigs, true)...) return swConfigs, errList } func SwitchPool(swConfigs map[string]*Switch, unipede bool) []error { var errList []error swChan := make(chan *Switch, 10) errChan := make(chan error, 10) var wg sync.WaitGroup go SwitchErrors(errChan, &errList) for w := 1; w <= 10; w++ { go SwitchConfigGather(swChan, errChan, unipede, &wg) } for _, sw := range swConfigs { wg.Add(1) swChan <- sw time.Sleep(time.Millisecond * 150) } wg.Wait() close(swChan) close(errChan) return errList } func SwitchErrors(errChan chan error, errList *[]error) { for e := range errChan { *errList = append(*errList, e) } return } func SwitchConfigGather(swChan chan *Switch, errChan chan error, unipede bool, wg *sync.WaitGroup) { for sw := range swChan { if err := sw.Pull(unipede, nil); err != nil { errChan <- err } wg.Done() } } func SwitchPortConfigs(swData []*SwPortData, workers int, u *unipede.Client) { swChan := make(chan *SwPortData, workers) defer close(swChan) var wg sync.WaitGroup for x := 1; x <= workers; x++ { go GatherPortConfigs(swChan, &wg, u) } for _, swd := range swData { wg.Add(1) swChan <- swd } wg.Wait() } func GatherPortConfigs(swChan chan *SwPortData, wg *sync.WaitGroup, u *unipede.Client) { for swd := range swChan { client, err := New(u, "", swd.SwitchName) if err != nil { // log.Println(err) continue } if err := client.Pull(true, nil); err != nil { // log.Println(err) continue } for pn, pd := range swd.Ports { pc := client.PortConfig(pn) if pc != nil { if pc.ChannelGroup != nil { po := client.PortChannelConfig(*pc.ChannelGroup) if po != nil { *pd.Po = *po } } *pd.Port = *pc } } wg.Done() } }