diff --git a/http.go b/http.go index 73c4429722e76afa570073172aac0230cda5a119..ad8016e188ec43508e40bc2af8eb66ddabc0fff8 100644 --- a/http.go +++ b/http.go @@ -172,48 +172,26 @@ func httpApi(writer http.ResponseWriter, request *http.Request) { case "getDevice": deviceIdentifier := query.Get("identifier") - // TODO: Think about something better than this. - // deviceIdentifier can be a uuid or a string. - // Because of that we check at first if the parsed uuid is 00000000-0000-0000-0000-000000000000. - // If yes it was not a valid uuid and it must be a device name. - // If not we check if the provided identifier should be a device UUID and we search for a uuid. - id, _ := uuid.Parse(deviceIdentifier) - idAsString := id.String() + // id, _ := uuid.Parse(deviceIdentifier) + // idAsString := id.String() - if idAsString == "00000000-0000-0000-0000-000000000000" { - device, err := httpPnd.MarshalDevice(deviceIdentifier) - if err != nil { - switch err.(type) { - case *errors.ErrNotFound: - writer.WriteHeader(http.StatusNotFound) - default: - writer.WriteHeader(http.StatusInternalServerError) - } - log.Error(err) - - return + // if idAsString == "00000000-0000-0000-0000-000000000000" { + device, err := httpPnd.MarshalDevice(deviceIdentifier) + if err != nil { + switch err.(type) { + case *errors.ErrNotFound: + writer.WriteHeader(http.StatusNotFound) + default: + writer.WriteHeader(http.StatusInternalServerError) } + log.Error(err) - writer.Header().Set("Content-Type", "application/json") - fmt.Fprintf(writer, "%v", device) - - } else { - device, err := httpPnd.MarshalDevice(id) - if err != nil { - switch err.(type) { - case *errors.ErrNotFound: - writer.WriteHeader(http.StatusNotFound) - default: - writer.WriteHeader(http.StatusInternalServerError) - } - log.Error(err) - - return - } - writer.Header().Set("Content-Type", "application/json") - fmt.Fprintf(writer, "%v", device) + return } + writer.Header().Set("Content-Type", "application/json") + fmt.Fprintf(writer, "%v", device) + case "getIDs": pnds := c.pndc.UUIDs() diff --git a/nucleus/errors/errors.go b/nucleus/errors/errors.go index 3aad202118e0bceb2b4e91dd34ce075c1ed454e5..d4b8527c9faed572b099024293f10ee6cf80339f 100644 --- a/nucleus/errors/errors.go +++ b/nucleus/errors/errors.go @@ -41,6 +41,14 @@ func (e *ErrAlreadyExists) Error() string { return fmt.Sprintf("%v already exists", e.Item) } +// ErrNoValidUUID implements the Error interface and is called if a UUID is not valid. +type ErrNoValidUUID struct { +} + +func (e *ErrNoValidUUID) Error() string { + return fmt.Sprintf("UUID not valid") +} + // ErrInvalidTypeAssertion implements the Error interface and is called if the // type of a storable item does not correspond to the expected type. type ErrInvalidTypeAssertion struct { diff --git a/nucleus/principalNetworkDomain.go b/nucleus/principalNetworkDomain.go index f130a89d602c2675a16e31457627ec69b7fb0ceb..305edb9f10be5ec76861bf8fb3b81854699c8af2 100644 --- a/nucleus/principalNetworkDomain.go +++ b/nucleus/principalNetworkDomain.go @@ -31,7 +31,7 @@ type PrincipalNetworkDomain interface { RequestAll(string) error GetName() string GetDescription() string - MarshalDevice(interface{}) (string, error) + MarshalDevice(string) (string, error) MarshalDeviceByName(name string) (string, error) ContainsDevice(uuid.UUID) bool GetSBIs() interface{} @@ -48,7 +48,7 @@ func NewPND(name, description string, id uuid.UUID, sbi SouthboundInterface) (Pr name: name, description: description, sbic: SbiStore{store{}}, - devices: DeviceStore{store{}}, + devices: NewDeviceStore(), pendingChanges: ChangeStore{store{}}, committedChanges: ChangeStore{store{}}, confirmedChanges: ChangeStore{store{}}, @@ -66,7 +66,7 @@ type pndImplementation struct { name string description string sbic SbiStore - devices DeviceStore + devices *DeviceStore pendingChanges ChangeStore committedChanges ChangeStore confirmedChanges ChangeStore @@ -188,7 +188,7 @@ func (pnd *pndImplementation) AddDevice(device interface{}) error { } func (pnd *pndImplementation) GetDevice(uuid uuid.UUID) (ygot.GoStruct, error) { - d, err := pnd.devices.Get(uuid) + d, err := pnd.devices.Get(FromString(uuid.String())) if err != nil { return nil, err } @@ -215,7 +215,7 @@ func (pnd *pndImplementation) removeSbi(id uuid.UUID) error { } func (pnd *pndImplementation) addDevice(device *Device) error { - err := pnd.devices.Add(device) + err := pnd.devices.Add(device, device.Name) if err != nil { return err } @@ -226,40 +226,45 @@ func (pnd *pndImplementation) addDevice(device *Device) error { } func (pnd *pndImplementation) getDeviceByUUID(id uuid.UUID) (*Device, error) { - return pnd.devices.Get(id) + return pnd.devices.Get(FromString("wasd")) } func (pnd *pndImplementation) getDeviceByName(name string) (*Device, error) { - deviceUUID, found := pnd.deviceNameToUUIDLookup[name] - if !found { - return nil, &errors.ErrNotFound{ID: name} - } - return pnd.devices.Get(deviceUUID) + // deviceUUID, found := pnd.deviceNameToUUIDLookup[name] + // if !found { + // return nil, &errors.ErrNotFound{ID: name} + // } + return pnd.devices.Get(FromString("wasd")) } func (pnd *pndImplementation) removeDevice(id uuid.UUID) error { return pnd.devices.Delete(id) } -func (pnd *pndImplementation) MarshalDevice(identifier interface{}) (string, error) { - var foundDevice *Device - var err error +func (pnd *pndImplementation) MarshalDevice(identifier string) (string, error) { + // var foundDevice *Device + // var err error - switch id := identifier.(type) { - case uuid.UUID: - foundDevice, err = pnd.getDeviceByUUID(id) - if err != nil { - return "", err - } - case string: - foundDevice, err = pnd.getDeviceByName(id) - if err != nil { - return "", err - } - default: - return "", &errors.ErrNotFound{ID: identifier} + foundDevice, err := pnd.devices.Get(FromString(identifier)) + if err != nil { + return "", err } + // switch id := identifier.(type) { + // case uuid.UUID: + // foundDevice, err = pnd.getDeviceByUUID(id) + // if err != nil { + // return "", err + // } + // case string: + // foundDevice, err = pnd.getDeviceByName(id) + // if err != nil { + // return "", err + // } + // default: + // return "", &errors.ErrNotFound{ID: identifier} + // } + jsonTree, err := json.MarshalIndent(foundDevice.GoStruct, "", "\t") if err != nil { return "", err diff --git a/nucleus/store.go b/nucleus/store.go index 605ab915d999eb884a2d7ee9ee3cac831242718d..dd94dc34f2e276ee403890d9245b870e7e618e15 100644 --- a/nucleus/store.go +++ b/nucleus/store.go @@ -1,6 +1,7 @@ package nucleus import ( + "fmt" "reflect" "sync" @@ -43,7 +44,7 @@ func NewSbiStore() *SbiStore { // NewDeviceStore returns a DeviceStore func NewDeviceStore() *DeviceStore { - return &DeviceStore{store{}} + return &DeviceStore{store: store{}, deviceNameToUUIDLookup: make(map[string]uuid.UUID)} } // NewChangeStore returns a ChangeStore @@ -170,13 +171,38 @@ func (s PndStore) Get(id uuid.UUID) (PrincipalNetworkDomain, error) { // DeviceStore is used to store Devices type DeviceStore struct { + deviceNameToUUIDLookup map[string]uuid.UUID store } // Get takes a Device's UUID and returns the Device. If the requested // Device does not exist an error is returned. -func (s DeviceStore) Get(id uuid.UUID) (*Device, error) { - item, err := s.store.Get(id) +func (s DeviceStore) Get(id uuid.UUID, idAsString string, parseErrors ...error) (*Device, error) { + log.Debug(fmt.Sprintf("Devicestore: %+v", s.store)) + log.Debug(fmt.Sprintf("deviceNameToUUIDLookup: %+v", s.deviceNameToUUIDLookup)) + log.Debug(fmt.Sprintf("Errors: %+v", parseErrors)) + log.Debug(fmt.Sprintf("Length Errors: %+v", len(parseErrors))) + + var foundID uuid.UUID + + foundID = id + + for _, parseErrs := range parseErrors { + if parseErrs != nil { + log.Debug("lookup device") + log.Debug(fmt.Sprint(idAsString)) + myID, ok := s.deviceNameToUUIDLookup[idAsString] + if !ok { + log.Debug("no device found") + return nil, &errors.ErrNotFound{} + } + + foundID = myID + + } + } + + item, err := s.store.Get(foundID) if err != nil { return nil, err } @@ -191,9 +217,67 @@ func (s DeviceStore) Get(id uuid.UUID) (*Device, error) { "uuid": id, "name": device.Name, }).Debug("device was accessed") + return device, nil } +func FromString(id string) (uuid.UUID, string, error) { + idAsUUID, _ := uuid.Parse(id) + + // id is no UUID therefore check if it is name registered in the lookup table. + if idAsUUID.String() == "00000000-0000-0000-0000-000000000000" { + return uuid.Nil, id, &errors.ErrNoValidUUID{} + } + + return idAsUUID, id, nil +} + +// id := uuid.New() +// Get(id) +// stringId := id.String() +// Get(FromString(stringId)) + +func (s DeviceStore) Add(item Storable, name string) error { + if s.Exists(item.ID()) { + return &errors.ErrAlreadyExists{Item: item} + } + + s.deviceNameToUUIDLookup[name] = item.ID() + + storeLock.Lock() + s.store[item.ID()] = item + storeLock.Unlock() + + log.WithFields(log.Fields{ + "type": reflect.TypeOf(item), + "uuid": item.ID(), + }).Debug("storable was added") + + return nil +} + +func (s DeviceStore) Delete(id uuid.UUID) error { + if !s.Exists(id) { + return &errors.ErrNotFound{ID: id} + } + + storeLock.Lock() + delete(s.store, id) + storeLock.Unlock() + + for key, value := range s.deviceNameToUUIDLookup { + if value == id { + delete(s.deviceNameToUUIDLookup, key) + } + } + + log.WithFields(log.Fields{ + "uuid": id, + }).Debug("storable was deleted") + + return nil +} + // ChangeStore is used to store Changes type ChangeStore struct { store