Select Git revision
pndStore.go
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
pndStore.go 4.43 KiB
package store
import (
"encoding/json"
"fmt"
"io/ioutil"
"reflect"
tpb "code.fbi.h-da.de/danet/api/go/gosdn/transport"
"code.fbi.h-da.de/danet/gosdn/interfaces/networkdomain"
"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"
)
// DeviceDetails contains details of a device used by the cSBI mechanism
type DeviceDetails struct {
ID string
Address string
TransportOption *tpb.TransportOption
}
// PndStore is used to store PrincipalNetworkDomains
type PndStore struct {
pndStoreName string
pendingChannels map[uuid.UUID]chan DeviceDetails
*genericStore
}
// NewPndStore returns a PndStore
func NewPndStore() *PndStore {
return &PndStore{
genericStore: newGenericStore(),
pendingChannels: make(map[uuid.UUID]chan DeviceDetails),
pndStoreName: "pnd-store.json"}
}
// GetPND takes a PrincipalNetworkDomain's UUID and returns the PrincipalNetworkDomain. If the requested
// PrincipalNetworkDomain does not exist an error is returned.
func (s *PndStore) GetPND(id uuid.UUID) (networkdomain.NetworkDomain, error) {
item, err := s.genericStore.Get(id)
if err != nil {
return nil, err
}
pnd, ok := item.(networkdomain.NetworkDomain)
if !ok {
return nil, &errors.ErrInvalidTypeAssertion{
Value: pnd,
Type: (*networkdomain.NetworkDomain)(nil),
}
}
log.WithFields(log.Fields{
"uuid": id,
}).Debug("principal network domain was accessed")
return pnd, nil
}
// Add adds a device to the device store.
// It also adds the name of the device to the lookup table.
func (s *PndStore) Add(item store.Storable) error {
if s.Exists(item.ID()) {
return &errors.ErrAlreadyExists{Item: item}
}
s.storeLock.Lock()
s.genericStore.Store[item.ID()] = item
s.storeLock.Unlock()
log.WithFields(log.Fields{
"type": reflect.TypeOf(item),
"uuid": item.ID(),
}).Debug("storable was added")
err := s.persist(item)
if err != nil {
return err
}
return nil
}
// PendingChannels holds channels used communicate with pending
// cSBI deployments
func (s *PndStore) PendingChannels(id uuid.UUID, parseErrors ...error) (chan DeviceDetails, error) {
ch, ok := s.pendingChannels[id]
if !ok {
return nil, &errors.ErrNotFound{ID: id}
}
return ch, nil
}
// AddPendingChannel adds a pending channel to the map
func (s *PndStore) AddPendingChannel(id uuid.UUID, ch chan DeviceDetails) {
s.pendingChannels[id] = ch
}
// RemovePendingChannel removes a pending channel from the map
func (s *PndStore) RemovePendingChannel(id uuid.UUID) {
delete(s.pendingChannels, id)
}
func (s *PndStore) persist(item store.Storable) error {
ensureFilesystemStorePathExists(s.pndStoreName)
_, ok := item.(networkdomain.NetworkDomain)
if !ok {
return fmt.Errorf("item is no NetworkDoman. got=%T", item)
}
var networkDomainsToPersist []LoadedPnd
for _, value := range s.genericStore.Store {
networkDomain, ok := value.(networkdomain.NetworkDomain)
if !ok {
return fmt.Errorf("item is no Device. got=%T", item)
}
networkDomainsToPersist = append(networkDomainsToPersist, LoadedPnd{
Name: networkDomain.GetName(),
Description: networkDomain.GetDescription(),
ID: networkDomain.ID(),
})
}
storeDataAsJSON, err := json.MarshalIndent(networkDomainsToPersist, "", " ")
if err != nil {
return err
}
err = ioutil.WriteFile(getCompletePathToFileStore(s.pndStoreName), storeDataAsJSON, 0644)
if err != nil {
return err
}
return nil
}
// LoadedPnd represents a Principal Network Domain that was loaeded by using
// the Load() method of the PndStore.
type LoadedPnd struct {
ID uuid.UUID `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
}
// Load unmarshals the contents of the storage file associated with a PndStore
// and returns it as []LoadedPnd.
func (s *PndStore) Load() ([]LoadedPnd, error) {
var loadedNetworkDomains []LoadedPnd
err := ensureFilesystemStorePathExists(s.pndStoreName)
if err != nil {
log.Debug(fmt.Printf("Err: %+v\n", err))
return loadedNetworkDomains, err
}
dat, err := ioutil.ReadFile(getCompletePathToFileStore(s.pndStoreName))
if err != nil {
log.Debug(fmt.Printf("Err: %+v\n", err))
return loadedNetworkDomains, err
}
err = json.Unmarshal(dat, &loadedNetworkDomains)
if err != nil {
log.Debug(fmt.Printf("Err: %+v\n", err))
return loadedNetworkDomains, err
}
return loadedNetworkDomains, nil
}