Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
pnd.go 6.96 KiB
package api

import (
	ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd"
	tpb "code.fbi.h-da.de/danet/api/go/gosdn/transport"
	"code.fbi.h-da.de/danet/gosdn/interfaces/change"
	"code.fbi.h-da.de/danet/gosdn/interfaces/device"
	"code.fbi.h-da.de/danet/gosdn/interfaces/networkdomain"
	"code.fbi.h-da.de/danet/gosdn/interfaces/southbound"
	"code.fbi.h-da.de/danet/gosdn/interfaces/store"
	"code.fbi.h-da.de/danet/gosdn/nucleus/errors"
	"github.com/google/uuid"
	log "github.com/sirupsen/logrus"
	"google.golang.org/protobuf/proto"
)

// PrincipalNetworkDomainAdapter is an API adapter to reflect the NetworkDomain
// interface
type PrincipalNetworkDomainAdapter struct {
	id       uuid.UUID
	endpoint string
}

// NewAdapter creates a PND Adapter. It requires a valid PND UUID and a reachable
// goSDN endpoint.
func NewAdapter(id, endpoint string) (networkdomain.NetworkDomain, error) {
	pid, err := uuid.Parse(id)
	if err != nil {
		return nil, err
	}
	return &PrincipalNetworkDomainAdapter{
		id:       pid,
		endpoint: endpoint,
	}, nil
}

// Destroy destroys the PND Adapter. Currently not implemented
func (p *PrincipalNetworkDomainAdapter) Destroy() error {
	return &errors.ErrNotYetImplemented{}
}

// AddSbi adds an SBI to the PND Adapter. Currently not implemented
func (p *PrincipalNetworkDomainAdapter) AddSbi(s southbound.SouthboundInterface) error {
	return &errors.ErrNotYetImplemented{}
}

// RemoveSbi removes an SBI from the PND Adapter. Currently not implemented
func (p *PrincipalNetworkDomainAdapter) RemoveSbi(uuid.UUID) error {
	return &errors.ErrNotYetImplemented{}
}

// AddDevice 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 *PrincipalNetworkDomainAdapter) AddDevice(name string, opts *tpb.TransportOption, sid uuid.UUID) error {
	resp, err := addDevice(p.endpoint, name, opts, sid, p.ID())
	if err != nil {
		return err
	}
	log.Info(resp)
	return nil
}

// AddDeviceFromStore adds a new device from store to the controller. Currently not implemented
func (p *PrincipalNetworkDomainAdapter) AddDeviceFromStore(name string, did uuid.UUID, opts *tpb.TransportOption, sid uuid.UUID) error {
	return &errors.ErrNotYetImplemented{}
}

// GetDevice requests one or multiple devices belonging to a given
// PrincipalNetworkDomain from the controller. If no device identifier
// is provided, all devices are requested.
func (p *PrincipalNetworkDomainAdapter) GetDevice(identifier string) (device.Device, error) {
	resp, err := getDevice(p.endpoint, p.id.String(), identifier)
	if err != nil {
		return nil, err
	}
	// TODO: Parse into device.Device
	log.Info(resp)
	return nil, nil
}

// RemoveDevice removes a device from the PND Adapter
func (p *PrincipalNetworkDomainAdapter) RemoveDevice(did uuid.UUID) error {
	resp, err := deleteDevice(p.endpoint, p.id.String(), did.String())
	if err != nil {
		return err
	}
	log.Info(resp)
	return nil
}

// Devices sends an API call to the controller requesting the UUIDs of all
// registered devices. Returns nil.
func (p *PrincipalNetworkDomainAdapter) Devices() []uuid.UUID {
	return nil
}

// ChangeOND 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 *PrincipalNetworkDomainAdapter) ChangeOND(duid uuid.UUID, operation ppb.ApiOperation, path string, value ...string) (uuid.UUID, error) {
	var v string
	if len(value) != 0 {
		v = value[0]
	}
	resp, err := changeRequest(p.endpoint, duid.String(), p.id.String(), path, v, operation)
	if err != nil {
		return uuid.Nil, err
	}
	log.Info(resp)
	return uuid.Nil, err
}

