Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Huawei SmartAX OLT #23

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module github.com/networklore/netrasp
module github.com/AlbertodelaCruz/netrasp

go 1.13

require (
github.com/magefile/mage v1.11.0
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c
github.com/magefile/mage v1.15.0
golang.org/x/crypto v0.14.0
)
51 changes: 40 additions & 11 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,14 +1,43 @@
github.com/magefile/mage v1.11.0 h1:C/55Ywp9BpgVVclD3lRnSYCwXTYxmSppIgLeDYlNuls=
github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c h1:9HhBz5L/UjnK9XLtiZhYAdue5BVKep3PMmS2LuPDt8k=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
5 changes: 5 additions & 0 deletions pkg/netrasp/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ func initDevice(platform string, conn connection) (Platform, error) {
driver := &sros{}
driver.Connection = conn

return driver, nil
case "smartax":
driver := &smartax{}
driver.Connection = conn

return driver, nil
}

Expand Down
5 changes: 5 additions & 0 deletions pkg/netrasp/platform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ func TestNewDevice(t *testing.T) {
platform: "nxos",
succeed: true,
},
{
name: "huawei_smartax",
platform: "smartax",
succeed: true,
},
{
name: "driver_missing",
platform: "",
Expand Down
100 changes: 100 additions & 0 deletions pkg/netrasp/smartax.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package netrasp

import (
"context"
"fmt"
"regexp"
"strings"
)

var generalSmartaxPrompt = regexp.MustCompile(`^[a-zA-Z0-9<"_()-]+[>|#]`)
var enableSmartaxPrompt = regexp.MustCompile(`^[a-zA-Z0-9<"_-]+#`)

// Smartax Huawei OLTs MA5XXX.
type smartax struct {
Connection connection
}

// Close connection to device.
func (i smartax) Close(ctx context.Context) error {
i.Connection.Close(ctx)

return nil
}

// Configure device.
func (i smartax) Configure(ctx context.Context, commands []string) (ConfigResult, error) {
var result ConfigResult
_, err := i.Run(ctx, "config")
if err != nil {
return result, fmt.Errorf("unable to enter config mode: %w", err)
}
for _, command := range commands {
output, err := i.Run(ctx, command)
configCommand := ConfigCommand{Command: command, Output: output}
result.ConfigCommands = append(result.ConfigCommands, configCommand)
if err != nil {
return result, fmt.Errorf("unable to run command '%s': %w", command, err)
}
}
_, err = i.Run(ctx, "quit")
if err != nil {
return result, fmt.Errorf("unable to exit from config mode: %w", err)
}

return result, nil
}

// Dial opens a connection to a device.
func (i smartax) Dial(ctx context.Context) error {
commands := []string{"undo smart", "scroll"}

return establishConnection(ctx, i, i.Connection, i.basePrompt(), commands)
}

// Enable elevates privileges.
func (i smartax) Enable(ctx context.Context) error {
_, err := i.RunUntil(ctx, "enable", enableSmartaxPrompt)
if err != nil {
return err
}
return nil
}

// Run executes a command on a device.
func (i smartax) Run(ctx context.Context, command string) (string, error) {
output, err := i.RunUntil(ctx, command, i.basePrompt())
if err != nil {
return "", err
}

output = strings.ReplaceAll(output, "\r\n", "\n")
lines := strings.Split(output, "\n")
result := ""

for i := 1; i < len(lines)-1; i++ {
result += lines[i] + "\n"
}

return result, nil
}

// RunUntil executes a command and reads until the provided prompt.
func (i smartax) RunUntil(ctx context.Context, command string, prompt *regexp.Regexp) (string, error) {
err := i.Connection.Send(ctx, command)
if err != nil {
return "", fmt.Errorf("unable to send command to device: %w", err)
}

reader := i.Connection.Recv(ctx)
output, err := readUntilPrompt(ctx, reader, prompt)
if err != nil {
return "", err
}

return output, nil
}

func (i smartax) basePrompt() *regexp.Regexp {
return generalSmartaxPrompt
}
64 changes: 64 additions & 0 deletions pkg/netrasp/smartax_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package netrasp

import (
"context"
"strings"
"testing"
)

func TestFakeSmartaxRunCommand(t *testing.T) {
device, err := New("test1",
WithUsernamePassword("username", "password"),
WithInsecureIgnoreHostKey(),
WithDriver("smartax"),
withFakeFileConnection("testdata/smartax/basic"),
)
if err != nil {
t.Fatalf("unable to create device: %v", err)
}
defer device.Close(context.Background())

err = device.Dial(context.Background())
if err != nil {
t.Fatalf("could not establish connection. Error: '%v'", err)
}
output, err := device.Run(context.Background(), "display version")
if err != nil {
t.Fatalf("unable to run command. Error: %v", err)
}
want := "VERSION : MA5800V100R015C10"
if !strings.Contains(output, want) {
t.Fatalf("expected to find '%s' in '%s'", want, output)
}
}

func TestFakeSmartaxEnableAndConfigureCommand(t *testing.T) {
device, err := New("test1",
WithUsernamePassword("username", "password"),
WithInsecureIgnoreHostKey(),
WithDriver("smartax"),
withFakeFileConnection("testdata/smartax/enable_with_config"),
)
if err != nil {
t.Fatalf("unable to create device: %v", err)
}
defer device.Close(context.Background())

err = device.Dial(context.Background())
if err != nil {
t.Fatalf("could not establish connection. Error: '%v'", err)
}

err = device.Enable(context.Background())
if err != nil {
t.Fatalf("could not establish connection. Error: '%v'", err)
}

config := []string{"display current-configuration"}

_, err = device.Configure(context.Background(), config)

if err != nil {
t.Fatalf("could not send config. Error: '%v'", err)
}
}
4 changes: 4 additions & 0 deletions pkg/netrasp/testdata/smartax/basic/display_version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
gpon1#display version

VERSION : MA5800V100R015C10
gpon1#
6 changes: 6 additions & 0 deletions pkg/netrasp/testdata/smartax/basic/initial.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Welcome to the Dummy Device

Thanks for stopping by.


gpon1#
1 change: 1 addition & 0 deletions pkg/netrasp/testdata/smartax/basic/scroll.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gpon1#
1 change: 1 addition & 0 deletions pkg/netrasp/testdata/smartax/basic/undo_smart.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gpon1#
3 changes: 3 additions & 0 deletions pkg/netrasp/testdata/smartax/enable_with_config/config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
gpon1#config

gpon1(config)#
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
gpon1(config)#display current-configuration

sysman server source telnet any-interface
sysman server source telnet ipv6 ::
sysman server source twamp any-interface
sysman server source ancp-proxy any-interface
sysman server source ipdr any-interface
#
undo evpn-route-origin igp
#
return

gpon1(config)#

3 changes: 3 additions & 0 deletions pkg/netrasp/testdata/smartax/enable_with_config/enable.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
gpon1>enable

gpon1#
6 changes: 6 additions & 0 deletions pkg/netrasp/testdata/smartax/enable_with_config/initial.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Welcome to the Dummy Device

Thanks for stopping by.


gpon1#
3 changes: 3 additions & 0 deletions pkg/netrasp/testdata/smartax/enable_with_config/quit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
gpon1(config)#quit

gpon1#
1 change: 1 addition & 0 deletions pkg/netrasp/testdata/smartax/enable_with_config/scroll.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gpon1#
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gpon1#