-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ad9f107
commit dab1349
Showing
19 changed files
with
3,593 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
testdata/fsos_s5/*.txt text eol=crlf | ||
testdata/fsos_n5/*.txt text eol=crlf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package fsos_n5 | ||
|
||
import ( | ||
"github.com/g-portal/switchmgr-go/pkg/models" | ||
"github.com/g-portal/switchmgr-go/pkg/vendors/fsos_s3/utils" | ||
"golang.org/x/exp/slices" | ||
"regexp" | ||
"strings" | ||
) | ||
|
||
// Example | ||
// 1 649d.99d2.502d MLAG AggregatePort 10 32d 21:31:31 | ||
var arpLineRgx = regexp.MustCompile(`^([0-9]+)\s+([0-9a-f]{4}\.[0-9a-f]{4}\.[0-9a-f]{4})\s+([A-Z]+)\s+([a-zA-Z]+\s[0-9]+)\s+([0-9a-z]+)\s([0-9:]+)$`) | ||
|
||
func (fs *FSComN5) ListArpTable() ([]models.ArpEntry, error) { | ||
output, err := fs.SendCommands("show mac-address-table") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return ParseArpTable(output) | ||
} | ||
|
||
func ParseArpTable(output string) ([]models.ArpEntry, error) { | ||
var table []models.ArpEntry | ||
|
||
portsWithMac := map[string][]models.MacAddress{} | ||
|
||
for _, line := range strings.Split(output, "\n") { | ||
line = strings.TrimSpace(line) | ||
if !arpLineRgx.MatchString(line) { | ||
continue | ||
} | ||
|
||
matches := arpLineRgx.FindStringSubmatch(line) | ||
if len(matches) != 7 { | ||
continue | ||
} | ||
|
||
matches[4] = utils.ConvertInterface(matches[4]) | ||
if _, ok := portsWithMac[matches[4]]; !ok { | ||
portsWithMac[matches[4]] = []models.MacAddress{} | ||
} | ||
|
||
mac := models.MacAddress(strings.TrimSpace(matches[2])) | ||
if !mac.Valid() { | ||
continue | ||
} | ||
|
||
// reformat mac address | ||
mac = models.MacAddress(mac.String()) | ||
|
||
// avoid duplicate entries | ||
if slices.Contains(portsWithMac[matches[4]], mac) { | ||
continue | ||
} | ||
|
||
portsWithMac[matches[4]] = append(portsWithMac[matches[4]], mac) | ||
} | ||
|
||
for portName, macs := range portsWithMac { | ||
table = append(table, models.ArpEntry{ | ||
SwitchPort: portName, | ||
MacAddresses: macs, | ||
}) | ||
} | ||
|
||
return table, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package fsos_n5_test | ||
|
||
import ( | ||
"github.com/g-portal/switchmgr-go/pkg/models" | ||
"github.com/g-portal/switchmgr-go/pkg/vendors/fsos_n5" | ||
"github.com/g-portal/switchmgr-go/pkg/vendors/fsos_n5/utils" | ||
"github.com/google/go-cmp/cmp" | ||
"github.com/google/go-cmp/cmp/cmpopts" | ||
"testing" | ||
) | ||
|
||
var expectedEntries = map[string][]models.MacAddress{ | ||
"AggregatePort 1": { | ||
"00:c0:1d:c0:ff:ee", | ||
"98:5d:82:47:d0:93", | ||
"98:5d:82:47:d6:d9", | ||
}, | ||
"AggregatePort 7": { | ||
"48:df:37:79:be:20", | ||
}, | ||
"AggregatePort 8": { | ||
"48:df:37:79:be:90", | ||
}, | ||
} | ||
|
||
func TestParseArpTable(t *testing.T) { | ||
entries, err := fsos_n5.ParseArpTable(utils.ReadTestData("show mac address table", nil)) | ||
if err != nil { | ||
t.Errorf("unexpected error: %s", err.Error()) | ||
} | ||
|
||
if len(entries) != 3 { | ||
t.Fatalf("expected 3 entries, got %d", len(entries)) | ||
} | ||
|
||
for _, entry := range entries { | ||
expectedMacs, ok := expectedEntries[entry.SwitchPort] | ||
if !ok { | ||
t.Fatalf("unexpected port %s", entry.SwitchPort) | ||
} | ||
|
||
if len(entry.MacAddresses) != len(expectedMacs) { | ||
t.Fatalf("invalid amount of macs for port %q, got %v, expected %v", entry.SwitchPort, | ||
len(entry.MacAddresses), len(expectedMacs)) | ||
} | ||
|
||
if diff := cmp.Diff(entry.MacAddresses, expectedMacs, cmpopts.SortSlices(func(a, b string) bool { return a < b })); diff != "" { | ||
t.Fatalf("mac addresses for port %q don't match. diff: %s", entry.SwitchPort, diff) | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package fsos_n5 | ||
|
||
import ( | ||
"fmt" | ||
"github.com/g-portal/switchmgr-go/pkg/iosconfig" | ||
"github.com/g-portal/switchmgr-go/pkg/models" | ||
"github.com/g-portal/switchmgr-go/pkg/utils" | ||
) | ||
|
||
type Configuration iosconfig.Config | ||
|
||
func (cfg Configuration) ListInterfaces() ([]*models.Interface, error) { | ||
iosConfig := iosconfig.Config(cfg) | ||
|
||
vlanIDs := make([]int32, 0) | ||
for id := range iosConfig.Vlans() { | ||
vlanIDs = append(vlanIDs, id) | ||
} | ||
|
||
interfaces := make([]*models.Interface, 0) | ||
for nic, config := range iosConfig.Interfaces() { | ||
mgmt := false | ||
|
||
mode := InterfaceMode(config.GetStringValue("switchport mode", string(InterfaceModeAccess))) | ||
|
||
var untaggedVLAN *int32 | ||
var taggedVLANs []int32 | ||
|
||
enable := !config.Exists("shutdown", true) | ||
|
||
interfaceMode := models.InterfaceModeAccess | ||
|
||
switch mode { | ||
case InterfaceModeAccess: | ||
accessVlanID := config.GetInt32Value("switchport access vlan", 1) | ||
untaggedVLAN = &accessVlanID | ||
case InterfaceModeTrunk: | ||
interfaceMode = models.InterfaceModeTrunk | ||
accessVlanID := int32(1) | ||
if config.Exists("switchport trunk vlan-untagged", false) { | ||
accessVlanID = config.GetInt32Value("switchport trunk vlan-untagged", 1) | ||
} else if config.Exists("switchport trunk native vlan", false) { | ||
accessVlanID = config.GetInt32Value("switchport trunk native vlan", 1) | ||
} | ||
|
||
untaggedVLAN = &accessVlanID | ||
taggedVLANs = config.GetInt32Values("switchport trunk allowed vlan add", vlanIDs) | ||
|
||
if config.Exists("switchport trunk allowed vlan add", false) { | ||
taggedVLANs = utils.ConvertVlans(config.GetStringValue("switchport trunk allowed vlan add", ""), ",") | ||
} | ||
|
||
// remove untagged vlan from tagged VLANs | ||
taggedVLANs = utils.DeleteVlanFromIDs(taggedVLANs, *untaggedVLAN) | ||
case InterfaceModeHybrid: | ||
interfaceMode = models.InterfaceModeTrunk | ||
//TODO implement hybrid mode | ||
default: | ||
return nil, fmt.Errorf("unknown interface mode %q", mode) | ||
} | ||
|
||
if config.Exists("ip address", false) { | ||
mgmt = true | ||
} | ||
|
||
interfaces = append(interfaces, &models.Interface{ | ||
Name: nic, | ||
Description: config.GetStringValue("description", ""), | ||
Enabled: enable, | ||
Mode: interfaceMode, | ||
UntaggedVLAN: untaggedVLAN, | ||
TaggedVLANs: taggedVLANs, | ||
Management: mgmt, | ||
}) | ||
} | ||
|
||
return interfaces, nil | ||
} | ||
|
||
// GetConfiguration returns the configuration of a FSComS3 switch. | ||
func (fs *FSComN5) GetConfiguration() (*Configuration, error) { | ||
output, err := fs.SendCommands("show running-config") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
cfg := ParseConfiguration(output) | ||
config := Configuration(cfg) | ||
|
||
return &config, nil | ||
} | ||
|
||
func (cfg Configuration) GetInterface(name string) (*models.Interface, error) { | ||
nics, err := cfg.ListInterfaces() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, nic := range nics { | ||
if nic.Name == name { | ||
return nic, nil | ||
} | ||
} | ||
|
||
return nil, fmt.Errorf("interface %q not found", name) | ||
} | ||
|
||
// ParseConfiguration parses the configuration of a FSComS3 switch. | ||
func ParseConfiguration(cfg string) iosconfig.Config { | ||
return iosconfig.Parse(cfg) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package fsos_n5 | ||
|
||
import ( | ||
"github.com/g-portal/switchmgr-go/pkg/vendors/fsos_s3" | ||
) | ||
|
||
type FSComN5 struct { | ||
fsos_s3.FSComS3 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package fsos_n5 | ||
|
||
import ( | ||
"errors" | ||
"github.com/g-portal/switchmgr-go/pkg/models" | ||
"regexp" | ||
) | ||
|
||
var serialRegex = regexp.MustCompile(`System\sserial\snumber\s+:\s([0-9A-Z]+)\r\n`) | ||
var modelRegex = regexp.MustCompile(`System\sdescription\s+:\s.+\(([0-9A-Z-]+)\).+\r\n`) | ||
var versionRegex = regexp.MustCompile(`System\ssoftware\sversion\s+:\s(.+)\r\n`) | ||
var hostnameRegex = regexp.MustCompile(`hostname\s(.+)\r\n`) | ||
|
||
func (fs *FSComN5) GetHardwareInfo() (*models.HardwareInfo, error) { | ||
output, err := fs.SendCommands("show version", "show running-config | include hostname") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return ParseHardwareInfo(output) | ||
} | ||
|
||
func ParseHardwareInfo(output string) (*models.HardwareInfo, error) { | ||
hwInfo := &models.HardwareInfo{ | ||
Vendor: "Fiberstore", | ||
} | ||
|
||
// serial | ||
matches := serialRegex.FindStringSubmatch(output) | ||
if len(matches) != 2 { | ||
return nil, errors.New("could not parse serial") | ||
} | ||
hwInfo.Serial = matches[1] | ||
|
||
// model | ||
matches = modelRegex.FindStringSubmatch(output) | ||
if len(matches) != 2 { | ||
return nil, errors.New("could not parse model") | ||
} | ||
hwInfo.Model = matches[1] | ||
|
||
// firmware version | ||
matches = versionRegex.FindStringSubmatch(output) | ||
if len(matches) != 2 { | ||
return nil, errors.New("could not parse firmware version") | ||
} | ||
hwInfo.FirmwareVersion = matches[1] | ||
|
||
// hostname | ||
matches = hostnameRegex.FindStringSubmatch(output) | ||
if len(matches) != 2 { | ||
return nil, errors.New("could not parse hostname") | ||
} | ||
hwInfo.Hostname = matches[1] | ||
|
||
return hwInfo, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package fsos_n5_test | ||
|
||
import ( | ||
"github.com/g-portal/switchmgr-go/pkg/vendors/fsos_n5" | ||
"github.com/g-portal/switchmgr-go/pkg/vendors/fsos_n5/utils" | ||
"testing" | ||
) | ||
|
||
func TestParseHardwareInfo(t *testing.T) { | ||
hwInfo, err := fsos_n5.ParseHardwareInfo(utils.ReadTestData("show version", nil)) | ||
if err != nil { | ||
t.Fatalf("Error parsing hardware info: %s", err.Error()) | ||
} | ||
|
||
if hwInfo == nil { | ||
t.Fatalf("Hardware info is nil") | ||
} | ||
|
||
if hwInfo.Serial != "G1RL71S00XXXX" { | ||
t.Fatalf("Serial number is wrong: %s", hwInfo.Serial) | ||
} | ||
|
||
if hwInfo.Model != "N5860-48SC" { | ||
t.Fatalf("Model is wrong: %s", hwInfo.Model) | ||
} | ||
|
||
if hwInfo.Vendor != "Fiberstore" { | ||
t.Fatalf("Vendor is wrong: %s", hwInfo.Vendor) | ||
} | ||
|
||
if hwInfo.FirmwareVersion != "N5860_FSOS 11.0(5)B9P66S2" { | ||
t.Fatalf("Firmware version is wrong: %s", hwInfo.FirmwareVersion) | ||
} | ||
|
||
if hwInfo.Hostname != "openshift-core2" { | ||
t.Fatalf("Hostname is wrong: %s", hwInfo.Hostname) | ||
} | ||
|
||
} |
Oops, something went wrong.