blob: 7e259fb6d6f3736ac4743ce30eca53bf314c6fec [file] [log] [blame]
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -08003 *
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 org.onosproject.incubator.rpc.grpc;
17
18import static com.google.common.base.Preconditions.checkNotNull;
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070019import static java.util.concurrent.Executors.newScheduledThreadPool;
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -080020import static java.util.stream.Collectors.toList;
Jian Lid40252c2017-12-08 04:13:20 +090021import org.onosproject.incubator.protobuf.models.net.device.DeviceProtoTranslator;
22import org.onosproject.incubator.protobuf.models.net.device.PortProtoTranslator;
23import org.onosproject.incubator.protobuf.models.net.MastershipRoleProtoTranslator;
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -080024import static org.onosproject.net.DeviceId.deviceId;
25
26import java.io.IOException;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080027import java.util.Map;
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -080028import java.util.Set;
29import java.util.concurrent.CompletableFuture;
30import java.util.concurrent.ExecutionException;
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070031import java.util.concurrent.ScheduledExecutorService;
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -080032import java.util.concurrent.TimeUnit;
33import java.util.concurrent.TimeoutException;
34import java.util.concurrent.atomic.AtomicInteger;
35
36import org.apache.felix.scr.annotations.Activate;
37import org.apache.felix.scr.annotations.Component;
38import org.apache.felix.scr.annotations.Deactivate;
39import org.apache.felix.scr.annotations.Modified;
40import org.apache.felix.scr.annotations.Property;
41import org.apache.felix.scr.annotations.Reference;
42import org.apache.felix.scr.annotations.ReferenceCardinality;
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070043import org.onlab.util.Tools;
Yuta HIGUCHI9efba1e2016-07-09 11:07:13 -070044import org.onosproject.grpc.net.device.DeviceProviderRegistryRpcGrpc.DeviceProviderRegistryRpcImplBase;
HIGUCHI Yutae3e90632016-05-11 16:44:01 -070045import org.onosproject.grpc.net.device.DeviceService.DeviceConnected;
46import org.onosproject.grpc.net.device.DeviceService.DeviceDisconnected;
47import org.onosproject.grpc.net.device.DeviceService.DeviceProviderMsg;
48import org.onosproject.grpc.net.device.DeviceService.DeviceProviderServiceMsg;
49import org.onosproject.grpc.net.device.DeviceService.IsReachableResponse;
50import org.onosproject.grpc.net.device.DeviceService.PortStatusChanged;
51import org.onosproject.grpc.net.device.DeviceService.ReceivedRoleReply;
52import org.onosproject.grpc.net.device.DeviceService.RegisterProvider;
53import org.onosproject.grpc.net.device.DeviceService.UpdatePortStatistics;
54import org.onosproject.grpc.net.device.DeviceService.UpdatePorts;
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -080055import org.onosproject.net.DeviceId;
56import org.onosproject.net.MastershipRole;
Saurav Dasa2d37502016-03-25 17:50:40 -070057import org.onosproject.net.PortNumber;
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -080058import org.onosproject.net.device.DeviceProvider;
59import org.onosproject.net.device.DeviceProviderRegistry;
60import org.onosproject.net.device.DeviceProviderService;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080061import org.onosproject.net.link.LinkProvider;
62import org.onosproject.net.link.LinkProviderRegistry;
63import org.onosproject.net.link.LinkProviderService;
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -080064import org.onosproject.net.provider.ProviderId;
65import org.osgi.service.component.ComponentContext;
66import org.slf4j.Logger;
67import org.slf4j.LoggerFactory;
68
69import com.google.common.cache.Cache;
70import com.google.common.cache.CacheBuilder;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080071import com.google.common.collect.Maps;
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -080072import com.google.common.collect.Sets;
73
74import io.grpc.Server;
75import io.grpc.netty.NettyServerBuilder;
76import io.grpc.stub.StreamObserver;
77
78// gRPC Server on Metro-side
79// Translates request received on RPC channel, and calls corresponding Service on
80// Metro-ONOS cluster.
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080081
82// Currently supports DeviceProviderRegistry, LinkProviderService
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -080083/**
84 * Server side implementation of gRPC based RemoteService.
85 */
86@Component(immediate = true)
87public class GrpcRemoteServiceServer {
88
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080089 static final String RPC_PROVIDER_NAME = "org.onosproject.rpc.provider.grpc";
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -080090
91 // TODO pick a number
92 public static final int DEFAULT_LISTEN_PORT = 11984;
93
94 private final Logger log = LoggerFactory.getLogger(getClass());
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected DeviceProviderRegistry deviceProviderRegistry;
98
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080099 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected LinkProviderRegistry linkProviderRegistry;
101
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800102
103 @Property(name = "listenPort", intValue = DEFAULT_LISTEN_PORT,
104 label = "Port to listen on")
105 protected int listenPort = DEFAULT_LISTEN_PORT;
106
107 private Server server;
108 private final Set<DeviceProviderServerProxy> registeredProviders = Sets.newConcurrentHashSet();
109
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800110 // scheme -> ...
111 // updates must be guarded by synchronizing `this`
112 private final Map<String, LinkProviderService> linkProviderServices = Maps.newConcurrentMap();
113 private final Map<String, LinkProvider> linkProviders = Maps.newConcurrentMap();
114
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -0700115 private ScheduledExecutorService executor;
116
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800117 @Activate
118 protected void activate(ComponentContext context) throws IOException {
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -0700119 executor = newScheduledThreadPool(1, Tools.groupedThreads("grpc", "%d", log));
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800120 modified(context);
121
122 log.debug("Server starting on {}", listenPort);
123 try {
124 server = NettyServerBuilder.forPort(listenPort)
Yuta HIGUCHI9efba1e2016-07-09 11:07:13 -0700125 .addService(new DeviceProviderRegistryServerProxy())
126 .addService(new LinkProviderServiceServerProxy(this))
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800127 .build().start();
128 } catch (IOException e) {
129 log.error("Failed to start gRPC server", e);
130 throw e;
131 }
132
133 log.info("Started on {}", listenPort);
134 }
135
136 @Deactivate
137 protected void deactivate() {
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -0700138 executor.shutdown();
139 try {
140 executor.awaitTermination(5, TimeUnit.SECONDS);
141 } catch (InterruptedException e) {
142 Thread.currentThread().interrupt();
143 }
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800144
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700145 registeredProviders.forEach(deviceProviderRegistry::unregister);
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800146
147 server.shutdown();
148 // Should we wait for shutdown?
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800149
150 unregisterLinkProviders();
151
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800152 log.info("Stopped");
153 }
154
155 @Modified
156 public void modified(ComponentContext context) {
157 // TODO support dynamic reconfiguration and restarting server?
158 }
159
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800160 /**
161 * Registers {@link StubLinkProvider} for given ProviderId scheme.
162 *
163 * DO NOT DIRECTLY CALL THIS METHOD.
164 * Only expected to be called from {@link #getLinkProviderServiceFor(String)}.
165 *
166 * @param scheme ProviderId scheme.
167 * @return {@link LinkProviderService} registered.
168 */
169 private synchronized LinkProviderService registerStubLinkProvider(String scheme) {
170 StubLinkProvider provider = new StubLinkProvider(scheme);
171 linkProviders.put(scheme, provider);
172 return linkProviderRegistry.register(provider);
173 }
174
175 /**
176 * Unregisters all registered LinkProviders.
177 */
178 private synchronized void unregisterLinkProviders() {
HIGUCHI Yuta6381a242016-03-13 23:29:10 -0700179 // TODO remove all links registered by these providers
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800180 linkProviders.values().forEach(linkProviderRegistry::unregister);
181 linkProviders.clear();
182 linkProviderServices.clear();
183 }
184
185 /**
186 * Gets or creates {@link LinkProviderService} registered for given ProviderId scheme.
187 *
188 * @param scheme ProviderId scheme.
189 * @return {@link LinkProviderService}
190 */
191 protected LinkProviderService getLinkProviderServiceFor(String scheme) {
192 return linkProviderServices.computeIfAbsent(scheme, this::registerStubLinkProvider);
193 }
194
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -0700195 protected ScheduledExecutorService getSharedExecutor() {
196 return executor;
197 }
198
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800199 // RPC Server-side code
200 // RPC session Factory
201 /**
202 * Relays DeviceProviderRegistry calls from RPC client.
203 */
Yuta HIGUCHI9efba1e2016-07-09 11:07:13 -0700204 class DeviceProviderRegistryServerProxy extends DeviceProviderRegistryRpcImplBase {
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800205
206 @Override
207 public StreamObserver<DeviceProviderServiceMsg> register(StreamObserver<DeviceProviderMsg> toDeviceProvider) {
208 log.trace("DeviceProviderRegistryServerProxy#register called!");
209
210 DeviceProviderServerProxy provider = new DeviceProviderServerProxy(toDeviceProvider);
211
212 return new DeviceProviderServiceServerProxy(provider, toDeviceProvider);
213 }
214 }
215
216 // Lower -> Upper Controller message
217 // RPC Server-side code
218 // RPC session handler
219 private final class DeviceProviderServiceServerProxy
220 implements StreamObserver<DeviceProviderServiceMsg> {
221
222 // intentionally shadowing
223 private final Logger log = LoggerFactory.getLogger(getClass());
224
225 private final DeviceProviderServerProxy pairedProvider;
226 private final StreamObserver<DeviceProviderMsg> toDeviceProvider;
227
228 private final Cache<Integer, CompletableFuture<Boolean>> outstandingIsReachable;
229
230 // wrapped providerService
231 private DeviceProviderService deviceProviderService;
232
233
234 DeviceProviderServiceServerProxy(DeviceProviderServerProxy provider,
235 StreamObserver<DeviceProviderMsg> toDeviceProvider) {
236 this.pairedProvider = provider;
237 this.toDeviceProvider = toDeviceProvider;
238 outstandingIsReachable = CacheBuilder.newBuilder()
239 .expireAfterWrite(1, TimeUnit.MINUTES)
240 .build();
241
242 // pair RPC session in other direction
243 provider.pair(this);
244 }
245
246 @Override
247 public void onNext(DeviceProviderServiceMsg msg) {
248 try {
249 log.trace("DeviceProviderServiceServerProxy received: {}", msg);
250 onMethod(msg);
251 } catch (Exception e) {
252 log.error("Exception thrown handling {}", msg, e);
253 onError(e);
254 throw e;
255 }
256 }
257
258 /**
259 * Translates received RPC message to {@link DeviceProviderService} method calls.
260 * @param msg DeviceProviderService message
261 */
262 private void onMethod(DeviceProviderServiceMsg msg) {
263 switch (msg.getMethodCase()) {
264 case REGISTER_PROVIDER:
265 RegisterProvider registerProvider = msg.getRegisterProvider();
266 // TODO Do we care about provider name?
267 pairedProvider.setProviderId(new ProviderId(registerProvider.getProviderScheme(), RPC_PROVIDER_NAME));
268 registeredProviders.add(pairedProvider);
HIGUCHI Yuta6381a242016-03-13 23:29:10 -0700269 log.info("registering DeviceProvider {} via gRPC", pairedProvider.id());
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800270 deviceProviderService = deviceProviderRegistry.register(pairedProvider);
271 break;
272
273 case DEVICE_CONNECTED:
274 DeviceConnected deviceConnected = msg.getDeviceConnected();
275 deviceProviderService.deviceConnected(deviceId(deviceConnected.getDeviceId()),
Jian Lid40252c2017-12-08 04:13:20 +0900276 DeviceProtoTranslator.translate(deviceConnected.getDeviceDescription()));
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800277 break;
278 case DEVICE_DISCONNECTED:
279 DeviceDisconnected deviceDisconnected = msg.getDeviceDisconnected();
280 deviceProviderService.deviceDisconnected(deviceId(deviceDisconnected.getDeviceId()));
281 break;
282 case UPDATE_PORTS:
283 UpdatePorts updatePorts = msg.getUpdatePorts();
284 deviceProviderService.updatePorts(deviceId(updatePorts.getDeviceId()),
285 updatePorts.getPortDescriptionsList()
286 .stream()
Jian Lid40252c2017-12-08 04:13:20 +0900287 .map(PortProtoTranslator::translate)
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800288 .collect(toList()));
289 break;
290 case PORT_STATUS_CHANGED:
291 PortStatusChanged portStatusChanged = msg.getPortStatusChanged();
292 deviceProviderService.portStatusChanged(deviceId(portStatusChanged.getDeviceId()),
Jian Lid40252c2017-12-08 04:13:20 +0900293 PortProtoTranslator.translate(portStatusChanged.getPortDescription()));
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800294 break;
295 case RECEIVED_ROLE_REPLY:
296 ReceivedRoleReply receivedRoleReply = msg.getReceivedRoleReply();
297 deviceProviderService.receivedRoleReply(deviceId(receivedRoleReply.getDeviceId()),
Thomas Vachuska0e11dcb2017-12-13 16:57:14 -0800298 (MastershipRole) MastershipRoleProtoTranslator
299 .translate(receivedRoleReply.getRequested()).get(),
300 (MastershipRole) MastershipRoleProtoTranslator
301 .translate(receivedRoleReply.getResponse()).get());
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800302 break;
303 case UPDATE_PORT_STATISTICS:
304 UpdatePortStatistics updatePortStatistics = msg.getUpdatePortStatistics();
305 deviceProviderService.updatePortStatistics(deviceId(updatePortStatistics.getDeviceId()),
306 updatePortStatistics.getPortStatisticsList()
307 .stream()
Jian Lid40252c2017-12-08 04:13:20 +0900308 .map(PortProtoTranslator::translate)
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800309 .collect(toList()));
310 break;
311
312 // return value of DeviceProvider#isReachable
313 case IS_REACHABLE_RESPONSE:
314 IsReachableResponse isReachableResponse = msg.getIsReachableResponse();
315 int xid = isReachableResponse.getXid();
316 boolean isReachable = isReachableResponse.getIsReachable();
317 CompletableFuture<Boolean> result = outstandingIsReachable.asMap().remove(xid);
318 if (result != null) {
319 result.complete(isReachable);
320 }
321 break;
322
323 case METHOD_NOT_SET:
324 default:
325 log.warn("Unexpected message received {}", msg);
326 break;
327 }
328 }
329
330 @Override
331 public void onCompleted() {
332 log.info("DeviceProviderServiceServerProxy completed");
333 deviceProviderRegistry.unregister(pairedProvider);
334 registeredProviders.remove(pairedProvider);
335 toDeviceProvider.onCompleted();
336 }
337
338 @Override
339 public void onError(Throwable e) {
340 log.error("DeviceProviderServiceServerProxy#onError", e);
HIGUCHI Yuta6381a242016-03-13 23:29:10 -0700341 if (pairedProvider != null) {
342 // TODO call deviceDisconnected against all devices
343 // registered for this provider scheme
344 log.info("unregistering DeviceProvider {} via gRPC", pairedProvider.id());
345 deviceProviderRegistry.unregister(pairedProvider);
346 registeredProviders.remove(pairedProvider);
347 }
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800348 // TODO What is the proper clean up for bi-di stream on error?
349 // sample suggests no-op
350 toDeviceProvider.onError(e);
351 }
352
353
354 /**
355 * Registers Future for {@link DeviceProvider#isReachable(DeviceId)} return value.
356 * @param xid IsReachable call ID.
357 * @param reply Future to
358 */
359 void register(int xid, CompletableFuture<Boolean> reply) {
360 outstandingIsReachable.put(xid, reply);
361 }
362
363 }
364
365 // Upper -> Lower Controller message
366 /**
367 * Relay DeviceProvider calls to RPC client.
368 */
369 private final class DeviceProviderServerProxy
370 implements DeviceProvider {
371
372 private final Logger log = LoggerFactory.getLogger(getClass());
373
374 // xid for isReachable calls
375 private final AtomicInteger xidPool = new AtomicInteger();
376 private final StreamObserver<DeviceProviderMsg> toDeviceProvider;
377
378 private DeviceProviderServiceServerProxy deviceProviderServiceProxy = null;
379 private ProviderId providerId;
380
381 DeviceProviderServerProxy(StreamObserver<DeviceProviderMsg> toDeviceProvider) {
382 this.toDeviceProvider = toDeviceProvider;
383 }
384
385 void setProviderId(ProviderId pid) {
386 this.providerId = pid;
387 }
388
389 /**
390 * Registers RPC stream in other direction.
HIGUCHI Yuta6381a242016-03-13 23:29:10 -0700391 *
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800392 * @param deviceProviderServiceProxy {@link DeviceProviderServiceServerProxy}
393 */
394 void pair(DeviceProviderServiceServerProxy deviceProviderServiceProxy) {
395 this.deviceProviderServiceProxy = deviceProviderServiceProxy;
396 }
397
398 @Override
399 public void triggerProbe(DeviceId deviceId) {
Yuta HIGUCHIad4861e2016-07-13 19:19:03 -0700400 try {
401 onTriggerProbe(deviceId);
402 } catch (Exception e) {
403 log.error("Exception caught handling triggerProbe({})",
404 deviceId, e);
405 toDeviceProvider.onError(e);
406 }
407 }
408
409 private void onTriggerProbe(DeviceId deviceId) {
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800410 log.trace("triggerProbe({})", deviceId);
411 DeviceProviderMsg.Builder msgBuilder = DeviceProviderMsg.newBuilder();
412 msgBuilder.setTriggerProbe(msgBuilder.getTriggerProbeBuilder()
413 .setDeviceId(deviceId.toString())
414 .build());
415 DeviceProviderMsg triggerProbeMsg = msgBuilder.build();
416 toDeviceProvider.onNext(triggerProbeMsg);
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800417 }
418
419 @Override
420 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
Yuta HIGUCHIad4861e2016-07-13 19:19:03 -0700421 try {
422 onRoleChanged(deviceId, newRole);
423 } catch (Exception e) {
424 log.error("Exception caught handling onRoleChanged({}, {})",
425 deviceId, newRole, e);
426 toDeviceProvider.onError(e);
427 }
428 }
429
430 private void onRoleChanged(DeviceId deviceId, MastershipRole newRole) {
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800431 log.trace("roleChanged({}, {})", deviceId, newRole);
432 DeviceProviderMsg.Builder msgBuilder = DeviceProviderMsg.newBuilder();
433 msgBuilder.setRoleChanged(msgBuilder.getRoleChangedBuilder()
434 .setDeviceId(deviceId.toString())
Jian Lid40252c2017-12-08 04:13:20 +0900435 .setNewRole(MastershipRoleProtoTranslator.translate(newRole))
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800436 .build());
437 toDeviceProvider.onNext(msgBuilder.build());
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800438 }
439
440 @Override
441 public boolean isReachable(DeviceId deviceId) {
Yuta HIGUCHIad4861e2016-07-13 19:19:03 -0700442 try {
443 return onIsReachable(deviceId);
444 } catch (Exception e) {
445 log.error("Exception caught handling onIsReachable({})",
446 deviceId, e);
447 toDeviceProvider.onError(e);
448 return false;
449 }
450 }
451
452 private boolean onIsReachable(DeviceId deviceId) {
453
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800454 log.trace("isReachable({})", deviceId);
455 CompletableFuture<Boolean> result = new CompletableFuture<>();
456 final int xid = xidPool.incrementAndGet();
457
458 DeviceProviderMsg.Builder msgBuilder = DeviceProviderMsg.newBuilder();
459 msgBuilder.setIsReachableRequest(msgBuilder.getIsReachableRequestBuilder()
460 .setXid(xid)
461 .setDeviceId(deviceId.toString())
462 .build());
463
464 // Associate xid and register above future some where
465 // in DeviceProviderService channel to receive reply
466 if (deviceProviderServiceProxy != null) {
467 deviceProviderServiceProxy.register(xid, result);
468 }
469
470 // send message down RPC
471 toDeviceProvider.onNext(msgBuilder.build());
472
473 // wait for reply
474 try {
475 return result.get(10, TimeUnit.SECONDS);
476 } catch (InterruptedException e) {
477 log.debug("isReachable({}) was Interrupted", deviceId, e);
478 Thread.currentThread().interrupt();
479 } catch (TimeoutException e) {
480 log.warn("isReachable({}) Timed out", deviceId, e);
481 } catch (ExecutionException e) {
482 log.error("isReachable({}) Execution failed", deviceId, e);
Yuta HIGUCHIad4861e2016-07-13 19:19:03 -0700483 // close session
484 toDeviceProvider.onError(e);
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800485 }
486 return false;
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800487 }
488
489 @Override
490 public ProviderId id() {
491 return checkNotNull(providerId, "not initialized yet");
492 }
493
Saurav Dasa2d37502016-03-25 17:50:40 -0700494 @Override
495 public void changePortState(DeviceId deviceId, PortNumber portNumber,
496 boolean enable) {
Yuta HIGUCHIad4861e2016-07-13 19:19:03 -0700497 // TODO Implement if required
498 log.error("changePortState not supported yet");
499 toDeviceProvider.onError(new UnsupportedOperationException("not implemented yet"));
Saurav Dasa2d37502016-03-25 17:50:40 -0700500 }
501
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800502 }
503}