Initial gNOI implementation added. Introduced system Time and Reboot RPC
Change-Id: I8accdcc6c1ff247408ce54490ceff3972fdf850f
diff --git a/WORKSPACE b/WORKSPACE
index 0fe619d..f4c2b4d 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -80,6 +80,10 @@
generate_gnmi()
+load("//tools/build/bazel:gnoi_workspace.bzl", "generate_gnoi")
+
+generate_gnoi()
+
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
diff --git a/cli/src/main/java/org/onosproject/cli/net/DeviceRebootCommand.java b/cli/src/main/java/org/onosproject/cli/net/DeviceRebootCommand.java
new file mode 100644
index 0000000..63306b4
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/DeviceRebootCommand.java
@@ -0,0 +1,63 @@
+/*
+ * 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.cli.net;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.behaviour.BasicSystemOperations;
+
+/**
+ * Administratively reboots device.
+ */
+@Service
+@Command(scope = "onos", name = "device-reboot",
+ description = "Administratively reboots a device")
+public class DeviceRebootCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "deviceId", description = "Device ID",
+ required = true, multiValued = false)
+ @Completion(DeviceIdCompleter.class)
+ String deviceId = null;
+
+ @Override
+ protected void doExecute() {
+ Device dev = get(DeviceService.class).getDevice(DeviceId.deviceId(deviceId));
+ if (dev == null) {
+ print(" %s", "Device does not exist");
+ return;
+ }
+
+ if (dev.is(BasicSystemOperations.class)) {
+ print("Reboot for the device %s issued", deviceId);
+ dev.as(BasicSystemOperations.class)
+ .reboot().whenComplete((future, error) -> {
+ if (error == null) {
+ print("Reboot for the device %s succeed.", deviceId);
+ } else {
+ log.error("Exception while rebooting device " + deviceId, error);
+ }
+ });
+
+ } else {
+ log.error("Device does not support {} behaviour", BasicSystemOperations.class.getName());
+ }
+ }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/DeviceTimeCommand.java b/cli/src/main/java/org/onosproject/cli/net/DeviceTimeCommand.java
new file mode 100644
index 0000000..e6eb7ee
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/DeviceTimeCommand.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.cli.net;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.BasicSystemOperations;
+import org.onosproject.net.device.DeviceService;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Gets time since epoch.
+ */
+@Service
+@Command(scope = "onos", name = "device-time",
+ description = "Returns the current time on the target device")
+public class DeviceTimeCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "deviceId", description = "Device ID",
+ required = true, multiValued = false)
+ @Completion(DeviceIdCompleter.class)
+ String deviceId = null;
+
+ @Override
+ protected void doExecute() {
+ Device dev = get(DeviceService.class).getDevice(DeviceId.deviceId(deviceId));
+ if (dev == null) {
+ print(" %s", "Device does not exist");
+ return;
+ }
+
+ if (dev.is(BasicSystemOperations.class)) {
+ try {
+ CompletableFuture<Long> timeFuture = dev.as(BasicSystemOperations.class).time();
+ print("Current time on the device: %s %d", deviceId, timeFuture.get());
+ } catch (InterruptedException | ExecutionException e) {
+ log.error("Exception while getting system time for device" + deviceId, e);
+ }
+ } else {
+ log.error("Device does not support {} behaviour", BasicSystemOperations.class.getName());
+ }
+ }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/BasicSystemOperations.java b/core/api/src/main/java/org/onosproject/net/behaviour/BasicSystemOperations.java
new file mode 100644
index 0000000..17f5868
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/BasicSystemOperations.java
@@ -0,0 +1,41 @@
+/*
+ * 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.net.behaviour;
+
+import org.onosproject.net.driver.HandlerBehaviour;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Handler behaviour capable of device reboot execution and getting system time since UNIX epoch.
+ */
+public interface BasicSystemOperations extends HandlerBehaviour {
+
+ /**
+ * Causes the target to reboot immediately.
+ *
+ * @return true if the operation was successful, false otherwise
+ */
+ CompletableFuture<Boolean> reboot();
+
+ /**
+ * Returns the current time on the target.
+ *
+ * @return Current time in nanoseconds since UNIX epoch.
+ */
+ CompletableFuture<Long> time();
+}
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>
diff --git a/drivers/stratum/BUILD b/drivers/stratum/BUILD
index c075491..1d19c3c 100644
--- a/drivers/stratum/BUILD
+++ b/drivers/stratum/BUILD
@@ -2,6 +2,7 @@
"@io_grpc_grpc_java//core",
"//drivers/p4runtime:onos-drivers-p4runtime",
"//drivers/gnmi:onos-drivers-gnmi",
+ "//drivers/gnoi:onos-drivers-gnoi",
"//pipelines/basic:onos-pipelines-basic",
]
@@ -18,6 +19,7 @@
required_apps = [
"org.onosproject.generaldeviceprovider",
"org.onosproject.drivers.gnmi",
+ "org.onosproject.drivers.gnoi",
"org.onosproject.drivers.p4runtime",
"org.onosproject.pipelines.basic",
],
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
index b7c56e9..a9a7e2f 100644
--- a/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/AbstractStratumBehaviour.java
+++ b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/AbstractStratumBehaviour.java
@@ -32,10 +32,12 @@
protected B p4runtime;
protected B gnmi;
+ protected B gnoi;
- public AbstractStratumBehaviour(B p4runtime, B gnmi) {
+ public AbstractStratumBehaviour(B p4runtime, B gnmi, B gnoi) {
this.p4runtime = p4runtime;
this.gnmi = gnmi;
+ this.gnoi = gnoi;
}
@Override
@@ -43,6 +45,7 @@
super.setHandler(handler);
p4runtime.setHandler(handler);
gnmi.setHandler(handler);
+ gnoi.setHandler(handler);
}
@Override
@@ -50,5 +53,6 @@
super.setData(data);
p4runtime.setData(data);
gnmi.setData(data);
+ gnoi.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
index 4a65e26..f2e6e8d 100644
--- a/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumDeviceDescriptionDiscovery.java
+++ b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumDeviceDescriptionDiscovery.java
@@ -17,6 +17,7 @@
package org.onosproject.drivers.stratum;
import org.onosproject.drivers.gnmi.OpenConfigGnmiDeviceDescriptionDiscovery;
+import org.onosproject.drivers.gnoi.GnoiDeviceDescriptionDiscovery;
import org.onosproject.drivers.p4runtime.P4RuntimeDeviceDescriptionDiscovery;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DefaultAnnotations;
@@ -42,12 +43,14 @@
public StratumDeviceDescriptionDiscovery() {
super(new P4RuntimeDeviceDescriptionDiscovery(),
- new OpenConfigGnmiDeviceDescriptionDiscovery());
+ new OpenConfigGnmiDeviceDescriptionDiscovery(),
+ new GnoiDeviceDescriptionDiscovery());
}
@Override
public DeviceDescription discoverDeviceDetails() {
final DeviceDescription p4Descr = p4runtime.discoverDeviceDetails();
+ final DeviceDescription gnoiDescr = gnoi.discoverDeviceDetails();
final DeviceDescription gnmiDescr = gnmi.discoverDeviceDetails();
return new DefaultDeviceDescription(
data().deviceId().uri(),
@@ -61,8 +64,9 @@
p4Descr.isDefaultAvailable(),
DefaultAnnotations.builder()
.set(AnnotationKeys.PROTOCOL, format(
- "%s, %s",
+ "%s, %s, %s",
p4Descr.annotations().value(AnnotationKeys.PROTOCOL),
+ gnoiDescr.annotations().value(AnnotationKeys.PROTOCOL),
gnmiDescr.annotations().value(AnnotationKeys.PROTOCOL)))
.build());
}
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 8ce68d7..d512d3b 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
@@ -17,6 +17,7 @@
package org.onosproject.drivers.stratum;
import org.onosproject.drivers.gnmi.GnmiHandshaker;
+import org.onosproject.drivers.gnoi.GnoiHandshaker;
import org.onosproject.drivers.p4runtime.P4RuntimeHandshaker;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.device.DeviceAgentListener;
@@ -33,7 +34,7 @@
implements DeviceHandshaker {
public StratumHandshaker() {
- super(new P4RuntimeHandshaker(), new GnmiHandshaker());
+ super(new P4RuntimeHandshaker(), new GnmiHandshaker(), new GnoiHandshaker());
}
@Override
@@ -89,17 +90,19 @@
@Override
public CompletableFuture<Boolean> connect() {
// We should execute connections in parallel.
- return p4runtime.connect().thenCombine(gnmi.connect(), Boolean::logicalAnd);
+ return p4runtime.connect().thenCombine(gnmi.connect(), Boolean::logicalAnd)
+ .thenCombine(gnoi.connect(), Boolean::logicalAnd);
}
@Override
public boolean isConnected() {
- return p4runtime.isConnected() && gnmi.isConnected();
+ return p4runtime.isConnected() && gnmi.isConnected() && gnoi.isConnected();
}
@Override
public void disconnect() {
p4runtime.disconnect();
gnmi.disconnect();
+ gnoi.disconnect();
}
}
diff --git a/drivers/stratum/src/main/resources/stratum-drivers.xml b/drivers/stratum/src/main/resources/stratum-drivers.xml
index f854d5f..72e224b 100644
--- a/drivers/stratum/src/main/resources/stratum-drivers.xml
+++ b/drivers/stratum/src/main/resources/stratum-drivers.xml
@@ -16,7 +16,7 @@
-->
<drivers>
<driver name="stratum" manufacturer="Open Networking Foundation"
- hwVersion="master" swVersion="Stratum" extends="p4runtime,gnmi">
+ hwVersion="master" swVersion="Stratum" extends="p4runtime,gnmi,gnoi">
<behaviour api="org.onosproject.net.device.DeviceHandshaker"
impl="org.onosproject.drivers.stratum.StratumHandshaker"/>
<behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
diff --git a/protocols/gnoi/BUILD b/protocols/gnoi/BUILD
new file mode 100644
index 0000000..3666ea6
--- /dev/null
+++ b/protocols/gnoi/BUILD
@@ -0,0 +1,17 @@
+BUNDLES = [
+ "//protocols/gnoi/stub:onos-protocols-gnoi-stub",
+ "//protocols/gnoi/ctl:onos-protocols-gnoi-ctl",
+ "//protocols/gnoi/api:onos-protocols-gnoi-api",
+]
+
+onos_app(
+ app_name = "org.onosproject.protocols.gnoi",
+ category = "Protocol",
+ description = "gNOI protocol subsystem",
+ included_bundles = BUNDLES,
+ required_apps = [
+ "org.onosproject.protocols.grpc",
+ ],
+ title = "gNOI Protocol Subsystem",
+ url = "http://onosproject.org",
+)
diff --git a/protocols/gnoi/api/BUILD b/protocols/gnoi/api/BUILD
new file mode 100644
index 0000000..600f437
--- /dev/null
+++ b/protocols/gnoi/api/BUILD
@@ -0,0 +1,8 @@
+COMPILE_DEPS = CORE_DEPS + [
+ "//protocols/grpc/api:onos-protocols-grpc-api",
+ "//protocols/gnoi/stub:onos-protocols-gnoi-stub",
+]
+
+osgi_jar(
+ deps = COMPILE_DEPS,
+)
diff --git a/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/GnoiClient.java b/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/GnoiClient.java
new file mode 100644
index 0000000..d66c6f1
--- /dev/null
+++ b/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/GnoiClient.java
@@ -0,0 +1,46 @@
+/*
+ * 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.gnoi.api;
+
+import gnoi.system.SystemOuterClass.TimeResponse;
+import gnoi.system.SystemOuterClass.RebootRequest;
+import gnoi.system.SystemOuterClass.RebootResponse;
+import com.google.common.annotations.Beta;
+import org.onosproject.grpc.api.GrpcClient;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Client to control a gNOI server.
+ */
+@Beta
+public interface GnoiClient extends GrpcClient {
+
+ /**
+ * Returns the current time on the target.
+ *
+ * @return the TimeResponse result
+ */
+ CompletableFuture<TimeResponse> time();
+
+ /**
+ * Causes the target to reboot immediately.
+ *
+ * @param request RebootRequest
+ * @return the RebootResponse result
+ */
+ CompletableFuture<RebootResponse> reboot(RebootRequest request);
+}
diff --git a/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/GnoiClientKey.java b/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/GnoiClientKey.java
new file mode 100644
index 0000000..e246d74
--- /dev/null
+++ b/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/GnoiClientKey.java
@@ -0,0 +1,42 @@
+/*
+ * 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.gnoi.api;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.grpc.api.GrpcClientKey;
+import org.onosproject.net.DeviceId;
+
+import java.net.URI;
+
+/**
+ * Key that uniquely identifies a gNOI client.
+ */
+@Beta
+public class GnoiClientKey extends GrpcClientKey {
+
+ private static final String GNOI = "gNOI";
+
+ /**
+ * Creates a new gNOI client key.
+ *
+ * @param deviceId ONOS device ID
+ * @param serverUri gNOI server URI
+ */
+ public GnoiClientKey(DeviceId deviceId, URI serverUri) {
+ super(GNOI, deviceId, serverUri);
+ }
+}
diff --git a/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/GnoiController.java b/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/GnoiController.java
new file mode 100644
index 0000000..b601e21
--- /dev/null
+++ b/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/GnoiController.java
@@ -0,0 +1,28 @@
+/*
+ * 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.gnoi.api;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.grpc.api.GrpcClientController;
+
+/**
+ * Controller of gNOI devices.
+ */
+@Beta
+public interface GnoiController
+ extends GrpcClientController<GnoiClientKey, GnoiClient> {
+}
diff --git a/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/package-info.java b/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/package-info.java
new file mode 100644
index 0000000..ff86859
--- /dev/null
+++ b/protocols/gnoi/api/src/main/java/org/onosproject/gnoi/api/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.
+ */
+
+/**
+ * gNOI protocol API.
+ */
+package org.onosproject.gnoi.api;
diff --git a/protocols/gnoi/ctl/BUILD b/protocols/gnoi/ctl/BUILD
new file mode 100644
index 0000000..9fdb3a8
--- /dev/null
+++ b/protocols/gnoi/ctl/BUILD
@@ -0,0 +1,23 @@
+COMPILE_DEPS = CORE_DEPS + KRYO + [
+ "//protocols/gnoi/api:onos-protocols-gnoi-api",
+ "//protocols/gnoi/stub:onos-protocols-gnoi-stub",
+ "//protocols/grpc/api:onos-protocols-grpc-api",
+ "//protocols/grpc/ctl:onos-protocols-grpc-ctl",
+ "//protocols/grpc:grpc-core",
+ "@com_google_protobuf//:protobuf_java",
+ "@io_grpc_grpc_java//netty",
+ "@io_grpc_grpc_java//protobuf-lite",
+ "@io_grpc_grpc_java//stub",
+ "@com_google_api_grpc_proto_google_common_protos//jar",
+]
+
+TEST_DEPS = TEST + [
+ "@minimal_json//jar",
+ "@io_grpc_grpc_java//core:inprocess",
+ "@io_grpc_grpc_java//protobuf-lite",
+]
+
+osgi_jar_with_tests(
+ test_deps = TEST_DEPS,
+ deps = COMPILE_DEPS,
+)
diff --git a/protocols/gnoi/ctl/src/main/java/org/onosproject/gnoi/ctl/GnoiClientImpl.java b/protocols/gnoi/ctl/src/main/java/org/onosproject/gnoi/ctl/GnoiClientImpl.java
new file mode 100644
index 0000000..f1f1482
--- /dev/null
+++ b/protocols/gnoi/ctl/src/main/java/org/onosproject/gnoi/ctl/GnoiClientImpl.java
@@ -0,0 +1,141 @@
+/*
+ * 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.gnoi.ctl;
+
+import gnoi.system.SystemGrpc;
+import gnoi.system.SystemOuterClass.TimeRequest;
+import gnoi.system.SystemOuterClass.TimeResponse;
+import gnoi.system.SystemOuterClass.RebootRequest;
+import gnoi.system.SystemOuterClass.RebootResponse;
+import io.grpc.ManagedChannel;
+import io.grpc.stub.StreamObserver;
+import org.onosproject.gnoi.api.GnoiClient;
+import org.onosproject.gnoi.api.GnoiClientKey;
+import org.onosproject.grpc.ctl.AbstractGrpcClient;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of gNOI client.
+ */
+public class GnoiClientImpl extends AbstractGrpcClient implements GnoiClient {
+
+ private static final int RPC_TIMEOUT_SECONDS = 10;
+ private static final Logger log = LoggerFactory.getLogger(GnoiClientImpl.class);
+
+ GnoiClientImpl(GnoiClientKey clientKey, ManagedChannel managedChannel, GnoiControllerImpl controller) {
+ super(clientKey, managedChannel, false, controller);
+ }
+
+ @Override
+ public CompletableFuture<Boolean> probeService() {
+ return this.time().handle((response, t) -> {
+ if (t == null) {
+ log.debug("gNOI probeService succeed");
+ return true;
+ } else {
+ log.debug("gNOI probeService failed", t);
+ return false;
+ }
+ });
+ }
+
+ @Override
+ public CompletableFuture<TimeResponse> time() {
+ // The TimeRequest message is empty one so just form it
+ final TimeRequest requestMsg = TimeRequest.getDefaultInstance();
+ final CompletableFuture<TimeResponse> future = new CompletableFuture<>();
+
+ final StreamObserver<TimeResponse> observer =
+ new StreamObserver<TimeResponse>() {
+ @Override
+ public void onNext(TimeResponse value) {
+ future.complete(value);
+ }
+ @Override
+ public void onError(Throwable t) {
+ handleRpcError(t, "gNOI time request");
+ future.completeExceptionally(t);
+ }
+ @Override
+ public void onCompleted() {
+ // ignore
+ }
+ };
+
+ execRpc(s -> s.time(requestMsg, observer));
+ return future;
+ }
+
+ @Override
+ public CompletableFuture<RebootResponse> reboot(RebootRequest request) {
+ final CompletableFuture<RebootResponse> future = new CompletableFuture<>();
+
+ final StreamObserver<RebootResponse> observer =
+ new StreamObserver<RebootResponse>() {
+ @Override
+ public void onNext(RebootResponse value) {
+ future.complete(value);
+ }
+ @Override
+ public void onError(Throwable t) {
+ handleRpcError(t, "gNOI reboot request");
+ future.completeExceptionally(t);
+ }
+ @Override
+ public void onCompleted() {
+ // ignore
+ }
+ };
+
+ execRpc(s -> s.reboot(request, observer));
+ return future;
+ }
+
+ /**
+ * Forces execution of an RPC in a cancellable context with a timeout.
+ *
+ * @param stubConsumer SystemStub stub consumer
+ */
+ private void execRpc(Consumer<SystemGrpc.SystemStub> stubConsumer) {
+ if (log.isTraceEnabled()) {
+ log.trace("Executing RPC with timeout {} seconds (context deadline {})...",
+ RPC_TIMEOUT_SECONDS, context().getDeadline());
+ }
+ runInCancellableContext(() -> stubConsumer.accept(
+ SystemGrpc.newStub(channel)
+ .withDeadlineAfter(RPC_TIMEOUT_SECONDS, TimeUnit.SECONDS)));
+ }
+
+ /**
+ * Forces execution of an RPC in a cancellable context with no timeout.
+ *
+ * @param stubConsumer SystemStub stub consumer
+ */
+ void execRpcNoTimeout(Consumer<SystemGrpc.SystemStub> stubConsumer) {
+ if (log.isTraceEnabled()) {
+ log.trace("Executing RPC with no timeout (context deadline {})...",
+ context().getDeadline());
+ }
+ runInCancellableContext(() -> stubConsumer.accept(
+ SystemGrpc.newStub(channel)));
+ }
+
+}
diff --git a/protocols/gnoi/ctl/src/main/java/org/onosproject/gnoi/ctl/GnoiControllerImpl.java b/protocols/gnoi/ctl/src/main/java/org/onosproject/gnoi/ctl/GnoiControllerImpl.java
new file mode 100644
index 0000000..09ef01d
--- /dev/null
+++ b/protocols/gnoi/ctl/src/main/java/org/onosproject/gnoi/ctl/GnoiControllerImpl.java
@@ -0,0 +1,43 @@
+/*
+ * 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.gnoi.ctl;
+
+import io.grpc.ManagedChannel;
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.event.EventListener;
+import org.onosproject.gnoi.api.GnoiClient;
+import org.onosproject.gnoi.api.GnoiClientKey;
+import org.onosproject.gnoi.api.GnoiController;
+import org.onosproject.grpc.ctl.AbstractGrpcClientController;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * Implementation of gNOI controller.
+ */
+@Component(immediate = true, service = GnoiController.class)
+public class GnoiControllerImpl
+ extends AbstractGrpcClientController<GnoiClientKey, GnoiClient, AbstractEvent, EventListener<AbstractEvent>>
+ implements GnoiController {
+
+ public GnoiControllerImpl() {
+ super(AbstractEvent.class);
+ }
+
+ @Override
+ protected GnoiClient createClientInstance(GnoiClientKey clientKey, ManagedChannel channel) {
+ return new GnoiClientImpl(clientKey, channel, this);
+ }
+}
\ No newline at end of file
diff --git a/protocols/gnoi/ctl/src/main/java/org/onosproject/gnoi/ctl/package-info.java b/protocols/gnoi/ctl/src/main/java/org/onosproject/gnoi/ctl/package-info.java
new file mode 100644
index 0000000..e031bb7
--- /dev/null
+++ b/protocols/gnoi/ctl/src/main/java/org/onosproject/gnoi/ctl/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.
+ */
+
+/**
+ * Implementation classes of the gNOI protocol subsystem.
+ */
+package org.onosproject.gnoi.ctl;
diff --git a/protocols/gnoi/stub/BUILD b/protocols/gnoi/stub/BUILD
new file mode 100644
index 0000000..c6a3deb
--- /dev/null
+++ b/protocols/gnoi/stub/BUILD
@@ -0,0 +1,15 @@
+load("//tools/build/bazel:osgi_java_library.bzl", "osgi_proto_jar")
+
+PROTOS = [
+ "@com_github_openconfig_gnoi//:gnoi_system_proto",
+ "@com_github_openconfig_gnoi//:gnoi_types_proto",
+ "@com_github_openconfig_gnoi//:gnoi_common_proto",
+]
+
+osgi_proto_jar(
+ grpc_proto_lib = "@com_github_openconfig_gnoi//:gnoi_system_proto",
+ proto_libs = PROTOS,
+ deps = [
+ "@com_google_api_grpc_proto_google_common_protos//jar",
+ ],
+)
diff --git a/tools/build/bazel/gnoi_BUILD b/tools/build/bazel/gnoi_BUILD
new file mode 100644
index 0000000..c9dd1c3
--- /dev/null
+++ b/tools/build/bazel/gnoi_BUILD
@@ -0,0 +1,47 @@
+# Prefix string to remove from proto import statements
+IMPORT_PREFIX_COMMON = "github.com/openconfig/gnoi/common/"
+IMPORT_PREFIX = "github.com/openconfig/gnoi/"
+
+proto_library(
+ name = "gnoi_system_proto",
+ srcs = [":gnoi_system_sed"],
+ deps = [
+ ":gnoi_types_proto",
+ ":gnoi_common_proto",
+ "@com_google_protobuf//:any_proto",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+proto_library(
+ name = "gnoi_types_proto",
+ srcs = ["types/types.proto"],
+ deps = [
+ "@com_google_protobuf//:descriptor_proto",
+ "@com_google_protobuf//:any_proto",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+proto_library(
+ name = "gnoi_common_proto",
+ srcs = [":gnoi_common_sed"],
+ deps = [":gnoi_types_proto"],
+ visibility = ["//visibility:public"],
+)
+
+genrule(
+ name = "gnoi_common_sed",
+ srcs = ["common/common.proto"],
+ outs = ["common.proto"],
+ cmd = "sed -e 's:import \"%s:import \":g' $(location common/common.proto) > \"$@\""
+ % IMPORT_PREFIX,
+)
+
+genrule(
+ name = "gnoi_system_sed",
+ srcs = ["system/system.proto"],
+ outs = ["system.proto"],
+ cmd = "sed -e 's:import \"%s:import \":g' -e 's:import \"%s:import \":g' $(location system/system.proto) > \"$@\""
+ % (IMPORT_PREFIX_COMMON, IMPORT_PREFIX),
+)
diff --git a/tools/build/bazel/gnoi_workspace.bzl b/tools/build/bazel/gnoi_workspace.bzl
new file mode 100644
index 0000000..f345a8a
--- /dev/null
+++ b/tools/build/bazel/gnoi_workspace.bzl
@@ -0,0 +1,13 @@
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+GNOI_COMMIT = "d703187b4d437508375f55c4e4f44268ccce412f"
+GNOI_SHA = "7c34f6efb48d4efd145059a06702e391840591cdb4668267f9089232de4f9617"
+
+def generate_gnoi():
+ http_archive(
+ name = "com_github_openconfig_gnoi",
+ urls = ["https://github.com/openconfig/gnoi/archive/%s.zip" % GNOI_COMMIT],
+ sha256 = GNOI_SHA,
+ strip_prefix = "gnoi-%s" % GNOI_COMMIT,
+ build_file = "//tools/build/bazel:gnoi_BUILD",
+ )
diff --git a/tools/build/bazel/modules.bzl b/tools/build/bazel/modules.bzl
index 2820cb9..6a1603f 100644
--- a/tools/build/bazel/modules.bzl
+++ b/tools/build/bazel/modules.bzl
@@ -104,6 +104,7 @@
"//drivers/hp:onos-drivers-hp-oar",
"//drivers/p4runtime:onos-drivers-p4runtime-oar",
"//drivers/gnmi:onos-drivers-gnmi-oar",
+ "//drivers/gnoi:onos-drivers-gnoi-oar",
"//drivers/polatis/netconf:onos-drivers-polatis-netconf-oar",
"//drivers/polatis/openflow:onos-drivers-polatis-openflow-oar",
"//drivers/odtn-driver:onos-drivers-odtn-driver-oar",
@@ -256,6 +257,7 @@
"//protocols/grpc:onos-protocols-grpc-oar",
"//protocols/p4runtime:onos-protocols-p4runtime-oar",
"//protocols/gnmi:onos-protocols-gnmi-oar",
+ "//protocols/gnoi:onos-protocols-gnoi-oar",
"//protocols/xmpp/core:onos-protocols-xmpp-core-oar",
"//protocols/xmpp/pubsub:onos-protocols-xmpp-pubsub-oar",
]