blob: db220d55f6e9d1b1413dd1f4c32bcb3294cea15d [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"
20 "github.com/opencord/voltha-go/common/log"
21 "github.com/opencord/voltha-go/db/model"
William Kurkiandaa6bb22019-03-07 12:26:28 -050022 "github.com/opencord/voltha-protos/go/voltha"
Stephane Barbariea75791c2019-01-24 10:58:06 -050023 "google.golang.org/grpc/codes"
24 "google.golang.org/grpc/status"
25 "sync"
26)
27
28type LogicalDeviceManager struct {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040029 logicalDeviceAgents sync.Map
Stephane Barbariea75791c2019-01-24 10:58:06 -050030 deviceMgr *DeviceManager
31 grpcNbiHdlr *APIHandler
32 clusterDataProxy *model.Proxy
33 exitChannel chan int
34 lockLogicalDeviceAgentsMap sync.RWMutex
35}
36
37func newLogicalDeviceManager(deviceMgr *DeviceManager, cdProxy *model.Proxy) *LogicalDeviceManager {
38 var logicalDeviceMgr LogicalDeviceManager
39 logicalDeviceMgr.exitChannel = make(chan int, 1)
Stephane Barbariea75791c2019-01-24 10:58:06 -050040 logicalDeviceMgr.deviceMgr = deviceMgr
41 logicalDeviceMgr.clusterDataProxy = cdProxy
42 logicalDeviceMgr.lockLogicalDeviceAgentsMap = sync.RWMutex{}
43 return &logicalDeviceMgr
44}
45
46func (ldMgr *LogicalDeviceManager) setGrpcNbiHandler(grpcNbiHandler *APIHandler) {
47 ldMgr.grpcNbiHdlr = grpcNbiHandler
48}
49
50func (ldMgr *LogicalDeviceManager) start(ctx context.Context) {
51 log.Info("starting-logical-device-manager")
52 log.Info("logical-device-manager-started")
53}
54
55func (ldMgr *LogicalDeviceManager) stop(ctx context.Context) {
56 log.Info("stopping-logical-device-manager")
57 ldMgr.exitChannel <- 1
58 log.Info("logical-device-manager-stopped")
59}
60
61func (ldMgr *LogicalDeviceManager) addLogicalDeviceAgentToMap(agent *LogicalDeviceAgent) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040062 if _, exist := ldMgr.logicalDeviceAgents.Load(agent.logicalDeviceId); !exist {
63 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceId, agent)
Stephane Barbariea75791c2019-01-24 10:58:06 -050064 }
65}
66
67func (ldMgr *LogicalDeviceManager) getLogicalDeviceAgent(logicalDeviceId string) *LogicalDeviceAgent {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040068 if agent, ok := ldMgr.logicalDeviceAgents.Load(logicalDeviceId); ok {
69 //return agent
70 return agent.(*LogicalDeviceAgent)
Stephane Barbariea75791c2019-01-24 10:58:06 -050071 }
72 return nil
73}
74
75func (ldMgr *LogicalDeviceManager) deleteLogicalDeviceAgent(logicalDeviceId string) {
Stephane Barbarieef6650d2019-07-18 12:15:09 -040076 ldMgr.logicalDeviceAgents.Delete(logicalDeviceId)
Stephane Barbariea75791c2019-01-24 10:58:06 -050077}
78
79// GetLogicalDevice provides a cloned most up to date logical device
80func (ldMgr *LogicalDeviceManager) getLogicalDevice(id string) (*voltha.LogicalDevice, error) {
81 log.Debugw("getlogicalDevice", log.Fields{"logicaldeviceid": id})
82 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
83 return agent.GetLogicalDevice()
84 }
85 return nil, status.Errorf(codes.NotFound, "%s", id)
86}
87
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -050088func (ldMgr *LogicalDeviceManager) IsLogicalDeviceInCache(id string) bool {
89 ldMgr.lockLogicalDeviceAgentsMap.Lock()
90 defer ldMgr.lockLogicalDeviceAgentsMap.Unlock()
Stephane Barbarieef6650d2019-07-18 12:15:09 -040091 _, exist := ldMgr.logicalDeviceAgents.Load(id)
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -050092 return exist
93}
94
Stephane Barbariea75791c2019-01-24 10:58:06 -050095func (ldMgr *LogicalDeviceManager) listLogicalDevices() (*voltha.LogicalDevices, error) {
96 log.Debug("ListAllLogicalDevices")
97 result := &voltha.LogicalDevices{}
Stephane Barbarieef6650d2019-07-18 12:15:09 -040098 if logicalDevices := ldMgr.clusterDataProxy.List(context.Background(), "/logical_devices", 0, false,
99 ""); logicalDevices != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500100 for _, logicalDevice := range logicalDevices.([]interface{}) {
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500101 // If device is not in memory then set it up
102 if !ldMgr.IsLogicalDeviceInCache(logicalDevice.(*voltha.LogicalDevice).Id) {
103 agent := newLogicalDeviceAgent(
Stephane Barbariea75791c2019-01-24 10:58:06 -0500104 logicalDevice.(*voltha.LogicalDevice).Id,
105 logicalDevice.(*voltha.LogicalDevice).RootDeviceId,
106 ldMgr,
107 ldMgr.deviceMgr,
108 ldMgr.clusterDataProxy,
109 )
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500110 if err := agent.start(nil, true); err != nil {
111 log.Warnw("failure-starting-agent", log.Fields{"logicalDeviceId": logicalDevice.(*voltha.LogicalDevice).Id})
112 agent.stop(nil)
113 } else {
114 ldMgr.addLogicalDeviceAgentToMap(agent)
115 }
Stephane Barbariea75791c2019-01-24 10:58:06 -0500116 }
117 result.Items = append(result.Items, logicalDevice.(*voltha.LogicalDevice))
118 }
119 }
120 return result, nil
121}
122
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500123// load loads a logical device manager in memory
124func (ldMgr *LogicalDeviceManager) load(lDeviceId string) error {
125 log.Debugw("loading-logical-device", log.Fields{"lDeviceId": lDeviceId})
126 // To prevent a race condition, let's hold the logical device agent map lock. This will prevent a loading and
127 // a create logical device callback from occurring at the same time.
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400128 if ldAgent, _ := ldMgr.logicalDeviceAgents.Load(lDeviceId); ldAgent == nil {
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500129 // Logical device not in memory - create a temp logical device Agent and let it load from memory
130 agent := newLogicalDeviceAgent(lDeviceId, "", ldMgr, ldMgr.deviceMgr, ldMgr.clusterDataProxy)
131 if err := agent.start(nil, true); err != nil {
132 agent.stop(nil)
133 return err
134 }
Stephane Barbarieef6650d2019-07-18 12:15:09 -0400135 ldMgr.logicalDeviceAgents.Store(agent.logicalDeviceId, agent)
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -0500136 }
137 // TODO: load the child device
138 return nil
139}
140
Stephane Barbariea75791c2019-01-24 10:58:06 -0500141func (ldMgr *LogicalDeviceManager) getLogicalDeviceId(device *voltha.Device) (*string, error) {
142 // Device can either be a parent or a child device
143 if device.Root {
144 // Parent device. The ID of a parent device is the logical device ID
145 return &device.ParentId, nil
146 }
147 // Device is child device
148 // retrieve parent device using child device ID
149 if parentDevice := ldMgr.deviceMgr.getParentDevice(device); parentDevice != nil {
150 return &parentDevice.ParentId, nil
151 }
152 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
153}
154
155func (ldMgr *LogicalDeviceManager) getLogicalPortId(device *voltha.Device) (*voltha.LogicalPortId, error) {
156 // Get the logical device where this device is attached
157 var lDeviceId *string
158 var err error
159 if lDeviceId, err = ldMgr.getLogicalDeviceId(device); err != nil {
160 return nil, err
161 }
162 var lDevice *voltha.LogicalDevice
163 if lDevice, err = ldMgr.getLogicalDevice(*lDeviceId); err != nil {
164 return nil, err
165 }
166 // Go over list of ports
167 for _, port := range lDevice.Ports {
168 if port.DeviceId == device.Id {
169 return &voltha.LogicalPortId{Id: *lDeviceId, PortId: port.Id}, nil
170 }
171 }
172 return nil, status.Errorf(codes.NotFound, "%s", device.Id)
173}
174
175func (ldMgr *LogicalDeviceManager) ListLogicalDevicePorts(ctx context.Context, id string) (*voltha.LogicalPorts, error) {
176 log.Debugw("ListLogicalDevicePorts", log.Fields{"logicaldeviceid": id})
177 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
178 return agent.ListLogicalDevicePorts()
179 }
180 return nil, status.Errorf(codes.NotFound, "%s", id)
181
182}
183
184func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlows(ctx context.Context, id string) (*voltha.Flows, error) {
185 log.Debugw("ListLogicalDeviceFlows", log.Fields{"logicaldeviceid": id})
186 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
187 return agent.ListLogicalDeviceFlows()
188 }
189 return nil, status.Errorf(codes.NotFound, "%s", id)
190
191}
192
193func (ldMgr *LogicalDeviceManager) ListLogicalDeviceFlowGroups(ctx context.Context, id string) (*voltha.FlowGroups, error) {
194 log.Debugw("ListLogicalDeviceFlowGroups", log.Fields{"logicaldeviceid": id})
195 if agent := ldMgr.getLogicalDeviceAgent(id); agent != nil {
196 return agent.ListLogicalDeviceFlowGroups()
197 }
198 return nil, status.Errorf(codes.NotFound, "%s", id)
199
200}
201
202func (ldMgr *LogicalDeviceManager) getLogicalPort(lPortId *voltha.LogicalPortId) (*voltha.LogicalPort, error) {
203 // Get the logical device where this device is attached
204 var err error
205 var lDevice *voltha.LogicalDevice
206 if lDevice, err = ldMgr.getLogicalDevice(lPortId.Id); err != nil {
207 return nil, err
208 }
209 // Go over list of ports
210 for _, port := range lDevice.Ports {
211 if port.Id == lPortId.PortId {
212 return port, nil
213 }
214 }
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400215 return nil, status.Errorf(codes.NotFound, "%s-%s", lPortId.Id, lPortId.PortId)
Stephane Barbariea75791c2019-01-24 10:58:06 -0500216}