blob: ed30bb728c33149cd8764993bfcd8a75a55c0814 [file] [log] [blame]
khenaidoobf6e7bb2018-08-14 22:27:29 -04001/*
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 */
khenaidoob9203542018-09-17 22:56:37 -040016package core
khenaidoobf6e7bb2018-08-14 22:27:29 -040017
18import (
19 "context"
20 "errors"
21 "github.com/golang/protobuf/ptypes/empty"
22 da "github.com/opencord/voltha-go/common/core/northbound/grpc"
23 "github.com/opencord/voltha-go/common/log"
24 "github.com/opencord/voltha-go/protos/common"
25 "github.com/opencord/voltha-go/protos/openflow_13"
26 "github.com/opencord/voltha-go/protos/voltha"
khenaidoob9203542018-09-17 22:56:37 -040027 "google.golang.org/grpc/codes"
khenaidoobf6e7bb2018-08-14 22:27:29 -040028 "google.golang.org/grpc/metadata"
khenaidoob9203542018-09-17 22:56:37 -040029 "google.golang.org/grpc/status"
khenaidoobf6e7bb2018-08-14 22:27:29 -040030)
31
32type APIHandler struct {
khenaidoob9203542018-09-17 22:56:37 -040033 deviceMgr *DeviceManager
34 logicalDeviceMgr *LogicalDeviceManager
khenaidoobf6e7bb2018-08-14 22:27:29 -040035 da.DefaultAPIHandler
36}
37
khenaidoo9a468962018-09-19 15:33:13 -040038func NewAPIHandler(deviceMgr *DeviceManager, lDeviceMgr *LogicalDeviceManager) *APIHandler {
khenaidoob9203542018-09-17 22:56:37 -040039 handler := &APIHandler{deviceMgr: deviceMgr,
khenaidoo9a468962018-09-19 15:33:13 -040040 logicalDeviceMgr: lDeviceMgr}
khenaidoobf6e7bb2018-08-14 22:27:29 -040041 return handler
42}
khenaidoo4d4802d2018-10-04 21:59:49 -040043
44// isTestMode is a helper function to determine a function is invoked for testing only
khenaidoobf6e7bb2018-08-14 22:27:29 -040045func isTestMode(ctx context.Context) bool {
46 md, _ := metadata.FromIncomingContext(ctx)
47 _, exist := md[common.TestModeKeys_api_test.String()]
48 return exist
49}
50
khenaidoo4d4802d2018-10-04 21:59:49 -040051// waitForNilResponseOnSuccess is a helper function to wait for a response on channel ch where an nil
52// response is expected in a successful scenario
53func waitForNilResponseOnSuccess(ctx context.Context, ch chan interface{}) (*empty.Empty, error) {
54 select {
55 case res := <-ch:
56 if res == nil {
57 return new(empty.Empty), nil
58 } else if err, ok := res.(error); ok {
59 return new(empty.Empty), err
60 } else {
61 log.Warnw("unexpected-return-type", log.Fields{"result": res})
62 err = status.Errorf(codes.Internal, "%s", res)
63 return new(empty.Empty), err
64 }
65 case <-ctx.Done():
66 log.Debug("client-timeout")
67 return nil, ctx.Err()
68 }
69}
70
khenaidoobf6e7bb2018-08-14 22:27:29 -040071func (handler *APIHandler) UpdateLogLevel(ctx context.Context, logging *voltha.Logging) (*empty.Empty, error) {
72 log.Debugw("UpdateLogLevel-request", log.Fields{"newloglevel": logging.Level, "intval": int(logging.Level)})
khenaidoo92e62c52018-10-03 14:02:54 -040073 out := new(empty.Empty)
74 log.SetPackageLogLevel(logging.PackageName, int(logging.Level))
75 return out, nil
khenaidoobf6e7bb2018-08-14 22:27:29 -040076}
77
78func (handler *APIHandler) EnableLogicalDevicePort(ctx context.Context, id *voltha.LogicalPortId) (*empty.Empty, error) {
79 log.Debugw("EnableLogicalDevicePort-request", log.Fields{"id": id, "test": common.TestModeKeys_api_test.String()})
80 if isTestMode(ctx) {
81 out := new(empty.Empty)
82 return out, nil
83 }
khenaidoo4d4802d2018-10-04 21:59:49 -040084 ch := make(chan interface{})
85 defer close(ch)
khenaidoo19d7b632018-10-30 10:49:50 -040086 go handler.logicalDeviceMgr.enableLogicalPort(ctx, id, ch)
khenaidoo4d4802d2018-10-04 21:59:49 -040087 return waitForNilResponseOnSuccess(ctx, ch)
khenaidoobf6e7bb2018-08-14 22:27:29 -040088}
89
90func (handler *APIHandler) DisableLogicalDevicePort(ctx context.Context, id *voltha.LogicalPortId) (*empty.Empty, error) {
91 log.Debugw("DisableLogicalDevicePort-request", log.Fields{"id": id, "test": common.TestModeKeys_api_test.String()})
92 if isTestMode(ctx) {
93 out := new(empty.Empty)
94 return out, nil
95 }
khenaidoo19d7b632018-10-30 10:49:50 -040096 ch := make(chan interface{})
97 defer close(ch)
98 go handler.logicalDeviceMgr.disableLogicalPort(ctx, id, ch)
99 return waitForNilResponseOnSuccess(ctx, ch)
khenaidoobf6e7bb2018-08-14 22:27:29 -0400100}
101
102func (handler *APIHandler) UpdateLogicalDeviceFlowTable(ctx context.Context, flow *openflow_13.FlowTableUpdate) (*empty.Empty, error) {
103 log.Debugw("UpdateLogicalDeviceFlowTable-request", log.Fields{"flow": flow, "test": common.TestModeKeys_api_test.String()})
104 if isTestMode(ctx) {
105 out := new(empty.Empty)
106 return out, nil
107 }
khenaidoo19d7b632018-10-30 10:49:50 -0400108 ch := make(chan interface{})
109 defer close(ch)
110 go handler.logicalDeviceMgr.updateFlowTable(ctx, flow.Id, flow.FlowMod, ch)
111 return waitForNilResponseOnSuccess(ctx, ch)
khenaidoobf6e7bb2018-08-14 22:27:29 -0400112}
113
114func (handler *APIHandler) UpdateLogicalDeviceFlowGroupTable(ctx context.Context, flow *openflow_13.FlowGroupTableUpdate) (*empty.Empty, error) {
115 log.Debugw("UpdateLogicalDeviceFlowGroupTable-request", log.Fields{"flow": flow, "test": common.TestModeKeys_api_test.String()})
116 if isTestMode(ctx) {
117 out := new(empty.Empty)
118 return out, nil
119 }
khenaidoo19d7b632018-10-30 10:49:50 -0400120 ch := make(chan interface{})
121 defer close(ch)
122 go handler.logicalDeviceMgr.updateGroupTable(ctx, flow.Id, flow.GroupMod, ch)
123 return waitForNilResponseOnSuccess(ctx, ch)
khenaidoobf6e7bb2018-08-14 22:27:29 -0400124}
125
khenaidoob9203542018-09-17 22:56:37 -0400126// GetDevice must be implemented in the read-only containers - should it also be implemented here?
127func (handler *APIHandler) GetDevice(ctx context.Context, id *voltha.ID) (*voltha.Device, error) {
128 log.Debugw("GetDevice-request", log.Fields{"id": id})
khenaidoo19d7b632018-10-30 10:49:50 -0400129 return handler.deviceMgr.GetDevice(id.Id)
khenaidoob9203542018-09-17 22:56:37 -0400130}
131
132// GetDevice must be implemented in the read-only containers - should it also be implemented here?
133func (handler *APIHandler) ListDevices(ctx context.Context, empty *empty.Empty) (*voltha.Devices, error) {
134 log.Debug("ListDevices")
135 return handler.deviceMgr.ListDevices()
136}
137
138// GetLogicalDevice must be implemented in the read-only containers - should it also be implemented here?
139func (handler *APIHandler) GetLogicalDevice(ctx context.Context, id *voltha.ID) (*voltha.LogicalDevice, error) {
140 log.Debugw("GetLogicalDevice-request", log.Fields{"id": id})
141 return handler.logicalDeviceMgr.getLogicalDevice(id.Id)
142}
143
144// ListLogicalDevices must be implemented in the read-only containers - should it also be implemented here?
145func (handler *APIHandler) ListLogicalDevices(ctx context.Context, empty *empty.Empty) (*voltha.LogicalDevices, error) {
146 log.Debug("ListLogicalDevices")
147 return handler.logicalDeviceMgr.listLogicalDevices()
148}
149
khenaidoo19d7b632018-10-30 10:49:50 -0400150// ListLogicalDevicePorts must be implemented in the read-only containers - should it also be implemented here?
151func (handler *APIHandler) ListLogicalDevicePorts(ctx context.Context, id *voltha.ID) (*voltha.LogicalPorts, error) {
152 log.Debugw("ListLogicalDevicePorts", log.Fields{"logicaldeviceid": id})
153 return handler.logicalDeviceMgr.ListLogicalDevicePorts(ctx, id.Id)
154}
155
khenaidoo4d4802d2018-10-04 21:59:49 -0400156// CreateDevice creates a new parent device in the data model
khenaidoobf6e7bb2018-08-14 22:27:29 -0400157func (handler *APIHandler) CreateDevice(ctx context.Context, device *voltha.Device) (*voltha.Device, error) {
khenaidoob9203542018-09-17 22:56:37 -0400158 log.Debugw("createdevice", log.Fields{"device": *device})
khenaidoobf6e7bb2018-08-14 22:27:29 -0400159 if isTestMode(ctx) {
160 return &voltha.Device{Id: device.Id}, nil
161 }
khenaidoob9203542018-09-17 22:56:37 -0400162 ch := make(chan interface{})
163 defer close(ch)
164 go handler.deviceMgr.createDevice(ctx, device, ch)
165 select {
166 case res := <-ch:
khenaidoo92e62c52018-10-03 14:02:54 -0400167 if res != nil {
168 if err, ok := res.(error); ok {
169 return &voltha.Device{}, err
170 }
171 if d, ok := res.(*voltha.Device); ok {
172 return d, nil
173 }
khenaidoob9203542018-09-17 22:56:37 -0400174 }
khenaidoo92e62c52018-10-03 14:02:54 -0400175 log.Warnw("create-device-unexpected-return-type", log.Fields{"result": res})
176 err := status.Errorf(codes.Internal, "%s", res)
177 return &voltha.Device{}, err
khenaidoob9203542018-09-17 22:56:37 -0400178 case <-ctx.Done():
179 log.Debug("createdevice-client-timeout")
180 return nil, ctx.Err()
181 }
khenaidoobf6e7bb2018-08-14 22:27:29 -0400182}
183
khenaidoo4d4802d2018-10-04 21:59:49 -0400184// EnableDevice activates a device by invoking the adopt_device API on the appropriate adapter
khenaidoobf6e7bb2018-08-14 22:27:29 -0400185func (handler *APIHandler) EnableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
khenaidoob9203542018-09-17 22:56:37 -0400186 log.Debugw("enabledevice", log.Fields{"id": id})
khenaidoobf6e7bb2018-08-14 22:27:29 -0400187 if isTestMode(ctx) {
khenaidoo4d4802d2018-10-04 21:59:49 -0400188 return new(empty.Empty), nil
khenaidoobf6e7bb2018-08-14 22:27:29 -0400189 }
khenaidoob9203542018-09-17 22:56:37 -0400190 ch := make(chan interface{})
191 defer close(ch)
192 go handler.deviceMgr.enableDevice(ctx, id, ch)
khenaidoo4d4802d2018-10-04 21:59:49 -0400193 return waitForNilResponseOnSuccess(ctx, ch)
khenaidoobf6e7bb2018-08-14 22:27:29 -0400194}
195
khenaidoo4d4802d2018-10-04 21:59:49 -0400196// DisableDevice disables a device along with any child device it may have
khenaidoobf6e7bb2018-08-14 22:27:29 -0400197func (handler *APIHandler) DisableDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
198 log.Debugw("disabledevice-request", log.Fields{"id": id})
199 if isTestMode(ctx) {
khenaidoo4d4802d2018-10-04 21:59:49 -0400200 return new(empty.Empty), nil
khenaidoobf6e7bb2018-08-14 22:27:29 -0400201 }
khenaidoo92e62c52018-10-03 14:02:54 -0400202 ch := make(chan interface{})
203 defer close(ch)
204 go handler.deviceMgr.disableDevice(ctx, id, ch)
khenaidoo4d4802d2018-10-04 21:59:49 -0400205 return waitForNilResponseOnSuccess(ctx, ch)
khenaidoobf6e7bb2018-08-14 22:27:29 -0400206}
207
khenaidoo4d4802d2018-10-04 21:59:49 -0400208//RebootDevice invoked the reboot API to the corresponding adapter
khenaidoobf6e7bb2018-08-14 22:27:29 -0400209func (handler *APIHandler) RebootDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
khenaidoo4d4802d2018-10-04 21:59:49 -0400210 log.Debugw("rebootDevice-request", log.Fields{"id": id})
khenaidoobf6e7bb2018-08-14 22:27:29 -0400211 if isTestMode(ctx) {
khenaidoo4d4802d2018-10-04 21:59:49 -0400212 return new(empty.Empty), nil
khenaidoobf6e7bb2018-08-14 22:27:29 -0400213 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400214 ch := make(chan interface{})
215 defer close(ch)
216 go handler.deviceMgr.rebootDevice(ctx, id, ch)
217 return waitForNilResponseOnSuccess(ctx, ch)
khenaidoobf6e7bb2018-08-14 22:27:29 -0400218}
219
khenaidoo4d4802d2018-10-04 21:59:49 -0400220// DeleteDevice removes a device from the data model
khenaidoobf6e7bb2018-08-14 22:27:29 -0400221func (handler *APIHandler) DeleteDevice(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
222 log.Debugw("deletedevice-request", log.Fields{"id": id})
223 if isTestMode(ctx) {
khenaidoo4d4802d2018-10-04 21:59:49 -0400224 return new(empty.Empty), nil
khenaidoobf6e7bb2018-08-14 22:27:29 -0400225 }
khenaidoo4d4802d2018-10-04 21:59:49 -0400226 ch := make(chan interface{})
227 defer close(ch)
228 go handler.deviceMgr.deleteDevice(ctx, id, ch)
229 return waitForNilResponseOnSuccess(ctx, ch)
khenaidoobf6e7bb2018-08-14 22:27:29 -0400230}
231
232func (handler *APIHandler) DownloadImage(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
233 log.Debugw("DownloadImage-request", log.Fields{"img": *img})
234 if isTestMode(ctx) {
235 resp := &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}
236 return resp, nil
237 }
238
239 return nil, errors.New("UnImplemented")
240}
241
242func (handler *APIHandler) CancelImageDownload(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
243 log.Debugw("CancelImageDownload-request", log.Fields{"img": *img})
244 if isTestMode(ctx) {
245 resp := &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}
246 return resp, nil
247 }
248 return nil, errors.New("UnImplemented")
249}
250
251func (handler *APIHandler) ActivateImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
252 log.Debugw("ActivateImageUpdate-request", log.Fields{"img": *img})
253 if isTestMode(ctx) {
254 resp := &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}
255 return resp, nil
256 }
257 return nil, errors.New("UnImplemented")
258}
259
260func (handler *APIHandler) RevertImageUpdate(ctx context.Context, img *voltha.ImageDownload) (*common.OperationResp, error) {
261 log.Debugw("RevertImageUpdate-request", log.Fields{"img": *img})
262 if isTestMode(ctx) {
263 resp := &common.OperationResp{Code: common.OperationResp_OPERATION_SUCCESS}
264 return resp, nil
265 }
266 return nil, errors.New("UnImplemented")
267}
268
269func (handler *APIHandler) UpdateDevicePmConfigs(ctx context.Context, configs *voltha.PmConfigs) (*empty.Empty, error) {
270 log.Debugw("UpdateDevicePmConfigs-request", log.Fields{"configs": *configs})
271 if isTestMode(ctx) {
272 out := new(empty.Empty)
273 return out, nil
274 }
275 return nil, errors.New("UnImplemented")
276}
277
278func (handler *APIHandler) CreateAlarmFilter(ctx context.Context, filter *voltha.AlarmFilter) (*voltha.AlarmFilter, error) {
279 log.Debugw("CreateAlarmFilter-request", log.Fields{"filter": *filter})
280 if isTestMode(ctx) {
281 f := &voltha.AlarmFilter{Id: filter.Id}
282 return f, nil
283 }
284 return nil, errors.New("UnImplemented")
285}
286
287func (handler *APIHandler) UpdateAlarmFilter(ctx context.Context, filter *voltha.AlarmFilter) (*voltha.AlarmFilter, error) {
288 log.Debugw("UpdateAlarmFilter-request", log.Fields{"filter": *filter})
289 if isTestMode(ctx) {
290 f := &voltha.AlarmFilter{Id: filter.Id}
291 return f, nil
292 }
293 return nil, errors.New("UnImplemented")
294}
295
296func (handler *APIHandler) DeleteAlarmFilter(ctx context.Context, id *voltha.ID) (*empty.Empty, error) {
297 log.Debugw("DeleteAlarmFilter-request", log.Fields{"id": *id})
298 if isTestMode(ctx) {
299 out := new(empty.Empty)
300 return out, nil
301 }
302 return nil, errors.New("UnImplemented")
303}
304
305func (handler *APIHandler) SelfTest(ctx context.Context, id *voltha.ID) (*voltha.SelfTestResponse, error) {
306 log.Debugw("SelfTest-request", log.Fields{"id": id})
307 if isTestMode(ctx) {
308 resp := &voltha.SelfTestResponse{Result: voltha.SelfTestResponse_SUCCESS}
309 return resp, nil
310 }
311 return nil, errors.New("UnImplemented")
312}