Skip to content
Snippets Groups Projects
deviceFilesystemStore.go 4.13 KiB
Newer Older
  • Learn to ignore specific revisions
  • package nucleus
    
    import (
    	"encoding/json"
    	"io/ioutil"
    	"sync"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/device"
    	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
    	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
    	"code.fbi.h-da.de/danet/gosdn/controller/nucleus/filesystem"
    	"code.fbi.h-da.de/danet/gosdn/controller/store"
    	"github.com/google/uuid"
    )
    
    // FilesystemDeviceStore is the filesystem implementation of the device store
    type FilesystemDeviceStore struct {
    	sbiStore         southbound.Store
    	pndUUID          uuid.UUID
    	fileMutex        sync.Mutex
    	pathToDeviceFile string
    }
    
    // NewFilesystemDeviceStore returns a filesystem implementation for a pnd store.
    func NewFilesystemDeviceStore(pndUUID uuid.UUID) device.Store {
    	deviceFilenameForUUID := store.GetStoreFilenameForUUID(pndUUID, filesystem.DeviceFilenameSuffix)
    
    	store.EnsureFilesystemStorePathExists(deviceFilenameForUUID)
    	return &FilesystemDeviceStore{
    		pathToDeviceFile: store.GetCompletePathToFileStore(deviceFilenameForUUID),
    		fileMutex:        sync.Mutex{},
    		pndUUID:          pndUUID,
    	}
    }
    
    func (s *FilesystemDeviceStore) readAllDevicesFromFile() ([]device.LoadedDevice, error) {
    	var loadedDevices []device.LoadedDevice
    
    	content, err := ioutil.ReadFile(s.pathToDeviceFile)
    	if err != nil {
    		return nil, err
    	}
    
    	err = json.Unmarshal(content, &loadedDevices)
    	if err != nil {
    		return nil, err
    	}
    
    	return loadedDevices, nil
    }
    
    func (s *FilesystemDeviceStore) writeAllDevicesToFile(devices []device.LoadedDevice) error {
    	serializedData, err := json.Marshal(devices)
    	if err != nil {
    		return err
    	}
    
    	err = ioutil.WriteFile(s.pathToDeviceFile, serializedData, 0600)
    	if err != nil {
    		return err
    	}
    
    	return nil
    }
    
    // Get takes a Device's UUID or name and returns the Device.
    func (s *FilesystemDeviceStore) Get(query store.Query) (device.LoadedDevice, error) {
    	s.fileMutex.Lock()
    	defer s.fileMutex.Unlock()
    
    	var device device.LoadedDevice
    
    	devices, err := s.readAllDevicesFromFile()
    	if err != nil {
    		return device, err
    	}
    
    	for _, device := range devices {
    		if device.ID == query.ID.String() {
    			return device, nil
    		}
    	}
    
    	return device, &errors.ErrNotFound{ID: query.ID}
    }
    
    // GetAll returns all stored devices.
    func (s *FilesystemDeviceStore) GetAll() ([]device.LoadedDevice, error) {
    	s.fileMutex.Lock()
    	defer s.fileMutex.Unlock()
    
    	devices, err := s.readAllDevicesFromFile()
    
    	return devices, err
    }
    
    // Add adds a device to the device store.
    func (s *FilesystemDeviceStore) Add(deviceToAdd device.Device) error {
    	s.fileMutex.Lock()
    	defer s.fileMutex.Unlock()
    
    	devices, err := s.readAllDevicesFromFile()
    	if err != nil {
    		return err
    	}
    
    	var loadedDevice device.LoadedDevice
    	loadedDevice, err = store.TransformObjectToLoadedObject[device.Device, device.LoadedDevice](deviceToAdd)
    	if err != nil {
    		return err
    	}
    
    	devices = append(devices, loadedDevice)
    
    	err = s.writeAllDevicesToFile(devices)
    	if err != nil {
    		return err
    	}
    
    	return nil
    }
    
    // Update updates a existing device.
    func (s *FilesystemDeviceStore) Update(deviceToUpdate device.Device) error {
    	s.fileMutex.Lock()
    	defer s.fileMutex.Unlock()
    
    
    	loadedDeviceToUpdate, err := store.TransformObjectToLoadedObject[device.Device, device.LoadedDevice](deviceToUpdate)
    
    
    	devices, err := s.readAllDevicesFromFile()
    	if err != nil {
    		return err
    	}
    
    	for i, device := range devices {
    		if device.ID == deviceToUpdate.ID().String() {
    
    			err = s.writeAllDevicesToFile(devices)
    			if err != nil {
    				return err
    			}
    
    		}
    	}
    
    	return &errors.ErrNotFound{ID: deviceToUpdate.ID().String()}
    }
    
    // Delete deletes a device from the device store.
    func (s *FilesystemDeviceStore) Delete(deviceToDelete device.Device) error {
    	s.fileMutex.Lock()
    	defer s.fileMutex.Unlock()
    
    	devices, err := s.readAllDevicesFromFile()
    	if err != nil {
    		return err
    	}
    
    	for i, device := range devices {
    		if device.ID == deviceToDelete.ID().String() {
    			//remove item from slice
    			devices[i] = devices[len(devices)-1]
    			devices = devices[:len(devices)-1]
    
    			err = s.writeAllDevicesToFile(devices)
    			if err != nil {
    				return err
    			}
    
    			return nil
    		}
    	}
    
    	return &errors.ErrNotFound{ID: deviceToDelete.ID}
    }