Skip to content
Snippets Groups Projects
grpc.go 11.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • Manuel Kieweg's avatar
    Manuel Kieweg committed
    package api
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    
    import (
    	"context"
    	"errors"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"time"
    
    
    	pb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/core"
    	ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
    
    	apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac"
    
    	spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
    	tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
    	nbi "code.fbi.h-da.de/danet/gosdn/controller/northbound/client"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"github.com/google/uuid"
    
    	"github.com/openconfig/goyang/pkg/yang"
    	"github.com/openconfig/ygot/ygot"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	log "github.com/sirupsen/logrus"
    	"github.com/spf13/viper"
    
    	"google.golang.org/grpc"
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	"google.golang.org/grpc/credentials/insecure"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    )
    
    var dialOptions []grpc.DialOption
    
    func init() {
    	dialOptions = []grpc.DialOption{
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		grpc.WithTransportCredentials(insecure.NewCredentials()),
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    }
    
    // Init initialises the CLI client.
    func Init(addr string) error {
    	ctx := context.Background()
    
    	resp, err := GetAllCore(ctx, addr)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    		return err
    	}
    	if len(resp.Pnd) > 0 {
    		pid := resp.Pnd[0].Id
    		viper.Set("CLI_PND", pid)
    		log.Infof("PND: %v", pid)
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		// if len(resp.Pnd[0].Sbi) != 0 {
    		// 	sbi := resp.Pnd[0].Sbi[0].Id
    		// 	viper.Set("CLI_SBI", sbi)
    		// 	log.Infof("SBI: %v", sbi)
    		// }
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    	return viper.WriteConfig()
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    }
    
    // GetIds requests all UUID information from the controller
    func GetIds(addr string) ([]*ppb.PrincipalNetworkDomain, error) {
    	ctx := context.Background()
    
    	resp, err := GetAllCore(ctx, addr)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    		return nil, err
    	}
    	return resp.Pnd, nil
    }
    
    
    // GetAllCore requests all PNDs
    
    func GetAllCore(ctx context.Context, addr string) (*pb.GetPndListResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	coreClient, err := nbi.CoreClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	req := &pb.GetPndListRequest{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return coreClient.GetPndList(ctx, req)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    }
    
    // AddPnd takes a name, description and SBI UUID to create a new
    // PrincipalNetworkDomain on the controller
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    func AddPnd(addr, name, description, sbi string) (*pb.CreatePndListResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	coreClient, err := nbi.CoreClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    	ctx := context.Background()
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	req := &pb.CreatePndListRequest{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Pnd: []*pb.PndCreateProperties{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			{
    				Name:        name,
    				Description: description,
    				Sbi:         sbi,
    			},
    		},
    	}
    
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return coreClient.CreatePndList(ctx, req)
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    // GetPnd requests one PrincipalNetworkDomain from the
    // controller.
    func GetPnd(addr string, args ...string) (*pb.GetPndResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	coreClient, err := nbi.CoreClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    	if len(args) <= 0 {
    		return nil, errors.New("not enough arguments")
    	}
    	ctx := context.Background()
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	req := &pb.GetPndRequest{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    		Pid:       args,
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return coreClient.GetPnd(ctx, req)
    }
    
    // GetPnds requests all PrincipalNetworkDomains from the
    // controller.
    func GetPnds(addr string, args ...string) (*pb.GetPndListResponse, error) {
    	coreClient, err := nbi.CoreClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    	if len(args) <= 0 {
    		return nil, errors.New("not enough arguments")
    	}
    	ctx := context.Background()
    	req := &pb.GetPndListRequest{
    		Timestamp: time.Now().UnixNano(),
    	}
    	return coreClient.GetPndList(ctx, req)
    
    // DeletePnd requests a deletion of the provided PND.
    func DeletePnd(addr string, pid string) (*pb.DeletePndResponse, error) {
    
    	coreClient, err := nbi.CoreClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    	ctx := context.Background()
    	req := &pb.DeletePndRequest{
    		Timestamp: time.Now().UnixNano(),
    		Pid:       pid,
    	}
    	return coreClient.DeletePnd(ctx, req)
    }
    
    
    // GetSbi requests one or more to the provided PND belonging SBIs from the
    // controller.
    func GetSbi(addr string, pid string, sid ...string) (*ppb.GetSbiResponse, error) {
    	client, err := nbi.PndClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    	ctx := context.Background()
    	req := &ppb.GetSbiRequest{
    		Timestamp: time.Now().UnixNano(),
    		Pid:       pid,
    		Sid:       sid,
    	}
    	return client.GetSbi(ctx, req)
    }
    
    //GetSBIs requests all to the provided PND belonging SBIs from the controller.
    func GetSBIs(addr string, pid string) (*ppb.GetSbiListResponse, error) {
    	client, err := nbi.PndClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    	ctx := context.Background()
    	req := &ppb.GetSbiListRequest{
    		Timestamp: time.Now().UnixNano(),
    		Pid:       pid,
    	}
    	return client.GetSbiList(ctx, req)
    }
    
    // GetChanges requests all pending and unconfirmed changes from the controller
    func GetChanges(addr, pnd string) (*ppb.GetChangeListResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	ctx := context.Background()
    	client, err := nbi.PndClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	req := &ppb.GetChangeListRequest{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Pid:       pnd,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return client.GetChangeList(ctx, req)
    
    // Commit sends a Commit request for one or multiple changes to the
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // controller.
    
    func Commit(addr, pnd string, cuids ...string) (*ppb.SetChangeListResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	changes := make([]*ppb.SetChange, len(cuids))
    	for i, arg := range cuids {
    		changes[i] = &ppb.SetChange{
    			Cuid: arg,
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    			Op:   ppb.Operation_OPERATION_COMMIT,
    
    	return CommitConfirm(addr, pnd, changes)
    
    // Confirm sends a Confirm request for one or multiple changes to the
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // controller
    
    func Confirm(addr, pnd string, cuids ...string) (*ppb.SetChangeListResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	changes := make([]*ppb.SetChange, len(cuids))
    	for i, arg := range cuids {
    		changes[i] = &ppb.SetChange{
    			Cuid: arg,
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    			Op:   ppb.Operation_OPERATION_CONFIRM,
    
    	return CommitConfirm(addr, pnd, changes)
    
    // CommitConfirm confirms a commit
    
    func CommitConfirm(addr, pnd string, changes []*ppb.SetChange) (*ppb.SetChangeListResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	ctx := context.Background()
    	client, err := nbi.PndClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	req := &ppb.SetChangeListRequest{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    		Change:    changes,
    		Pid:       pnd,
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return client.SetChangeList(ctx, req)
    
    // AddDevice adds a new device to the controller. The device name is optional.
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // If no name is provided a name will be generated upon device creation.
    
    func AddDevice(addr, deviceName string, opt *tpb.TransportOption, sid, pid uuid.UUID) (*ppb.SetOndListResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	pndClient, err := nbi.PndClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	req := &ppb.SetOndListRequest{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    		Ond: []*ppb.SetOnd{
    			{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				Address: opt.GetAddress(),
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				Sbi: &spb.SouthboundInterface{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    					Id: sid.String(),
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				DeviceName:      deviceName,
    				TransportOption: opt,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			},
    		},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Pid: pid.String(),
    	}
    
    Malte Bauch's avatar
    Malte Bauch committed
    	switch t := opt.Type; t {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	case spb.Type_TYPE_CONTAINERISED, spb.Type_TYPE_PLUGIN:
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		req.Ond[0].Sbi.Id = uuid.Nil.String()
    
    Malte Bauch's avatar
    Malte Bauch committed
    		req.Ond[0].Sbi.Type = t
    		req.Ond[0].TransportOption.Type = t
    	default:
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    	ctx := context.Background()
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return pndClient.SetOndList(ctx, req)
    
    // GetDevice requests one device belonging to a given
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // PrincipalNetworkDomain from the controller. If no device identifier
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    // is provided, an error is thrown.
    
    func GetDevice(addr, pid string, did ...string) (*ppb.GetOndResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	pndClient, err := nbi.PndClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    
    	if len(did) == 0 {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		return nil, err
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	req := &ppb.GetOndRequest{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Did:       did,
    		Pid:       pid,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    	ctx := context.Background()
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return pndClient.GetOnd(ctx, req)
    
    // GetSbiSchemaTree gets the sbi tree for a sbi
    
    func GetSbiSchemaTree(addr string, pid, sid uuid.UUID) (map[string]*yang.Entry, error) {
    	sbiClient, err := nbi.SbiClient(addr, dialOptions...)
    	if err != nil {
    		return map[string]*yang.Entry{}, err
    	}
    
    	req := &spb.GetSchemaRequest{
    		Timestamp: time.Now().UnixNano(),
    		Pid:       pid.String(),
    		Sid:       sid.String(),
    	}
    
    	ctx, cancel := context.WithTimeout(context.Background(), time.Minute*10)
    	defer cancel()
    	sClient, err := sbiClient.GetSchema(ctx, req)
    	if err != nil {
    		return map[string]*yang.Entry{}, err
    	}
    
    	sTreeBytes := []byte{}
    
    	for {
    		payload, err := sClient.Recv()
    		if err != nil {
    			if err == io.EOF {
    				break
    			}
    			log.Error(err)
    			sClient.CloseSend()
    			return map[string]*yang.Entry{}, err
    		}
    		sTreeBytes = append(sTreeBytes, payload.Chunk...)
    	}
    
    	sTreeMap, err := ygot.GzipToSchema(sTreeBytes)
    	if err != nil {
    		return map[string]*yang.Entry{}, err
    	}
    
    	return sTreeMap, nil
    }
    
    // GetDevices requests all devices belonging to a given
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    // PrincipalNetworkDomain from the controller.
    
    func GetDevices(addr, pid string) (*ppb.GetOndListResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	pndClient, err := nbi.PndClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	req := &ppb.GetOndListRequest{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Pid:       pid,
    	}
    	ctx := context.Background()
    	return pndClient.GetOndList(ctx, req)
    }
    
    
    // GetPath requests a specific path
    
    func GetPath(addr, pid, did, path string) (*ppb.GetPathResponse, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	pndClient, err := nbi.PndClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    
    	req := &ppb.GetPathRequest{
    		Timestamp: time.Now().UnixNano(),
    		Did:       did,
    		Pid:       pid,
    		Path:      path,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    	ctx := context.Background()
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return pndClient.GetPath(ctx, req)
    
    // DeleteDevice deletes a device
    
    func DeleteDevice(addr, pid, did string) (*ppb.DeleteOndResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	pndClient, err := nbi.PndClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	req := &ppb.DeleteOndRequest{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Did:       did,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Pid:       pid,
    	}
    	ctx := context.Background()
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return pndClient.DeleteOnd(ctx, req)
    
    // ChangeRequest change creates a ChangeRequest for the specified OND. ApiOperations are
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    // used to specify the type of the change (update, replace, delete as specified
    // in https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md#34-modifying-state)
    // For delete operations the value field needs to contain an empty string.
    
    func ChangeRequest(addr, did, pid, path, value string, op ppb.ApiOperation) (*ppb.SetPathListResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	req := &ppb.ChangeRequest{
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Did:   did,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Path:  path,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Value: value,
    		ApiOp: op,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    	return SendChangeRequest(addr, pid, req)
    
    // SendChangeRequest sends a change request
    
    func SendChangeRequest(addr, pid string, req *ppb.ChangeRequest) (*ppb.SetPathListResponse, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	pndClient, err := nbi.PndClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    	ctx := context.Background()
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	r := &ppb.SetPathListRequest{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp:     time.Now().UnixNano(),
    		ChangeRequest: []*ppb.ChangeRequest{req},
    		Pid:           pid,
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return pndClient.SetPathList(ctx, r)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    }
    
    func Login(addr, username, pwd string) (*apb.LoginResponse, error) {
    	authClient, err := nbi.AuthClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    	ctx := context.Background()
    	r := &apb.LoginRequest{
    		Timestamp: time.Now().UnixNano(),
    		Username:  username,
    		Pwd:       pwd,
    	}
    	return authClient.Login(ctx, r)
    }
    
    
    func Logout(addr, username string) (*apb.LogoutResponse, error) {
    	authClient, err := nbi.AuthClient(addr, dialOptions...)
    	if err != nil {
    		return nil, err
    	}
    	ctx := context.Background()
    	r := &apb.LogoutRequest{
    		Timestamp: time.Now().UnixNano(),
    		Username:  username,
    	}
    	return authClient.Logout(ctx, r)
    }