Initial gNOI implementation added. Introduced system Time and Reboot RPC
Change-Id: I8accdcc6c1ff247408ce54490ceff3972fdf850f
diff --git a/drivers/gnoi/BUILD b/drivers/gnoi/BUILD
new file mode 100644
index 0000000..3a710a8
--- /dev/null
+++ b/drivers/gnoi/BUILD
@@ -0,0 +1,33 @@
+COMPILE_DEPS = CORE_DEPS + KRYO + [
+ "@com_google_protobuf//:protobuf_java",
+ "@io_grpc_grpc_java//core",
+ "@io_grpc_grpc_java//netty",
+ "@io_grpc_grpc_java//stub",
+ "//protocols/gnoi/stub:onos-protocols-gnoi-stub",
+ "//protocols/gnoi/api:onos-protocols-gnoi-api",
+ "//protocols/grpc/api:onos-protocols-grpc-api",
+]
+
+BUNDLES = [
+ ":onos-drivers-gnoi",
+]
+
+osgi_jar(
+ resources = glob(["src/main/resources/**"]),
+ resources_root = "src/main/resources",
+ deps = COMPILE_DEPS,
+)
+
+onos_app(
+ app_name = "org.onosproject.drivers.gnoi",
+ category = "Drivers",
+ description = "Adds support for devices using gNOI protocol based on " +
+ " openconfig proto definitions: https://github.com/openconfig/gnoi/ .",
+ included_bundles = BUNDLES,
+ required_apps = [
+ "org.onosproject.generaldeviceprovider",
+ "org.onosproject.protocols.gnoi",
+ ],
+ title = "gNOI Drivers",
+ url = "https://github.com/openconfig/gnoi/",
+)
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
new file mode 100644
index 0000000..23181b4
--- /dev/null
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/AbstractGnoiHandlerBehaviour.java
@@ -0,0 +1,89 @@
+/*
+ * 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.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.basics.BasicDeviceConfig;
+import org.onosproject.net.device.DeviceService;
+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 DeviceService deviceService;
+ protected Device device;
+ protected GnoiController controller;
+ protected GnoiClient client;
+
+ protected boolean setupBehaviour() {
+ deviceId = handler().data().deviceId();
+ deviceService = handler().get(DeviceService.class);
+ controller = handler().get(GnoiController.class);
+ client = controller.getClient(deviceId);
+
+ if (client == null) {
+ log.warn("Unable to find client for {}, aborting operation", deviceId);
+ 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
new file mode 100644
index 0000000..411a8bf
--- /dev/null
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiBasicSystemOperationsImpl.java
@@ -0,0 +1,76 @@
+/*
+ * 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 gnoi.system.SystemOuterClass.RebootRequest;
+import gnoi.system.SystemOuterClass.RebootResponse;
+import gnoi.system.SystemOuterClass.RebootMethod;
+import org.onosproject.net.behaviour.BasicSystemOperations;
+import java.util.concurrent.CompletableFuture;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of the BasicSystemOperations behavior for gNOI-enabled devices.
+ */
+public class GnoiBasicSystemOperationsImpl
+ extends AbstractGnoiHandlerBehaviour implements BasicSystemOperations {
+
+ private static final Logger log = LoggerFactory
+ .getLogger(GnoiBasicSystemOperationsImpl.class);
+
+ @Override
+ public CompletableFuture<Boolean> reboot() {
+ if (!setupBehaviour()) {
+ return CompletableFuture.completedFuture(false);
+ }
+
+ final RebootRequest.Builder requestMsg = RebootRequest.newBuilder().setMethod(RebootMethod.COLD);
+ final CompletableFuture<Boolean> future = client.reboot(requestMsg.build())
+ .handle((response, error) -> {
+ if (error == null) {
+ log.debug("gNOI reboot() for device {} returned {}", deviceId, response);
+ return RebootResponse.getDefaultInstance().equals(response);
+ } else {
+ log.error("Exception while performing gNOI reboot() for device " + deviceId, error);
+ return false;
+ }
+ });
+
+ return future;
+ }
+
+ @Override
+ public CompletableFuture<Long> time() {
+ if (!setupBehaviour()) {
+ return CompletableFuture.completedFuture(0L);
+ }
+ final CompletableFuture<Long> future = client.time()
+ .handle((response, error) -> {
+ if (error == null) {
+ log.debug("gNOI time() for device {} returned {}", deviceId.uri(), response.getTime());
+ return response.getTime();
+ } else {
+ log.error("Exception while performing gNOI time() for device " + deviceId, error);
+ return 0L;
+ }
+ });
+
+ return future;
+ }
+}
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
new file mode 100644
index 0000000..3c308d6
--- /dev/null
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDeviceDescriptionDiscovery.java
@@ -0,0 +1,61 @@
+/*
+ * 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 org.onlab.packet.ChassisId;
+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.Collections;
+import java.util.List;
+
+/**
+ * Implementation of DeviceDescriptionDiscovery for gNOI devices.
+ */
+public class GnoiDeviceDescriptionDiscovery
+ extends AbstractGnoiHandlerBehaviour implements DeviceDescriptionDiscovery {
+
+ private static final String UNKNOWN = "unknown";
+
+ @Override
+ public DeviceDescription discoverDeviceDetails() {
+
+ return new DefaultDeviceDescription(
+ data().deviceId().uri(),
+ Device.Type.SWITCH,
+ data().driver().manufacturer(),
+ data().driver().hwVersion(),
+ data().driver().swVersion(),
+ UNKNOWN,
+ new ChassisId(),
+ false,
+ DefaultAnnotations.builder()
+ .set(AnnotationKeys.PROTOCOL, "gNOI")
+ .build());
+ }
+
+
+ @Override
+ public List<PortDescription> discoverPortDetails() {
+ return Collections.emptyList();
+ }
+}
diff --git a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDriversLoader.java b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDriversLoader.java
new file mode 100644
index 0000000..2758176
--- /dev/null
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDriversLoader.java
@@ -0,0 +1,36 @@
+/*
+ * 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 org.osgi.service.component.annotations.Component;
+import org.onosproject.net.driver.AbstractDriverLoader;
+
+/**
+ * Loader for gNOI device drivers.
+ */
+@Component(immediate = true)
+public class GnoiDriversLoader extends AbstractDriverLoader {
+
+ public GnoiDriversLoader() {
+ super("/gnoi-drivers.xml");
+ }
+
+ @Override
+ public void activate() {
+ super.activate();
+ }
+}
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
new file mode 100644
index 0000000..36a4971
--- /dev/null
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiHandshaker.java
@@ -0,0 +1,97 @@
+/*
+ * 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 org.onosproject.gnoi.api.GnoiClient;
+import org.onosproject.gnoi.api.GnoiClientKey;
+import org.onosproject.gnoi.api.GnoiController;
+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 {
+
+ @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();
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return isReachable();
+ }
+
+ @Override
+ public CompletableFuture<Boolean> probeAvailability() {
+ return probeReachability();
+ }
+
+ @Override
+ public void roleChanged(MastershipRole newRole) {
+ throw new UnsupportedOperationException("Mastership operation not supported");
+ }
+
+ @Override
+ 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());
+ }
+}
diff --git a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/package-info.java b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/package-info.java
new file mode 100644
index 0000000..fde5c57
--- /dev/null
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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 for gNOI device drivers.
+ */
+package org.onosproject.drivers.gnoi;
diff --git a/drivers/gnoi/src/main/resources/gnoi-drivers.xml b/drivers/gnoi/src/main/resources/gnoi-drivers.xml
new file mode 100644
index 0000000..891fcd7
--- /dev/null
+++ b/drivers/gnoi/src/main/resources/gnoi-drivers.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<drivers>
+ <driver name="gnoi" manufacturer="gnoi" hwVersion="master" swVersion="master">
+ <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
+ impl="org.onosproject.drivers.gnoi.GnoiDeviceDescriptionDiscovery"/>
+ <behaviour api="org.onosproject.net.behaviour.BasicSystemOperations"
+ impl="org.onosproject.drivers.gnoi.GnoiBasicSystemOperationsImpl"/>
+ <behaviour api="org.onosproject.net.device.DeviceHandshaker"
+ impl="org.onosproject.drivers.gnoi.GnoiHandshaker"/>
+ </driver>
+</drivers>