blob: 97bc6038b7d966e6518845f7f7f38dd49d670a1d [file] [log] [blame]
Stephane Barbariea75791c2019-01-24 10:58:06 -05001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
npujar03b018e2019-11-13 15:29:36 +053016
Stephane Barbariea75791c2019-01-24 10:58:06 -050017package core
18
19import (
20 "context"
npujar03b018e2019-11-13 15:29:36 +053021 "sync"
22
sbarbari17d7e222019-11-05 10:02:29 -050023 "github.com/opencord/voltha-go/db/model"
Scott Baker807addd2019-10-24 15:16:21 -070024 "github.com/opencord/voltha-lib-go/v2/pkg/log"
25 "github.com/opencord/voltha-lib-go/v2/pkg/probe"
Scott Baker555307d2019-11-04 08:58:01 -080026 "github.com/opencord/voltha-protos/v2/go/voltha"
Stephane Barbariea75791c2019-01-24 10:58:06 -050027 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/status"
Stephane Barbariea75791c2019-01-24 10:58:06 -050029)
30
npujar03b018e2019-11-13 15:29:36 +053031// LogicalDeviceManager represents logical device manager related information
Stephane Barbariea75791c2019-01-24 10:58:06 -050032type LogicalDeviceManager struct {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040033 logicalDeviceAgents sync.Map
Stephane Barbariea75791c2019-01-24 10:58:06 -050034 deviceMgr *DeviceManager
35 grpcNbiHdlr *APIHandler
36 clusterDataProxy *model.Proxy
37 exitChannel chan int
38 lockLogicalDeviceAgentsMap sync.RWMutex
39}
40
41func newLogicalDeviceManager(deviceMgr *DeviceManager, cdProxy *model.Proxy) *LogicalDeviceManager {
42 var logicalDeviceMgr LogicalDeviceManager
43 logicalDeviceMgr.exitChannel = make(chan int, 1)
Stephane Barbariea75791c2019-01-24 10:58:06 -050044 logicalDeviceMgr.deviceMgr = deviceMgr
45 logicalDeviceMgr.clusterDataProxy = cdProxy
46 logicalDeviceMgr.lockLogicalDeviceAgentsMap = sync.RWMutex{}
47 return &logicalDeviceMgr
48}
49
50func (ldMgr *LogicalDeviceManager) setGrpcNbiHandler(grpcNbiHandler *APIHandler) {
51 ldMgr.grpcNbiHdlr = grpcNbiHandler
52}
53
54func (ldMgr *LogicalDeviceManager) start(ctx context.Context) {
55 log.Info("starting-logical-device-manager")
Hardik Windlassdc63dde2019-09-30 07:15:13 +000056 probe.UpdateStatusFromContext(ctx, "logical-device-manager", probe.ServiceStatusRunning)
Stephane Barbariea75791c2019-01-24 10:58:06 -050057 log.Info("logical-device-manager-started")
58}
59
60func (ldMgr *LogicalDeviceManager) stop(ctx context.Context) {
61 log.Info("stopping-logical-device-manager")
62 ldMgr.exitChannel <- 1
Hardik Windlassdc63dde2019-09-30 07:15:13 +000063 probe.UpdateStatusFromContext(ctx, "logical-device-manager", probe.ServiceStatusStopped)
Stephane Barbariea75791c2019-01-24 10:58:06 -050064 log.Info("logical-device-manager-stopped")
65}
66
67func (ldMgr *LogicalDeviceManager) addLogicalDeviceAgentToMap(agent *LogicalDeviceAgent) {
npujar03b018e2019-11-13 15:29:36 +053068 if _, exist := ldMgr.logicalDeviceAgents.Load(agent.logicalDeviceID); !exist {
69 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceID, agent)
Stephane Barbariea75791c2019-01-24 10:58:06 -050070 }
71}
72
Scott Baker2225dd82019-11-12 13:20:10 -080073// getLogicalDeviceAgent returns the logical device agent. If the device is not in memory then the device will
74// be loaded from dB and a logical device agent created to managed it.
npujar03b018e2019-11-13 15:29:36 +053075func (ldMgr *LogicalDeviceManager) getLogicalDeviceAgent(logicalDeviceID string) *LogicalDeviceAgent {
76 agent, ok := ldMgr.logicalDeviceAgents.Load(logicalDeviceID)
77 if ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040078 return agent.(*LogicalDeviceAgent)
npujar03b018e2019-11-13 15:29:36 +053079 }
80 // Try to load into memory - loading will also create the logical device agent
81 if err := ldMgr.load(logicalDeviceID); err == nil {
82 if agent, ok = ldMgr.logicalDeviceAgents.Load(logicalDeviceID); ok {
83 return agent.(*LogicalDeviceAgent)
Scott Baker2225dd82019-11-12 13:20:10 -080084 }
Stephane Barbariea75791c2019-01-24 10:58:06 -050085 }
86 return nil
87}
88
npujar03b018e2019-11-13 15:29:36 +053089func (ldMgr *LogicalDeviceManager) deleteLogicalDeviceAgent(logicalDeviceID string) {
90 ldMgr.logicalDeviceAgents.Delete(logicalDeviceID)
Stephane Barbariea75791c2019-01-24 10:58:06 -050091}
92
93// GetLogicalDevice provides a cloned most up to date logical device
94func (ldMgr *LogicalDeviceManager) getLogicalDevice(id string) (*voltha.LogicalDevice, error) {
95 log.Debugw("getlogicalDevice", log.Fields{"logicaldeviceid": id})
96 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
97 return agent.GetLogicalDevice()
98 }
99 return nil, status.Errorf(codes.NotFound, "%s", id)
100}
101
Scott Baker2225dd82019-11-12 13:20:10 -0800102//listLogicalDevices returns the list of all logical devices
Stephane Barbariea75791c2019-01-24 10:58:06 -0500103func (ldMgr *LogicalDeviceManager) listLogicalDevices() (*voltha.LogicalDevices, error) {
104 log.Debug("ListAllLogicalDevices")
105 result := &voltha.LogicalDevices{}
Scott Baker2225dd82019-11-12 13:20:10 -0800106 if logicalDevices := ldMgr.clusterDataProxy.List(context.Background(), "/logical_devices", 0, false, ""); logicalDevices != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500107 for _, logicalDevice := range logicalDevices.([]interface{}) {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500108 result.Items = append(result.Items, logicalDevice.(*voltha.LogicalDevice))
109 }
110 }
111 return result, nil
112}
113
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500114// load loads a logical device manager in memory
npujar03b018e2019-11-13 15:29:36 +0530115func (ldMgr *LogicalDeviceManager) load(lDeviceID string) error {
116 log.Debugw("loading-logical-device", log.Fields{"lDeviceID": lDeviceID})
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500117 // To prevent a race condition, let's hold the logical device agent map lock. This will prevent a loading and
118 // a create logical device callback from occurring at the same time.
npujar03b018e2019-11-13 15:29:36 +0530119 if ldAgent, _ := ldMgr.logicalDeviceAgents.Load(lDeviceID); ldAgent == nil {
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500120 // Logical device not in memory - create a temp logical device Agent and let it load from memory
npujar03b018e2019-11-13 15:29:36 +0530121 agent := newLogicalDeviceAgent(lDeviceID, "", ldMgr, ldMgr.deviceMgr, ldMgr.clusterDataProxy)
122 if err := agent.start(context.TODO(), true); err != nil {
123 agent.stop(context.TODO())
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500124 return err
125 }
npujar03b018e2019-11-13 15:29:36 +0530126 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceID, agent)
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500127 }
128 // TODO: load the child device
129 return nil
130}
131
npujar03b018e2019-11-13 15:29:36 +0530132func (ldMgr *LogicalDeviceManager) getLogicalDeviceID(device *voltha.Device) (*string, error) {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500133 // Device can either be a parent or a child device
134 if device.Root {
135 // Parent device. The ID of a parent device is the logical device ID
136 return &device.ParentId, nil
137 }
138 // Device is child device
139 // retrieve parent device using child device ID
140 if parentDevice := ldMgr.deviceMgr.getParentDevice(device); parentDevice != nil {
141 return &parentDevice.ParentId, nil
142 }
143 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
144}
145
npujar03b018e2019-11-13 15:29:36 +0530146func (ldMgr *LogicalDeviceManager) getLogicalPortID(device *voltha.Device) (*voltha.LogicalPortId, error) {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500147 // Get the logical device where this device is attached
npujar03b018e2019-11-13 15:29:36 +0530148 var lDeviceID *string
Stephane Barbariea75791c2019-01-24 10:58:06 -0500149 var err error
npujar03b018e2019-11-13 15:29:36 +0530150 if lDeviceID, err = ldMgr.getLogicalDeviceID(device); err != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500151 return nil, err
152 }
153 var lDevice *voltha.LogicalDevice
npujar03b018e2019-11-13 15:29:36 +0530154 if lDevice, err = ldMgr.getLogicalDevice(*lDeviceID); err != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500155 return nil, err
156 }
157 // Go over list of ports
158 for _, port := range lDevice.Ports {
159 if port.DeviceId == device.Id {
npujar03b018e2019-11-13 15:29:36 +0530160 return &voltha.LogicalPortId{Id: *lDeviceID, PortId: port.Id}, nil
Stephane Barbariea75791c2019-01-24 10:58:06 -0500161 }
162 }
163 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
164}
165
npujar03b018e2019-11-13 15:29:36 +0530166// ListLogicalDevicePorts returns port details for a specific logical device entry
Stephane Barbariea75791c2019-01-24 10:58:06 -0500167func (ldMgr *LogicalDeviceManager) ListLogicalDevicePorts(ctx context.Context, id string) (*voltha.LogicalPorts, error) {
168 log.Debugw("ListLogicalDevicePorts", log.Fields{"logicaldeviceid": id})
169 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
170 return agent.ListLogicalDevicePorts()
171 }
172 return nil, status.Errorf(codes.NotFound, "%s", id)
173
174}
175
npujar03b018e2019-11-13 15:29:36 +0530176// ListLogicalDeviceFlows returns flow details for a specific logical device entry
Stephane Barbariea75791c2019-01-24 10:58:06 -0500177func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlows(ctx context.Context, id string) (*voltha.Flows, error) {
178 log.Debugw("ListLogicalDeviceFlows", log.Fields{"logicaldeviceid": id})
179 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
180 return agent.ListLogicalDeviceFlows()
181 }
182 return nil, status.Errorf(codes.NotFound, "%s", id)
183
184}
185
npujar03b018e2019-11-13 15:29:36 +0530186// ListLogicalDeviceFlowGroups returns flow group details for a specific logical device entry
Stephane Barbariea75791c2019-01-24 10:58:06 -0500187func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlowGroups(ctx context.Context, id string) (*voltha.FlowGroups, error) {
188 log.Debugw("ListLogicalDeviceFlowGroups", log.Fields{"logicaldeviceid": id})
189 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
190 return agent.ListLogicalDeviceFlowGroups()
191 }
192 return nil, status.Errorf(codes.NotFound, "%s", id)
193
194}
195
npujar03b018e2019-11-13 15:29:36 +0530196func (ldMgr *LogicalDeviceManager) getLogicalPort(lPortID *voltha.LogicalPortId) (*voltha.LogicalPort, error) {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500197 // Get the logical device where this device is attached
198 var err error
199 var lDevice *voltha.LogicalDevice
npujar03b018e2019-11-13 15:29:36 +0530200 if lDevice, err = ldMgr.getLogicalDevice(lPortID.Id); err != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500201 return nil, err
202 }
203 // Go over list of ports
204 for _, port := range lDevice.Ports {
npujar03b018e2019-11-13 15:29:36 +0530205 if port.Id == lPortID.PortId {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500206 return port, nil
207 }
208 }
npujar03b018e2019-11-13 15:29:36 +0530209 return nil, status.Errorf(codes.NotFound, "%s-%s", lPortID.Id, lPortID.PortId)
Stephane Barbariea75791c2019-01-24 10:58:06 -0500210}