Andrea Campanella
Committed by Gerrit Code Review

ONOS-3754 Create driver/behavior for Ciena waveserver

Change-Id: I2e8741f0ad858eb712f7fe4f4a5fdf5e146aefd6
/*
* Copyright 2015 Open Networking Laboratory
*
* 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.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.PortDiscovery;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
/**
* Command that gets the configuration of the specified type from the specified
* device. If configuration cannot be retrieved it prints an error string.
*
* This is a temporary development tool for use until yang integration is complete.
* This uses a not properly specified behavior. DO NOT USE AS AN EXAMPLE.
*/
@Command(scope = "onos", name = "device-ports",
description = "Gets the ports of the specified device.")
public class DevicePortGetterCommand extends AbstractShellCommand {
@Argument(index = 0, name = "uri", description = "Device ID",
required = true, multiValued = false)
String uri = null;
private DeviceId deviceId;
@Override
protected void execute() {
DriverService service = get(DriverService.class);
deviceId = DeviceId.deviceId(uri);
DriverHandler h = service.createHandler(deviceId);
PortDiscovery portConfig = h.behaviour(PortDiscovery.class);
print(portConfig.getPorts().toString());
}
}
\ No newline at end of file
......@@ -127,6 +127,12 @@
</completers>
</command>
<command>
<action class="org.onosproject.cli.net.DevicePortGetterCommand"/>
<completers>
<ref component-id="deviceIdCompleter"/>
</completers>
</command>
<command>
<action class="org.onosproject.cli.net.DeviceRemoveCommand"/>
<completers>
<ref component-id="deviceIdCompleter"/>
......
/*
*
* * Copyright 2016 Open Networking Laboratory
* *
* * 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.device.PortDescription;
import org.onosproject.net.driver.HandlerBehaviour;
import java.util.List;
/**
* Discovers the set of ports from a device through a device specific protocol.
* The returned ports are not retrieved from the information stored in ONOS.
*/
public interface PortDiscovery extends HandlerBehaviour {
/**
* Retrieves the set of ports from a device.
* @return a set of port descriptions.
*/
List<PortDescription> getPorts();
}
\ No newline at end of file
......@@ -25,5 +25,7 @@
<bundle>mvn:${project.groupId}/onos-ovsdb-rfc/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-netconf-api/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-restsb-api/${project.version}</bundle>
</feature>
</features>
......
......@@ -69,6 +69,11 @@
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-restsb-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-netconf-api</artifactId>
<version>${project.version}</version>
</dependency>
......
......@@ -14,14 +14,23 @@
* limitations under the License.
*/
package org.onosproject.driver.netconf;
package org.onosproject.driver;
import com.google.common.collect.Lists;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.ConfigurationNode;
import org.onlab.packet.IpAddress;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.behaviour.ControllerInfo;
import org.onosproject.net.device.OchPortDescription;
import org.onosproject.net.device.PortDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -33,7 +42,7 @@ import java.util.List;
/**
* Parser for Netconf XML configurations and replys.
*/
final class XmlConfigParser {
public final class XmlConfigParser {
public static final Logger log = LoggerFactory
.getLogger(XmlConfigParser.class);
......@@ -42,7 +51,7 @@ final class XmlConfigParser {
}
protected static HierarchicalConfiguration loadXml(InputStream xmlStream) {
public static HierarchicalConfiguration loadXml(InputStream xmlStream) {
XMLConfiguration cfg = new XMLConfiguration();
try {
cfg.load(xmlStream);
......@@ -52,7 +61,7 @@ final class XmlConfigParser {
}
}
protected static List<ControllerInfo> parseStreamControllers(HierarchicalConfiguration cfg) {
public static List<ControllerInfo> parseStreamControllers(HierarchicalConfiguration cfg) {
List<ControllerInfo> controllers = new ArrayList<>();
List<HierarchicalConfiguration> fields =
cfg.configurationsAt("data.capable-switch." +
......@@ -67,7 +76,7 @@ final class XmlConfigParser {
return controllers;
}
protected static String parseSwitchId(HierarchicalConfiguration cfg) {
public static String parseSwitchId(HierarchicalConfiguration cfg) {
HierarchicalConfiguration field =
cfg.configurationAt("data.capable-switch." +
"logical-switches." +
......@@ -75,13 +84,13 @@ final class XmlConfigParser {
return field.getProperty("id").toString();
}
protected static String parseCapableSwitchId(HierarchicalConfiguration cfg) {
public static String parseCapableSwitchId(HierarchicalConfiguration cfg) {
HierarchicalConfiguration field =
cfg.configurationAt("data.capable-switch");
return field.getProperty("id").toString();
}
protected static String createControllersConfig(HierarchicalConfiguration cfg,
public static String createControllersConfig(HierarchicalConfiguration cfg,
HierarchicalConfiguration actualCfg,
String target, String netconfOperation,
String controllerOperation,
......@@ -122,5 +131,44 @@ final class XmlConfigParser {
}
public static List<HierarchicalConfiguration> parseWaveServerCienaPorts(HierarchicalConfiguration cfg) {
return cfg.configurationsAt("ws-ports.port-interface");
}
public static PortDescription parseWaveServerCienaOCHPorts(long portNumber, long oduPortSpeed,
HierarchicalConfiguration config,
SparseAnnotations annotations) {
final List<String> tunableType = Lists.newArrayList("Performance-Optimized", "Accelerated");
final String transmitterPath = "ptp-config.transmitter-state";
final String tunablePath = "ptp-config.adv-config.tx-tuning-mode";
final String gridTypePath = "ptp-config.adv-config.wl-spacing";
final String frequencyPath = "ptp-config.adv-config.frequency";
boolean isEnabled = config.getString(transmitterPath).equals("enabled");
boolean isTunable = tunableType.contains(config.getString(tunablePath));
//FIXME change when all optical types have two way information methods, see jira tickets
final int speed100GbpsinMbps = 100000;
OduSignalType oduSignalType = oduPortSpeed == speed100GbpsinMbps ? OduSignalType.ODU4 : null;
GridType gridType = config.getString(gridTypePath).equals("FlexGrid") ? GridType.FLEX : null;
ChannelSpacing chSpacing = gridType == GridType.FLEX ? ChannelSpacing.CHL_6P25GHZ : null;
//Working in Ghz //(Nominal central frequency - 193.1)/channelSpacing = spacingMultiplier
final int baseFrequency = 193100;
int spacingMult = (int) (toGbps((Integer.parseInt(config.getString(frequencyPath)) -
baseFrequency)) / toGbpsFromHz(chSpacing.frequency().asHz())); //FIXME is there a better way ?
return new OchPortDescription(PortNumber.portNumber(portNumber), isEnabled, oduSignalType, isTunable,
new OchSignal(gridType, chSpacing, spacingMult, 1), annotations);
}
//FIXME remove when all optical types have two way information methods, see jira tickets
private static long toGbps(long speed) {
return speed * 1000;
}
private static long toGbpsFromHz(long speed) {
return speed / 1000;
}
//TODO implement mor methods for parsing configuration when you need them
}
......
......@@ -17,6 +17,7 @@
package org.onosproject.driver.netconf;
import com.google.common.base.Preconditions;
import org.onosproject.driver.XmlConfigParser;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.ControllerConfig;
import org.onosproject.net.behaviour.ControllerInfo;
......
/*
*
* * Copyright 2016 Open Networking Laboratory
* *
* * 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.driver.rest;
import com.google.common.collect.Lists;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.onosproject.driver.XmlConfigParser;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.CltSignalType;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.behaviour.PortDiscovery;
import org.onosproject.net.device.OduCltPortDescription;
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 java.util.ArrayList;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Discovers the ports from a Ciena WaveServer Rest device.
*/
public class PortDiscoveryCienaWaveserverImpl extends AbstractHandlerBehaviour
implements PortDiscovery {
private static final String SPEED = "speed";
private static final String GBPS = "Gbps";
private static final String PORT_ID = "port-id";
private static final String XML = "xml";
private static final String ENABLED = "enabled";
private static final String EMPTY_STRING = "";
private static final String NAME = "name";
private static final String ADMIN_STATE = "admin-state";
private static final ArrayList<String> LINESIDE = Lists.newArrayList(
"1.1", "1.2", "12.1", "12.2");
private static final String GENERAL_PORT_REQUEST =
"yang-api/datastore/ws-ports?config=true&format=xml&depth=unbounded";
private static final String SPECIFIC_PORT_PATH = "yang-api/datastore/ws-ptps/ptp/";
private static final String SPECIFIC_PORT_CONFIG =
"/ptp-config?config=true&format=xml&depth=unbounded";
@Override
public List<PortDescription> getPorts() {
List<PortDescription> ports = Lists.newArrayList();
DriverHandler handler = handler();
RestSBController controller = checkNotNull(handler.get(RestSBController.class));
DeviceId deviceId = handler.data().deviceId();
HierarchicalConfiguration config = XmlConfigParser.
loadXml(controller.get(deviceId, GENERAL_PORT_REQUEST, XML));
List<HierarchicalConfiguration> portsConfig =
XmlConfigParser.parseWaveServerCienaPorts(config);
portsConfig.stream().forEach(sub -> {
String name = sub.getString(NAME);
SparseAnnotations annotations = DefaultAnnotations.builder()
.set(AnnotationKeys.NAME, String.valueOf(name)).build();
if (LINESIDE.contains(name)) {
String wsportInfoRequest = SPECIFIC_PORT_PATH + sub.getLong(PORT_ID) +
SPECIFIC_PORT_CONFIG;
ports.add(XmlConfigParser.parseWaveServerCienaOCHPorts(
sub.getLong(PORT_ID),
toGbps(Long.parseLong(sub.getString(SPEED).replace(GBPS, EMPTY_STRING))),
XmlConfigParser.loadXml(controller.get(deviceId, wsportInfoRequest, XML)),
annotations));
} else {
//FIXME change when all optical types have two way information methods, see jira tickets
final int speed100GbpsinMbps = 100000;
CltSignalType cltType = toGbps(Long.parseLong(
sub.getString(SPEED).replace(GBPS, EMPTY_STRING))) == speed100GbpsinMbps ?
CltSignalType.CLT_100GBE : null;
ports.add(new OduCltPortDescription(PortNumber.portNumber(sub.getLong(PORT_ID)),
sub.getString(ADMIN_STATE).equals(ENABLED),
cltType, annotations));
}
});
return ports;
}
//FIXME remove when all optical types have two way information methods, see jira tickets
private long toGbps(long speed) {
return speed * 1000;
}
}
/*
* Copyright 2016 Open Networking Laboratory
*
* 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.
*/
/**
* Implementations of the REST driver behaviours.
*/
package org.onosproject.driver.rest;
\ No newline at end of file
......@@ -128,7 +128,9 @@
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OltPipeline"/>
</driver>
<driver name="rest" manufacturer="" hwVersion="" swVersion="">
<driver name="restCiena" manufacturer="Ciena" hwVersion="1.0.0" swVersion="1.0.0">
<behaviour api="org.onosproject.net.behaviour.PortDiscovery"
impl="org.onosproject.driver.rest.PortDiscoveryCienaWaveserverImpl"/>
</driver>
<!-- The SoftRouter driver is meant to be used by any software/NPU based
~ switch that wishes to implement a simple 2-table router. To use this
......
......@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.onosproject.driver.netconf;
package org.onosproject.driver;
import org.junit.Test;
import org.onlab.packet.IpAddress;
......@@ -27,9 +27,7 @@ import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertTrue;
import static org.onosproject.driver.netconf.XmlConfigParser.*;
//import static org.junit.Assert.*;
import static org.onosproject.driver.XmlConfigParser.*;
/**
* Test the XML document Parsing for netconf configuration.
......
......@@ -128,6 +128,7 @@ public class RestSBControllerImpl implements RestSBController {
@Override
public boolean put(DeviceId device, String request, InputStream payload, String mediaType) {
WebResource webResource = getWebResource(device, request);
ClientResponse response = null;
if (payload != null) {
......
......@@ -31,6 +31,7 @@ import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.behaviour.PortDiscovery;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
......@@ -40,7 +41,8 @@ import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceProvider;
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.protocol.rest.RestSBController;
......@@ -51,7 +53,6 @@ import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
......@@ -84,6 +85,9 @@ public class RestDeviceProvider extends AbstractProvider
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DriverService driverService;
private DeviceProviderService providerService;
protected static final String ISNOTNULL = "Rest device is not null";
......@@ -170,11 +174,6 @@ public class RestDeviceProvider extends AbstractProvider
controller.addDevice(nodeId);
}
private void updatePorts(DeviceId deviceId, List<PortDescription> portDescriptions) {
// TODO get driver and call behavior to get ports
//signal the ports to onos
}
//when do I call it ?
public void deviceRemoved(RestSBDevice nodeId) {
Preconditions.checkNotNull(nodeId, ISNOTNULL);
......@@ -204,8 +203,15 @@ public class RestDeviceProvider extends AbstractProvider
log.error("Configuration error {}", e);
}
log.info("REST Devices {}", controller.getDevices());
//TODO ask for ports then call update ports.
controller.getDevices().keySet().forEach(deviceId -> {
DriverHandler h = driverService.createHandler(deviceId);
PortDiscovery portConfig = h.behaviour(PortDiscovery.class);
if (portConfig != null) {
providerService.updatePorts(deviceId, portConfig.getPorts());
} else {
log.warn("No portGetter behaviour for device {}", deviceId);
}
});
}
private boolean testDeviceConnection(RestSBDevice device) {
......
......@@ -2,7 +2,7 @@
"devices": {
"rest:127.0.0.1:8080": {
"basic": {
"driver": "rest"
"driver": "restCiena"
}
}
},
......