blob: 3b958ccc098397487aee51bc2715cfc4836f488c [file] [log] [blame]
Carmelo Cascone95dcaa02019-03-08 10:53:01 -08001/*
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 */
16
17package org.onosproject.drivers.gnmi;
18
19import com.google.common.collect.Maps;
20import org.onlab.util.SharedExecutors;
21import org.onosproject.gnmi.api.GnmiController;
22import org.onosproject.net.DeviceId;
23import org.onosproject.net.MastershipRole;
24import org.onosproject.net.device.DeviceAgentEvent;
25import org.onosproject.net.device.DeviceAgentListener;
26import org.onosproject.net.device.DeviceHandshaker;
27import org.onosproject.net.provider.ProviderId;
28
29import java.util.TimerTask;
30import java.util.concurrent.ConcurrentMap;
31
32import static com.google.common.base.Preconditions.checkNotNull;
33
34/**
35 * Implementation of DeviceHandshaker that allows using the gNMI driver as a
36 * standalone one. Since gNMI does not support mastership, this driver stores a
37 * copy of the agent listeners registered by the providers, needed to
38 * acknowledge whatever role was requested.
39 */
40public class GnmiHandshakerStandalone
41 extends GnmiHandshaker implements DeviceHandshaker {
42
43 private static final int ROLE_REPLY_LATENCY_MILLIS = 200;
44 private static final ConcurrentMap<DeviceId, ConcurrentMap<ProviderId, DeviceAgentListener>>
45 AGENT_LISTENERS = Maps.newConcurrentMap();
46 private static final ConcurrentMap<DeviceId, MastershipRole>
47 ROLES = Maps.newConcurrentMap();
48
49 @Override
50 public void roleChanged(MastershipRole newRole) {
51 final DeviceAgentEvent.Type eventType;
52 switch (newRole) {
53 case MASTER:
54 eventType = DeviceAgentEvent.Type.ROLE_MASTER;
55 break;
56 case STANDBY:
57 eventType = DeviceAgentEvent.Type.ROLE_STANDBY;
58 break;
59 case NONE:
60 eventType = DeviceAgentEvent.Type.ROLE_NONE;
61 break;
62 default:
63 log.error("Unrecognized mastership role {}", newRole);
64 return;
65 }
66 SharedExecutors.getTimer().schedule(new TimerTask() {
67 @Override
68 public void run() {
69 if (newRole == MastershipRole.NONE) {
70 ROLES.remove(deviceId);
71 } else {
72 ROLES.put(data().deviceId(), newRole);
73 }
74 postAgentEvent(new DeviceAgentEvent(
75 eventType, data().deviceId()));
76 }
77 }, ROLE_REPLY_LATENCY_MILLIS);
78 }
79
80 @Override
81 public MastershipRole getRole() {
82 return ROLES.getOrDefault(data().deviceId(), MastershipRole.NONE);
83 }
84
85 @Override
86 public void addDeviceAgentListener(ProviderId providerId, DeviceAgentListener listener) {
87 handler().get(GnmiController.class)
88 .addDeviceAgentListener(data().deviceId(), providerId, listener);
89 AGENT_LISTENERS.putIfAbsent(deviceId, Maps.newConcurrentMap());
90 AGENT_LISTENERS.get(deviceId).put(providerId, listener);
91 }
92
93 @Override
94 public void removeDeviceAgentListener(ProviderId providerId) {
95 handler().get(GnmiController.class)
96 .removeDeviceAgentListener(data().deviceId(), providerId);
97 AGENT_LISTENERS.computeIfPresent(deviceId, (did, listeners) -> {
98 listeners.remove(providerId);
99 return listeners.isEmpty() ? null : listeners;
100 });
101 }
102
103 private void postAgentEvent(DeviceAgentEvent event) {
104 checkNotNull(event);
105 if (AGENT_LISTENERS.containsKey(event.subject())) {
106 AGENT_LISTENERS.get(event.subject()).values()
107 .forEach(l -> l.event(event));
108 }
109 }
110
111 @Override
112 public void disconnect() {
113 ROLES.remove(data().deviceId());
114 AGENT_LISTENERS.remove(data().deviceId());
115 super.disconnect();
116 }
117}