blob: e9e433fb95b6f5f610a044bdda6b367c4d32f3c3 [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"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080024 "github.com/opencord/voltha-lib-go/v3/pkg/log"
25 "github.com/opencord/voltha-lib-go/v3/pkg/probe"
26 "github.com/opencord/voltha-protos/v3/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{}
Thomas Lee Se5a44012019-11-07 20:32:24 +0530106 if logicalDevices, err := ldMgr.clusterDataProxy.List(context.Background(), "/logical_devices", 0, false,
107 ""); err != nil {
108 log.Errorw("failed-to-list-devices", log.Fields{"error": err})
109 return nil, err
110 } else if logicalDevices != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500111 for _, logicalDevice := range logicalDevices.([]interface{}) {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500112 result.Items = append(result.Items, logicalDevice.(*voltha.LogicalDevice))
113 }
114 }
115 return result, nil
116}
117
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500118// load loads a logical device manager in memory
npujar03b018e2019-11-13 15:29:36 +0530119func (ldMgr *LogicalDeviceManager) load(lDeviceID string) error {
120 log.Debugw("loading-logical-device", log.Fields{"lDeviceID": lDeviceID})
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500121 // To prevent a race condition, let's hold the logical device agent map lock. This will prevent a loading and
122 // a create logical device callback from occurring at the same time.
npujar03b018e2019-11-13 15:29:36 +0530123 if ldAgent, _ := ldMgr.logicalDeviceAgents.Load(lDeviceID); ldAgent == nil {
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500124 // Logical device not in memory - create a temp logical device Agent and let it load from memory
npujar03b018e2019-11-13 15:29:36 +0530125 agent := newLogicalDeviceAgent(lDeviceID, "", ldMgr, ldMgr.deviceMgr, ldMgr.clusterDataProxy)
126 if err := agent.start(context.TODO(), true); err != nil {
127 agent.stop(context.TODO())
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500128 return err
129 }
npujar03b018e2019-11-13 15:29:36 +0530130 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceID, agent)
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500131 }
132 // TODO: load the child device
133 return nil
134}
135
npujar03b018e2019-11-13 15:29:36 +0530136func (ldMgr *LogicalDeviceManager) getLogicalDeviceID(device *voltha.Device) (*string, error) {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500137 // Device can either be a parent or a child device
138 if device.Root {
139 // Parent device. The ID of a parent device is the logical device ID
140 return &device.ParentId, nil
141 }
142 // Device is child device
143 // retrieve parent device using child device ID
144 if parentDevice := ldMgr.deviceMgr.getParentDevice(device); parentDevice != nil {
145 return &parentDevice.ParentId, nil
146 }
147 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
148}
149
npujar03b018e2019-11-13 15:29:36 +0530150func (ldMgr *LogicalDeviceManager) getLogicalPortID(device *voltha.Device) (*voltha.LogicalPortId, error) {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500151 // Get the logical device where this device is attached
npujar03b018e2019-11-13 15:29:36 +0530152 var lDeviceID *string
Stephane Barbariea75791c2019-01-24 10:58:06 -0500153 var err error
npujar03b018e2019-11-13 15:29:36 +0530154 if lDeviceID, err = ldMgr.getLogicalDeviceID(device); err != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500155 return nil, err
156 }
157 var lDevice *voltha.LogicalDevice
npujar03b018e2019-11-13 15:29:36 +0530158 if lDevice, err = ldMgr.getLogicalDevice(*lDeviceID); err != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500159 return nil, err
160 }
161 // Go over list of ports
162 for _, port := range lDevice.Ports {
163 if port.DeviceId == device.Id {
npujar03b018e2019-11-13 15:29:36 +0530164 return &voltha.LogicalPortId{Id: *lDeviceID, PortId: port.Id}, nil
Stephane Barbariea75791c2019-01-24 10:58:06 -0500165 }
166 }
167 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
168}
169
npujar03b018e2019-11-13 15:29:36 +0530170// ListLogicalDevicePorts returns port details for a specific logical device entry
Stephane Barbariea75791c2019-01-24 10:58:06 -0500171func (ldMgr *LogicalDeviceManager) ListLogicalDevicePorts(ctx context.Context, id string) (*voltha.LogicalPorts, error) {
172 log.Debugw("ListLogicalDevicePorts", log.Fields{"logicaldeviceid": id})
173 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
174 return agent.ListLogicalDevicePorts()
175 }
176 return nil, status.Errorf(codes.NotFound, "%s", id)
177
178}
179
npujar03b018e2019-11-13 15:29:36 +0530180// ListLogicalDeviceFlows returns flow details for a specific logical device entry
Stephane Barbariea75791c2019-01-24 10:58:06 -0500181func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlows(ctx context.Context, id string) (*voltha.Flows, error) {
182 log.Debugw("ListLogicalDeviceFlows", log.Fields{"logicaldeviceid": id})
183 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
184 return agent.ListLogicalDeviceFlows()
185 }
186 return nil, status.Errorf(codes.NotFound, "%s", id)
187
188}
189
npujar03b018e2019-11-13 15:29:36 +0530190// ListLogicalDeviceFlowGroups returns flow group details for a specific logical device entry
Stephane Barbariea75791c2019-01-24 10:58:06 -0500191func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlowGroups(ctx context.Context, id string) (*voltha.FlowGroups, error) {
192 log.Debugw("ListLogicalDeviceFlowGroups", log.Fields{"logicaldeviceid": id})
193 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
194 return agent.ListLogicalDeviceFlowGroups()
195 }
196 return nil, status.Errorf(codes.NotFound, "%s", id)
197
198}
199
npujar03b018e2019-11-13 15:29:36 +0530200func (ldMgr *LogicalDeviceManager) getLogicalPort(lPortID *voltha.LogicalPortId) (*voltha.LogicalPort, error) {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500201 // Get the logical device where this device is attached
202 var err error
203 var lDevice *voltha.LogicalDevice
npujar03b018e2019-11-13 15:29:36 +0530204 if lDevice, err = ldMgr.getLogicalDevice(lPortID.Id); err != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500205 return nil, err
206 }
207 // Go over list of ports
208 for _, port := range lDevice.Ports {
npujar03b018e2019-11-13 15:29:36 +0530209 if port.Id == lPortID.PortId {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500210 return port, nil
211 }
212 }
npujar03b018e2019-11-13 15:29:36 +0530213 return nil, status.Errorf(codes.NotFound, "%s-%s", lPortID.Id, lPortID.PortId)
Stephane Barbariea75791c2019-01-24 10:58:06 -0500214}