Add support for enabling/disabling ports for gNMI devices

This change also includes:
- Refactoring of gNMI protocol+driver to take advantage of the recent
changes to the gRPC protocol subsystem (e.g. no more locking, start RPC
with timeouts, etc.).
- Fixed Stratum driver to work after GeneralDeviceProvider refactoring
- Updated bmv2.py to generate ChassisConfig for stratum_bmv2
- Fixed portstate command to use the same port name as in the store

Change-Id: I0dad3bc73e4b6d907b5cf6b7b9a2852943226be7
diff --git a/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/AbstractStratumBehaviour.java b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/AbstractStratumBehaviour.java
new file mode 100644
index 0000000..b7c56e9
--- /dev/null
+++ b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/AbstractStratumBehaviour.java
@@ -0,0 +1,54 @@
+/*
+ * 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.stratum;
+
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.driver.DriverData;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.HandlerBehaviour;
+
+/**
+ * Abstract implementation of a driver behaviour for Stratum devices that
+ * provides access to protocol-specific implementations of the same behavior.
+ *
+ * @param <B> type of behaviour
+ */
+public abstract class AbstractStratumBehaviour<B extends HandlerBehaviour>
+        extends AbstractHandlerBehaviour {
+
+    protected B p4runtime;
+    protected B gnmi;
+
+    public AbstractStratumBehaviour(B p4runtime, B gnmi) {
+        this.p4runtime = p4runtime;
+        this.gnmi = gnmi;
+    }
+
+    @Override
+    public void setHandler(DriverHandler handler) {
+        super.setHandler(handler);
+        p4runtime.setHandler(handler);
+        gnmi.setHandler(handler);
+    }
+
+    @Override
+    public void setData(DriverData data) {
+        super.setData(data);
+        p4runtime.setData(data);
+        gnmi.setData(data);
+    }
+}
diff --git a/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumDeviceDescriptionDiscovery.java b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumDeviceDescriptionDiscovery.java
new file mode 100644
index 0000000..4a65e26
--- /dev/null
+++ b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumDeviceDescriptionDiscovery.java
@@ -0,0 +1,74 @@
+/*
+ * 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.stratum;
+
+import org.onosproject.drivers.gnmi.OpenConfigGnmiDeviceDescriptionDiscovery;
+import org.onosproject.drivers.p4runtime.P4RuntimeDeviceDescriptionDiscovery;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.Device;
+import org.onosproject.net.device.DefaultDeviceDescription;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.DeviceDescriptionDiscovery;
+import org.onosproject.net.device.PortDescription;
+
+import java.util.List;
+
+import static java.lang.String.format;
+
+/**
+ * Implementation of DeviceDescriptionDiscovery for Stratum devices.
+ */
+public class StratumDeviceDescriptionDiscovery
+        extends AbstractStratumBehaviour<DeviceDescriptionDiscovery>
+        implements DeviceDescriptionDiscovery {
+
+    private static final String UNKNOWN = "unknown";
+
+
+    public StratumDeviceDescriptionDiscovery() {
+        super(new P4RuntimeDeviceDescriptionDiscovery(),
+              new OpenConfigGnmiDeviceDescriptionDiscovery());
+    }
+
+    @Override
+    public DeviceDescription discoverDeviceDetails() {
+        final DeviceDescription p4Descr = p4runtime.discoverDeviceDetails();
+        final DeviceDescription gnmiDescr = gnmi.discoverDeviceDetails();
+        return new DefaultDeviceDescription(
+                data().deviceId().uri(),
+                Device.Type.SWITCH,
+                data().driver().manufacturer(),
+                data().driver().hwVersion(),
+                data().driver().swVersion(),
+                UNKNOWN,
+                p4Descr.chassisId(),
+                // Availability is mandated by P4Runtime.
+                p4Descr.isDefaultAvailable(),
+                DefaultAnnotations.builder()
+                        .set(AnnotationKeys.PROTOCOL, format(
+                                "%s, %s",
+                                p4Descr.annotations().value(AnnotationKeys.PROTOCOL),
+                                gnmiDescr.annotations().value(AnnotationKeys.PROTOCOL)))
+                        .build());
+    }
+
+    @Override
+    public List<PortDescription> discoverPortDetails() {
+        return gnmi.discoverPortDetails();
+    }
+}
diff --git a/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumHandshaker.java b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumHandshaker.java
index 8762af0..8ce68d7 100644
--- a/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumHandshaker.java
+++ b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumHandshaker.java
@@ -21,9 +21,6 @@
 import org.onosproject.net.MastershipRole;
 import org.onosproject.net.device.DeviceAgentListener;
 import org.onosproject.net.device.DeviceHandshaker;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.onosproject.net.driver.DriverData;
-import org.onosproject.net.driver.DriverHandler;
 import org.onosproject.net.provider.ProviderId;
 
 import java.util.concurrent.CompletableFuture;
@@ -31,33 +28,20 @@
 /**
  * Implementation of DeviceHandshaker for Stratum device.
  */
-public class StratumHandshaker extends AbstractHandlerBehaviour implements DeviceHandshaker {
-
-    private P4RuntimeHandshaker p4runtime;
-    private GnmiHandshaker gnmi;
+public class StratumHandshaker
+        extends AbstractStratumBehaviour<DeviceHandshaker>
+        implements DeviceHandshaker {
 
     public StratumHandshaker() {
-        p4runtime = new P4RuntimeHandshaker();
-        gnmi = new GnmiHandshaker();
-    }
-
-    @Override
-    public void setHandler(DriverHandler handler) {
-        super.setHandler(handler);
-        p4runtime.setHandler(handler);
-        gnmi.setHandler(handler);
-    }
-
-    @Override
-    public void setData(DriverData data) {
-        super.setData(data);
-        p4runtime.setData(data);
-        gnmi.setData(data);
+        super(new P4RuntimeHandshaker(), new GnmiHandshaker());
     }
 
     @Override
     public boolean isReachable() {
-        return p4runtime.isReachable() && gnmi.isReachable();
+        // Reachability is mainly used for mastership contests and it's a
+        // prerequisite for availability. We can probably live without gNMI and
+        // gNOI, but we will always need P4Runtime.
+        return p4runtime.isReachable();
     }
 
     @Override
diff --git a/drivers/stratum/src/main/resources/stratum-drivers.xml b/drivers/stratum/src/main/resources/stratum-drivers.xml
index fa0c0c4..f854d5f 100644
--- a/drivers/stratum/src/main/resources/stratum-drivers.xml
+++ b/drivers/stratum/src/main/resources/stratum-drivers.xml
@@ -19,6 +19,8 @@
             hwVersion="master" swVersion="Stratum" extends="p4runtime,gnmi">
         <behaviour api="org.onosproject.net.device.DeviceHandshaker"
                    impl="org.onosproject.drivers.stratum.StratumHandshaker"/>
+        <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
+                   impl="org.onosproject.drivers.stratum.StratumDeviceDescriptionDiscovery"/>
     </driver>
 
     <driver name="stratum-dummy" manufacturer="Open Networking Foundation"