blob: d971c4aa1a866516185e460e415ff7e32582579e [file] [log] [blame]
Stephane Barbariea75791c2019-01-24 10:58:06 -05001/*
2 * Copyright 2019-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"
David K. Bainbridgef430cd52019-05-28 15:00:35 -070021 "encoding/json"
npujar03b018e2019-11-13 15:29:36 +053022
sbarbari17d7e222019-11-05 10:02:29 -050023 "github.com/opencord/voltha-go/db/model"
Scott Baker807addd2019-10-24 15:16:21 -070024 "github.com/opencord/voltha-lib-go/v2/pkg/log"
25 "github.com/opencord/voltha-lib-go/v2/pkg/version"
Scott Baker555307d2019-11-04 08:58:01 -080026 "github.com/opencord/voltha-protos/v2/go/voltha"
Stephane Barbariea75791c2019-01-24 10:58:06 -050027 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/status"
29)
30
npujar03b018e2019-11-13 15:29:36 +053031// DataModelType - Enumerated type to keep track of miscellaneous data path agents
Stephane Barbariea75791c2019-01-24 10:58:06 -050032type DataModelType int
33
34// Enumerated list of data path agents
35const (
36 Adapters DataModelType = 1 + iota
Devmalya Paulc594bb32019-11-06 07:34:27 +000037 EventFilters
Stephane Barbariea75791c2019-01-24 10:58:06 -050038 CoreInstances
39 DeviceTypes
40 DeviceGroups
41 Voltha
42)
43
npujar03b018e2019-11-13 15:29:36 +053044// SentinelAdapterID is used to watch adapters in kv
45const SentinelAdapterID = "adapter_sentinel"
David K. Bainbridgebe883962019-05-22 14:49:12 -070046
Stephane Barbariea75791c2019-01-24 10:58:06 -050047// String equivalent for data path agents
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040048var commonTypes = []string{
Stephane Barbariea75791c2019-01-24 10:58:06 -050049 "Adapters",
Devmalya Paulc594bb32019-11-06 07:34:27 +000050 "EventFilters",
Stephane Barbariea75791c2019-01-24 10:58:06 -050051 "CoreInstances",
52 "DeviceTypes",
53 "DeviceGroups",
54 "Voltha",
55}
56
57// String converts the enumerated data path agent value to its string equivalent
58func (t DataModelType) String() string {
59 return commonTypes[t-1]
60}
61
npujar03b018e2019-11-13 15:29:36 +053062// MultipleValuesMsg represents multiple values message
David K. Bainbridgee14914d2019-05-24 13:43:05 -070063const MultipleValuesMsg = "Expected a single value for KV query for an instance (%s) of type '%s', but received multiple values"
64
Stephane Barbariea75791c2019-01-24 10:58:06 -050065// ModelProxyManager controls requests made to the miscellaneous data path agents
66type ModelProxyManager struct {
67 modelProxy map[string]*ModelProxy
68 clusterDataProxy *model.Proxy
69}
70
71func newModelProxyManager(cdProxy *model.Proxy) *ModelProxyManager {
72 var mgr ModelProxyManager
73 mgr.modelProxy = make(map[string]*ModelProxy)
74 mgr.clusterDataProxy = cdProxy
75 return &mgr
76}
77
npujar03b018e2019-11-13 15:29:36 +053078// GetVoltha - GetDeviceType returns the device type associated to the provided id
Stephane Barbariea75791c2019-01-24 10:58:06 -050079func (mpMgr *ModelProxyManager) GetVoltha(ctx context.Context) (*voltha.Voltha, error) {
80 log.Debug("GetVoltha")
81
David K. Bainbridgef430cd52019-05-28 15:00:35 -070082 /*
83 * For now, encode all the version information into a JSON object and
84 * pass that back as "version" so the client can get all the
85 * information associated with the version. Long term the API should
86 * better accomidate this, but for now this will work.
87 */
88 data, err := json.Marshal(&version.VersionInfo)
89 info := version.VersionInfo.Version
90 if err != nil {
91 log.Warnf("Unable to encode version information as JSON: %s", err.Error())
92 } else {
93 info = string(data)
94 }
95
David K. Bainbridgee14914d2019-05-24 13:43:05 -070096 return &voltha.Voltha{
David K. Bainbridgef430cd52019-05-28 15:00:35 -070097 Version: info,
David K. Bainbridgee14914d2019-05-24 13:43:05 -070098 }, nil
Stephane Barbariea75791c2019-01-24 10:58:06 -050099}
100
101// ListCoreInstances returns all the core instances known to the system
102func (mpMgr *ModelProxyManager) ListCoreInstances(ctx context.Context) (*voltha.CoreInstances, error) {
103 log.Debug("ListCoreInstances")
104
105 // TODO: Need to retrieve the list of registered cores
106
107 return &voltha.CoreInstances{}, status.Errorf(codes.NotFound, "no-core-instances")
108}
109
110// GetCoreInstance returns the core instance associated to the provided id
111func (mpMgr *ModelProxyManager) GetCoreInstance(ctx context.Context, id string) (*voltha.CoreInstance, error) {
112 log.Debugw("GetCoreInstance", log.Fields{"id": id})
113
114 // TODO: Need to retrieve the list of registered cores
115
116 return &voltha.CoreInstance{}, status.Errorf(codes.NotFound, "core-instance-%s", id)
117}
118
119// ListAdapters returns all the device types known to the system
120func (mpMgr *ModelProxyManager) ListAdapters(ctx context.Context) (*voltha.Adapters, error) {
121 log.Debug("ListAdapters")
122
123 var agent *ModelProxy
124 var exists bool
David K. Bainbridgebe883962019-05-22 14:49:12 -0700125 var adapter *voltha.Adapter
Stephane Barbariea75791c2019-01-24 10:58:06 -0500126
127 if agent, exists = mpMgr.modelProxy[Adapters.String()]; !exists {
128 agent = newModelProxy("adapters", mpMgr.clusterDataProxy)
129 mpMgr.modelProxy[Adapters.String()] = agent
130 }
131
132 adapters := &voltha.Adapters{}
David K. Bainbridgee14914d2019-05-24 13:43:05 -0700133 if items, err := agent.Get(); err != nil {
134 return nil, status.Errorf(codes.Internal, err.Error())
135 } else if items != nil {
136 list, ok := items.([]interface{})
137 if !ok {
138 list = []interface{}{items}
139 }
140 for _, item := range list {
David K. Bainbridgebe883962019-05-22 14:49:12 -0700141 adapter = item.(*voltha.Adapter)
npujar03b018e2019-11-13 15:29:36 +0530142 if adapter.Id != SentinelAdapterID { // don't report the sentinel
David K. Bainbridgebe883962019-05-22 14:49:12 -0700143 adapters.Items = append(adapters.Items, adapter)
144 }
Stephane Barbariea75791c2019-01-24 10:58:06 -0500145 }
146 log.Debugw("retrieved-adapters", log.Fields{"adapters": adapters})
147 return adapters, nil
148 }
149
150 return adapters, status.Errorf(codes.NotFound, "no-adapters")
151}
152
153// ListDeviceTypes returns all the device types known to the system
154func (mpMgr *ModelProxyManager) ListDeviceTypes(ctx context.Context) (*voltha.DeviceTypes, error) {
155 log.Debug("ListDeviceTypes")
156
157 var agent *ModelProxy
158 var exists bool
159
160 if agent, exists = mpMgr.modelProxy[DeviceTypes.String()]; !exists {
161 agent = newModelProxy("device_types", mpMgr.clusterDataProxy)
162 mpMgr.modelProxy[DeviceTypes.String()] = agent
163 }
164
165 deviceTypes := &voltha.DeviceTypes{}
David K. Bainbridgee14914d2019-05-24 13:43:05 -0700166 if items, err := agent.Get(); err != nil {
167 return nil, status.Errorf(codes.Internal, err.Error())
168 } else if items != nil {
169 list, ok := items.([]interface{})
170 if !ok {
171 list = []interface{}{items}
172 }
173 for _, item := range list {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500174 deviceTypes.Items = append(deviceTypes.Items, item.(*voltha.DeviceType))
175 }
176 return deviceTypes, nil
177 }
178
179 return deviceTypes, status.Errorf(codes.NotFound, "no-device-types")
180}
181
182// GetDeviceType returns the device type associated to the provided id
183func (mpMgr *ModelProxyManager) GetDeviceType(ctx context.Context, id string) (*voltha.DeviceType, error) {
184 log.Debugw("GetDeviceType", log.Fields{"id": id})
185
186 var agent *ModelProxy
187 var exists bool
188
189 if agent, exists = mpMgr.modelProxy[DeviceTypes.String()]; !exists {
190 agent = newModelProxy("device_types", mpMgr.clusterDataProxy)
191 mpMgr.modelProxy[DeviceTypes.String()] = agent
192 }
193
David K. Bainbridgee14914d2019-05-24 13:43:05 -0700194 if deviceType, err := agent.Get(id); err != nil {
195 return nil, status.Errorf(codes.Internal, err.Error())
196 } else if deviceType != nil {
197 _, ok := deviceType.(*voltha.DeviceType)
198 if !ok {
199 return nil, status.Errorf(codes.Internal, MultipleValuesMsg,
200 id, DeviceTypes.String())
201 }
Stephane Barbariea75791c2019-01-24 10:58:06 -0500202 return deviceType.(*voltha.DeviceType), nil
203 }
204
205 return &voltha.DeviceType{}, status.Errorf(codes.NotFound, "device-type-%s", id)
206}
207
208// ListDeviceGroups returns all the device groups known to the system
209func (mpMgr *ModelProxyManager) ListDeviceGroups(ctx context.Context) (*voltha.DeviceGroups, error) {
210 log.Debug("ListDeviceGroups")
211
212 var agent *ModelProxy
213 var exists bool
214
215 if agent, exists = mpMgr.modelProxy[DeviceGroups.String()]; !exists {
216 agent = newModelProxy("device_groups", mpMgr.clusterDataProxy)
217 mpMgr.modelProxy[DeviceGroups.String()] = agent
218 }
219
220 deviceGroups := &voltha.DeviceGroups{}
David K. Bainbridgee14914d2019-05-24 13:43:05 -0700221 if items, err := agent.Get(); err != nil {
222 return nil, status.Errorf(codes.Internal, err.Error())
223 } else if items != nil {
224 list, ok := items.([]interface{})
225 if !ok {
226 list = []interface{}{items}
227 }
228 for _, item := range list {
Stephane Barbariea75791c2019-01-24 10:58:06 -0500229 deviceGroups.Items = append(deviceGroups.Items, item.(*voltha.DeviceGroup))
230 }
231 return deviceGroups, nil
232 }
233
234 return deviceGroups, status.Errorf(codes.NotFound, "no-device-groups")
235}
236
237// GetDeviceGroup returns the device group associated to the provided id
238func (mpMgr *ModelProxyManager) GetDeviceGroup(ctx context.Context, id string) (*voltha.DeviceGroup, error) {
239 log.Debugw("GetDeviceGroup", log.Fields{"id": id})
240
241 var agent *ModelProxy
242 var exists bool
243
244 if agent, exists = mpMgr.modelProxy[DeviceGroups.String()]; !exists {
245 agent = newModelProxy("device_groups", mpMgr.clusterDataProxy)
246 mpMgr.modelProxy[DeviceGroups.String()] = agent
247 }
248
David K. Bainbridgee14914d2019-05-24 13:43:05 -0700249 if deviceGroup, err := agent.Get(id); err != nil {
250 return nil, status.Errorf(codes.Internal, err.Error())
251 } else if deviceGroup != nil {
252 _, ok := deviceGroup.(*voltha.DeviceGroup)
253 if !ok {
254 return nil, status.Errorf(codes.Internal, MultipleValuesMsg,
255 id, DeviceGroups.String())
256 }
Stephane Barbariea75791c2019-01-24 10:58:06 -0500257 return deviceGroup.(*voltha.DeviceGroup), nil
258 }
259
260 return &voltha.DeviceGroup{}, status.Errorf(codes.NotFound, "device-group-%s", id)
261}
262
Devmalya Paulc594bb32019-11-06 07:34:27 +0000263// ListEventFilters returns all the event filters known to the system
264func (mpMgr *ModelProxyManager) ListEventFilters(ctx context.Context) (*voltha.EventFilters, error) {
265 log.Debug("ListEventFilters")
Stephane Barbariea75791c2019-01-24 10:58:06 -0500266
267 var agent *ModelProxy
268 var exists bool
269
Devmalya Paulc594bb32019-11-06 07:34:27 +0000270 if agent, exists = mpMgr.modelProxy[EventFilters.String()]; !exists {
271 agent = newModelProxy("event_filters", mpMgr.clusterDataProxy)
272 mpMgr.modelProxy[EventFilters.String()] = agent
Stephane Barbariea75791c2019-01-24 10:58:06 -0500273 }
274
Devmalya Paulc594bb32019-11-06 07:34:27 +0000275 eventFilters := &voltha.EventFilters{}
David K. Bainbridgee14914d2019-05-24 13:43:05 -0700276 if items, err := agent.Get(); err != nil {
277 return nil, status.Errorf(codes.Internal, err.Error())
278 } else if items != nil {
279 list, ok := items.([]interface{})
280 if !ok {
281 list = []interface{}{items}
282 }
283 for _, item := range list {
Devmalya Paulc594bb32019-11-06 07:34:27 +0000284 eventFilters.Filters = append(eventFilters.Filters, item.(*voltha.EventFilter))
Stephane Barbariea75791c2019-01-24 10:58:06 -0500285 }
Devmalya Paulc594bb32019-11-06 07:34:27 +0000286 return eventFilters, nil
Stephane Barbariea75791c2019-01-24 10:58:06 -0500287 }
288
Devmalya Paulc594bb32019-11-06 07:34:27 +0000289 return eventFilters, status.Errorf(codes.NotFound, "no-event-filters")
Stephane Barbariea75791c2019-01-24 10:58:06 -0500290}
291
Devmalya Paulc594bb32019-11-06 07:34:27 +0000292// GetEventFilter returns the event filter associated to the provided device id
293func (mpMgr *ModelProxyManager) GetEventFilter(ctx context.Context, id string) (*voltha.EventFilters, error) {
294 log.Debugw("GetEventFilter", log.Fields{"id": id})
Stephane Barbariea75791c2019-01-24 10:58:06 -0500295
296 var agent *ModelProxy
297 var exists bool
298
Devmalya Paulc594bb32019-11-06 07:34:27 +0000299 if agent, exists = mpMgr.modelProxy[EventFilters.String()]; !exists {
300 agent = newModelProxy("event_filters", mpMgr.clusterDataProxy)
301 mpMgr.modelProxy[EventFilters.String()] = agent
Stephane Barbariea75791c2019-01-24 10:58:06 -0500302 }
303
Devmalya Paulc594bb32019-11-06 07:34:27 +0000304 if _, err := agent.Get(id); err != nil {
David K. Bainbridgee14914d2019-05-24 13:43:05 -0700305 return nil, status.Errorf(codes.Internal, err.Error())
Stephane Barbariea75791c2019-01-24 10:58:06 -0500306 }
Devmalya Paulc594bb32019-11-06 07:34:27 +0000307 //TODO: VOL-2305 Code to get filters for a particular device once Event filtering mechanism is implemented
308
309 return &voltha.EventFilters{}, status.Errorf(codes.NotFound, "event-filter-%s", id)
Stephane Barbariea75791c2019-01-24 10:58:06 -0500310}