Skip to content
Snippets Groups Projects
PndAdapter.go 8.27 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	mnepb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
    
    	prb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-registry"
    
    	ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
    
    	tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
    	"code.fbi.h-da.de/danet/gosdn/controller/api"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/customerrs"
    
    	"github.com/google/uuid"
    
    	"github.com/openconfig/gnmi/proto/gnmi"
    
    	"github.com/openconfig/goyang/pkg/yang"
    	"golang.org/x/sync/errgroup"
    	"google.golang.org/protobuf/proto"
    )
    
    // PndAdapter is an API adapter to reflect the NetworkDomain
    
    type PndAdapter struct {
    	id       uuid.UUID
    	endpoint string
    }
    
    
    // NewPndAdapter creates a PND Adapter. It requires a valid PND UUID and a reachable
    
    // goSDN endpoint.
    func NewPndAdapter(id, endpoint string) (*PndAdapter, error) {
    	pid, err := uuid.Parse(id)
    	if err != nil {
    		return nil, err
    	}
    	return &PndAdapter{
    		id:       pid,
    		endpoint: endpoint,
    	}, nil
    }
    
    
    func (p *PndAdapter) GetAvailablePlugins(ctx context.Context) (*prb.GetResponse, error) {
    	return api.GetAvailablePlugins(ctx, p.endpoint)
    
    // RemoveSbi removes an SBI from the PND Adapter. Currently not implemented.
    
    func (p *PndAdapter) RemoveSbi(uuid.UUID) error {
    
    // AddNetworkElement adds a new device to the controller. The device name is optional.
    
    // If no name is provided a name will be generated upon device creation.
    
    func (p *PndAdapter) AddNetworkElement(ctx context.Context, name, mneUUID string, opts *tpb.TransportOption, pluginId uuid.UUID, gNMISubscribePaths []string) (*mnepb.AddListResponse, error) {
    	return api.AddNetworkElement(ctx, p.endpoint, name, mneUUID, opts, pluginId, p.ID(), gNMISubscribePaths)
    
    // GetPluginSchemaTree requests a plugin schema tree.
    func (p *PndAdapter) GetPluginSchemaTree(ctx context.Context, pluginID uuid.UUID) (map[string]*yang.Entry, error) {
    	return api.GetPluginSchemaTree(ctx, p.Endpoint(), pluginID)
    
    // GetNetworkElement requests one or multiple devices belonging to a given
    
    // PrincipalNetworkDomain from the controller.
    
    func (p *PndAdapter) GetNetworkElement(ctx context.Context, identifier string) (*mnepb.GetResponse, error) {
    
    	return api.GetNetworkElement(ctx, p.endpoint, p.id.String(), identifier)
    
    // GetFlattenedNetworkElements requests a device belonging to the
    // PrincipalNetworkDomain attached to this adapter.
    
    func (p *PndAdapter) GetFlattenedNetworkElement(ctx context.Context, identifier string) (*mnepb.GetFlattenedResponse, error) {
    
    	return api.GetFlattenedNetworkElement(ctx, p.endpoint, p.id.String(), identifier)
    }
    
    // GetFlattenedNetworkElements requests all devices belonging to the
    // PrincipalNetworkDomain attached to this adapter.
    
    func (p *PndAdapter) GetFlattenedNetworkElements(ctx context.Context) (*mnepb.GetAllFlattenedResponse, error) {
    
    	return api.GetFlattenedNetworkElements(ctx, p.endpoint, p.id.String())
    
    // RemoveNetworkElement removes a device from the controller.
    
    func (p *PndAdapter) RemoveNetworkElement(ctx context.Context, did uuid.UUID) (*mnepb.DeleteResponse, error) {
    
    	return api.DeleteNetworkElement(ctx, p.endpoint, p.id.String(), did.String())
    
    // RemovePnd removes a PND from the controller.
    
    func (p *PndAdapter) RemovePnd(ctx context.Context, pid uuid.UUID) (*ppb.DeletePndResponse, error) {
    
    	return api.DeletePnd(ctx, p.endpoint, pid.String())
    
    // ChangeMNE sends an API call to the controller requesting the creation of
    
    // a change from the provided Operation, path and value. The Change is marked
    
    // as Pending and times out after the specified timeout period.
    
    func (p *PndAdapter) ChangeMNE(ctx context.Context, duid uuid.UUID, operation mnepb.ApiOperation, path *gnmi.Path, value *gnmi.TypedValue) (*mnepb.SetPathListResponse, error) {
    	return api.ChangeRequest(ctx, p.endpoint, duid.String(), p.id.String(), path, value, operation)
    
    }
    
    // Request sends an API call to the controller requesting the specified path
    
    func (p *PndAdapter) RequestPath(ctx context.Context, did uuid.UUID, path string) (*mnepb.GetPathResponse, error) {
    
    	return api.GetPath(ctx, p.endpoint, p.id.String(), did.String(), path)
    
    // RequestIntendedPath sends an API call to the controller requesting the specified intended path
    // for the specified device.
    func (p *PndAdapter) RequestIntendedPath(ctx context.Context, did uuid.UUID, intendedPath string) (*mnepb.GetIntendedPathResponse, error) {
    	return api.GetIntendedPath(ctx, p.endpoint, p.id.String(), did.String(), intendedPath)
    }
    
    
    // SubscribeMNEPath sends an API call to the controller requesting to subscribe
    
    // to a specific path of a specifc device.
    
    func (p *PndAdapter) SubscribeMNEPath(ctx context.Context, did uuid.UUID, slist *mnepb.SubscriptionList) (mnepb.NetworkElementService_SubscribePathClient, error) {
    
    	return api.SubscribePath(ctx, p.endpoint, p.id.String(), did.String(), slist)
    
    // RequestAll sends an API call to the controller requesting the specified path
    // for all registered devices. Not yet implemented.
    
    func (p *PndAdapter) RequestAll(ctx context.Context, path string) ([]proto.Message, error) {
    
    	resp, err := api.GetFlattenedNetworkElements(ctx, p.Endpoint(), p.ID().String())
    
    	if err != nil {
    		return []proto.Message{}, err
    	}
    
    	reqResult := make([]proto.Message, len(resp.Mne))
    
    	g := new(errgroup.Group)
    
    	for i, mne := range resp.Mne {
    
    		// TODO: probably the controller should do this; this would result in a
    		// single request from CLI side.
    		g.Go(func() error {
    
    			resp, err := api.GetPath(ctx, p.endpoint, p.id.String(), mne.GetId(), path)
    
    			if err != nil {
    				return err
    			}
    			reqResult[i] = resp
    			return nil
    		})
    	}
    	if err := g.Wait(); err != nil {
    		// return the parts that succeeded, aswell as the errors that have been
    		// encountered
    		return reqResult, err
    	}
    	return reqResult, nil
    }
    
    
    // ContainsNetworkElement sends an API call to the controller checking if a device
    
    // with the given UUID is present. Not implemented, always returns false.
    
    func (p *PndAdapter) ContainsNetworkElement(uuid.UUID) bool {
    
    // ID returns the PND Adapter's UUID.
    
    func (p *PndAdapter) ID() uuid.UUID {
    	return p.id
    }
    
    
    // Endpoint returns the PND Adapter's endpoint.
    
    func (p *PndAdapter) Endpoint() string {
    	return p.endpoint
    }
    
    // PendingChanges sends an API call to the controller requesting
    
    // the UUIDs of all pending changes.
    
    func (p *PndAdapter) PendingChanges(ctx context.Context) ([]*mnepb.Change, error) {
    
    	resp, err := api.GetChanges(ctx, p.endpoint, p.id.String())
    
    	return filterChanges(mnepb.ChangeState_CHANGE_STATE_PENDING, resp), nil
    
    }
    
    // CommittedChanges sends an API call to the controller requesting
    
    // the UUIDs of all committed changes.
    
    func (p *PndAdapter) CommittedChanges(ctx context.Context) ([]*mnepb.Change, error) {
    
    	resp, err := api.GetChanges(ctx, p.endpoint, p.id.String())
    
    	return filterChanges(mnepb.ChangeState_CHANGE_STATE_COMMITTED, resp), nil
    
    // ConfirmedChanges sends an API call to the controller requesting
    
    // the UUIDs of all confirmed changes.
    
    func (p *PndAdapter) ConfirmedChanges(ctx context.Context) ([]*mnepb.Change, error) {
    
    	resp, err := api.GetChanges(ctx, p.endpoint, p.id.String())
    	if err != nil {
    		return nil, err
    	}
    
    	return filterChanges(mnepb.ChangeState_CHANGE_STATE_CONFIRMED, resp), nil
    
    }
    
    // GetChange sends an API call to the controller requesting one or more changes
    
    func (p *PndAdapter) GetChange(ctx context.Context, identifier ...string) (*mnepb.GetChangeResponse, error) {
    
    	return api.GetChange(ctx, p.endpoint, p.id.String(), identifier...)
    
    // Commit sends an API call to the controller committing the specified change.
    
    func (p *PndAdapter) Commit(ctx context.Context, cuid uuid.UUID) (*mnepb.SetChangeListResponse, error) {
    
    	return api.Commit(ctx, p.endpoint, p.id.String(), cuid.String())
    
    // Confirm sends an API call to the controller confirming the specified change.
    
    func (p *PndAdapter) Confirm(ctx context.Context, cuid uuid.UUID) (*mnepb.SetChangeListResponse, error) {
    
    	return api.Confirm(ctx, p.endpoint, p.id.String(), cuid.String())
    
    func filterChanges(state mnepb.ChangeState, resp *mnepb.GetChangeListResponse) []*mnepb.Change {
    	changes := make([]*mnepb.Change, 0)
    
    	for _, ch := range resp.Change {
    		if ch.State == state {
    
    			changes = append(changes, ch)