blob: 2bf2081d145e80316bce465b921a48365b414eae [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
Ray Milkeyd84f89b2018-08-17 14:54:17 -070036import org.osgi.service.component.annotations.Activate;
37import org.osgi.service.component.annotations.Component;
38import org.osgi.service.component.annotations.Deactivate;
39import org.osgi.service.component.annotations.Modified;
40import org.osgi.service.component.annotations.Property;
41import org.osgi.service.component.annotations.Reference;
42import org.osgi.service.component.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
Ray Milkeyd84f89b2018-08-17 14:54:17 -070096 @Reference(cardinality = ReferenceCardinality.MANDATORY)
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -080097 protected DeviceProviderRegistry deviceProviderRegistry;
98
Ray Milkeyd84f89b2018-08-17 14:54:17 -070099 @Reference(cardinality = ReferenceCardinality.MANDATORY)
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800100 protected LinkProviderRegistry linkProviderRegistry;
101
Thomas Vachuska00b5d4f2018-10-30 15:13:20 -0700102 /** Port to listen on */
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800103 protected int listenPort = DEFAULT_LISTEN_PORT;
104
105 private Server server;
106 private final Set<DeviceProviderServerProxy> registeredProviders = Sets.newConcurrentHashSet();
107
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800108 // scheme -> ...
109 // updates must be guarded by synchronizing `this`
110 private final Map<String, LinkProviderService> linkProviderServices = Maps.newConcurrentMap();
111 private final Map<String, LinkProvider> linkProviders = Maps.newConcurrentMap();
112
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -0700113 private ScheduledExecutorService executor;
114
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800115 @Activate
116 protected void activate(ComponentContext context) throws IOException {
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -0700117 executor = newScheduledThreadPool(1, Tools.groupedThreads("grpc", "%d", log));
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800118 modified(context);
119
120 log.debug("Server starting on {}", listenPort);
121 try {
122 server = NettyServerBuilder.forPort(listenPort)
Yuta HIGUCHI9efba1e2016-07-09 11:07:13 -0700123 .addService(new DeviceProviderRegistryServerProxy())
124 .addService(new LinkProviderServiceServerProxy(this))
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800125 .build().start();
126 } catch (IOException e) {
127 log.error("Failed to start gRPC server", e);
128 throw e;
129 }
130
131 log.info("Started on {}", listenPort);
132 }
133
134 @Deactivate
135 protected void deactivate() {
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -0700136 executor.shutdown();
137 try {
138 executor.awaitTermination(5, TimeUnit.SECONDS);
139 } catch (InterruptedException e) {
140 Thread.currentThread().interrupt();
141 }
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800142
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700143 registeredProviders.forEach(deviceProviderRegistry::unregister);
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800144
145 server.shutdown();
146 // Should we wait for shutdown?
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800147
148 unregisterLinkProviders();
149
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800150 log.info("Stopped");
151 }
152
153 @Modified
154 public void modified(ComponentContext context) {
155 // TODO support dynamic reconfiguration and restarting server?
156 }
157
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800158 /**
159 * Registers {@link StubLinkProvider} for given ProviderId scheme.
160 *
161 * DO NOT DIRECTLY CALL THIS METHOD.
162 * Only expected to be called from {@link #getLinkProviderServiceFor(String)}.
163 *
164 * @param scheme ProviderId scheme.
165 * @return {@link LinkProviderService} registered.
166 */
167 private synchronized LinkProviderService registerStubLinkProvider(String scheme) {
168 StubLinkProvider provider = new StubLinkProvider(scheme);
169 linkProviders.put(scheme, provider);
170 return linkProviderRegistry.register(provider);
171 }
172
173 /**
174 * Unregisters all registered LinkProviders.
175 */
176 private synchronized void unregisterLinkProviders() {
HIGUCHI Yuta6381a242016-03-13 23:29:10 -0700177 // TODO remove all links registered by these providers
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800178 linkProviders.values().forEach(linkProviderRegistry::unregister);
179 linkProviders.clear();
180 linkProviderServices.clear();
181 }
182
183 /**
184 * Gets or creates {@link LinkProviderService} registered for given ProviderId scheme.
185 *
186 * @param scheme ProviderId scheme.
187 * @return {@link LinkProviderService}
188 */
189 protected LinkProviderService getLinkProviderServiceFor(String scheme) {
190 return linkProviderServices.computeIfAbsent(scheme, this::registerStubLinkProvider);
191 }
192
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -0700193 protected ScheduledExecutorService getSharedExecutor() {
194 return executor;
195 }
196
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800197 // RPC Server-side code
198 // RPC session Factory
199 /**
200 * Relays DeviceProviderRegistry calls from RPC client.
201 */
Yuta HIGUCHI9efba1e2016-07-09 11:07:13 -0700202 class DeviceProviderRegistryServerProxy extends DeviceProviderRegistryRpcImplBase {
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800203
204 @Override
205 public StreamObserver<DeviceProviderServiceMsg> register(StreamObserver<DeviceProviderMsg> toDeviceProvider) {
206 log.trace("DeviceProviderRegistryServerProxy#register called!");
207
208 DeviceProviderServerProxy provider = new DeviceProviderServerProxy(toDeviceProvider);
209
210 return new DeviceProviderServiceServerProxy(provider, toDeviceProvider);
211 }
212 }
213
214 // Lower -> Upper Controller message
215 // RPC Server-side code
216 // RPC session handler
217 private final class DeviceProviderServiceServerProxy
218 implements StreamObserver<DeviceProviderServiceMsg> {
219
220 // intentionally shadowing
221 private final Logger log = LoggerFactory.getLogger(getClass());
222
223 private final DeviceProviderServerProxy pairedProvider;
224 private final StreamObserver<DeviceProviderMsg> toDeviceProvider;
225
226 private final Cache<Integer, CompletableFuture<Boolean>> outstandingIsReachable;
227
228 // wrapped providerService
229 private DeviceProviderService deviceProviderService;
230
231
232 DeviceProviderServiceServerProxy(DeviceProviderServerProxy provider,
233 StreamObserver<DeviceProviderMsg> toDeviceProvider) {
234 this.pairedProvider = provider;
235 this.toDeviceProvider = toDeviceProvider;
236 outstandingIsReachable = CacheBuilder.newBuilder()
237 .expireAfterWrite(1, TimeUnit.MINUTES)
238 .build();
239
240 // pair RPC session in other direction
241 provider.pair(this);
242 }
243
244 @Override
245 public void onNext(DeviceProviderServiceMsg msg) {
246 try {
247 log.trace("DeviceProviderServiceServerProxy received: {}", msg);
248 onMethod(msg);
249 } catch (Exception e) {
250 log.error("Exception thrown handling {}", msg, e);
251 onError(e);
252 throw e;
253 }
254 }
255
256 /**
257 * Translates received RPC message to {@link DeviceProviderService} method calls.
258 * @param msg DeviceProviderService message
259 */
260 private void onMethod(DeviceProviderServiceMsg msg) {
261 switch (msg.getMethodCase()) {
262 case REGISTER_PROVIDER:
263 RegisterProvider registerProvider = msg.getRegisterProvider();
264 // TODO Do we care about provider name?
265 pairedProvider.setProviderId(new ProviderId(registerProvider.getProviderScheme(), RPC_PROVIDER_NAME));
266 registeredProviders.add(pairedProvider);
HIGUCHI Yuta6381a242016-03-13 23:29:10 -0700267 log.info("registering DeviceProvider {} via gRPC", pairedProvider.id());
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800268 deviceProviderService = deviceProviderRegistry.register(pairedProvider);
269 break;
270
271 case DEVICE_CONNECTED:
272 DeviceConnected deviceConnected = msg.getDeviceConnected();
273 deviceProviderService.deviceConnected(deviceId(deviceConnected.getDeviceId()),
Jian Lid40252c2017-12-08 04:13:20 +0900274 DeviceProtoTranslator.translate(deviceConnected.getDeviceDescription()));
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800275 break;
276 case DEVICE_DISCONNECTED:
277 DeviceDisconnected deviceDisconnected = msg.getDeviceDisconnected();
278 deviceProviderService.deviceDisconnected(deviceId(deviceDisconnected.getDeviceId()));
279 break;
280 case UPDATE_PORTS:
281 UpdatePorts updatePorts = msg.getUpdatePorts();
282 deviceProviderService.updatePorts(deviceId(updatePorts.getDeviceId()),
283 updatePorts.getPortDescriptionsList()
284 .stream()
Jian Lid40252c2017-12-08 04:13:20 +0900285 .map(PortProtoTranslator::translate)
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800286 .collect(toList()));
287 break;
288 case PORT_STATUS_CHANGED:
289 PortStatusChanged portStatusChanged = msg.getPortStatusChanged();
290 deviceProviderService.portStatusChanged(deviceId(portStatusChanged.getDeviceId()),
Jian Lid40252c2017-12-08 04:13:20 +0900291 PortProtoTranslator.translate(portStatusChanged.getPortDescription()));
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800292 break;
293 case RECEIVED_ROLE_REPLY:
294 ReceivedRoleReply receivedRoleReply = msg.getReceivedRoleReply();
295 deviceProviderService.receivedRoleReply(deviceId(receivedRoleReply.getDeviceId()),
Thomas Vachuska0e11dcb2017-12-13 16:57:14 -0800296 (MastershipRole) MastershipRoleProtoTranslator
297 .translate(receivedRoleReply.getRequested()).get(),
298 (MastershipRole) MastershipRoleProtoTranslator
299 .translate(receivedRoleReply.getResponse()).get());
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800300 break;
301 case UPDATE_PORT_STATISTICS:
302 UpdatePortStatistics updatePortStatistics = msg.getUpdatePortStatistics();
303 deviceProviderService.updatePortStatistics(deviceId(updatePortStatistics.getDeviceId()),
304 updatePortStatistics.getPortStatisticsList()
305 .stream()
Jian Lid40252c2017-12-08 04:13:20 +0900306 .map(PortProtoTranslator::translate)
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800307 .collect(toList()));
308 break;
309
310 // return value of DeviceProvider#isReachable
311 case IS_REACHABLE_RESPONSE:
312 IsReachableResponse isReachableResponse = msg.getIsReachableResponse();
313 int xid = isReachableResponse.getXid();
314 boolean isReachable = isReachableResponse.getIsReachable();
315 CompletableFuture<Boolean> result = outstandingIsReachable.asMap().remove(xid);
316 if (result != null) {
317 result.complete(isReachable);
318 }
319 break;
320
321 case METHOD_NOT_SET:
322 default:
323 log.warn("Unexpected message received {}", msg);
324 break;
325 }
326 }
327
328 @Override
329 public void onCompleted() {
330 log.info("DeviceProviderServiceServerProxy completed");
331 deviceProviderRegistry.unregister(pairedProvider);
332 registeredProviders.remove(pairedProvider);
333 toDeviceProvider.onCompleted();
334 }
335
336 @Override
337 public void onError(Throwable e) {
338 log.error("DeviceProviderServiceServerProxy#onError", e);
HIGUCHI Yuta6381a242016-03-13 23:29:10 -0700339 if (pairedProvider != null) {
340 // TODO call deviceDisconnected against all devices
341 // registered for this provider scheme
342 log.info("unregistering DeviceProvider {} via gRPC", pairedProvider.id());
343 deviceProviderRegistry.unregister(pairedProvider);
344 registeredProviders.remove(pairedProvider);
345 }
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800346 // TODO What is the proper clean up for bi-di stream on error?
347 // sample suggests no-op
348 toDeviceProvider.onError(e);
349 }
350
351
352 /**
353 * Registers Future for {@link DeviceProvider#isReachable(DeviceId)} return value.
354 * @param xid IsReachable call ID.
355 * @param reply Future to
356 */
357 void register(int xid, CompletableFuture<Boolean> reply) {
358 outstandingIsReachable.put(xid, reply);
359 }
360
361 }
362
363 // Upper -> Lower Controller message
364 /**
365 * Relay DeviceProvider calls to RPC client.
366 */
367 private final class DeviceProviderServerProxy
368 implements DeviceProvider {
369
370 private final Logger log = LoggerFactory.getLogger(getClass());
371
372 // xid for isReachable calls
373 private final AtomicInteger xidPool = new AtomicInteger();
374 private final StreamObserver<DeviceProviderMsg> toDeviceProvider;
375
376 private DeviceProviderServiceServerProxy deviceProviderServiceProxy = null;
377 private ProviderId providerId;
378
379 DeviceProviderServerProxy(StreamObserver<DeviceProviderMsg> toDeviceProvider) {
380 this.toDeviceProvider = toDeviceProvider;
381 }
382
383 void setProviderId(ProviderId pid) {
384 this.providerId = pid;
385 }
386
387 /**
388 * Registers RPC stream in other direction.
HIGUCHI Yuta6381a242016-03-13 23:29:10 -0700389 *
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800390 * @param deviceProviderServiceProxy {@link DeviceProviderServiceServerProxy}
391 */
392 void pair(DeviceProviderServiceServerProxy deviceProviderServiceProxy) {
393 this.deviceProviderServiceProxy = deviceProviderServiceProxy;
394 }
395
396 @Override
397 public void triggerProbe(DeviceId deviceId) {
Yuta HIGUCHIad4861e2016-07-13 19:19:03 -0700398 try {
399 onTriggerProbe(deviceId);
400 } catch (Exception e) {
401 log.error("Exception caught handling triggerProbe({})",
402 deviceId, e);
403 toDeviceProvider.onError(e);
404 }
405 }
406
407 private void onTriggerProbe(DeviceId deviceId) {
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800408 log.trace("triggerProbe({})", deviceId);
409 DeviceProviderMsg.Builder msgBuilder = DeviceProviderMsg.newBuilder();
410 msgBuilder.setTriggerProbe(msgBuilder.getTriggerProbeBuilder()
411 .setDeviceId(deviceId.toString())
412 .build());
413 DeviceProviderMsg triggerProbeMsg = msgBuilder.build();
414 toDeviceProvider.onNext(triggerProbeMsg);
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800415 }
416
417 @Override
418 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
Yuta HIGUCHIad4861e2016-07-13 19:19:03 -0700419 try {
420 onRoleChanged(deviceId, newRole);
421 } catch (Exception e) {
422 log.error("Exception caught handling onRoleChanged({}, {})",
423 deviceId, newRole, e);
424 toDeviceProvider.onError(e);
425 }
426 }
427
428 private void onRoleChanged(DeviceId deviceId, MastershipRole newRole) {
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800429 log.trace("roleChanged({}, {})", deviceId, newRole);
430 DeviceProviderMsg.Builder msgBuilder = DeviceProviderMsg.newBuilder();
431 msgBuilder.setRoleChanged(msgBuilder.getRoleChangedBuilder()
432 .setDeviceId(deviceId.toString())
Jian Lid40252c2017-12-08 04:13:20 +0900433 .setNewRole(MastershipRoleProtoTranslator.translate(newRole))
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800434 .build());
435 toDeviceProvider.onNext(msgBuilder.build());
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800436 }
437
438 @Override
439 public boolean isReachable(DeviceId deviceId) {
Yuta HIGUCHIad4861e2016-07-13 19:19:03 -0700440 try {
441 return onIsReachable(deviceId);
442 } catch (Exception e) {
443 log.error("Exception caught handling onIsReachable({})",
444 deviceId, e);
445 toDeviceProvider.onError(e);
446 return false;
447 }
448 }
449
450 private boolean onIsReachable(DeviceId deviceId) {
451
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800452 log.trace("isReachable({})", deviceId);
453 CompletableFuture<Boolean> result = new CompletableFuture<>();
454 final int xid = xidPool.incrementAndGet();
455
456 DeviceProviderMsg.Builder msgBuilder = DeviceProviderMsg.newBuilder();
457 msgBuilder.setIsReachableRequest(msgBuilder.getIsReachableRequestBuilder()
458 .setXid(xid)
459 .setDeviceId(deviceId.toString())
460 .build());
461
462 // Associate xid and register above future some where
463 // in DeviceProviderService channel to receive reply
464 if (deviceProviderServiceProxy != null) {
465 deviceProviderServiceProxy.register(xid, result);
466 }
467
468 // send message down RPC
469 toDeviceProvider.onNext(msgBuilder.build());
470
471 // wait for reply
472 try {
473 return result.get(10, TimeUnit.SECONDS);
474 } catch (InterruptedException e) {
475 log.debug("isReachable({}) was Interrupted", deviceId, e);
476 Thread.currentThread().interrupt();
477 } catch (TimeoutException e) {
478 log.warn("isReachable({}) Timed out", deviceId, e);
479 } catch (ExecutionException e) {
480 log.error("isReachable({}) Execution failed", deviceId, e);
Yuta HIGUCHIad4861e2016-07-13 19:19:03 -0700481 // close session
482 toDeviceProvider.onError(e);
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800483 }
484 return false;
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800485 }
486
487 @Override
488 public ProviderId id() {
489 return checkNotNull(providerId, "not initialized yet");
490 }
491
Saurav Dasa2d37502016-03-25 17:50:40 -0700492 @Override
493 public void changePortState(DeviceId deviceId, PortNumber portNumber,
494 boolean enable) {
Yuta HIGUCHIad4861e2016-07-13 19:19:03 -0700495 // TODO Implement if required
496 log.error("changePortState not supported yet");
497 toDeviceProvider.onError(new UnsupportedOperationException("not implemented yet"));
Saurav Dasa2d37502016-03-25 17:50:40 -0700498 }
499
HIGUCHI Yuta15653fd2015-11-09 11:05:09 -0800500 }
501}