package swModels import ( "regexp" "sort" "strings" "github.rackspace.com/gorax/tools/util" ) var ( VLANFULLRE = regexp.MustCompile(`(?i)(v|)lan\s+([0-9]+)\n((.|\n)*?)(\n v|\nv|$)`) VLANNAMERE = regexp.MustCompile(`(?i)name\s+(\S+)`) VLANRANGERE = regexp.MustCompile(`(?i)\n(|\s+)vlan\s+([0-9]+(,|-).*?)(\s+\n|\n)`) VLANONLYRE = regexp.MustCompile(`(?i)vlan\s+([0-9]+)(\s+\n!|\n!|\s+\n\s+!)`) VLANSTATUSRE = regexp.MustCompile(`(?i)vlan\s+name\s+status\s+ports((.|\n)*?)vlan\s+type\s+`) VLANSTATUSPARSERE = regexp.MustCompile(`(?i)([0-9]+)\s+(\S+)\s+(\S+)`) ) type ( VlanDB struct { Vlans []*VlanConfig `json:"vlans"` vlanMap map[int]*VlanConfig } VlanConfig struct { Vlan int `json:"vlan_number"` Name *string `json:"name"` Shut bool `json:"shutdown"` } VlanStatus struct { VlanStatus []*VlanStat `json:"vlan_status"` } VlanStat struct { Vlan int `json:"vlan_number"` Name string `json:"name"` Status string `json:"status"` Ports string `json:"ports"` } ) func ParseVlanConfig(s *string) *VlanDB { v := new(VlanDB) v.Parse(s) return v } func (V *VlanDB) Parse(s *string) { V.vlanMap = make(map[int]*VlanConfig) V.VlanFullParse(s) V.VlanRangeParse(s) V.VlanOnlyParse(s) if _, ok := V.vlanMap[1]; !ok { name := "default" V.vlanMap[1] = &VlanConfig{ Vlan: 1, Name: &name, } } V.AddVlans() } func (V *VlanDB) AddVlans() { for _, key := range V.SortKeys() { V.Vlans = append(V.Vlans, V.vlanMap[key]) } } func (V *VlanDB) SortKeys() (keys []int) { for k := range V.vlanMap { keys = append(keys, k) } sort.Ints(keys) return } func (V *VlanDB) VlanFullParse(s *string) { match := VLANFULLRE.FindAllStringSubmatch(*s, -1) if len(match) == 0 { return } for _, v := range match { vlan := util.Atoi(v[2]) if _, ok := V.vlanMap[vlan]; !ok { V.vlanMap[vlan] = &VlanConfig{ Vlan: vlan, Name: util.RegexpFindStringPtr(VLANNAMERE, v[3]), } } } } func (V *VlanDB) VlanRangeParse(s *string) { match := VLANRANGERE.FindAllStringSubmatch(*s, -1) if len(match) == 0 { return } for _, v := range match { for _, nv := range strings.Split(v[2], ",") { if nv == "1-4094" { continue } if strings.Contains(nv, "-") { hiLow := strings.Split(nv, "-") low := util.Atoi(hiLow[0]) hi := util.Atoi(hiLow[1]) if low != -9999 && hi != -9999 { for x := low; x <= hi; x++ { if _, ok := V.vlanMap[x]; !ok { V.vlanMap[x] = &VlanConfig{ Vlan: x, Name: nil, } } } continue } } if tv := util.Atoi(nv); tv != -9999 { if _, ok := V.vlanMap[tv]; !ok { V.vlanMap[tv] = &VlanConfig{ Vlan: tv, Name: nil, } } } } } } func (V *VlanDB) VlanOnlyParse(s *string) { match := VLANONLYRE.FindAllStringSubmatch(*s, -1) if len(match) == 0 { return } for _, v := range match { vlan := util.Atoi(v[1]) if _, ok := V.vlanMap[vlan]; !ok { V.vlanMap[vlan] = &VlanConfig{ Vlan: vlan, Name: nil, } } } } func (V *VlanStatus) Parse(s *string) { vstatus := util.RegexpFindStringPtr(VLANSTATUSRE, *s) if vstatus != nil { for _, v := range strings.Split(*vstatus, "\n") { vl := VLANSTATUSPARSERE.FindStringSubmatch(v) if len(vl) != 0 { V.VlanStatus = append(V.VlanStatus, &VlanStat{ Vlan: util.Atoi(vl[1]), Name: vl[2], Status: vl[3], }) } } } } func (V *VlanDB) VlanExist(vlan int) bool { return VlanExist(vlan, V.Vlans) } func VlanExist(vlan int, V []*VlanConfig) bool { for _, v := range V { if v.Vlan == vlan { return true } } return false } func (V *VlanDB) VlanName(vlan int) string { return VlanName(vlan, V.Vlans) } func VlanName(vlan int, V []*VlanConfig) string { for _, v := range V { if v.Vlan == vlan { if v.Name != nil { return *v.Name } } } return "" } func (V *VlanDB) FindVlan(vlan int) *VlanConfig { return FindVlan(vlan, V.Vlans) } func FindVlan(vlan int, V []*VlanConfig) *VlanConfig { for _, v := range V { if v.Vlan == vlan { return v } } return nil } func (V *VlanDB) VlanNameList(vlans []int) (vdata []*VlanConfig) { return VlanNameList(vlans, V.Vlans) } func VlanNameList(vlans []int, V []*VlanConfig) (vdata []*VlanConfig) { for _, v := range vlans { vlan := FindVlan(v, V) if vlan != nil { vdata = append(vdata, vlan) continue } } return } func (V *VlanDB) MissingVlans(mVlans []int) (mvl []int) { return MissingVlans(mVlans, V.Vlans) } func MissingVlans(mVlans []int, V []*VlanConfig) (mvl []int) { for _, v := range mVlans { if !VlanExist(v, V) { mvl = append(mvl, v) } } return mvl } func (V *VlanDB) VlanMap() map[int]*string { vm := make(map[int]*string) for _, v := range V.Vlans { v := v if _, ok := vm[v.Vlan]; !ok { vm[v.Vlan] = v.Name } } return vm }