blob: dfaf76771f6980e17c7401c222e4b8108c1ff45c [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/gogo/protobuf/proto"
21 "github.com/opencord/voltha-go/common/log"
22 "github.com/opencord/voltha-go/db/model"
William Kurkiandaa6bb22019-03-07 12:26:28 -050023 "github.com/opencord/voltha-protos/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 DeviceAgent struct {
30 deviceId string
31 deviceType string
32 lastData *voltha.Device
33 deviceMgr *DeviceManager
34 clusterDataProxy *model.Proxy
35 exitChannel chan int
36 lockDevice sync.RWMutex
37}
38
39//newDeviceAgent creates a new device agent along as creating a unique ID for the device and set the device state to
40//preprovisioning
41func newDeviceAgent(device *voltha.Device, deviceMgr *DeviceManager, cdProxy *model.Proxy) *DeviceAgent {
42 var agent DeviceAgent
43 agent.deviceId = device.Id
44 agent.deviceType = device.Type
45 agent.lastData = device
46 agent.deviceMgr = deviceMgr
47 agent.exitChannel = make(chan int, 1)
48 agent.clusterDataProxy = cdProxy
49 agent.lockDevice = sync.RWMutex{}
50 return &agent
51}
52
53// start save the device to the data model and registers for callbacks on that device
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -050054func (agent *DeviceAgent) start(ctx context.Context, loadFromDb bool) error {
Stephane Barbariea75791c2019-01-24 10:58:06 -050055 agent.lockDevice.Lock()
56 defer agent.lockDevice.Unlock()
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -050057 log.Debugw("starting-device-agent", log.Fields{"device": agent.lastData})
58 if loadFromDb {
59 if device := agent.clusterDataProxy.Get("/devices/"+agent.deviceId, 0, false, ""); device != nil {
60 if d, ok := device.(*voltha.Device); ok {
61 agent.lastData = proto.Clone(d).(*voltha.Device)
62 }
63 } else {
64 log.Errorw("failed-to-load-device", log.Fields{"deviceId": agent.deviceId})
65 return status.Errorf(codes.NotFound, "device-%s", agent.deviceId)
66 }
67 log.Debugw("device-loaded-from-dB", log.Fields{"device": agent.lastData})
68 }
Stephane Barbariea75791c2019-01-24 10:58:06 -050069 log.Debug("device-agent-started")
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -050070 return nil
Stephane Barbariea75791c2019-01-24 10:58:06 -050071}
72
73// stop stops the device agent. Not much to do for now
74func (agent *DeviceAgent) stop(ctx context.Context) {
75 agent.lockDevice.Lock()
76 defer agent.lockDevice.Unlock()
77 log.Debug("stopping-device-agent")
78 agent.exitChannel <- 1
79 log.Debug("device-agent-stopped")
80}
81
82// GetDevice retrieves the latest device information from the data model
83func (agent *DeviceAgent) getDevice() (*voltha.Device, error) {
84 agent.lockDevice.Lock()
85 defer agent.lockDevice.Unlock()
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -050086 if device := agent.clusterDataProxy.Get("/devices/"+agent.deviceId, 0, false, ""); device != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -050087 if d, ok := device.(*voltha.Device); ok {
88 cloned := proto.Clone(d).(*voltha.Device)
89 return cloned, nil
90 }
91 }
92 return nil, status.Errorf(codes.NotFound, "device-%s", agent.deviceId)
93}
94
95// getDeviceWithoutLock is a helper function to be used ONLY by any device agent function AFTER it has acquired the device lock.
96// This function is meant so that we do not have duplicate code all over the device agent functions
97func (agent *DeviceAgent) getDeviceWithoutLock() (*voltha.Device, error) {
Stephane Barbarie1e28f3e2019-02-08 15:45:20 -050098 if device := agent.clusterDataProxy.Get("/devices/"+agent.deviceId, 0, false, ""); device != nil {
Stephane Barbariea75791c2019-01-24 10:58:06 -050099 if d, ok := device.(*voltha.Device); ok {
100 cloned := proto.Clone(d).(*voltha.Device)
101 return cloned, nil
102 }
103 }
104 return nil, status.Errorf(codes.NotFound, "device-%s", agent.deviceId)
105}
106
107// getPorts retrieves the ports information of the device based on the port type.
108func (agent *DeviceAgent) getPorts(ctx context.Context, portType voltha.Port_PortType) *voltha.Ports {
109 log.Debugw("getPorts", log.Fields{"id": agent.deviceId, "portType": portType})
110 ports := &voltha.Ports{}
111 if device, _ := agent.deviceMgr.GetDevice(agent.deviceId); device != nil {
112 for _, port := range device.Ports {
113 if port.Type == portType {
114 ports.Items = append(ports.Items, port)
115 }
116 }
117 }
118 return ports
119}
120
121// ListDevicePorts retrieves the ports information for a particular device.
122func (agent *DeviceAgent) ListDevicePorts(ctx context.Context) (*voltha.Ports, error) {
123 log.Debugw("ListDevicePorts", log.Fields{"id": agent.deviceId})
124 ports := &voltha.Ports{}
125 if device, _ := agent.deviceMgr.GetDevice(agent.deviceId); device != nil {
126 for _, entry := range device.GetPorts() {
127 ports.Items = append(ports.Items, entry)
128 }
129 return ports, nil
130 }
131 return nil, status.Errorf(codes.NotFound, "device-%s", agent.deviceId)
132}
133
134// ListDevicePmConfigs retrieves the ports information for a particular device.
135func (agent *DeviceAgent) ListDevicePmConfigs(ctx context.Context) (*voltha.PmConfigs, error) {
136 log.Debugw("ListDevicePmConfigs", log.Fields{"id": agent.deviceId})
137 if device, _ := agent.deviceMgr.GetDevice(agent.deviceId); device != nil {
138 return device.GetPmConfigs(), nil
139 }
140 return nil, status.Errorf(codes.NotFound, "device-%s", agent.deviceId)
141}
142
143// ListDeviceFlows retrieves the ports information for a particular device.
144func (agent *DeviceAgent) ListDeviceFlows(ctx context.Context) (*voltha.Flows, error) {
145 log.Debugw("ListDeviceFlows", log.Fields{"id": agent.deviceId})
146 if device, _ := agent.deviceMgr.GetDevice(agent.deviceId); device != nil {
147 return device.GetFlows(), nil
148 }
149 return nil, status.Errorf(codes.NotFound, "device-%s", agent.deviceId)
150}
151
152// ListDeviceFlows retrieves the ports information for a particular device.
153func (agent *DeviceAgent) ListDeviceFlowGroups(ctx context.Context) (*voltha.FlowGroups, error) {
154 log.Debugw("ListDeviceFlowGroups", log.Fields{"id": agent.deviceId})
155 if device, _ := agent.deviceMgr.GetDevice(agent.deviceId); device != nil {
156 return device.GetFlowGroups(), nil
157 }
158 return nil, status.Errorf(codes.NotFound, "device-%s", agent.deviceId)
159}
160
161// GetImageDownloadStatus retrieves the download status of an image of a particular device.
162func (agent *DeviceAgent) GetImageDownloadStatus(ctx context.Context, imageName string) (*voltha.ImageDownload, error) {
163 log.Debugw("GetImageDownloadStatus", log.Fields{"id": agent.deviceId})
164 if device, _ := agent.deviceMgr.GetDevice(agent.deviceId); device != nil {
165 for _, img := range device.GetImageDownloads() {
166 if img.GetName() == imageName {
167 return img, nil
168 }
169 }
170 return nil, status.Errorf(codes.NotFound, "device-%s, image-%s", agent.deviceId, imageName)
171 }
172 return nil, status.Errorf(codes.NotFound, "device-%s", agent.deviceId)
173}
174
175// GetImageDownload retrieves the image download for a particular device.
176func (agent *DeviceAgent) GetImageDownload(ctx context.Context, imageName string) (*voltha.ImageDownload, error) {
177 log.Debugw("GetImageDownload", log.Fields{"id": agent.deviceId})
178 if device, _ := agent.deviceMgr.GetDevice(agent.deviceId); device != nil {
179 for _, img := range device.GetImageDownloads() {
180 if img.GetName() == imageName {
181 return img, nil
182 }
183 }
184 return nil, status.Errorf(codes.NotFound, "device-%s, image-%s", agent.deviceId, imageName)
185 }
186 return nil, status.Errorf(codes.NotFound, "device-%s", agent.deviceId)
187}
188
189// ListImageDownloads retrieves the image downloads for a particular device.
190func (agent *DeviceAgent) ListImageDownloads(ctx context.Context) (*voltha.ImageDownloads, error) {
191 log.Debugw("ListImageDownloads", log.Fields{"id": agent.deviceId})
192 if device, _ := agent.deviceMgr.GetDevice(agent.deviceId); device != nil {
193 return &voltha.ImageDownloads{Items: device.GetImageDownloads()}, nil
194 }
195 return nil, status.Errorf(codes.NotFound, "device-%s", agent.deviceId)
196}
197
198// GetImages retrieves the list of images for a particular device.
199func (agent *DeviceAgent) GetImages(ctx context.Context) (*voltha.Images, error) {
200 log.Debugw("GetImages", log.Fields{"id": agent.deviceId})
201 if device, _ := agent.deviceMgr.GetDevice(agent.deviceId); device != nil {
202 return device.GetImages(), nil
203 }
204 return nil, status.Errorf(codes.NotFound, "device-%s", agent.deviceId)
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400205}