Dell Rest Driver
Change-Id: I79eee0540766c56694f35d18f3d5be06fb59aea5
diff --git a/drivers/dellrest/BUILD b/drivers/dellrest/BUILD
new file mode 100644
index 0000000..2d53a22
--- /dev/null
+++ b/drivers/dellrest/BUILD
@@ -0,0 +1,32 @@
+COMPILE_DEPS = CORE_DEPS + JACKSON + [
+ "@javax_ws_rs_api//jar",
+ "//utils/rest:onlab-rest",
+ "//drivers/utilities:onos-drivers-utilities",
+ "//protocols/rest/api:onos-protocols-rest-api",
+]
+
+TEST_DEPS = TEST_ADAPTERS + [
+ "//core/api:onos-api-tests",
+]
+
+BUNDLES = [
+ ":onos-drivers-dellrest",
+ "//drivers/utilities:onos-drivers-utilities",
+]
+
+osgi_jar_with_tests(
+ resources = glob(["src/main/resources/**"]),
+ resources_root = "src/main/resources",
+ test_deps = TEST_DEPS,
+ deps = COMPILE_DEPS,
+)
+
+onos_app(
+ app_name = "org.onosproject.drivers.dellrest",
+ category = "Drivers",
+ description = "Adds support for Dell Networks devices using REST.",
+ included_bundles = BUNDLES,
+ required_apps = ["org.onosproject.restsb"],
+ title = "Dell Networks REST Drivers",
+ url = "http://onosproject.org",
+)
diff --git a/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestBridgeConfig.java b/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestBridgeConfig.java
new file mode 100644
index 0000000..f885b53
--- /dev/null
+++ b/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestBridgeConfig.java
@@ -0,0 +1,145 @@
+/*
+ * 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.dellrest;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.BridgeConfig;
+import org.onosproject.net.behaviour.BridgeDescription;
+import org.onosproject.net.behaviour.BridgeName;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.protocol.rest.RestSBController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.core.MediaType;
+import java.io.InputStream;
+import java.io.StringBufferInputStream;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class DellRestBridgeConfig extends AbstractHandlerBehaviour
+ implements BridgeConfig {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private static final String CLI_REQUEST = "/running/dell/_operations/cli";
+ private static final String CONFIG_COMMANDS = "<input>" +
+ "<config-commands>" +
+ "openflow of-instance 1\\r\\n" +
+ "shutdown\\r\\n" +
+ "exit\\r\\n" +
+ "%s" + // interface commands
+ "openflow of-instance 1\\r\\n" +
+ "no shutdown" +
+ "</config-commands>" +
+ "</input>";
+ private static final String PORT_ADD_COMMANDS = "interface %s\\r\\n" + // interface name
+ "of-instance 1\\r\\n" +
+ "no shutdown\\r\\n" +
+ "exit\\r\\n";
+ private static final String PORT_REMOVE_COMMANDS = "interface %s\\r\\n" + // interface name
+ "no of-instance\\r\\n" +
+ "exit\\r\\n";
+ private static final String TENGINTERFACE = "TenGigabitEthernet ";
+ private static final String FORTYGINTERFACE = "FortyGigE ";
+ private static final String SLASH = "/";
+ private static final String DASH = "-";
+
+ @Override
+ public boolean addBridge(BridgeDescription bridgeDescription) {
+ return false;
+ }
+
+ @Override
+ public void deleteBridge(BridgeName bridgeName) {
+
+ }
+
+ @Override
+ public Collection<BridgeDescription> getBridges() {
+ return null;
+ }
+
+ @Override
+ public void addPort(BridgeName bridgeName, String portName) {
+ // bridgeName is not used
+ checkNotNull(portName);
+ portName = portNameForCli(portName);
+ String portAddCommands = String.format(PORT_ADD_COMMANDS, portName);
+
+ DriverHandler handler = handler();
+ RestSBController controller = checkNotNull(handler.get(RestSBController.class));
+ DeviceId deviceId = handler.data().deviceId();
+
+ InputStream payload = new StringBufferInputStream(String.format(CONFIG_COMMANDS, portAddCommands));
+ String resp = controller.post(deviceId, CLI_REQUEST, payload, MediaType.valueOf("*/*"), String.class);
+ //TODO Parse resp and if error, return false
+ log.info("{}", resp);
+ return;
+ }
+
+ @Override
+ public void deletePort(BridgeName bridgeName, String portName) {
+ // bridgeName is not used
+ checkNotNull(portName);
+ portName = portNameForCli(portName);
+ String portRemoveCommands = String.format(PORT_REMOVE_COMMANDS, portName);
+
+ DriverHandler handler = handler();
+ RestSBController controller = checkNotNull(handler.get(RestSBController.class));
+ DeviceId deviceId = handler.data().deviceId();
+
+ InputStream payload = new StringBufferInputStream(String.format(CONFIG_COMMANDS, portRemoveCommands));
+ String resp = controller.post(deviceId, CLI_REQUEST, payload, MediaType.valueOf("*/*"), String.class);
+ log.info("{}", resp);
+ }
+
+ @Override
+ public Collection<PortDescription> getPorts() {
+ return null;
+ }
+
+ @Override
+ public Set<PortNumber> getPortNumbers() {
+ return null;
+ }
+
+ @Override
+ public List<PortNumber> getLocalPorts(Iterable<String> ifaceIds) {
+ return null;
+ }
+
+ private String portNameForCli(String portName) {
+ if (portName.toLowerCase().startsWith("tengig-")) {
+ // change eg. "tengig-1-1" to "TenGigabitEthernet 1/1"
+ portName = portName.replaceFirst("tengig-", TENGINTERFACE);
+ return portName.replaceFirst(DASH, SLASH);
+ } else if (portName.toLowerCase().startsWith("fortygig-")) {
+ // change eg. "fortygig-1-49" to "FortyGigE 1/49"
+ portName = portName.replaceFirst("fortygig-", FORTYGINTERFACE);
+ return portName.replaceFirst(DASH, SLASH);
+ } else {
+ return portName;
+ }
+ }
+}
diff --git a/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestDriversLoader.java b/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestDriversLoader.java
new file mode 100644
index 0000000..670cfff
--- /dev/null
+++ b/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestDriversLoader.java
@@ -0,0 +1,31 @@
+/*
+ * 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.dellrest;
+
+import org.osgi.service.component.annotations.Component;
+import org.onosproject.net.driver.AbstractDriverLoader;
+
+/**
+ * Loader for Dell device drivers.
+ */
+@Component(immediate = true)
+public class DellRestDriversLoader extends AbstractDriverLoader {
+
+ public DellRestDriversLoader() {
+ super("/dellrest-drivers.xml");
+ }
+}
diff --git a/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestOpenFlowControllerConfig.java b/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestOpenFlowControllerConfig.java
new file mode 100644
index 0000000..dcf0c99
--- /dev/null
+++ b/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestOpenFlowControllerConfig.java
@@ -0,0 +1,111 @@
+/*
+ * 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.dellrest;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.ControllerConfig;
+import org.onosproject.net.behaviour.ControllerInfo;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.protocol.rest.RestSBController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.core.MediaType;
+import java.io.InputStream;
+import java.io.StringBufferInputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class DellRestOpenFlowControllerConfig extends AbstractHandlerBehaviour
+ implements ControllerConfig {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private static final String TCP = "tcp";
+ private static final String CLI_REQUEST = "/running/dell/_operations/cli";
+ private static final String SET_CONTROLLERS_XML = "<input>" +
+ "<config-commands>" +
+ "openflow of-instance 1\\r\\n" + // for now supports only one instance
+ "shutdown\\r\\n" +
+ "%s" +
+ "of-version 1.3\\r\\n" +
+ "no shutdown" + // TODO: check previous state
+ "</config-commands>" +
+ "</input>";
+ private static final String SET_CONTROLLER = "controller %d %s port %d tcp\\r\\n";
+ private static final String NO_CONTROLLER = "no controller %d\\r\\n";
+ private static final int MAX_CONTROLLERS = 2;
+
+ @Override
+ public List<ControllerInfo> getControllers() {
+ return new ArrayList<>();
+ }
+
+ // Example test with ONOS CLI:
+ // device-setcontrollers rest:10.251.217.143:8008 tcp:1.2.3.4:2222
+
+ // TODO: assumes that of-instance 1 was in "no shutdown" state,
+ // check previous state
+ @Override
+ public void setControllers(List<ControllerInfo> controllers) {
+
+ // Dell supports max 2 controllers per of-instance
+ if (controllers.size() > MAX_CONTROLLERS) {
+ log.warn("Cannot set more than 2 controllers.");
+ }
+
+ DriverHandler handler = handler();
+ RestSBController controller = checkNotNull(handler.get(RestSBController.class));
+ DeviceId deviceId = handler.data().deviceId();
+
+ String controllerCommands = getControllerCommands(controllers).stream()
+ .reduce(String::concat)
+ .orElse("");
+
+ InputStream payload = new StringBufferInputStream(String.format(SET_CONTROLLERS_XML, controllerCommands));
+ String resp = controller.post(deviceId, CLI_REQUEST, payload, MediaType.valueOf("*/*"), String.class);
+ log.info("{}", resp);
+ }
+
+ // Get controller commands for maximum first 2 controllers
+ private List<String> getControllerCommands(List<ControllerInfo> controllers) {
+ List<String> controllerCommands = new ArrayList<>();
+
+ for (int controllerNum = 0; controllerNum < MAX_CONTROLLERS; ++controllerNum) {
+ if (controllers.size() > controllerNum) {
+ ControllerInfo controllerInfo = controllers.get(controllerNum);
+ // Only "tcp" type is supported
+ if (controllerInfo.type().equals(TCP)) {
+ String ip = controllerInfo.ip().toString();
+ int port = controllerInfo.port();
+ controllerCommands.add(String.format(SET_CONTROLLER, controllerNum + 1, ip, port));
+ } else {
+ log.warn("Controller type can only be 'tcp'");
+ controllerCommands.add(String.format(NO_CONTROLLER, controllerNum + 1));
+ }
+ } else {
+ // remove existing controller
+ controllerCommands.add(String.format(NO_CONTROLLER, controllerNum + 1));
+ }
+ }
+
+ return controllerCommands;
+ }
+}
diff --git a/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestPortDiscovery.java b/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestPortDiscovery.java
new file mode 100644
index 0000000..851d7a4
--- /dev/null
+++ b/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/DellRestPortDiscovery.java
@@ -0,0 +1,93 @@
+/*
+ * 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.dellrest;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.onosproject.drivers.utilities.XmlConfigParser;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.device.DefaultPortDescription;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.protocol.rest.RestSBController;
+import org.slf4j.Logger;
+
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Discovers the ports from a Dell Rest device.
+ */
+@Deprecated
+public class DellRestPortDiscovery extends AbstractHandlerBehaviour {
+
+ private final Logger log = getLogger(getClass());
+ private static final String NAME = "name";
+ private static final String INTERFACES = "interface";
+ private static final String INTERFACES_REQUEST = "/running/dell/interfaces";
+ private static final String TENGINTERFACENAME = "Te ";
+
+
+ @Deprecated
+ public List<PortDescription> getPorts() {
+ List<PortDescription> ports = Lists.newArrayList();
+ DriverHandler handler = handler();
+ RestSBController controller = checkNotNull(handler.get(RestSBController.class));
+ DeviceId deviceId = handler.data().deviceId();
+ String remotePortName = "";
+
+ // read configuration from REST API
+ HierarchicalConfiguration config = XmlConfigParser.
+ loadXml(controller.get(deviceId, INTERFACES_REQUEST, MediaType.valueOf("*/*")));
+
+ // get the interfaces part
+ List<HierarchicalConfiguration> portsConfig = parseDellPorts(config);
+
+ portsConfig.stream().forEach(sub -> {
+ String portName = sub.getString(NAME);
+ DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
+ .set(AnnotationKeys.PORT_NAME, portName);
+ // TODO: obtain proper port speed and type
+ long portSpeed = 10_000;
+ Port.Type portType = Port.Type.COPPER;
+ PortNumber portNumber = PortNumber.fromString(remotePortName.replaceAll(TENGINTERFACENAME, ""));
+
+ ports.add(DefaultPortDescription.builder()
+ .withPortNumber(portNumber)
+ .isEnabled(true)
+ .type(portType)
+ .portSpeed(portSpeed)
+ .annotations(annotations.build())
+ .build());
+ });
+ return ImmutableList.copyOf(ports);
+ }
+
+ public static List<HierarchicalConfiguration> parseDellPorts(HierarchicalConfiguration cfg) {
+ return cfg.configurationsAt(INTERFACES);
+ }
+}
+
diff --git a/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/package-info.java b/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/package-info.java
new file mode 100644
index 0000000..5cbbc4a
--- /dev/null
+++ b/drivers/dellrest/src/main/java/org/onosproject/drivers/dellrest/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 Dell device drivers.
+ */
+package org.onosproject.drivers.dellrest;
\ No newline at end of file
diff --git a/drivers/dellrest/src/main/resources/dellrest-drivers.xml b/drivers/dellrest/src/main/resources/dellrest-drivers.xml
new file mode 100644
index 0000000..14bd7fe
--- /dev/null
+++ b/drivers/dellrest/src/main/resources/dellrest-drivers.xml
@@ -0,0 +1,27 @@
+<?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="dellrest" manufacturer="Dell" hwVersion="1.0.0" swVersion="1.0.0">
+ <behaviour api="org.onosproject.net.behaviour.PortDiscovery"
+ impl="org.onosproject.drivers.dellrest.DellRestPortDiscovery"/>
+ <behaviour api="org.onosproject.net.behaviour.ControllerConfig"
+ impl="org.onosproject.drivers.dellrest.DellRestOpenFlowControllerConfig"/>
+ <behaviour api="org.onosproject.net.behaviour.BridgeConfig"
+ impl="org.onosproject.drivers.dellrest.DellRestBridgeConfig"/>
+ </driver>
+</drivers>
+
diff --git a/drivers/dellrest/src/test/java/org/onosproject/drivers/dellrest/DellrestDriversLoaderTest.java b/drivers/dellrest/src/test/java/org/onosproject/drivers/dellrest/DellrestDriversLoaderTest.java
new file mode 100644
index 0000000..0c3de7f
--- /dev/null
+++ b/drivers/dellrest/src/test/java/org/onosproject/drivers/dellrest/DellrestDriversLoaderTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.dellrest;
+
+import org.junit.Before;
+import org.onosproject.net.driver.AbstractDriverLoaderTest;
+
+/**
+ * Dellrest drivers loader test.
+ */
+public class DellrestDriversLoaderTest extends AbstractDriverLoaderTest {
+
+ @Before
+ public void setUp() {
+ loader = new DellRestDriversLoader();
+ }
+}