blob: d12c2a521fda6b665d70d1e34f4f43499b9acc60 [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 */
16package core
17
18import (
19 "context"
sbarbari17d7e222019-11-05 10:02:29 -050020 "github.com/opencord/voltha-go/db/model"
Scott Baker807addd2019-10-24 15:16:21 -070021 "github.com/opencord/voltha-lib-go/v2/pkg/log"
22 "github.com/opencord/voltha-lib-go/v2/pkg/probe"
Scott Baker555307d2019-11-04 08:58:01 -080023 "github.com/opencord/voltha-protos/v2/go/voltha"
Stephane Barbariea75791c2019-01-24 10:58:06 -050024 "google.golang.org/grpc/codes"
25 "google.golang.org/grpc/status"
26 "sync"
27)
28
29type LogicalDeviceManager struct {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040030 logicalDeviceAgents sync.Map
Stephane Barbariea75791c2019-01-24 10:58:06 -050031 deviceMgr *DeviceManager
32 grpcNbiHdlr *APIHandler
33 clusterDataProxy *model.Proxy
34 exitChannel chan int
35 lockLogicalDeviceAgentsMap sync.RWMutex
36}
37
38func newLogicalDeviceManager(deviceMgr *DeviceManager, cdProxy *model.Proxy) *LogicalDeviceManager {
39 var logicalDeviceMgr LogicalDeviceManager
40 logicalDeviceMgr.exitChannel = make(chan int, 1)
Stephane Barbariea75791c2019-01-24 10:58:06 -050041 logicalDeviceMgr.deviceMgr = deviceMgr
42 logicalDeviceMgr.clusterDataProxy = cdProxy
43 logicalDeviceMgr.lockLogicalDeviceAgentsMap = sync.RWMutex{}
44 return &logicalDeviceMgr
45}
46
47func (ldMgr *LogicalDeviceManager) setGrpcNbiHandler(grpcNbiHandler *APIHandler) {
48 ldMgr.grpcNbiHdlr = grpcNbiHandler
49}
50
51func (ldMgr *LogicalDeviceManager) start(ctx context.Context) {
52 log.Info("starting-logical-device-manager")
Hardik Windlassdc63dde2019-09-30 07:15:13 +000053 probe.UpdateStatusFromContext(ctx, "logical-device-manager", probe.ServiceStatusRunning)
Stephane Barbariea75791c2019-01-24 10:58:06 -050054 log.Info("logical-device-manager-started")
55}
56
57func (ldMgr *LogicalDeviceManager) stop(ctx context.Context) {
58 log.Info("stopping-logical-device-manager")
59 ldMgr.exitChannel <- 1
Hardik Windlassdc63dde2019-09-30 07:15:13 +000060 probe.UpdateStatusFromContext(ctx, "logical-device-manager", probe.ServiceStatusStopped)
Stephane Barbariea75791c2019-01-24 10:58:06 -050061 log.Info("logical-device-manager-stopped")
62}
63
64func (ldMgr *LogicalDeviceManager) addLogicalDeviceAgentToMap(agent *LogicalDeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040065 if _, exist := ldMgr.logicalDeviceAgents.Load(agent.logicalDeviceId); !exist {
66 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceId, agent)
Stephane Barbariea75791c2019-01-24 10:58:06 -050067 }
68}
69
Scott Baker2225dd82019-11-12 13:20:10 -080070// getLogicalDeviceAgent returns the logical device agent. If the device is not in memory then the device will
71// be loaded from dB and a logical device agent created to managed it.
Stephane Barbariea75791c2019-01-24 10:58:06 -050072func (ldMgr *LogicalDeviceManager) getLogicalDeviceAgent(logicalDeviceId string) *LogicalDeviceAgent {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040073 if agent, ok := ldMgr.logicalDeviceAgents.Load(logicalDeviceId); ok {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040074 return agent.(*LogicalDeviceAgent)
Scott Baker2225dd82019-11-12 13:20:10 -080075 } else {
76 // Try to load into memory - loading will also create the logical device agent
77 if err := ldMgr.load(logicalDeviceId); err == nil {
78 if agent, ok = ldMgr.logicalDeviceAgents.Load(logicalDeviceId); ok {
79 return agent.(*LogicalDeviceAgent)
80 }
81 }
Stephane Barbariea75791c2019-01-24 10:58:06 -050082 }
83 return nil
84}
85
86func (ldMgr *LogicalDeviceManager) deleteLogicalDeviceAgent(logicalDeviceId string) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040087 ldMgr.logicalDeviceAgents.Delete(logicalDeviceId)
Stephane Barbariea75791c2019-01-24 10:58:06 -050088}
89
90// GetLogicalDevice provides a cloned most up to date logical device
91func (ldMgr *LogicalDeviceManager) getLogicalDevice(id string) (*voltha.LogicalDevice, error) {
92 log.Debugw("getlogicalDevice", log.Fields{"logicaldeviceid": id})
93 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
94 return agent.GetLogicalDevice()
95 }
96 return nil, status.Errorf(codes.NotFound, "%s", id)
97}
98
Scott Baker2225dd82019-11-12 13:20:10 -080099//listLogicalDevices returns the list of all logical devices
Stephane Barbariea75791c2019-01-24 10:58:06 -0500100func (ldMgr *LogicalDeviceManager) listLogicalDevices() (*voltha.LogicalDevices, error) {
101 log.Debug("ListAllLogicalDevices")
102 result := &voltha.LogicalDevices{}
Scott Baker2225dd82019-11-12 13:20:10 -0800103 if logicalDevices := ldMgr.clusterDataProxy.List(context.Background(), "/logical_devices", 0, false, ""); logicalDevices != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500104 for _, logicalDevice := range logicalDevices.([]interface{}) {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500105 result.Items = append(result.Items, logicalDevice.(*voltha.LogicalDevice))
106 }
107 }
108 return result, nil
109}
110
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500111// load loads a logical device manager in memory
112func (ldMgr *LogicalDeviceManager) load(lDeviceId string) error {
113 log.Debugw("loading-logical-device", log.Fields{"lDeviceId": lDeviceId})
114 // To prevent a race condition, let's hold the logical device agent map lock. This will prevent a loading and
115 // a create logical device callback from occurring at the same time.
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400116 if ldAgent, _ := ldMgr.logicalDeviceAgents.Load(lDeviceId); ldAgent == nil {
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500117 // Logical device not in memory - create a temp logical device Agent and let it load from memory
118 agent := newLogicalDeviceAgent(lDeviceId, "", ldMgr, ldMgr.deviceMgr, ldMgr.clusterDataProxy)
119 if err := agent.start(nil, true); err != nil {
120 agent.stop(nil)
121 return err
122 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400123 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceId, agent)
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500124 }
125 // TODO: load the child device
126 return nil
127}
128
Stephane Barbariea75791c2019-01-24 10:58:06 -0500129func (ldMgr *LogicalDeviceManager) getLogicalDeviceId(device *voltha.Device) (*string, error) {
130 // Device can either be a parent or a child device
131 if device.Root {
132 // Parent device. The ID of a parent device is the logical device ID
133 return &device.ParentId, nil
134 }
135 // Device is child device
136 // retrieve parent device using child device ID
137 if parentDevice := ldMgr.deviceMgr.getParentDevice(device); parentDevice != nil {
138 return &parentDevice.ParentId, nil
139 }
140 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
141}
142
143func (ldMgr *LogicalDeviceManager) getLogicalPortId(device *voltha.Device) (*voltha.LogicalPortId, error) {
144 // Get the logical device where this device is attached
145 var lDeviceId *string
146 var err error
147 if lDeviceId, err = ldMgr.getLogicalDeviceId(device); err != nil {
148 return nil, err
149 }
150 var lDevice *voltha.LogicalDevice
151 if lDevice, err = ldMgr.getLogicalDevice(*lDeviceId); err != nil {
152 return nil, err
153 }
154 // Go over list of ports
155 for _, port := range lDevice.Ports {
156 if port.DeviceId == device.Id {
157 return &voltha.LogicalPortId{Id: *lDeviceId, PortId: port.Id}, nil
158 }
159 }
160 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
161}
162
163func (ldMgr *LogicalDeviceManager) ListLogicalDevicePorts(ctx context.Context, id string) (*voltha.LogicalPorts, error) {
164 log.Debugw("ListLogicalDevicePorts", log.Fields{"logicaldeviceid": id})
165 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
166 return agent.ListLogicalDevicePorts()
167 }
168 return nil, status.Errorf(codes.NotFound, "%s", id)
169
170}
171
172func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlows(ctx context.Context, id string) (*voltha.Flows, error) {
173 log.Debugw("ListLogicalDeviceFlows", log.Fields{"logicaldeviceid": id})
174 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
175 return agent.ListLogicalDeviceFlows()
176 }
177 return nil, status.Errorf(codes.NotFound, "%s", id)
178
179}
180
181func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlowGroups(ctx context.Context, id string) (*voltha.FlowGroups, error) {
182 log.Debugw("ListLogicalDeviceFlowGroups", log.Fields{"logicaldeviceid": id})
183 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
184 return agent.ListLogicalDeviceFlowGroups()
185 }
186 return nil, status.Errorf(codes.NotFound, "%s", id)
187
188}
189
190func (ldMgr *LogicalDeviceManager) getLogicalPort(lPortId *voltha.LogicalPortId) (*voltha.LogicalPort, error) {
191 // Get the logical device where this device is attached
192 var err error
193 var lDevice *voltha.LogicalDevice
194 if lDevice, err = ldMgr.getLogicalDevice(lPortId.Id); err != nil {
195 return nil, err
196 }
197 // Go over list of ports
198 for _, port := range lDevice.Ports {
199 if port.Id == lPortId.PortId {
200 return port, nil
201 }
202 }
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400203 return nil, status.Errorf(codes.NotFound, "%s-%s", lPortId.Id, lPortId.PortId)
Stephane Barbariea75791c2019-01-24 10:58:06 -0500204}