// // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // This source code is part of the near-RT RIC (RAN Intelligent Controller) // platform project (RICP). package managers import ( "e2mgr/e2managererrors" "e2mgr/logger" "e2mgr/services" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" "math" "sync" "time" ) type E2TInstancesManager struct { rnibDataService services.RNibDataService logger *logger.Logger mux sync.Mutex } type IE2TInstancesManager interface { GetE2TAddresses() ([]string, error) GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error) GetE2TInstances() ([]*entities.E2TInstance, error) GetE2TInstancesNoLogs() ([]*entities.E2TInstance, error) AddE2TInstance(e2tAddress string) error RemoveE2TInstance(e2tAddress string) error SelectE2TInstance() (string, error) AddRanToInstance(ranName string, e2tAddress string) error RemoveRanFromInstance(ranName string, e2tAddress string) error ResetKeepAliveTimestamp(e2tAddress string) error ClearRansOfAllE2TInstances() error SetE2tInstanceState(e2tAddress string, currentState entities.E2TInstanceState, newState entities.E2TInstanceState) error } func NewE2TInstancesManager(rnibDataService services.RNibDataService, logger *logger.Logger) *E2TInstancesManager { return &E2TInstancesManager{ rnibDataService: rnibDataService, logger: logger, } } func (m *E2TInstancesManager) GetE2TInstance(e2tAddress string) (*entities.E2TInstance, error) { e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress) if err != nil { _, ok := err.(*common.ResourceNotFoundError) if !ok { m.logger.Errorf("#E2TInstancesManager.GetE2TInstance - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err) } else { m.logger.Infof("#E2TInstancesManager.GetE2TInstance - E2T Instance address: %s not found on DB", e2tAddress) } } return e2tInstance, err } func (m *E2TInstancesManager) GetE2TInstancesNoLogs() ([]*entities.E2TInstance, error) { e2tAddresses, err := m.rnibDataService.GetE2TAddressesNoLogs() if err != nil { _, ok := err.(*common.ResourceNotFoundError) if !ok { m.logger.Errorf("#E2TInstancesManager.GetE2TInstancesNoLogs - Failed retrieving E2T addresses. error: %s", err) return nil, e2managererrors.NewRnibDbError() } return []*entities.E2TInstance{}, nil } if len(e2tAddresses) == 0 { return []*entities.E2TInstance{}, nil } e2tInstances, err := m.rnibDataService.GetE2TInstancesNoLogs(e2tAddresses) if err != nil { _, ok := err.(*common.ResourceNotFoundError) if !ok { m.logger.Errorf("#E2TInstancesManager.GetE2TInstancesNoLogs - Failed retrieving E2T instances list. error: %s", err) } return e2tInstances, err } return e2tInstances, nil } func (m *E2TInstancesManager) GetE2TAddresses() ([]string, error) { e2tAddresses, err := m.rnibDataService.GetE2TAddresses() if err != nil { _, ok := err.(*common.ResourceNotFoundError) if !ok { m.logger.Errorf("#E2TInstancesManager.GetE2TAddresses - Failed retrieving E2T addresses. error: %s", err) return nil, e2managererrors.NewRnibDbError() } } return e2tAddresses, nil } func (m *E2TInstancesManager) GetE2TInstances() ([]*entities.E2TInstance, error) { e2tAddresses, err := m.GetE2TAddresses() if err != nil { return nil, e2managererrors.NewRnibDbError() } if len(e2tAddresses) == 0 { m.logger.Infof("#E2TInstancesManager.GetE2TInstances - Empty E2T addresses list") return []*entities.E2TInstance{}, nil } e2tInstances, err := m.rnibDataService.GetE2TInstances(e2tAddresses) if err != nil { m.logger.Errorf("#E2TInstancesManager.GetE2TInstances - Failed retrieving E2T instances list. error: %s", err) return e2tInstances, e2managererrors.NewRnibDbError() } if len(e2tInstances) == 0 { m.logger.Warnf("#E2TInstancesManager.GetE2TInstances - Empty E2T instances list") return e2tInstances, nil } return e2tInstances, nil } func (m *E2TInstancesManager) ResetKeepAliveTimestampsForAllE2TInstances() { e2tInstances, err := m.GetE2TInstances() if err != nil { m.logger.Errorf("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - Couldn't reset timestamps due to a DB error") return } if len(e2tInstances) == 0 { m.logger.Infof("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - No instances, ignoring reset") return } for _, v := range e2tInstances { if v.State != entities.Active { continue } v.KeepAliveTimestamp = time.Now().UnixNano() err := m.rnibDataService.SaveE2TInstance(v) if err != nil { m.logger.Errorf("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - E2T address: %s - failed resetting e2t instance keep alive timestamp. error: %s", v.Address, err) } } m.logger.Infof("E2TInstancesManager.ResetKeepAliveTimestampForAllE2TInstances - Done with reset") } func findActiveE2TInstanceWithMinimumAssociatedRans(e2tInstances []*entities.E2TInstance) *entities.E2TInstance { var minInstance *entities.E2TInstance minAssociatedRanCount := math.MaxInt32 for _, v := range e2tInstances { if v.State == entities.Active && len(v.AssociatedRanList) < minAssociatedRanCount { minAssociatedRanCount = len(v.AssociatedRanList) minInstance = v } } return minInstance } func (m *E2TInstancesManager) AddE2TInstance(e2tAddress string) error { m.mux.Lock() defer m.mux.Unlock() e2tInstance := entities.NewE2TInstance(e2tAddress) err := m.rnibDataService.SaveE2TInstance(e2tInstance) if err != nil { m.logger.Errorf("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - Failed saving E2T instance. error: %s", e2tInstance.Address, err) return err } e2tAddresses, err := m.rnibDataService.GetE2TAddresses() if err != nil { _, ok := err.(*common.ResourceNotFoundError) if !ok { m.logger.Errorf("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - Failed retrieving E2T addresses list. error: %s", e2tInstance.Address, err) return err } } e2tAddresses = append(e2tAddresses, e2tInstance.Address) err = m.rnibDataService.SaveE2TAddresses(e2tAddresses) if err != nil { m.logger.Errorf("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - Failed saving E2T addresses list. error: %s", e2tInstance.Address, err) return err } m.logger.Infof("#E2TInstancesManager.AddE2TInstance - E2T Instance address: %s - successfully added E2T instance", e2tInstance.Address) return nil } func (m *E2TInstancesManager) RemoveRanFromInstance(ranName string, e2tAddress string) error { m.mux.Lock() defer m.mux.Unlock() e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress) if err != nil { m.logger.Errorf("#E2TInstancesManager.RemoveRanFromInstance - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err) return e2managererrors.NewRnibDbError() } i := 0 // output index for _, v := range e2tInstance.AssociatedRanList { if v != ranName { // copy and increment index e2tInstance.AssociatedRanList[i] = v i++ } } e2tInstance.AssociatedRanList = e2tInstance.AssociatedRanList[:i] err = m.rnibDataService.SaveE2TInstance(e2tInstance) if err != nil { m.logger.Errorf("#E2TInstancesManager.RemoveRanFromInstance - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err) return e2managererrors.NewRnibDbError() } m.logger.Infof("#E2TInstancesManager.RemoveRanFromInstance - successfully dissociated RAN %s from E2T %s", ranName, e2tInstance.Address) return nil } func (m *E2TInstancesManager) RemoveE2TInstance(e2tAddress string) error { m.mux.Lock() defer m.mux.Unlock() err := m.rnibDataService.RemoveE2TInstance(e2tAddress) if err != nil { m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed removing E2TInstance. error: %s", e2tAddress, err) return e2managererrors.NewRnibDbError() } e2tAddresses, err := m.rnibDataService.GetE2TAddresses() if err != nil { m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed retrieving E2T addresses list. error: %s", e2tAddress, err) return e2managererrors.NewRnibDbError() } e2tAddresses = m.removeAddressFromList(e2tAddresses, e2tAddress) err = m.rnibDataService.SaveE2TAddresses(e2tAddresses) if err != nil { m.logger.Errorf("#E2TInstancesManager.RemoveE2TInstance - E2T Instance address: %s - Failed saving E2T addresses list. error: %s", e2tAddress, err) return e2managererrors.NewRnibDbError() } return nil } func (m *E2TInstancesManager) removeAddressFromList(e2tAddresses []string, addressToRemove string) []string { newAddressList := []string{} for _, address := range e2tAddresses { if address != addressToRemove { newAddressList = append(newAddressList, address) } } return newAddressList } func (m *E2TInstancesManager) SelectE2TInstance() (string, error) { e2tInstances, err := m.GetE2TInstances() if err != nil { return "", err } if len(e2tInstances) == 0 { m.logger.Errorf("#E2TInstancesManager.SelectE2TInstance - No E2T instance found") return "", e2managererrors.NewE2TInstanceAbsenceError() } min := findActiveE2TInstanceWithMinimumAssociatedRans(e2tInstances) if min == nil { m.logger.Errorf("#E2TInstancesManager.SelectE2TInstance - No active E2T instance found") return "", e2managererrors.NewE2TInstanceAbsenceError() } m.logger.Infof("#E2TInstancesManager.SelectE2TInstance - successfully selected E2T instance. address: %s", min.Address) return min.Address, nil } func (m *E2TInstancesManager) AddRanToInstance(ranName string, e2tAddress string) error { m.mux.Lock() defer m.mux.Unlock() e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress) if err != nil { m.logger.Errorf("#E2TInstancesManager.AddRanToInstance - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err) return e2managererrors.NewRnibDbError() } e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, ranName) err = m.rnibDataService.SaveE2TInstance(e2tInstance) if err != nil { m.logger.Errorf("#E2TInstancesManager.AddRanToInstance - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err) return e2managererrors.NewRnibDbError() } m.logger.Infof("#E2TInstancesManager.AddRanToInstance - RAN %s was added successfully to E2T %s", ranName, e2tInstance.Address) return nil } func (m *E2TInstancesManager) ResetKeepAliveTimestamp(e2tAddress string) error { m.mux.Lock() defer m.mux.Unlock() e2tInstance, err := m.rnibDataService.GetE2TInstanceNoLogs(e2tAddress) if err != nil { m.logger.Errorf("#E2TInstancesManager.ResetKeepAliveTimestamp - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err) return err } if e2tInstance.State == entities.ToBeDeleted || e2tInstance.State == entities.RoutingManagerFailure { m.logger.Warnf("#E2TInstancesManager.ResetKeepAliveTimestamp - Ignore. This Instance is about to deleted") return nil } e2tInstance.KeepAliveTimestamp = time.Now().UnixNano() err = m.rnibDataService.SaveE2TInstanceNoLogs(e2tInstance) if err != nil { m.logger.Errorf("#E2TInstancesManager.ResetKeepAliveTimestamp - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tAddress, err) return err } return nil } func (m *E2TInstancesManager) SetE2tInstanceState(e2tAddress string, currentState entities.E2TInstanceState, newState entities.E2TInstanceState) error { m.mux.Lock() defer m.mux.Unlock() e2tInstance, err := m.rnibDataService.GetE2TInstance(e2tAddress) if err != nil { m.logger.Errorf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Failed retrieving E2TInstance. error: %s", e2tAddress, err) return e2managererrors.NewRnibDbError() } if (currentState != e2tInstance.State) { m.logger.Warnf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Current state is not: %s", e2tAddress, currentState) return e2managererrors.NewInternalError() } e2tInstance.State = newState if (newState == entities.Active) { e2tInstance.KeepAliveTimestamp = time.Now().UnixNano() } err = m.rnibDataService.SaveE2TInstance(e2tInstance) if err != nil { m.logger.Errorf("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - Failed saving E2TInstance. error: %s", e2tInstance.Address, err) return err } m.logger.Infof("#E2TInstancesManager.SetE2tInstanceState - E2T Instance address: %s - State change: %s --> %s", e2tAddress, currentState, newState) return nil } func (m *E2TInstancesManager) ClearRansOfAllE2TInstances() error { m.logger.Infof("#E2TInstancesManager.ClearRansOfAllE2TInstances - Going to clear associated RANs from E2T instances") m.mux.Lock() defer m.mux.Unlock() e2tInstances, err := m.GetE2TInstances() if err != nil { return err } if len(e2tInstances) == 0 { m.logger.Errorf("#E2TInstancesManager.ClearRansOfAllE2TInstances - No E2T instances to clear associated RANs from") return nil } for _, v := range e2tInstances { v.AssociatedRanList = []string{} err := m.rnibDataService.SaveE2TInstance(v) if err != nil { m.logger.Errorf("#E2TInstancesManager.ClearRansOfAllE2TInstances - e2t address: %s - failed saving e2t instance. error: %s", v.Address, err) } } return nil }