blob: 6085bbcf2c63fc45fbcbe2d32fd0179f0726db24 [file] [log] [blame]
Thomas Vachuskaee79ad32019-03-05 17:26:55 -08001/*
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 */
16
17package org.onosproject.onlpdemo;
18
19import com.google.common.collect.ImmutableList;
20import com.google.common.collect.Maps;
21import com.google.common.util.concurrent.Futures;
22import gnmi.Gnmi;
23import org.onlab.util.SharedExecutors;
24import org.onosproject.gnmi.api.GnmiClient;
25import org.onosproject.gnmi.api.GnmiController;
26import org.onosproject.net.DeviceId;
27import org.onosproject.net.Port;
28import org.onosproject.net.config.NetworkConfigService;
29import org.onosproject.net.device.DeviceService;
30import org.onosproject.ui.UiExtension;
31import org.onosproject.ui.UiExtensionService;
32import org.onosproject.ui.UiMessageHandlerFactory;
33import org.onosproject.ui.UiTopoOverlay;
34import org.onosproject.ui.UiTopoOverlayFactory;
35import org.onosproject.ui.UiView;
36import org.onosproject.ui.UiViewHidden;
37import org.osgi.service.component.annotations.Activate;
38import org.osgi.service.component.annotations.Component;
39import org.osgi.service.component.annotations.Deactivate;
40import org.osgi.service.component.annotations.Reference;
41import org.osgi.service.component.annotations.ReferenceCardinality;
42import org.slf4j.Logger;
43import org.slf4j.LoggerFactory;
44
45import java.util.List;
46import java.util.Map;
47import java.util.TimerTask;
48import java.util.concurrent.CompletableFuture;
49
50/**
51 * Extends the ONOS GUI to display various ONLP device data.
52 */
53@Component(immediate = true, service = OnlpDemoManager.class)
54public class OnlpDemoManager {
55
56 private Logger log = LoggerFactory.getLogger(getClass());
57
58 private static final String EXTENSION_ID = "onlpdemo";
59 private static final String OVERLAY_ID = "od-overlay";
60
61 private static final String OVERLAY_VIEW_ID = "odTopov";
62 private static final String TABLE_VIEW_ID = "onlp";
63
64 // List of application views
65 private final List<UiView> uiViews = ImmutableList.of(
66 new UiViewHidden(OVERLAY_VIEW_ID),
67 new UiViewHidden(TABLE_VIEW_ID)
68 );
69
70 // Factory for UI message handlers
71 private final UiMessageHandlerFactory messageHandlerFactory =
72 () -> ImmutableList.of(new OnlpDemoViewMessageHandler(new GnmiOnlpDataSource()));
73
74 // Factory for UI topology overlays
75 private final UiTopoOverlayFactory topoOverlayFactory =
76 () -> ImmutableList.of(new UiTopoOverlay(OVERLAY_ID));
77
78 // Application UI extension
79 protected UiExtension extension =
80 new UiExtension.Builder(getClass().getClassLoader(), uiViews)
81 .resourcePath(EXTENSION_ID)
82 .messageHandlerFactory(messageHandlerFactory)
83 .topoOverlayFactory(topoOverlayFactory)
84 .build();
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY)
87 protected NetworkConfigService networkConfigService;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY)
90 protected DeviceService deviceService;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY)
93 protected UiExtensionService uiExtensionService;
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY)
96 protected GnmiController gnmiController;
97
98 @Activate
99 protected void activate() {
100 uiExtensionService.register(extension);
101 log.info("Started");
102 }
103
104 @Deactivate
105 protected void deactivate() {
106 uiExtensionService.unregister(extension);
107 log.info("Stopped");
108 }
109
110
111 public class OnlpData {
112 String id;
113 String presence;
114 String vendor;
115 String modelNumber;
116 String serialNumber;
117 String formFactor;
118
119 OnlpData(String id, String presence, String vendor, String modelNumber,
120 String serialNumber, String formFactor) {
121 this.id = id;
122 this.presence = presence;
123 this.vendor = vendor;
124 this.modelNumber = modelNumber;
125 this.serialNumber = serialNumber;
126 this.formFactor = formFactor;
127 }
128 }
129
130 public interface OnlpDataSource {
131 List<OnlpData> getData(DeviceId deviceId);
132 }
133
134
135 public class GnmiOnlpDataSource implements OnlpDataSource {
136
137 private Map<DeviceId, List<OnlpData>> cache = Maps.newConcurrentMap();
138
139 GnmiOnlpDataSource() {
140 SharedExecutors.getTimer().schedule(new TimerTask() {
141 @Override
142 public void run() {
143 cache.keySet().forEach(GnmiOnlpDataSource.this::fetchData);
144 }
145 }, 5000, 5000);
146 }
147
148 @Override
149 public List<OnlpData> getData(DeviceId deviceId) {
150 return cache.computeIfAbsent(deviceId, k -> ImmutableList.of());
151 }
152
153 private void fetchData(DeviceId deviceId) {
154 ImmutableList.Builder<OnlpData> builder = ImmutableList.builder();
155 GnmiClient gnmiClient = gnmiController.getClient(deviceId);
156 deviceService.getPorts(deviceId)
157 .forEach(port -> builder.add(getOnlpData(gnmiClient, port)));
158 cache.put(deviceId, builder.build());
159 }
160
161 private OnlpData getOnlpData(GnmiClient gnmiClient, Port port) {
162 CompletableFuture<Gnmi.GetResponse> prReq = gnmiClient.get(fieldRequest(port, "present"));
163 CompletableFuture<Gnmi.GetResponse> veReq = gnmiClient.get(fieldRequest(port, "vendor"));
164 CompletableFuture<Gnmi.GetResponse> snReq = gnmiClient.get(fieldRequest(port, "serial-no"));
165 CompletableFuture<Gnmi.GetResponse> vpReq = gnmiClient.get(fieldRequest(port, "vendor-part"));
166 CompletableFuture<Gnmi.GetResponse> ffReq = gnmiClient.get(fieldRequest(port, "form-factor"));
167
168 return new OnlpData("sfp-" + port.number().name().replaceFirst("/[0-9]", ""),
169 value(prReq).equals("PRESENT") ? "*" : "",
170 value(veReq), value(vpReq), value(snReq), value(ffReq));
171 }
172
173 private String value(CompletableFuture<Gnmi.GetResponse> req) {
174 Gnmi.GetResponse response = Futures.getUnchecked(req);
175 return response.getNotificationList().isEmpty() ?
176 "" : response.getNotification(0).getUpdate(0).getVal().getStringVal().trim();
177 }
178
179 private Gnmi.GetRequest fieldRequest(Port port, String field) {
180 Gnmi.Path path = Gnmi.Path.newBuilder()
181 .addElem(Gnmi.PathElem.newBuilder().setName("components").build())
182 .addElem(Gnmi.PathElem.newBuilder().setName("component").putKey("name",
183 port.number().name()).build())
184 .addElem(Gnmi.PathElem.newBuilder().setName("transceiver").build())
185 .addElem(Gnmi.PathElem.newBuilder().setName("state").build())
186 .addElem(Gnmi.PathElem.newBuilder().setName(field).build())
187 .build();
188 return Gnmi.GetRequest.newBuilder()
189 .addPath(path)
190 .setType(Gnmi.GetRequest.DataType.ALL)
191 .setEncoding(Gnmi.Encoding.PROTO)
192 .build();
193 }
194 }
195
196}