Newer
Older
. "code.fbi.h-da.de/cocsn/gosdn/nucleus/pnd"
"github.com/openconfig/ygot/ygot"
"github.com/openconfig/ygot/ytypes"
// PrincipalNetworkDomain provides an
// interface for PND implementations
type PrincipalNetworkDomain interface {
Destroy() error
AddSbi(interface{}) error
RemoveSbi(uuid.UUID) error
AddDevice(interface{}) error
GetDevice(uuid uuid.UUID) (ygot.GoStruct, error)
ChangeOND(uuid uuid.UUID, operation Operation, path string, value string) error
RemoveDevice(uuid.UUID) error
Request(uuid.UUID, string) error
RequestAll(string) error
Malte Bauch
committed
GetName() string
GetDescription() string
MarshalDevice(uuid.UUID) (string, error)
ContainsDevice(uuid.UUID) bool
name string
description string
sbic sbiStore
devices deviceStore
pendingChanges store
committedChanges store
confirmedChanges store
id uuid.UUID
// NewPND creates a Principle Network Domain
func NewPND(name, description string, id uuid.UUID, sbi SouthboundInterface) (PrincipalNetworkDomain, error) {
name: name,
description: description,
sbic: sbiStore{store{}},
devices: deviceStore{store{}},
pendingChanges: store{},
committedChanges: store{},
confirmedChanges: store{},
id: id,
}
if err := pnd.sbic.add(sbi); err != nil {
return nil, &ErrAlreadyExists{item: sbi}
}
return pnd, nil
}
func (pnd *pndImplementation) ID() uuid.UUID {
// GetName returns the name of the PND
// ContainsDevice checks if the given device uuid is registered for this PND
func (pnd *pndImplementation) ContainsDevice(id uuid.UUID) bool {
return pnd.devices.exists(id)
// GetDescription returns the current description of the PND
func (pnd *pndImplementation) GetDescription() string {
// GetSBIs returns the registered SBIs
func (pnd *pndImplementation) GetSBIs() interface{} {
return &pnd.sbic
// Destroy destroys the PND
func (pnd *pndImplementation) Destroy() error {
return destroy()
}
// AddSbi adds a SBI to the PND which will be supported
func (pnd *pndImplementation) AddSbi(sbi interface{}) error {
s, ok := sbi.(SouthboundInterface)
if !ok {
return &ErrInvalidTypeAssertion{
v: sbi,
t: "Device",
}
}
return pnd.addSbi(s)
// TODO: this should to recursivly through
// devices and remove the devices using
// this SBI
func (pnd *pndImplementation) RemoveSbi(id uuid.UUID) error {
return pnd.removeSbi(id)
func (pnd *pndImplementation) AddDevice(device interface{}) error {
d, ok := device.(*Device)
if !ok {
return &ErrInvalidTypeAssertion{
v: device,
t: "Device",
}
}
return pnd.addDevice(d)
func (pnd *pndImplementation) GetDevice(uuid uuid.UUID) (ygot.GoStruct, error) {
d, err := pnd.devices.get(uuid)
if err != nil {
return nil, err
}
return ygot.DeepCopy(d)
}
// RemoveDevice removes a device from the PND
func (pnd *pndImplementation) RemoveDevice(uuid uuid.UUID) error {
// Actual implementation, bind to struct if
// neccessary
func destroy() error {
return nil
}
func (pnd *pndImplementation) addSbi(sbi SouthboundInterface) error {
func (pnd *pndImplementation) removeSbi(id uuid.UUID) error {
return pnd.sbic.delete(id)
func (pnd *pndImplementation) addDevice(device *Device) error {
func (pnd *pndImplementation) getDevice(id uuid.UUID) (*Device, error) {
return pnd.devices.get(id)
func (pnd *pndImplementation) removeDevice(id uuid.UUID) error {
return pnd.devices.delete(id)
func (pnd *pndImplementation) MarshalDevice(uuid uuid.UUID) (string, error) {
d, err := pnd.getDevice(uuid)
if err != nil {
return "", err
}
jsonTree, err := json.MarshalIndent(d.GoStruct, "", "\t")
if err != nil {
return "", err
}
"device": uuid,
}).Info("marshalled device")
return string(jsonTree), nil
// Request sends a get request to a specific device
func (pnd *pndImplementation) Request(uuid uuid.UUID, path string) error {
d, err := pnd.getDevice(uuid)
if err != nil {
return err
}
res, err := d.Transport.Get(ctx, path)
if err != nil {
return err
}
err = d.Transport.ProcessResponse(res, d.GoStruct, d.SBI.Schema())
if err != nil {
return err
}
return nil
}
// RequestAll sends a request for all registered devices
func (pnd *pndImplementation) RequestAll(path string) error {
for _, k := range pnd.devices.UUIDs() {
if err := pnd.Request(k, path); err != nil {
return err
}
}
"path": path,
}).Info("sent request to all devices")
// ChangeOND creates a change from the provided Operation, path and value. The Change is pending and
func (pnd *pndImplementation) ChangeOND(uuid uuid.UUID, operation Operation, path string, value string) error {
d, err := pnd.getDevice(uuid)
if err != nil {
cpy, err := ygot.DeepCopy(d.GoStruct)
p, err := ygot.StringToStructuredPath(path)
if err != nil {
return err
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
switch operation {
case TRANSPORT_UPDATE:
if err := ytypes.SetNode(d.SBI.Schema().RootSchema(), cpy, p, value); err != nil {
return err
}
case TRANSPORT_REPLACE:
if err := ytypes.SetNode(d.SBI.Schema().RootSchema(), cpy, p, value); err != nil {
return err
}
case TRANSPORT_DELETE:
if err := ytypes.DeleteNode(d.SBI.Schema().RootSchema(), cpy, p); err != nil {
return err
}
default:
return &ErrOperationNotSupported{o: operation}
}
callback := func(state ygot.GoStruct, change ygot.GoStruct) error {
ctx := context.Background()
return d.Transport.Set(ctx, state, change)
}
change := NewChange(uuid, d.GoStruct, cpy, callback)
return pnd.pendingChanges.add(change)