// Request sends an API call to the controller requesting the specified path
// for the specified device
func (p *PrincipalNetworkDomainAdapter) Request(did uuid.UUID, path string) (proto.Message, error) {
	resp, err := getPath(p.endpoint, p.id.String(), did.String(), path)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

// RequestAll sends an API call to the controller requesting the specified path
// for all registered devices. Not yet implemented.
func (p *PrincipalNetworkDomainAdapter) RequestAll(string) error {
	return &errors.ErrNotYetImplemented{}
}

// GetName returns the PND Adapter's name
func (p *PrincipalNetworkDomainAdapter) GetName() string {
	return "PND Adapter"
}

// GetDescription returns the PND Adapter's description
func (p *PrincipalNetworkDomainAdapter) GetDescription() string {
	return "PND Adapter"
}

// MarshalDevice sends an API call to the controller requesting the specified
// device as JSON representation. Not yet implemented
func (p *PrincipalNetworkDomainAdapter) MarshalDevice(string) (string, error) {
	return "", &errors.ErrNotYetImplemented{}
}

// ContainsDevice sends an API call to the controller checking if a device
// with the given UUID is present. Not implemented, always returns false
func (p *PrincipalNetworkDomainAdapter) ContainsDevice(uuid.UUID) bool {
	return false
}

// GetSBIs sends an API call to the controller requesting the
// registered SBIs. Not implemented, always returns nil
func (p *PrincipalNetworkDomainAdapter) GetSBIs() store.Store {
	return nil
}

// ID returns the PND Adapter's UUID
func (p *PrincipalNetworkDomainAdapter) ID() uuid.UUID {
	return p.id
}

// PendingChanges sends an API call to the controller requesting
// the UUIDs of all pending changes
func (p *PrincipalNetworkDomainAdapter) PendingChanges() []uuid.UUID {
	resp, err := getChanges(p.endpoint, p.id.String())
	if err != nil {
		log.Error(err)
		return nil
	}
	return filterChanges(ppb.ChangeState_CHANGE_STATE_PENDING, resp)
}

// CommittedChanges sends an API call to the controller requesting
// the UUIDs of all committed changes
func (p *PrincipalNetworkDomainAdapter) CommittedChanges() []uuid.UUID {
	resp, err := getChanges(p.endpoint, p.id.String())
	if err != nil {
		log.Error(err)
		return nil
	}
	return filterChanges(ppb.ChangeState_CHANGE_STATE_COMMITTED, resp)
}

// GetChange sends an API call to the controller requesting the specified change
func (p *PrincipalNetworkDomainAdapter) GetChange(uuid.UUID) (change.Change, error) {
	return nil, &errors.ErrNotYetImplemented{}
}

// Commit sends an API call to the controller committing the specified change
func (p *PrincipalNetworkDomainAdapter) Commit(cuid uuid.UUID) error {
	resp, err := commit(p.endpoint, p.id.String(), cuid.String())
	if err != nil {
		return err
	}
	log.Info(resp)
	return nil
}

// Confirm sends an API call to the controller confirming the specified change
func (p *PrincipalNetworkDomainAdapter) Confirm(cuid uuid.UUID) error {
	resp, err := confirm(p.endpoint, p.id.String(), cuid.String())
	if err != nil {
		return err
	}
	log.Info(resp)
	return nil
}

func filterChanges(state ppb.ChangeState, resp *ppb.GetChangeListResponse) []uuid.UUID {
	changes := make([]uuid.UUID, 0)
	for _, ch := range resp.Change {
		if ch.State == state {
			id, _ := uuid.Parse(ch.Id)
			changes = append(changes, id)
		}
	}
	return changes
}