Skip to content
Snippets Groups Projects
pnd.go 18.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • Manuel Kieweg's avatar
    Manuel Kieweg committed
    package server
    
    import (
    	"context"
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	"strings"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"time"
    
    
    	ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
    	spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/device"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkdomain"
    	"code.fbi.h-da.de/danet/gosdn/controller/metrics"
    	"code.fbi.h-da.de/danet/gosdn/controller/nucleus"
    	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/store"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"github.com/google/uuid"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"github.com/openconfig/ygot/ygot"
    
    Malte Bauch's avatar
    Malte Bauch committed
    	"github.com/prometheus/client_golang/prometheus"
    
    	log "github.com/sirupsen/logrus"
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	"google.golang.org/grpc/codes"
    	"google.golang.org/grpc/status"
    
    // PndServer implements a pnd server
    type PndServer struct {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	ppb.UnimplementedPndServiceServer
    
    	pndStore networkdomain.PndStore
    
    // NewPndServer receives a pndStore and returns a new pndServer.
    func NewPndServer(pndStore networkdomain.PndStore) *PndServer {
    	return &PndServer{
    		pndStore: pndStore,
    	}
    }
    
    // GetOnd gets a specific ond
    func (p PndServer) GetOnd(ctx context.Context, request *ppb.GetOndRequest) (*ppb.GetOndResponse, error) {
    
    Malte Bauch's avatar
    Malte Bauch committed
    	labels := prometheus.Labels{"service": "pnd", "rpc": "get"}
    	start := metrics.StartHook(labels, grpcRequestsTotal)
    	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	pid, err := uuid.Parse(request.Pid)
    	if err != nil {
    
    Malte Bauch's avatar
    Malte Bauch committed
    		return nil, handleRPCError(labels, err)
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    	device, err := pnd.GetDevice(request.Did)
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    	ond, err := fillOndBySpecificPath(pnd, device, "/")
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return &ppb.GetOndResponse{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    		Pnd: &ppb.PrincipalNetworkDomain{
    			Id:          pnd.ID().String(),
    			Name:        pnd.GetName(),
    			Description: pnd.GetDescription(),
    		},
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}, nil
    }
    
    
    // GetOndList returns a list of existing onds
    func (p PndServer) GetOndList(ctx context.Context, request *ppb.GetOndListRequest) (*ppb.GetOndListResponse, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	labels := prometheus.Labels{"service": "pnd", "rpc": "get"}
    	start := metrics.StartHook(labels, grpcRequestsTotal)
    	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
    	pid, err := uuid.Parse(request.Pid)
    	if err != nil {
    		return nil, handleRPCError(labels, err)
    	}
    
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    	onds := pnd.Devices()
    	ondsBySpecificPath := make([]*ppb.OrchestratedNetworkingDevice, len(onds))
    	for i, ond := range onds {
    		ond, err := fillOndBySpecificPath(pnd, ond, "/")
    
    		if err != nil {
    			log.Error(err)
    			return nil, status.Errorf(codes.Aborted, "%v", err)
    		}
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return &ppb.GetOndListResponse{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Pnd: &ppb.PrincipalNetworkDomain{
    			Id:          pnd.ID().String(),
    			Name:        pnd.GetName(),
    			Description: pnd.GetDescription(),
    		},
    
    func fillOndBySpecificPath(pnd networkdomain.NetworkDomain, d device.Device, path string) (*ppb.OrchestratedNetworkingDevice, error) {
    
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    
    	opts := []ytypes.GetNodeOpt{
    		&ytypes.GetHandleWildcards{},
    		&ytypes.GetPartialKeyMatch{},
    	}
    
    Andre Sterba's avatar
    Andre Sterba committed
    	nodes, err := ytypes.GetNode(d.SBI().Schema().RootSchema(), d.GetModel(), gnmiPath, opts...)
    
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    
    	devices := make([]*gnmi.Notification, len(nodes))
    	for i, node := range nodes {
    		dev, err := genGnmiNotification(gnmiPath, node.Data)
    
    		if err != nil {
    			log.Error(err)
    			return nil, status.Errorf(codes.Aborted, "%v", err)
    		}
    
    	}
    
    	sbi := spb.SouthboundInterface{}
    	if d.SBI() != nil {
    		sbi.Id = d.SBI().ID().String()
    		sbi.Type = d.SBI().Type()
    	}
    
    	ond := &ppb.OrchestratedNetworkingDevice{
    		Id:     d.ID().String(),
    		Name:   d.Name(),
    
    func genGnmiNotification(path *gnmi.Path, val any) (*gnmi.Notification, error) {
    	typedVal, err := ygot.EncodeTypedValue(val, gnmi.Encoding_JSON_IETF)
    
    	return &gnmi.Notification{
    		Timestamp: time.Now().UnixNano(),
    		Update: []*gnmi.Update{
    			{
    				Path: &gnmi.Path{
    					Elem: path.GetElem(),
    
    // GetSbi gets a specific sbi
    func (p PndServer) GetSbi(ctx context.Context, request *ppb.GetSbiRequest) (*ppb.GetSbiResponse, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	labels := prometheus.Labels{"service": "pnd", "rpc": "get"}
    	start := metrics.StartHook(labels, grpcRequestsTotal)
    	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
    	pid, err := uuid.Parse(request.Pid)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		return nil, handleRPCError(labels, err)
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    
    	sbiID, err := uuid.Parse(request.Sid)
    	if err != nil {
    		return nil, err
    	}
    
    	sbi, err := pnd.GetSBI(sbiID)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return &ppb.GetSbiResponse{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Pnd: &ppb.PrincipalNetworkDomain{
    			Id:          pnd.ID().String(),
    			Name:        pnd.GetName(),
    			Description: pnd.GetDescription(),
    		},
    
    		Sbi: &spb.SouthboundInterface{
    			Id:   sbiID.String(),
    			Type: sbi.Type(),
    		},
    
    // GetSbiList gets all existing sbis
    func (p PndServer) GetSbiList(ctx context.Context, request *ppb.GetSbiListRequest) (*ppb.GetSbiListResponse, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	labels := prometheus.Labels{"service": "pnd", "rpc": "get"}
    	start := metrics.StartHook(labels, grpcRequestsTotal)
    	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
    	pid, err := uuid.Parse(request.Pid)
    
    	if err != nil {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		return nil, handleRPCError(labels, err)
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return &ppb.GetSbiListResponse{
    
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Pnd: &ppb.PrincipalNetworkDomain{
    			Id:          pnd.ID().String(),
    			Name:        pnd.GetName(),
    			Description: pnd.GetDescription(),
    		},
    		Sbi: sbis,
    
    func fillSbis(pnd networkdomain.NetworkDomain) ([]*spb.SouthboundInterface, error) {
    
    	sbis, err := pnd.GetSBIs()
    	if err != nil {
    		return nil, err
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    	fmt.Printf("SBIS: %+v\n", sbis)
    
    	sbisToReturn := []*spb.SouthboundInterface{}
    
    	for _, sbi := range sbis {
    		sbisToReturn = append(sbisToReturn, &spb.SouthboundInterface{
    			Id: sbi.ID().String(),
    		})
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    
    	fmt.Printf("SBIS: %+v\n", sbisToReturn)
    
    	return sbisToReturn, nil
    
    func stringArrayToUUIDs(sid []string) ([]uuid.UUID, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	UUIDs := make([]uuid.UUID, len(sid))
    	for i, id := range sid {
    		parsed, err := uuid.Parse(id)
    		if err != nil {
    
    			log.Error(err)
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    			return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		UUIDs[i] = parsed
    	}
    	return UUIDs, nil
    }
    
    // GetPath gets a path on a ond
    func (p PndServer) GetPath(ctx context.Context, request *ppb.GetPathRequest) (*ppb.GetPathResponse, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	labels := prometheus.Labels{"service": "pnd", "rpc": "get"}
    	start := metrics.StartHook(labels, grpcRequestsTotal)
    	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
    	pid, err := uuid.Parse(request.Pid)
    	if err != nil {
    		return nil, handleRPCError(labels, err)
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    
    	device, err := pnd.GetDevice(request.Did)
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	duid, err := uuid.Parse(request.Did)
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	// In case we get the path from grpc-gateway we have to replace
    	path := strings.ReplaceAll(request.Path, "||", "/")
    
    	_, err = pnd.Request(duid, path)
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    	ond, err := fillOndBySpecificPath(pnd, device, path)
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return &ppb.GetPathResponse{
    		Timestamp: time.Now().UnixNano(),
    		Pnd: &ppb.PrincipalNetworkDomain{
    			Id:          pnd.ID().String(),
    			Name:        pnd.GetName(),
    			Description: pnd.GetDescription(),
    		},
    
    // GetChange gets a specific change of a ond
    func (p PndServer) GetChange(ctx context.Context, request *ppb.GetChangeRequest) (*ppb.GetChangeResponse, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	labels := prometheus.Labels{"service": "pnd", "rpc": "get"}
    	start := metrics.StartHook(labels, grpcRequestsTotal)
    	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
    	pid, err := uuid.Parse(request.Pid)
    	if err != nil {
    		return nil, handleRPCError(labels, err)
    	}
    
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    	changes, err := fillChanges(pnd, false, request.Cuid...)
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    	return &ppb.GetChangeResponse{
    		Timestamp: time.Now().UnixNano(),
    		Pnd: &ppb.PrincipalNetworkDomain{
    			Id:          pnd.ID().String(),
    			Name:        pnd.GetName(),
    			Description: pnd.GetDescription(),
    		},
    		Change: changes,
    	}, nil
    }
    
    
    // GetChangeList gets all existing changes
    func (p PndServer) GetChangeList(ctx context.Context, request *ppb.GetChangeListRequest) (*ppb.GetChangeListResponse, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	labels := prometheus.Labels{"service": "pnd", "rpc": "get"}
    	start := metrics.StartHook(labels, grpcRequestsTotal)
    	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
    	pid, err := uuid.Parse(request.Pid)
    	if err != nil {
    		return nil, handleRPCError(labels, err)
    	}
    
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    	changes, err := fillChanges(pnd, true, "")
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    	return &ppb.GetChangeListResponse{
    		Timestamp: time.Now().UnixNano(),
    		Pnd: &ppb.PrincipalNetworkDomain{
    			Id:          pnd.ID().String(),
    			Name:        pnd.GetName(),
    			Description: pnd.GetDescription(),
    		},
    		Change: changes,
    	}, nil
    
    func fillChanges(pnd networkdomain.NetworkDomain, all bool, cuid ...string) ([]*ppb.Change, error) {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	var changeList []uuid.UUID
    
    	switch all {
    	case true:
    		changeList = pnd.PendingChanges()
    		changeList = append(changeList, pnd.CommittedChanges()...)
    	default:
    		var err error
    		if len(cuid) == 0 {
    			return nil, &errors.ErrInvalidParameters{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    				Param: "length of 'did' cannot be '0' when 'all' is set to 'false'",
    			}
    		}
    
    		changeList, err = stringArrayToUUIDs(cuid)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		if err != nil {
    
    			log.Error(err)
    			return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		}
    	}
    
    	changes := make([]*ppb.Change, len(changeList))
    	for i, ch := range changeList {
    		c, err := pnd.GetChange(ch)
    		if err != nil {
    
    			log.Error(err)
    			return nil, status.Errorf(codes.Aborted, "%v", err)
    
    		diff, err := ygot.Diff(c.PreviousState(), c.IntendedState())
    		if err != nil {
    			log.Error(err)
    			return nil, status.Errorf(codes.Aborted, "%v", err)
    		}
    
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		changes[i] = &ppb.Change{
    			Id:    ch.String(),
    
    			Age:   c.Age().Microseconds(),
    			State: c.State(),
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		}
    	}
    	return changes, nil
    }
    
    
    // SetOndList updates the list of onds
    func (p PndServer) SetOndList(ctx context.Context, request *ppb.SetOndListRequest) (*ppb.SetOndListResponse, error) {
    
    Malte Bauch's avatar
    Malte Bauch committed
    	labels := prometheus.Labels{"service": "pnd", "rpc": "set"}
    	start := metrics.StartHook(labels, grpcRequestsTotal)
    	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	pid, err := uuid.Parse(request.Pid)
    	if err != nil {
    
    Malte Bauch's avatar
    Malte Bauch committed
    		return nil, handleRPCError(labels, err)
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	if err != nil {
    
    Malte Bauch's avatar
    Malte Bauch committed
    		return nil, handleRPCError(labels, err)
    
    	deviceIDs := make([]uuid.UUID, 0, len(request.Ond))
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	for _, r := range request.Ond {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		sid, err := uuid.Parse(r.Sbi.Id)
    		if err != nil {
    
    			log.Error(err)
    			return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		}
    
    		did, err := pnd.AddDevice(r.DeviceName, r.TransportOption, sid)
    		if err != nil {
    
    			log.Error(err)
    			return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		}
    
    		deviceIDs = append(deviceIDs, did)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    
    	r := make([]*ppb.SetResponse, len(deviceIDs))
    	for i, did := range deviceIDs {
    		r[i] = &ppb.SetResponse{Id: did.String(), Status: ppb.Status_STATUS_OK}
    	}
    
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return &ppb.SetOndListResponse{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Status:    ppb.Status_STATUS_OK,
    
    // SetChangeList sets a list of changes
    func (p PndServer) SetChangeList(ctx context.Context, request *ppb.SetChangeListRequest) (*ppb.SetChangeListResponse, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	labels := prometheus.Labels{"service": "pnd", "rpc": "set"}
    	start := metrics.StartHook(labels, grpcRequestsTotal)
    	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
    	pid, err := uuid.Parse(request.Pid)
    	if err != nil {
    		return nil, handleRPCError(labels, err)
    	}
    
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	if err != nil {
    		return nil, handleRPCError(labels, err)
    	}
    
    
    	responses := make([]*ppb.SetResponse, len(request.Change))
    
    	for i, r := range request.Change {
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		cuid, err := uuid.Parse(r.Cuid)
    		if err != nil {
    
    			log.Error(err)
    			return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		}
    		switch r.Op {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		case ppb.Operation_OPERATION_COMMIT:
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			if err := pnd.Commit(cuid); err != nil {
    
    				log.Error(err)
    				return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		case ppb.Operation_OPERATION_CONFIRM:
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			if err := pnd.Confirm(cuid); err != nil {
    
    				log.Error(err)
    				return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    			}
    		default:
    			return nil, &errors.ErrInvalidParameters{
    				Param: r.Op,
    			}
    		}
    
    
    		responses[i] = &ppb.SetResponse{
    			Id:     cuid.String(),
    			Status: ppb.Status_STATUS_OK,
    		}
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return &ppb.SetChangeListResponse{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Status:    ppb.Status_STATUS_OK,
    
    // SetPathList sets a list of paths
    func (p PndServer) SetPathList(ctx context.Context, request *ppb.SetPathListRequest) (*ppb.SetPathListResponse, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	labels := prometheus.Labels{"service": "pnd", "rpc": "set"}
    	start := metrics.StartHook(labels, grpcRequestsTotal)
    	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
    	pid, err := uuid.Parse(request.Pid)
    	if err != nil {
    		return nil, handleRPCError(labels, err)
    	}
    
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	if err != nil {
    		return nil, handleRPCError(labels, err)
    	}
    
    
    	responses := make([]*ppb.SetResponse, len(request.ChangeRequest))
    
    	for i, r := range request.ChangeRequest {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		did, err := uuid.Parse(r.Did)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		if err != nil {
    
    			log.Error(err)
    			return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		}
    
    		cid, err := pnd.ChangeOND(did, r.ApiOp, r.Path, r.Value)
    
    			log.Error(err)
    			return nil, status.Errorf(codes.Aborted, "%v", err)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		}
    
    
    		responses[i] = &ppb.SetResponse{
    			Status: ppb.Status_STATUS_OK,
    			Id:     cid.String(),
    		}
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return &ppb.SetPathListResponse{
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Status:    ppb.Status_STATUS_OK,
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	}, nil
    }
    
    // SetSbiList sets a list of sbis
    func (p PndServer) SetSbiList(ctx context.Context, request *ppb.SetSbiListRequest) (*ppb.SetSbiListResponse, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	labels := prometheus.Labels{"service": "pnd", "rpc": "set"}
    	start := metrics.StartHook(labels, grpcRequestsTotal)
    	defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds)
    	pid, err := uuid.Parse(request.Pid)
    	if err != nil {
    		return nil, handleRPCError(labels, err)
    	}
    
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	if err != nil {
    		return nil, handleRPCError(labels, err)
    	}
    
    	for _, r := range request.Sbi {
    		sbiType := filterSbiType(r.SbiType)
    		sbi, err := nucleus.NewSBI(sbiType)
    		if err != nil {
    			return nil, handleRPCError(labels, err)
    		}
    
    		err = pnd.AddSbi(sbi)
    		if err != nil {
    			return nil, handleRPCError(labels, err)
    		}
    	}
    
    	return &ppb.SetSbiListResponse{
    		Timestamp: time.Now().UnixNano(),
    		Status:    ppb.Status_STATUS_OK,
    		Responses: []*ppb.SetResponse{
    			{
    				Status: ppb.Status_STATUS_OK,
    			},
    		},
    	}, nil
    }
    
    func filterSbiType(sbiType ppb.SbiType) spb.Type {
    	var spbType spb.Type
    
    	switch sbiType {
    	case ppb.SbiType_SBI_TYPE_OPENCONFIG:
    		spbType = spb.Type_TYPE_OPENCONFIG
    	case ppb.SbiType_SBI_TYPE_CONTAINERISED:
    		spbType = spb.Type_TYPE_CONTAINERISED
    	case ppb.SbiType_SBI_TYPE_PLUGIN:
    		spbType = spb.Type_TYPE_PLUGIN
    	default:
    		spbType = spb.Type_TYPE_UNSPECIFIED
    	}
    
    	return spbType
    }
    
    
    // DeleteOnd deletes a ond
    func (p PndServer) DeleteOnd(ctx context.Context, request *ppb.DeleteOndRequest) (*ppb.DeleteOndResponse, error) {
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	pid, err := uuid.Parse(request.Pid)
    
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    	pnd, err := p.pndStore.Get(store.Query{ID: pid})
    
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	did, err := uuid.Parse(request.Did)
    
    	if err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    	if err := pnd.RemoveDevice(did); err != nil {
    		log.Error(err)
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	return &ppb.DeleteOndResponse{
    
    		Timestamp: time.Now().UnixNano(),
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		Status:    ppb.Status_STATUS_OK,