Allow sharing the same gRPC channel between clients
This change introduces a refactoring of the gRPC protocol subsystem that
allows the creation of a gRPC chanel independently of the client, while
allowing multiple clients to share the same channel (e.g. as in Stratum
where we use 3 clients).
Moreover, we refactor the P4RuntimeClient API to support multiple
P4Runtime-internal device ID using the same client. While before the
client was associated to one of such ID.
Finally, we provide an abstract implementation for gRPC-based driver
behaviors, reducing code duplication in P4Runtime, gNMI and gNOI drivers.
Change-Id: I1a46352bbbef1e0d24042f169ae8ba580202944f
diff --git a/drivers/gnoi/BUILD b/drivers/gnoi/BUILD
index 3a710a8..b5355a9 100644
--- a/drivers/gnoi/BUILD
+++ b/drivers/gnoi/BUILD
@@ -6,6 +6,7 @@
"//protocols/gnoi/stub:onos-protocols-gnoi-stub",
"//protocols/gnoi/api:onos-protocols-gnoi-api",
"//protocols/grpc/api:onos-protocols-grpc-api",
+ "//protocols/grpc/utils:onos-protocols-grpc-utils",
]
BUNDLES = [
diff --git a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/AbstractGnoiHandlerBehaviour.java b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/AbstractGnoiHandlerBehaviour.java
deleted file mode 100644
index 84043a8..0000000
--- a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/AbstractGnoiHandlerBehaviour.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2019-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.drivers.gnoi;
-
-import com.google.common.base.Strings;
-import org.onosproject.gnoi.api.GnoiClient;
-import org.onosproject.gnoi.api.GnoiClientKey;
-import org.onosproject.gnoi.api.GnoiController;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.config.basics.BasicDeviceConfig;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-
-/**
- * Abstract implementation of a behaviour handler for a gNOI device.
- */
-public class AbstractGnoiHandlerBehaviour extends AbstractHandlerBehaviour {
-
- protected final Logger log = LoggerFactory.getLogger(getClass());
- protected DeviceId deviceId;
- protected GnoiClient client;
-
- protected boolean setupBehaviour(String opName) {
- deviceId = handler().data().deviceId();
- client = getClientByKey();
-
- if (client == null) {
- log.warn("Missing client for {}, aborting {}", deviceId, opName);
- return false;
- }
-
- return true;
- }
-
- GnoiClient getClientByKey() {
- final GnoiClientKey clientKey = clientKey();
- if (clientKey == null) {
- return null;
- }
- return handler().get(GnoiController.class).getClient(clientKey);
- }
-
- protected GnoiClientKey clientKey() {
- deviceId = handler().data().deviceId();
-
- final BasicDeviceConfig cfg = handler().get(NetworkConfigService.class)
- .getConfig(deviceId, BasicDeviceConfig.class);
- if (cfg == null || Strings.isNullOrEmpty(cfg.managementAddress())) {
- log.error("Missing or invalid config for {}, cannot derive " +
- "gNOI server endpoints", deviceId);
- return null;
- }
-
- try {
- return new GnoiClientKey(
- deviceId, new URI(cfg.managementAddress()));
- } catch (URISyntaxException e) {
- log.error("Management address of {} is not a valid URI: {}",
- deviceId, cfg.managementAddress());
- return null;
- }
- }
-}
diff --git a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiBasicSystemOperationsImpl.java b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiBasicSystemOperationsImpl.java
index b979546..7876886 100644
--- a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiBasicSystemOperationsImpl.java
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiBasicSystemOperationsImpl.java
@@ -19,9 +19,10 @@
import gnoi.system.SystemOuterClass.RebootMethod;
import gnoi.system.SystemOuterClass.RebootRequest;
import gnoi.system.SystemOuterClass.RebootResponse;
+import org.onosproject.gnoi.api.GnoiClient;
+import org.onosproject.gnoi.api.GnoiController;
+import org.onosproject.grpc.utils.AbstractGrpcHandlerBehaviour;
import org.onosproject.net.behaviour.BasicSystemOperations;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.util.concurrent.CompletableFuture;
@@ -30,10 +31,12 @@
* devices.
*/
public class GnoiBasicSystemOperationsImpl
- extends AbstractGnoiHandlerBehaviour implements BasicSystemOperations {
+ extends AbstractGrpcHandlerBehaviour<GnoiClient, GnoiController>
+ implements BasicSystemOperations {
- private static final Logger log = LoggerFactory
- .getLogger(GnoiBasicSystemOperationsImpl.class);
+ public GnoiBasicSystemOperationsImpl() {
+ super(GnoiController.class);
+ }
@Override
public CompletableFuture<Boolean> reboot() {
diff --git a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDeviceDescriptionDiscovery.java b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDeviceDescriptionDiscovery.java
index 3c308d6..2010c53 100644
--- a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDeviceDescriptionDiscovery.java
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDeviceDescriptionDiscovery.java
@@ -24,6 +24,7 @@
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceDescriptionDiscovery;
import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
import java.util.Collections;
import java.util.List;
@@ -32,7 +33,8 @@
* Implementation of DeviceDescriptionDiscovery for gNOI devices.
*/
public class GnoiDeviceDescriptionDiscovery
- extends AbstractGnoiHandlerBehaviour implements DeviceDescriptionDiscovery {
+ extends AbstractHandlerBehaviour
+ implements DeviceDescriptionDiscovery {
private static final String UNKNOWN = "unknown";
diff --git a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiHandshaker.java b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiHandshaker.java
index 36a4971..1668bcc 100644
--- a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiHandshaker.java
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiHandshaker.java
@@ -17,33 +17,22 @@
package org.onosproject.drivers.gnoi;
import org.onosproject.gnoi.api.GnoiClient;
-import org.onosproject.gnoi.api.GnoiClientKey;
import org.onosproject.gnoi.api.GnoiController;
+import org.onosproject.grpc.utils.AbstractGrpcHandshaker;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.device.DeviceHandshaker;
import java.util.concurrent.CompletableFuture;
-import static java.util.concurrent.CompletableFuture.completedFuture;
-
/**
* Implementation of DeviceHandshaker for gNOI.
*/
-public class GnoiHandshaker extends AbstractGnoiHandlerBehaviour implements DeviceHandshaker {
+public class GnoiHandshaker
+ extends AbstractGrpcHandshaker<GnoiClient, GnoiController>
+ implements DeviceHandshaker {
- @Override
- public boolean isReachable() {
- final GnoiClient client = getClientByKey();
- return client != null && client.isServerReachable();
- }
-
- @Override
- public CompletableFuture<Boolean> probeReachability() {
- final GnoiClient client = getClientByKey();
- if (client == null) {
- return completedFuture(false);
- }
- return client.probeService();
+ public GnoiHandshaker() {
+ super(GnoiController.class);
}
@Override
@@ -65,33 +54,4 @@
public MastershipRole getRole() {
throw new UnsupportedOperationException("Mastership operation not supported");
}
-
- @Override
- public CompletableFuture<Boolean> connect() {
- return CompletableFuture.supplyAsync(this::createClient);
- }
-
- private boolean createClient() {
- GnoiClientKey clientKey = clientKey();
- if (clientKey == null) {
- return false;
- }
- if (!handler().get(GnoiController.class).createClient(clientKey)) {
- log.warn("Unable to create client for {}",
- handler().data().deviceId());
- return false;
- }
- return true;
- }
-
- @Override
- public boolean isConnected() {
- return getClientByKey() != null;
- }
-
- @Override
- public void disconnect() {
- handler().get(GnoiController.class)
- .removeClient(handler().data().deviceId());
- }
}