[SEBA-824] Shutting of and Powering on ONU

Change-Id: I6d797ba1182eb46e9edc887e9c7d8994be4585a2
diff --git a/internal/bbsimctl/commands/onu.go b/internal/bbsimctl/commands/onu.go
index 2e8f887..f99cb5c 100644
--- a/internal/bbsimctl/commands/onu.go
+++ b/internal/bbsimctl/commands/onu.go
@@ -19,6 +19,7 @@
 
 import (
 	"context"
+	"fmt"
 	"github.com/jessevdk/go-flags"
 	pb "github.com/opencord/bbsim/api/bbsim"
 	"github.com/opencord/bbsim/internal/bbsimctl/config"
@@ -26,33 +27,57 @@
 	log "github.com/sirupsen/logrus"
 	"google.golang.org/grpc"
 	"os"
+	"strings"
 )
 
 const (
 	DEFAULT_ONU_DEVICE_HEADER_FORMAT = "table{{ .PonPortID }}\t{{ .ID }}\t{{ .SerialNumber }}\t{{ .STag }}\t{{ .CTag }}\t{{ .OperState }}\t{{ .InternalState }}"
 )
 
-type ONUOptions struct{}
-
-func RegisterONUCommands(parser *flags.Parser) {
-	parser.AddCommand("onus", "List ONU Devices", "Commands to list the ONU devices and their internal state", &ONUOptions{})
+type OnuSnString string
+type ONUList struct{}
+type ONUShutDown struct {
+	Args struct {
+		OnuSn OnuSnString
+	} `positional-args:"yes" required:"yes"`
 }
 
-func getONUs() *pb.ONUs {
+type ONUPowerOn struct {
+	Args struct {
+		OnuSn OnuSnString
+	} `positional-args:"yes" required:"yes"`
+}
+
+type ONUOptions struct {
+	List     ONUList     `command:"list"`
+	ShutDown ONUShutDown `command:"shutdown"`
+	PowerOn  ONUPowerOn  `command:"poweron"`
+}
+
+func RegisterONUCommands(parser *flags.Parser) {
+	parser.AddCommand("onu", "ONU Commands", "Commands to query and manipulate ONU devices", &ONUOptions{})
+}
+
+func connect() (pb.BBSimClient, *grpc.ClientConn) {
 	conn, err := grpc.Dial(config.GlobalConfig.Server, grpc.WithInsecure())
 
 	if err != nil {
 		log.Fatalf("did not connect: %v", err)
-		return nil
+		return nil, conn
 	}
+	return pb.NewBBSimClient(conn), conn
+}
+
+func getONUs() *pb.ONUs {
+
+	client, conn := connect()
 	defer conn.Close()
-	c := pb.NewBBSimClient(conn)
 
 	// Contact the server and print out its response.
-
 	ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
 	defer cancel()
-	onus, err := c.GetONUs(ctx, &pb.Empty{})
+
+	onus, err := client.GetONUs(ctx, &pb.Empty{})
 	if err != nil {
 		log.Fatalf("could not get OLT: %v", err)
 		return nil
@@ -60,7 +85,7 @@
 	return onus
 }
 
-func (options *ONUOptions) Execute(args []string) error {
+func (options *ONUList) Execute(args []string) error {
 	onus := getONUs()
 
 	// print out
@@ -71,3 +96,69 @@
 
 	return nil
 }
+
+func (options *ONUShutDown) Execute(args []string) error {
+
+	client, conn := connect()
+	defer conn.Close()
+
+	ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+	defer cancel()
+	req := pb.ONURequest{
+		SerialNumber: string(options.Args.OnuSn),
+	}
+	res, err := client.ShutdownONU(ctx, &req)
+
+	if err != nil {
+		log.Fatalf("Cannot not shutdown ONU %s: %v", options.Args.OnuSn, err)
+		return err
+	}
+
+	fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+
+	return nil
+}
+
+func (options *ONUPowerOn) Execute(args []string) error {
+	client, conn := connect()
+	defer conn.Close()
+
+	ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+	defer cancel()
+	req := pb.ONURequest{
+		SerialNumber: string(options.Args.OnuSn),
+	}
+	res, err := client.PoweronONU(ctx, &req)
+
+	if err != nil {
+		log.Fatalf("Cannot not power on ONU %s: %v", options.Args.OnuSn, err)
+		return err
+	}
+
+	fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+
+	return nil
+}
+
+func (onuSn *OnuSnString) Complete(match string) []flags.Completion {
+	client, conn := connect()
+	defer conn.Close()
+
+	ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+	defer cancel()
+
+	onus, err := client.GetONUs(ctx, &pb.Empty{})
+	if err != nil {
+		log.Fatal("could not get ONUs: %v", err)
+		return nil
+	}
+
+	list := make([]flags.Completion, 0)
+	for _, k := range onus.Items {
+		if strings.HasPrefix(k.SerialNumber, match) {
+			list = append(list, flags.Completion{Item: k.SerialNumber})
+		}
+	}
+
+	return list
+}