change roadm app to support EDFA/ROADM/OPS devices, add OPS PowerConfig/LambdaQuery behaviour
Change-Id: Ieb6de727e766fdeb63740c0704f83fd11e44b935
diff --git a/apps/roadm/src/main/java/org/onosproject/roadm/ChannelData.java b/apps/roadm/src/main/java/org/onosproject/roadm/ChannelData.java
index 07c6c41..7011f1d8 100644
--- a/apps/roadm/src/main/java/org/onosproject/roadm/ChannelData.java
+++ b/apps/roadm/src/main/java/org/onosproject/roadm/ChannelData.java
@@ -58,8 +58,7 @@
PortNumber inPort = ((PortCriterion) in).port();
Criterion och = rule.selector().getCriterion(Criterion.Type.OCH_SIGID);
- checkNotNull(och);
- OchSignal ochSignal = ((OchSignalCriterion) och).lambda();
+ OchSignal ochSignal = och == null ? null : ((OchSignalCriterion) och).lambda();
PortNumber outPort = null;
List<Instruction> instructions = rule.treatment().allInstructions();
diff --git a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmDeviceViewMessageHandler.java b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmDeviceViewMessageHandler.java
index d2a6fe2..6577426 100644
--- a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmDeviceViewMessageHandler.java
+++ b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmDeviceViewMessageHandler.java
@@ -17,18 +17,21 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
+import org.onlab.osgi.ServiceDirectory;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.ui.RequestHandler;
+import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.table.TableModel;
import org.onosproject.ui.table.TableRequestHandler;
import java.util.Collection;
-import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.onosproject.net.Device.Type;
/**
* Table-View message handler for ROADM device view.
@@ -39,10 +42,9 @@
private static final String ROADM_DEVICE_DATA_RESP = "roadmDeviceDataResponse";
private static final String ROADM_DEVICES = "roadmDevices";
- private static final String NO_ROWS_MESSAGE = "No items found";
-
private static final String ID = "id";
- private static final String FRIENDLY_NAME = "name";
+ private static final String NAME = "name";
+ private static final String TYPE = "type";
private static final String MASTER = "master";
private static final String PORTS = "ports";
private static final String VENDOR = "vendor";
@@ -51,27 +53,22 @@
private static final String PROTOCOL = "protocol";
private static final String[] COLUMN_IDS = {
- ID, FRIENDLY_NAME, MASTER, PORTS, VENDOR, HW_VERSION, SW_VERSION,
- PROTOCOL
+ ID, NAME, TYPE, MASTER, PORTS, VENDOR, HW_VERSION, SW_VERSION, PROTOCOL
};
+ private DeviceService deviceService;
+ private MastershipService mastershipService;
+
+ @Override
+ public void init(UiConnection connection, ServiceDirectory directory) {
+ super.init(connection, directory);
+ deviceService = get(DeviceService.class);
+ mastershipService = get(MastershipService.class);
+ }
+
@Override
protected Collection<RequestHandler> createRequestHandlers() {
- return ImmutableSet.of(
- new DeviceTableDataRequestHandler()
- );
- }
-
- // Returns friendly name of the device from the annotations
- private static String deviceName(Device device) {
- String name = device.annotations().value(AnnotationKeys.NAME);
- return isNullOrEmpty(name) ? device.id().toString() : name;
- }
-
- // Returns the device protocol from annotations
- private static String deviceProtocol(Device device) {
- String protocol = device.annotations().value(PROTOCOL);
- return protocol != null ? protocol : "N/A";
+ return ImmutableSet.of(new DeviceTableDataRequestHandler());
}
// Handler for sample table requests
@@ -88,28 +85,31 @@
@Override
protected String noRowsMessage(ObjectNode payload) {
- return NO_ROWS_MESSAGE;
+ return RoadmUtil.NO_ROWS_MESSAGE;
}
@Override
protected void populateTable(TableModel tm, ObjectNode payload) {
- DeviceService ds = get(DeviceService.class);
- MastershipService ms = get(MastershipService.class);
- for (Device device : ds.getDevices(Device.Type.ROADM)) {
- populateRow(tm.addRow(), device, ds, ms);
+ for (Device device : deviceService.getDevices()) {
+ Type type = device.type();
+ if (type == Type.ROADM || type == Type.OPTICAL_AMPLIFIER || type == Type.FIBER_SWITCH) {
+ populateRow(tm.addRow(), device);
+ }
}
}
- private void populateRow(TableModel.Row row, Device device, DeviceService ds,
- MastershipService ms) {
- row.cell(ID, device.id().toString())
- .cell(FRIENDLY_NAME, deviceName(device))
- .cell(MASTER, ms.getMasterFor(device.id()))
- .cell(PORTS, ds.getPorts(device.id()).size())
+ private void populateRow(TableModel.Row row, Device device) {
+ DeviceId devId = device.id();
+ String id = devId.toString();
+ row.cell(ID, id)
+ .cell(NAME, RoadmUtil.getAnnotation(device.annotations(), AnnotationKeys.PORT_NAME, id))
+ .cell(TYPE, RoadmUtil.objectToString(device.type(), RoadmUtil.UNKNOWN))
+ .cell(MASTER, mastershipService.getMasterFor(devId))
+ .cell(PORTS, deviceService.getPorts(devId).size())
.cell(VENDOR, device.manufacturer())
.cell(HW_VERSION, device.hwVersion())
.cell(SW_VERSION, device.swVersion())
- .cell(PROTOCOL, deviceProtocol(device));
+ .cell(PROTOCOL, RoadmUtil.getAnnotation(device.annotations(), PROTOCOL));
}
}
}
diff --git a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmFlowViewMessageHandler.java b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmFlowViewMessageHandler.java
index 08e74f0..d0012d6 100644
--- a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmFlowViewMessageHandler.java
+++ b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmFlowViewMessageHandler.java
@@ -19,8 +19,11 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Range;
import org.onlab.osgi.ServiceDirectory;
+import org.onlab.util.Frequency;
+import org.onlab.util.Spectrum;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
import org.onosproject.net.OchSignal;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.FlowEntry;
@@ -42,6 +45,7 @@
import static org.onosproject.ui.JsonUtils.node;
import static org.onosproject.ui.JsonUtils.number;
+import static org.onosproject.net.Device.Type;
/**
* Table-View message handler for ROADM flow view.
@@ -60,9 +64,8 @@
private static final String ROADM_CREATE_FLOW_REQ = "roadmCreateFlowRequest";
private static final String ROADM_CREATE_FLOW_RESP = "roadmCreateFlowResponse";
- private static final String NO_ROWS_MESSAGE = "No items found";
-
- private static final String DEV_ID = "devId";
+ private static final String ROADM_SHOW_ITEMS_REQ = "roadmShowFlowItemsRequest";
+ private static final String ROADM_SHOW_ITEMS_RESP = "roadmShowFlowItemsResponse";
private static final String ID = "id";
private static final String FLOW_ID = "flowId";
@@ -80,28 +83,26 @@
private static final String CURRENT_POWER = "currentPower";
private static final String ATTENUATION = "attenuation";
private static final String HAS_ATTENUATION = "hasAttenuation";
+ private static final String CHANNEL_FREQUENCY = "channelFrequency";
private static final String[] COLUMN_IDS = {
ID, FLOW_ID, APP_ID, GROUP_ID, TABLE_ID, PRIORITY, TIMEOUT,
- PERMANENT, STATE, IN_PORT, OUT_PORT, CHANNEL_SPACING,
- CHANNEL_MULTIPLIER, CURRENT_POWER, ATTENUATION, HAS_ATTENUATION
+ PERMANENT, STATE, IN_PORT, OUT_PORT, CHANNEL_SPACING, CHANNEL_MULTIPLIER,
+ CHANNEL_FREQUENCY, CURRENT_POWER, ATTENUATION, HAS_ATTENUATION
};
- private static final String NA = "N/A";
- private static final String UNKNOWN = "Unknown";
-
- private static final long GHZ = 1_000_000_000L;
-
- private FlowRuleService flowRuleService;
private RoadmService roadmService;
+ private DeviceService deviceService;
+ private FlowRuleService flowRuleService;
private final Logger log = LoggerFactory.getLogger(getClass());
@Override
public void init(UiConnection connection, ServiceDirectory directory) {
super.init(connection, directory);
- flowRuleService = get(FlowRuleService.class);
roadmService = get(RoadmService.class);
+ deviceService = get(DeviceService.class);
+ flowRuleService = get(FlowRuleService.class);
}
@Override
@@ -110,7 +111,8 @@
new FlowTableDataRequestHandler(),
new SetAttenuationRequestHandler(),
new DeleteConnectionRequestHandler(),
- new CreateConnectionRequestHandler()
+ new CreateConnectionRequestHandler(),
+ new CreateShowItemsRequestHandler()
);
}
@@ -128,7 +130,7 @@
@Override
protected String noRowsMessage(ObjectNode payload) {
- return NO_ROWS_MESSAGE;
+ return RoadmUtil.NO_ROWS_MESSAGE;
}
@Override
@@ -140,8 +142,8 @@
@Override
protected void populateTable(TableModel tm, ObjectNode payload) {
- DeviceId deviceId = DeviceId.deviceId(string(payload, DEV_ID, "(none)"));
-
+ DeviceId deviceId = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
+ // Update flows
Iterable<FlowEntry> flowEntries = flowRuleService.getFlowEntries(deviceId);
for (FlowEntry flowEntry : flowEntries) {
populateRow(tm.addRow(), flowEntry, deviceId);
@@ -150,6 +152,17 @@
private void populateRow(TableModel.Row row, FlowEntry entry, DeviceId deviceId) {
ChannelData cd = ChannelData.fromFlow(entry);
+ String spacing = RoadmUtil.NA, multiplier = RoadmUtil.NA, channelFrequency = "";
+ OchSignal ochSignal = cd.ochSignal();
+ if (ochSignal != null) {
+ Frequency spacingFreq = ochSignal.channelSpacing().frequency();
+ spacing = RoadmUtil.asGHz(spacingFreq);
+ int spacingMult = ochSignal.spacingMultiplier();
+ multiplier = String.valueOf(spacingMult);
+ channelFrequency = String.format(" (%sGHz)",
+ RoadmUtil.asGHz(Spectrum.CENTER_FREQUENCY.add(spacingFreq.multiply(spacingMult))));
+ }
+
row.cell(ID, entry.id().value())
.cell(FLOW_ID, entry.id().value())
.cell(APP_ID, entry.appId())
@@ -159,52 +172,52 @@
.cell(STATE, entry.state().toString())
.cell(IN_PORT, cd.inPort().toLong())
.cell(OUT_PORT, cd.outPort().toLong())
- .cell(CHANNEL_SPACING, cd.ochSignal().channelSpacing().frequency().asHz() / GHZ)
- .cell(CHANNEL_MULTIPLIER, cd.ochSignal().spacingMultiplier())
+ .cell(CHANNEL_SPACING, spacing)
+ .cell(CHANNEL_MULTIPLIER, multiplier)
+ .cell(CHANNEL_FREQUENCY, channelFrequency)
.cell(CURRENT_POWER, getCurrentPower(deviceId, cd))
+ .cell(HAS_ATTENUATION, hasAttenuation(deviceId, cd))
.cell(ATTENUATION, getAttenuation(deviceId, cd));
}
private String getCurrentPower(DeviceId deviceId, ChannelData channelData) {
- Range<Long> range =
- roadmService.attenuationRange(deviceId,
- channelData.outPort(),
- channelData.ochSignal());
- if (range != null) {
- Long currentPower =
- roadmService.getCurrentChannelPower(deviceId,
- channelData.outPort(),
- channelData.ochSignal());
- if (currentPower != null) {
- return String.valueOf(currentPower);
- }
+ if (hasAttenuation(deviceId, channelData)) {
+ // report channel power if channel exists
+ Long currentPower = roadmService.getCurrentChannelPower(deviceId,
+ channelData.outPort(), channelData.ochSignal());
+ return RoadmUtil.objectToString(currentPower, RoadmUtil.UNKNOWN);
}
- return NA;
+ // otherwise, report port power
+ Type devType = deviceService.getDevice(deviceId).type();
+ PortNumber port = devType == Type.FIBER_SWITCH ? channelData.inPort() : channelData.outPort();
+ Long currentPower = roadmService.getCurrentPortPower(deviceId, port);
+ return RoadmUtil.objectToString(currentPower, RoadmUtil.UNKNOWN);
}
private String getAttenuation(DeviceId deviceId, ChannelData channelData) {
- Long attenuation =
- roadmService.getAttenuation(deviceId, channelData.outPort(),
- channelData.ochSignal());
- if (attenuation != null) {
- return String.valueOf(attenuation);
+ OchSignal signal = channelData.ochSignal();
+ if (signal == null) {
+ return RoadmUtil.NA;
}
- return UNKNOWN;
+ Long attenuation = roadmService.getAttenuation(deviceId, channelData.outPort(), signal);
+ return RoadmUtil.objectToString(attenuation, RoadmUtil.UNKNOWN);
+ }
+
+ private boolean hasAttenuation(DeviceId deviceId, ChannelData channelData) {
+ OchSignal signal = channelData.ochSignal();
+ if (signal == null) {
+ return false;
+ }
+ return roadmService.attenuationRange(deviceId, channelData.outPort(), signal) != null;
}
}
// Handler for setting attenuation
private final class SetAttenuationRequestHandler extends RequestHandler {
- // Keys for response message
- private static final String VALID = "valid";
- private static final String MESSAGE = "message";
-
// Error messages to display to user
- private static final String ATTENUATION_RANGE_MSG =
- "Attenuation must be in range %s.";
- private static final String NO_ATTENUATION_MSG =
- "Cannot set attenuation for this connection";
+ private static final String ATTENUATION_RANGE_MSG = "Attenuation must be in range %s.";
+ private static final String NO_ATTENUATION_MSG = "Cannot set attenuation for this connection";
private SetAttenuationRequestHandler() {
super(ROADM_SET_ATTENUATION_REQ);
@@ -212,36 +225,31 @@
@Override
public void process(ObjectNode payload) {
- DeviceId deviceId = DeviceId.deviceId(string(payload, DEV_ID, "(none)"));
+ DeviceId deviceId = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
FlowId flowId = FlowId.valueOf(number(payload, FLOW_ID));
- long attenuation = payload.get(ATTENUATION).asLong();
-
// Get connection information from the flow
FlowEntry entry = findFlow(deviceId, flowId);
if (entry == null) {
- log.error("Unable to find flow rule to set attenuation");
+ log.error("Unable to find flow rule to set attenuation for device {}", deviceId);
return;
}
- ChannelData cd = ChannelData.fromFlow(entry);
- Range<Long> range =
- roadmService.attenuationRange(deviceId, cd.outPort(),
- cd.ochSignal());
-
- boolean validAttenuation = (range != null && range.contains(attenuation));
+ ChannelData channelData = ChannelData.fromFlow(entry);
+ PortNumber port = channelData.outPort();
+ OchSignal signal = channelData.ochSignal();
+ Range<Long> range = roadmService.attenuationRange(deviceId, port, signal);
+ Long attenuation = payload.get(ATTENUATION).asLong();
+ boolean validAttenuation = range != null && range.contains(attenuation);
if (validAttenuation) {
- roadmService.setAttenuation(deviceId, cd.outPort(),
- cd.ochSignal(), attenuation);
+ roadmService.setAttenuation(deviceId, port, signal, attenuation);
}
-
ObjectNode rootNode = objectNode();
// Send back flowId so view can identify which callback function to use
rootNode.put(FLOW_ID, payload.get(FLOW_ID).asText());
- rootNode.put(VALID, validAttenuation);
- if (range != null) {
- rootNode.put(MESSAGE, String.format(ATTENUATION_RANGE_MSG,
- range.toString()));
+ rootNode.put(RoadmUtil.VALID, validAttenuation);
+ if (range == null) {
+ rootNode.put(RoadmUtil.MESSAGE, NO_ATTENUATION_MSG);
} else {
- rootNode.put(MESSAGE, NO_ATTENUATION_MSG);
+ rootNode.put(RoadmUtil.MESSAGE, String.format(ATTENUATION_RANGE_MSG, range.toString()));
}
sendMessage(ROADM_SET_ATTENUATION_RESP, rootNode);
}
@@ -264,7 +272,7 @@
@Override
public void process(ObjectNode payload) {
- DeviceId deviceId = DeviceId.deviceId(string(payload, DEV_ID, "(none)"));
+ DeviceId deviceId = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
FlowId flowId = FlowId.valueOf(payload.get(ID).asLong());
roadmService.removeConnection(deviceId, flowId);
}
@@ -276,7 +284,6 @@
// Keys to load from JSON
private static final String FORM_DATA = "formData";
private static final String CHANNEL_SPACING_INDEX = "index";
- private static final String INCLUDE_ATTENUATION = "includeAttenuation";
// Keys for validation results
private static final String CONNECTION = "connection";
@@ -285,20 +292,11 @@
// Error messages to display to user
private static final String IN_PORT_ERR_MSG = "Invalid input port.";
private static final String OUT_PORT_ERR_MSG = "Invalid output port.";
- private static final String CONNECTION_ERR_MSG =
- "Invalid connection from input port to output port.";
- private static final String CHANNEL_SPACING_ERR_MSG =
- "Channel spacing not supported.";
- private static final String CHANNEL_ERR_MSG =
- "Channel index must be in range %s.";
- private static final String CHANNEL_AVAILABLE_ERR_MSG =
- "Channel is already being used.";
- private static final String ATTENUATION_ERR_MSG =
- "Attenuation must be in range %s.";
-
- // Keys for validation object
- private static final String VALID = "valid";
- private static final String MESSAGE = "message";
+ private static final String CONNECTION_ERR_MSG = "Invalid connection from input port to output port.";
+ private static final String CHANNEL_SPACING_ERR_MSG = "Channel spacing not supported.";
+ private static final String CHANNEL_ERR_MSG = "Channel index must be in range %s.";
+ private static final String CHANNEL_AVAILABLE_ERR_MSG = "Channel is already being used.";
+ private static final String ATTENUATION_ERR_MSG = "Attenuation must be in range %s.";
private CreateConnectionRequestHandler() {
super(ROADM_CREATE_FLOW_REQ);
@@ -306,7 +304,7 @@
@Override
public void process(ObjectNode payload) {
- DeviceId did = DeviceId.deviceId(string(payload, DEV_ID, "(none)"));
+ DeviceId did = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
ObjectNode flowNode = node(payload, FORM_DATA);
int priority = (int) number(flowNode, PRIORITY);
boolean permanent = bool(flowNode, PERMANENT);
@@ -314,13 +312,12 @@
PortNumber inPort = PortNumber.portNumber(number(flowNode, IN_PORT));
PortNumber outPort = PortNumber.portNumber(number(flowNode, OUT_PORT));
ObjectNode chNode = node(flowNode, CHANNEL_SPACING);
- ChannelSpacing spacing =
- channelSpacing((int) number(chNode, CHANNEL_SPACING_INDEX));
+ ChannelSpacing spacing = channelSpacing((int) number(chNode, CHANNEL_SPACING_INDEX));
int multiplier = (int) number(flowNode, CHANNEL_MULTIPLIER);
OchSignal och = OchSignal.newDwdmSlot(spacing, multiplier);
- boolean includeAttenuation = bool(flowNode, INCLUDE_ATTENUATION);
long att = number(flowNode, ATTENUATION);
+ boolean showItems = deviceService.getDevice(did).type() != Type.FIBER_SWITCH;
boolean validInPort = roadmService.validInputPort(did, inPort);
boolean validOutPort = roadmService.validOutputPort(did, outPort);
boolean validConnect = roadmService.validConnection(did, inPort, outPort);
@@ -329,59 +326,51 @@
boolean channelAvailable = roadmService.channelAvailable(did, och);
boolean validAttenuation = roadmService.attenuationInRange(did, outPort, att);
- if (validConnect && validChannel && channelAvailable) {
- if (includeAttenuation && validAttenuation) {
- roadmService.createConnection(did, priority, permanent,
- timeout, inPort, outPort,
- och, att);
- } else if (!includeAttenuation) {
- roadmService.createConnection(did, priority, permanent,
- timeout, inPort, outPort,
- och);
- }
- }
-
- // Construct error for channel
- String channelMessage = "Invalid channel";
- if (!validChannel) {
- Set<OchSignal> lambdas = roadmService.queryLambdas(did, outPort);
- if (lambdas != null) {
- Range<Integer> range = channelRange(lambdas);
- if (range.contains(och.spacingMultiplier())) {
- // Channel spacing error
- validSpacing = false;
+ if (validConnect) {
+ if (validChannel && channelAvailable) {
+ if (validAttenuation) {
+ roadmService.createConnection(did, priority, permanent, timeout, inPort, outPort, och, att);
} else {
- channelMessage = String.format(CHANNEL_ERR_MSG, range.toString());
+ roadmService.createConnection(did, priority, permanent, timeout, inPort, outPort, och);
}
}
}
- // Construct error for attenuation
+ String channelMessage = "Invalid channel";
String attenuationMessage = "Invalid attenuation";
- if (!validAttenuation) {
- Range<Long> range =
- roadmService.attenuationRange(did, outPort, och);
- if (range != null) {
- attenuationMessage =
- String.format(ATTENUATION_ERR_MSG, range.toString());
+ if (showItems) {
+ // Construct error for channel
+ if (!validChannel) {
+ Set<OchSignal> lambdas = roadmService.queryLambdas(did, outPort);
+ if (lambdas != null) {
+ Range<Integer> range = channelRange(lambdas);
+ if (range.contains(och.spacingMultiplier())) {
+ // Channel spacing error
+ validSpacing = false;
+ } else {
+ channelMessage = String.format(CHANNEL_ERR_MSG, range.toString());
+ }
+ }
+ }
+
+ // Construct error for attenuation
+ if (!validAttenuation) {
+ Range<Long> range = roadmService.attenuationRange(did, outPort, och);
+ if (range != null) {
+ attenuationMessage = String.format(ATTENUATION_ERR_MSG, range.toString());
+ }
}
}
// Build response
ObjectNode node = objectNode();
-
node.set(IN_PORT, validationObject(validInPort, IN_PORT_ERR_MSG));
node.set(OUT_PORT, validationObject(validOutPort, OUT_PORT_ERR_MSG));
node.set(CONNECTION, validationObject(validConnect, CONNECTION_ERR_MSG));
- node.set(CHANNEL_SPACING, validationObject(validChannel || validSpacing,
- CHANNEL_SPACING_ERR_MSG));
- node.set(CHANNEL_MULTIPLIER, validationObject(validChannel || !validSpacing,
- channelMessage));
- node.set(CHANNEL_AVAILABLE, validationObject(!validChannel || channelAvailable,
- CHANNEL_AVAILABLE_ERR_MSG));
+ node.set(CHANNEL_SPACING, validationObject(validChannel || validSpacing, CHANNEL_SPACING_ERR_MSG));
+ node.set(CHANNEL_MULTIPLIER, validationObject(validChannel || !validSpacing, channelMessage));
+ node.set(CHANNEL_AVAILABLE, validationObject(!validChannel || channelAvailable, CHANNEL_AVAILABLE_ERR_MSG));
node.set(ATTENUATION, validationObject(validAttenuation, attenuationMessage));
- node.put(INCLUDE_ATTENUATION, includeAttenuation);
-
sendMessage(ROADM_CREATE_FLOW_RESP, node);
}
@@ -401,10 +390,10 @@
// Construct validation object to return to the view
private ObjectNode validationObject(boolean result, String message) {
ObjectNode node = objectNode();
- node.put(VALID, result);
+ node.put(RoadmUtil.VALID, result);
if (!result) {
// return error message to display if validation failed
- node.put(MESSAGE, message);
+ node.put(RoadmUtil.MESSAGE, message);
}
return node;
}
@@ -418,4 +407,23 @@
return Range.closed(minOch.spacingMultiplier(), maxOch.spacingMultiplier());
}
}
+
+ private final class CreateShowItemsRequestHandler extends RequestHandler {
+ private static final String SHOW_CHANNEL = "showChannel";
+ private static final String SHOW_ATTENUATION = "showAttenuation";
+ private CreateShowItemsRequestHandler() {
+ super(ROADM_SHOW_ITEMS_REQ);
+ }
+
+ @Override
+ public void process(ObjectNode payload) {
+ DeviceId did = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
+ Type devType = deviceService.getDevice(did).type();
+ // Build response
+ ObjectNode node = objectNode();
+ node.put(SHOW_CHANNEL, devType != Type.FIBER_SWITCH);
+ node.put(SHOW_ATTENUATION, devType == Type.ROADM);
+ sendMessage(ROADM_SHOW_ITEMS_RESP, node);
+ }
+ }
}
diff --git a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java
index 011c393..a0cace9 100644
--- a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java
+++ b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java
@@ -25,6 +25,7 @@
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Direction;
@@ -34,6 +35,9 @@
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.LambdaQuery;
import org.onosproject.net.behaviour.PowerConfig;
+import org.onosproject.net.behaviour.protection.ProtectionConfigBehaviour;
+import org.onosproject.net.behaviour.protection.ProtectedTransportEndpointState;
+import org.onosproject.net.behaviour.protection.TransportEndpointState;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
@@ -48,15 +52,21 @@
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.optical.OpticalAnnotations;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
+
import static com.google.common.base.Preconditions.checkNotNull;
/**
@@ -101,94 +111,46 @@
log.info("Stopped");
}
- private PowerConfig<Object> getPowerConfig(DeviceId deviceId) {
- Device device = deviceService.getDevice(deviceId);
- if (device != null && device.is(PowerConfig.class)) {
- return device.as(PowerConfig.class);
- }
- log.warn("Unable to load PowerConfig for {}", deviceId);
- return null;
- }
-
- private LambdaQuery getLambdaQuery(DeviceId deviceId) {
- Device device = deviceService.getDevice(deviceId);
- if (device != null && device.is(LambdaQuery.class)) {
- return device.as(LambdaQuery.class);
- }
- return null;
- }
-
- private void initDevices() {
- for (Device device : deviceService.getDevices(Device.Type.ROADM)) {
- initDevice(device.id());
- setAllInitialTargetPortPowers(device.id());
- }
- }
-
- // Initialize RoadmStore for a device to support target power
- private void initDevice(DeviceId deviceId) {
- if (!roadmStore.deviceAvailable(deviceId)) {
- roadmStore.addDevice(deviceId);
- }
- log.info("Initialized device {}", deviceId);
- }
-
- // Sets the target port powers for a port on a device
- // Attempts to read target powers from store. If no value is found then
- // default value is used instead.
- private void setInitialTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
- PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
- if (powerConfig == null) {
- log.warn("Unable to set default initial powers for port {} on device {}",
- portNumber, deviceId);
+ @Override
+ public void setProtectionSwitchWorkingPath(DeviceId deviceId, int index) {
+ checkNotNull(deviceId);
+ ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
+ if (behaviour == null) {
return;
}
-
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
- if (!range.isPresent()) {
- log.warn("No target power range found for port {} on device {}",
- portNumber, deviceId);
+ Map<ConnectPoint, ProtectedTransportEndpointState> map = getProtectionSwitchStates(behaviour);
+ if (map == null) {
+ log.warn("Failed to get protected transport endpoint state in device {}", deviceId);
return;
}
-
- Long power = roadmStore.getTargetPower(deviceId, portNumber);
- if (power == null) {
- // Set default to middle of the range
- power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
- roadmStore.setTargetPower(deviceId, portNumber, power);
+ if (map.isEmpty()) {
+ log.warn("No protected transport endpoint state found in device {}", deviceId);
+ return;
}
- powerConfig.setTargetPower(portNumber, Direction.ALL, power);
+ behaviour.switchWorkingPath(map.keySet().toArray(new ConnectPoint[0])[0], index);
}
- // Sets the target port powers for each each port on a device
- // Attempts to read target powers from store. If no value is found then
- // default value is used instead
- private void setAllInitialTargetPortPowers(DeviceId deviceId) {
- PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
- if (powerConfig == null) {
- log.warn("Unable to set default initial powers for device {}",
- deviceId);
- return;
+ @Override
+ public String getProtectionSwitchPortState(DeviceId deviceId, PortNumber portNumber) {
+ checkNotNull(deviceId);
+ ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
+ if (behaviour == null) {
+ return null;
}
-
- List<Port> ports = deviceService.getPorts(deviceId);
- for (Port port : ports) {
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(port.number(), Direction.ALL);
- if (range.isPresent()) {
- Long power = roadmStore.getTargetPower(deviceId, port.number());
- if (power == null) {
- // Set default to middle of the range
- power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
- roadmStore.setTargetPower(deviceId, port.number(), power);
+ Map<ConnectPoint, ProtectedTransportEndpointState> map = getProtectionSwitchStates(behaviour);
+ if (map == null) {
+ log.warn("Failed to get protected transport endpoint state in device {}", deviceId);
+ return null;
+ }
+ for (ProtectedTransportEndpointState state : map.values()) {
+ for (TransportEndpointState element : state.pathStates()) {
+ if (element.description().output().connectPoint().port().equals(portNumber)) {
+ return element.attributes().get(OpticalAnnotations.INPUT_PORT_STATUS);
}
- powerConfig.setTargetPower(port.number(), Direction.ALL, power);
- } else {
- log.warn("No target power range found for port {} on device {}",
- port.number(), deviceId);
}
}
+ log.warn("Unable to get port status, device: {}, port: {}", deviceId, portNumber);
+ return null;
}
@Override
@@ -208,8 +170,7 @@
public Long getTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
checkNotNull(deviceId);
checkNotNull(portNumber);
- // getTargetPortPower is not yet implemented in PowerConfig so we
- // access store instead
+ // getTargetPortPower is not yet implemented in PowerConfig so we access store instead
return roadmStore.getTargetPower(deviceId, portNumber);
}
@@ -229,15 +190,13 @@
}
@Override
- public Long getAttenuation(DeviceId deviceId, PortNumber portNumber,
- OchSignal ochSignal) {
+ public Long getAttenuation(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
checkNotNull(deviceId);
checkNotNull(portNumber);
checkNotNull(ochSignal);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Long> attenuation =
- powerConfig.getTargetPower(portNumber, ochSignal);
+ Optional<Long> attenuation = powerConfig.getTargetPower(portNumber, ochSignal);
if (attenuation.isPresent()) {
return attenuation.get();
}
@@ -251,8 +210,7 @@
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Long> currentPower =
- powerConfig.currentPower(portNumber, Direction.ALL);
+ Optional<Long> currentPower = powerConfig.currentPower(portNumber, Direction.ALL);
if (currentPower.isPresent()) {
return currentPower.get();
}
@@ -261,15 +219,13 @@
}
@Override
- public Long getCurrentChannelPower(DeviceId deviceId, PortNumber portNumber,
- OchSignal ochSignal) {
+ public Long getCurrentChannelPower(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
checkNotNull(deviceId);
checkNotNull(portNumber);
checkNotNull(ochSignal);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Long> currentPower =
- powerConfig.currentPower(portNumber, ochSignal);
+ Optional<Long> currentPower = powerConfig.currentPower(portNumber, ochSignal);
if (currentPower.isPresent()) {
return currentPower.get();
}
@@ -290,31 +246,31 @@
@Override
public FlowId createConnection(DeviceId deviceId, int priority, boolean isPermanent,
- int timeout, PortNumber inPort, PortNumber outPort,
- OchSignal ochSignal) {
+ int timeout, PortNumber inPort, PortNumber outPort, OchSignal ochSignal) {
checkNotNull(deviceId);
checkNotNull(inPort);
checkNotNull(outPort);
- FlowRule.Builder flowBuilder = new DefaultFlowRule.Builder();
- flowBuilder.fromApp(appId);
- flowBuilder.withPriority(priority);
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .add(Criteria.matchInPort(inPort))
+ .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
+ .add(Criteria.matchLambda(ochSignal))
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .add(Instructions.createOutput(outPort))
+ .build();
+
+ FlowRule.Builder flowBuilder = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .fromApp(appId)
+ .withPriority(priority)
+ .withSelector(selector)
+ .withTreatment(treatment);
if (isPermanent) {
flowBuilder.makePermanent();
} else {
flowBuilder.makeTemporary(timeout);
}
- flowBuilder.forDevice(deviceId);
-
- TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
- selectorBuilder.add(Criteria.matchInPort(inPort));
- selectorBuilder.add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID));
- selectorBuilder.add(Criteria.matchLambda(ochSignal));
- flowBuilder.withSelector(selectorBuilder.build());
-
- TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
- treatmentBuilder.add(Instructions.createOutput(outPort));
- flowBuilder.withTreatment(treatmentBuilder.build());
FlowRule flowRule = flowBuilder.build();
flowRuleService.applyFlowRules(flowRule);
@@ -332,26 +288,11 @@
checkNotNull(deviceId);
checkNotNull(inPort);
checkNotNull(outPort);
- FlowId flowId = createConnection(deviceId, priority, isPermanent,
- timeout, inPort, outPort, ochSignal);
+ FlowId flowId = createConnection(deviceId, priority, isPermanent, timeout, inPort, outPort, ochSignal);
delayedSetAttenuation(deviceId, outPort, ochSignal, attenuation);
return flowId;
}
- // Delay the call to setTargetPower because the flow may not be in the store yet
- private void delayedSetAttenuation(DeviceId deviceId, PortNumber outPort,
- OchSignal ochSignal, long attenuation) {
- Runnable setAtt = () -> {
- try {
- TimeUnit.SECONDS.sleep(1);
- } catch (InterruptedException e) {
- log.warn("Thread interrupted. Setting attenuation early.");
- }
- setAttenuation(deviceId, outPort, ochSignal, attenuation);
- };
- new Thread(setAtt).start();
- }
-
@Override
public void removeConnection(DeviceId deviceId, FlowId flowId) {
checkNotNull(deviceId);
@@ -371,37 +312,32 @@
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
return range.isPresent();
}
return false;
}
@Override
- public boolean portTargetPowerInRange(DeviceId deviceId, PortNumber portNumber,
- long power) {
+ public boolean portTargetPowerInRange(DeviceId deviceId, PortNumber portNumber, long power) {
checkNotNull(deviceId);
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
return range.isPresent() && range.get().contains(power);
}
return false;
}
@Override
- public boolean attenuationInRange(DeviceId deviceId, PortNumber outPort,
- long att) {
+ public boolean attenuationInRange(DeviceId deviceId, PortNumber outPort, long att) {
checkNotNull(deviceId);
checkNotNull(outPort);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
OchSignal stubOch = OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 0);
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(outPort, stubOch);
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(outPort, stubOch);
return range.isPresent() && range.get().contains(att);
}
return false;
@@ -413,8 +349,7 @@
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getInputPowerRange(portNumber, Direction.ALL);
+ Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
return range.isPresent();
}
return false;
@@ -426,10 +361,10 @@
}
@Override
- public boolean validChannel(DeviceId deviceId, PortNumber portNumber,
- OchSignal ochSignal) {
+ public boolean validChannel(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
checkNotNull(deviceId);
checkNotNull(portNumber);
+ checkNotNull(ochSignal);
LambdaQuery lambdaQuery = getLambdaQuery(deviceId);
if (lambdaQuery != null) {
Set<OchSignal> channels = lambdaQuery.queryLambdas(portNumber);
@@ -451,8 +386,7 @@
}
@Override
- public boolean validConnection(DeviceId deviceId, PortNumber inPort,
- PortNumber outPort) {
+ public boolean validConnection(DeviceId deviceId, PortNumber inPort, PortNumber outPort) {
checkNotNull(deviceId);
checkNotNull(inPort);
checkNotNull(outPort);
@@ -465,8 +399,7 @@
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
if (range.isPresent()) {
return range.get();
}
@@ -475,15 +408,13 @@
}
@Override
- public Range<Long> attenuationRange(DeviceId deviceId, PortNumber portNumber,
- OchSignal ochSignal) {
+ public Range<Long> attenuationRange(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
checkNotNull(deviceId);
checkNotNull(portNumber);
checkNotNull(ochSignal);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getTargetPowerRange(portNumber, ochSignal);
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, ochSignal);
if (range.isPresent()) {
return range.get();
}
@@ -497,8 +428,7 @@
checkNotNull(portNumber);
PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
if (powerConfig != null) {
- Optional<Range<Long>> range =
- powerConfig.getInputPowerRange(portNumber, Direction.ALL);
+ Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
if (range.isPresent()) {
return range.get();
}
@@ -506,6 +436,137 @@
return null;
}
+ private PowerConfig<Object> getPowerConfig(DeviceId deviceId) {
+ Device device = deviceService.getDevice(deviceId);
+ if (device != null && device.is(PowerConfig.class)) {
+ return device.as(PowerConfig.class);
+ }
+ log.warn("Unable to load PowerConfig for {}", deviceId);
+ return null;
+ }
+
+ private LambdaQuery getLambdaQuery(DeviceId deviceId) {
+ Device device = deviceService.getDevice(deviceId);
+ if (device != null && device.is(LambdaQuery.class)) {
+ return device.as(LambdaQuery.class);
+ }
+ log.warn("Unable to load LambdaQuery for {}", deviceId);
+ return null;
+ }
+
+ private ProtectionConfigBehaviour getProtectionConfig(DeviceId deviceId) {
+ Device device = deviceService.getDevice(deviceId);
+ if (device != null && device.is(ProtectionConfigBehaviour.class)) {
+ return device.as(ProtectionConfigBehaviour.class);
+ }
+ log.warn("Unable to load ProtectionConfigBehaviour for {}", deviceId);
+ return null;
+ }
+
+ // Initialize all devices
+ private void initDevices() {
+ for (Device device : deviceService.getDevices(Device.Type.ROADM)) {
+ initDevice(device.id());
+ //FIXME
+ // As roadm application is a optional tool for now.
+ // The target power initialization will be enhanced later,
+ // hopefully using an formal optical subsystem.
+ // setAllInitialTargetPortPowers(device.id());
+ }
+ }
+
+ // Initialize RoadmStore for a device to support target power
+ private void initDevice(DeviceId deviceId) {
+ if (!roadmStore.deviceAvailable(deviceId)) {
+ roadmStore.addDevice(deviceId);
+ }
+ log.info("Initialized device {}", deviceId);
+ }
+
+ // Sets the target port powers for a port on a device
+ // Attempts to read target powers from store. If no value is found then
+ // default value is used instead.
+ private void setInitialTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
+ PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
+ if (powerConfig == null) {
+ log.warn("Unable to set default initial powers for port {} on device {}", portNumber, deviceId);
+ return;
+ }
+
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
+ if (!range.isPresent()) {
+ log.warn("No target power range found for port {} on device {}", portNumber, deviceId);
+ return;
+ }
+
+ Long power = roadmStore.getTargetPower(deviceId, portNumber);
+ if (power == null) {
+ // Set default to middle of the range
+ power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
+ roadmStore.setTargetPower(deviceId, portNumber, power);
+ }
+ powerConfig.setTargetPower(portNumber, Direction.ALL, power);
+ }
+
+ // Sets the target port powers for each each port on a device
+ // Attempts to read target powers from store. If no value is found then
+ // default value is used instead
+ private void setAllInitialTargetPortPowers(DeviceId deviceId) {
+ PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
+ if (powerConfig == null) {
+ log.warn("Unable to set default initial powers for device {}", deviceId);
+ return;
+ }
+
+ List<Port> ports = deviceService.getPorts(deviceId);
+ for (Port port : ports) {
+ Optional<Range<Long>> range = powerConfig.getTargetPowerRange(port.number(), Direction.ALL);
+ if (range.isPresent()) {
+ Long power = roadmStore.getTargetPower(deviceId, port.number());
+ if (power == null) {
+ // Set default to middle of the range
+ power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
+ roadmStore.setTargetPower(deviceId, port.number(), power);
+ }
+ powerConfig.setTargetPower(port.number(), Direction.ALL, power);
+ } else {
+ log.warn("No target power range found for port {} on device {}", port.number(), deviceId);
+ }
+ }
+ }
+
+ // Delay the call to setTargetPower because the flow may not be in the store yet
+ private void delayedSetAttenuation(DeviceId deviceId, PortNumber outPort,
+ OchSignal ochSignal, long attenuation) {
+ Runnable setAtt = () -> {
+ try {
+ TimeUnit.SECONDS.sleep(1);
+ } catch (InterruptedException e) {
+ log.warn("Thread interrupted. Setting attenuation early.");
+ }
+ setAttenuation(deviceId, outPort, ochSignal, attenuation);
+ };
+ new Thread(setAtt).start();
+ }
+
+ // get protection endpoint states
+ private Map<ConnectPoint, ProtectedTransportEndpointState> getProtectionSwitchStates(
+ ProtectionConfigBehaviour behaviour) {
+ CompletableFuture<Map<ConnectPoint, ProtectedTransportEndpointState>>
+ states = behaviour.getProtectionEndpointStates();
+ Map<ConnectPoint, ProtectedTransportEndpointState> map;
+ try {
+ map = states.get();
+ } catch (InterruptedException e1) {
+ log.error("Interrupted.", e1);
+ return null;
+ } catch (ExecutionException e1) {
+ log.error("Exception caught.", e1);
+ return null;
+ }
+ return map;
+ }
+
// Listens to device events.
private class InternalDeviceListener implements DeviceListener {
@Override
@@ -519,7 +580,11 @@
break;
case PORT_ADDED:
case PORT_UPDATED:
- setInitialTargetPortPower(device.id(), deviceEvent.port().number());
+ //FIXME
+ // As roadm application is a optional tool for now.
+ // The target power initialization will be enhanced later,
+ // hopefully using an formal optical subsystem.
+ // setInitialTargetPortPower(device.id(), deviceEvent.port().number());
break;
default:
break;
diff --git a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java
index 81fb581..2aa80f7 100644
--- a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java
+++ b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java
@@ -19,12 +19,13 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Range;
import org.onlab.osgi.ServiceDirectory;
+import org.onlab.util.Frequency;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DeviceId;
-import org.onosproject.net.optical.OpticalAnnotations;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.OchSignal;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
-import org.onosproject.net.device.DeviceService;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
@@ -34,7 +35,12 @@
import org.slf4j.LoggerFactory;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
+import java.util.Set;
+
+import static org.onosproject.net.Device.Type;
/**
* Table-View message handler for ROADM port view.
@@ -44,17 +50,16 @@
private static final String ROADM_PORT_DATA_REQ = "roadmPortDataRequest";
private static final String ROADM_PORT_DATA_RESP = "roadmPortDataResponse";
private static final String ROADM_PORTS = "roadmPorts";
-
private static final String ROADM_SET_TARGET_POWER_REQ = "roadmSetTargetPowerRequest";
private static final String ROADM_SET_TARGET_POWER_RESP = "roadmSetTargetPowerResponse";
-
- private static final String NO_ROWS_MESSAGE = "No items found";
-
- private static final String DEV_ID = "devId";
+ private static final String ROADM_SHOW_ITEMS_REQ = "roadmShowPortItemsRequest";
+ private static final String ROADM_SHOW_ITEMS_RESP = "roadmShowPortItemsResponse";
+ private static final String ROADM_SET_OPS_MODE_REQ = "roadmSetOpsModeRequest";
+ private static final String ROADM_SET_OPS_MODE_RESP = "roadmSetOpsModeResponse";
private static final String ID = "id";
- private static final String TYPE = "type";
private static final String NAME = "name";
+ private static final String TYPE = "type";
private static final String ENABLED = "enabled";
private static final String MIN_FREQ = "minFreq";
private static final String MAX_FREQ = "maxFreq";
@@ -63,53 +68,32 @@
private static final String CURRENT_POWER = "currentPower";
private static final String TARGET_POWER = "targetPower";
private static final String HAS_TARGET_POWER = "hasTargetPower";
+ private static final String SERVICE_STATE = "serviceState";
private static final String[] COLUMN_IDS = {
ID, TYPE, NAME, ENABLED, MIN_FREQ, MAX_FREQ, GRID, INPUT_POWER_RANGE,
- CURRENT_POWER, TARGET_POWER, HAS_TARGET_POWER,
+ CURRENT_POWER, SERVICE_STATE, TARGET_POWER, HAS_TARGET_POWER
};
- private static final String NA = "N/A";
- private static final String UNKNOWN = "Unknown";
-
- private static final long GHZ = 1_000_000_000L;
- private static final long THZ = 1_000_000_000_000L;
-
- private DeviceService deviceService;
private RoadmService roadmService;
+ private DeviceService deviceService;
private final Logger log = LoggerFactory.getLogger(getClass());
@Override
public void init(UiConnection connection, ServiceDirectory directory) {
super.init(connection, directory);
- deviceService = get(DeviceService.class);
roadmService = get(RoadmService.class);
+ deviceService = get(DeviceService.class);
}
@Override
protected Collection<RequestHandler> createRequestHandlers() {
- return ImmutableSet.of(
- new PortTableDataRequestHandler(),
- new SetTargetPowerRequestHandler()
- );
- }
-
- private String asGHz(String value) {
- return String.valueOf(Double.valueOf(value) / GHZ);
- }
-
- private String asTHz(String value) {
- return String.valueOf(Double.valueOf(value) / THZ);
- }
-
- private String annotation(Port port, String key, String defaultValue) {
- String value = port.annotations().value(key);
- return value != null ? value : defaultValue;
- }
-
- private String annotation(Port port, String key) {
- return annotation(port, key, NA);
+ return ImmutableSet.of(new PortTableDataRequestHandler(),
+ new SetTargetPowerRequestHandler(),
+ new CreateShowItemsRequestHandler(),
+ new CreateOpsModeSetRequestHandler()
+ );
}
// Handler for sample table requests
@@ -126,13 +110,12 @@
@Override
protected String noRowsMessage(ObjectNode payload) {
- return NO_ROWS_MESSAGE;
+ return RoadmUtil.NO_ROWS_MESSAGE;
}
@Override
protected void populateTable(TableModel tm, ObjectNode payload) {
- DeviceId deviceId = DeviceId.deviceId(string(payload, DEV_ID, "(none)"));
-
+ DeviceId deviceId = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
if (deviceService.isAvailable(deviceId)) {
List<Port> ports = deviceService.getPorts(deviceId);
for (Port port : ports) {
@@ -142,53 +125,65 @@
}
private void populateRow(TableModel.Row row, Port port, DeviceId deviceId) {
- row.cell(ID, port.number().toLong())
+ PortNumber portNum = port.number();
+ getFrequencyLimit(deviceId, portNum);
+ row.cell(ID, portNum.toLong())
.cell(TYPE, port.type())
.cell(ENABLED, port.isEnabled())
- .cell(NAME, annotation(port, AnnotationKeys.PORT_NAME))
- .cell(MIN_FREQ, asTHz(annotation(port, OpticalAnnotations.MIN_FREQ_HZ)))
- .cell(MAX_FREQ, asTHz(annotation(port, OpticalAnnotations.MAX_FREQ_HZ)))
- .cell(GRID, asGHz(annotation(port, OpticalAnnotations.GRID_HZ)))
- .cell(INPUT_POWER_RANGE, getInputPowerRange(deviceId, port.number()))
- .cell(CURRENT_POWER, getCurrentPower(deviceId, port.number()))
- .cell(TARGET_POWER, getTargetPower(deviceId, port.number()))
- .cell(HAS_TARGET_POWER, roadmService.hasPortTargetPower(deviceId, port.number()));
+ .cell(NAME, RoadmUtil.getAnnotation(port.annotations(), AnnotationKeys.PORT_NAME))
+ .cell(MIN_FREQ, RoadmUtil.asTHz(minFreq))
+ .cell(MAX_FREQ, RoadmUtil.asTHz(maxFreq))
+ .cell(GRID, RoadmUtil.asGHz(channelSpacing))
+ .cell(INPUT_POWER_RANGE, getInputPowerRange(deviceId, portNum))
+ .cell(CURRENT_POWER, getCurrentPower(deviceId, portNum))
+ .cell(SERVICE_STATE, getPortServiceState(deviceId, portNum))
+ .cell(TARGET_POWER, getTargetPower(deviceId, portNum))
+ .cell(HAS_TARGET_POWER, roadmService.hasPortTargetPower(deviceId, portNum));
+ }
+
+ private String getPortServiceState(DeviceId deviceId, PortNumber portNumber) {
+ return RoadmUtil.defaultString(
+ roadmService.getProtectionSwitchPortState(deviceId, portNumber),
+ RoadmUtil.UNKNOWN);
+ }
+
+ private Frequency minFreq = null, maxFreq = null, channelSpacing = null;
+ // Gets min frequency, max frequency, channel spacing
+ private void getFrequencyLimit(DeviceId deviceId, PortNumber portNumber) {
+ Set<OchSignal> signals = roadmService.queryLambdas(deviceId, portNumber);
+ if (signals.isEmpty()) {
+ return;
+ }
+ Comparator<OchSignal> compare =
+ (OchSignal a, OchSignal b) -> a.spacingMultiplier() - b.spacingMultiplier();
+ OchSignal minOch = Collections.min(signals, compare);
+ OchSignal maxOch = Collections.max(signals, compare);
+ minFreq = minOch.centralFrequency();
+ maxFreq = maxOch.centralFrequency();
+ channelSpacing = minOch.channelSpacing().frequency();
}
// Returns the input power range as a string, N/A if the port is not an
// input port
private String getInputPowerRange(DeviceId deviceId, PortNumber portNumber) {
- Range<Long> range =
- roadmService.inputPortPowerRange(deviceId, portNumber);
- if (range != null) {
- return range.toString();
- }
- return NA;
+ Range<Long> range = roadmService.inputPortPowerRange(deviceId, portNumber);
+ return RoadmUtil.objectToString(range, RoadmUtil.NA);
}
// Returns the current power as a string, Unknown if no value can be found.
private String getCurrentPower(DeviceId deviceId, PortNumber portNumber) {
- Long currentPower =
- roadmService.getCurrentPortPower(deviceId, portNumber);
- if (currentPower != null) {
- return String.valueOf(currentPower);
- }
- return UNKNOWN;
+ Long currentPower = roadmService.getCurrentPortPower(deviceId, portNumber);
+ return RoadmUtil.objectToString(currentPower, RoadmUtil.UNKNOWN);
}
// Returns target power as a string, Unknown if target power is expected but
// cannot be found, N/A if port does not have configurable target power
private String getTargetPower(DeviceId deviceId, PortNumber portNumber) {
- if (roadmService.hasPortTargetPower(deviceId, portNumber)) {
- Long targetPower =
- roadmService.getTargetPortPower(deviceId, portNumber);
- if (targetPower != null) {
- return String.valueOf(targetPower);
- } else {
- return UNKNOWN;
- }
+ if (!roadmService.hasPortTargetPower(deviceId, portNumber)) {
+ return RoadmUtil.NA;
}
- return NA;
+ Long targetPower = roadmService.getTargetPortPower(deviceId, portNumber);
+ return RoadmUtil.objectToString(targetPower, RoadmUtil.UNKNOWN);
}
}
@@ -196,9 +191,6 @@
// Handler for setting port target power
private final class SetTargetPowerRequestHandler extends RequestHandler {
- private static final String VALID = "valid";
- private static final String MESSAGE = "message";
-
private static final String TARGET_POWER_ERR_MSG = "Target power range is %s.";
private SetTargetPowerRequestHandler() {
@@ -207,29 +199,78 @@
@Override
public void process(ObjectNode payload) {
- DeviceId deviceId = DeviceId.deviceId(string(payload, DEV_ID, "(none)"));
+ DeviceId deviceId = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
PortNumber portNumber = PortNumber.portNumber(payload.get(ID).asLong());
- long targetPower = payload.get(TARGET_POWER).asLong();
- boolean validTargetPower;
-
- Range<Long> range =
- roadmService.targetPortPowerRange(deviceId, portNumber);
- if (range != null) {
- validTargetPower = range.contains(targetPower);
-
- if (validTargetPower) {
- roadmService.setTargetPortPower(deviceId, portNumber, targetPower);
- }
-
- ObjectNode rootNode = objectNode();
- rootNode.put(ID, payload.get(ID).asText());
- rootNode.put(VALID, validTargetPower);
- rootNode.put(MESSAGE, String.format(TARGET_POWER_ERR_MSG, range.toString()));
- sendMessage(ROADM_SET_TARGET_POWER_RESP, rootNode);
-
- } else {
+ Range<Long> range = roadmService.targetPortPowerRange(deviceId, portNumber);
+ if (range == null) {
log.warn("Unable to determine target power range for device {}", deviceId);
+ return;
}
+ Long targetPower = payload.get(TARGET_POWER).asLong();
+ boolean validTargetPower = range.contains(targetPower);
+ if (validTargetPower) {
+ roadmService.setTargetPortPower(deviceId, portNumber, targetPower);
+ }
+ ObjectNode rootNode = objectNode();
+ rootNode.put(ID, payload.get(ID).asText());
+ rootNode.put(RoadmUtil.VALID, validTargetPower);
+ rootNode.put(RoadmUtil.MESSAGE, String.format(TARGET_POWER_ERR_MSG, range.toString()));
+ sendMessage(ROADM_SET_TARGET_POWER_RESP, rootNode);
+ }
+ }
+
+ private final class CreateShowItemsRequestHandler extends RequestHandler {
+ private static final String SHOW_TARGET_POWER = "showTargetPower";
+ private static final String SHOW_SERVICE_STATE = "showServiceState";
+ private static final String SHOW_FLOW_ICON = "showFlowIcon";
+
+ private CreateShowItemsRequestHandler() {
+ super(ROADM_SHOW_ITEMS_REQ);
+ }
+
+ @Override
+ public void process(ObjectNode payload) {
+ DeviceId did = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
+ Type devType = deviceService.getDevice(did).type();
+ // Build response
+ ObjectNode node = objectNode();
+ node.put(SHOW_TARGET_POWER, devType != Type.FIBER_SWITCH);
+ node.put(SHOW_SERVICE_STATE, devType == Type.FIBER_SWITCH);
+ node.put(SHOW_FLOW_ICON, devType == Type.ROADM);
+ sendMessage(ROADM_SHOW_ITEMS_RESP, node);
+ }
+ }
+
+ private final class CreateOpsModeSetRequestHandler extends RequestHandler {
+ private static final String OPS_SWITCH_INDEX = "index";
+ private static final String DEVICE_INVALID_ERR_MSG = "Apply failed: device is offline or unavailable.";
+ private static final String TYPE_INVALID_ERR_MSG = "Apply failed: invalid device type.";
+
+ private CreateOpsModeSetRequestHandler() {
+ super(ROADM_SET_OPS_MODE_REQ);
+ }
+
+ @Override
+ public void process(ObjectNode payload) {
+ DeviceId did = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
+ ObjectNode node = objectNode();
+ if (!deviceService.isAvailable(did)) {
+ node.put(RoadmUtil.VALID, false);
+ node.put(RoadmUtil.MESSAGE, DEVICE_INVALID_ERR_MSG);
+ sendMessage(ROADM_SET_OPS_MODE_RESP, node);
+ return;
+ }
+ Type devType = deviceService.getDevice(did).type();
+ if (devType != Type.FIBER_SWITCH) {
+ node.put(RoadmUtil.VALID, false);
+ node.put(RoadmUtil.MESSAGE, TYPE_INVALID_ERR_MSG);
+ sendMessage(ROADM_SET_OPS_MODE_RESP, node);
+ return;
+ }
+ // get virtual port and switch port from payload
+ roadmService.setProtectionSwitchWorkingPath(did, (int) number(payload, OPS_SWITCH_INDEX));
+ node.put(RoadmUtil.VALID, true);
+ sendMessage(ROADM_SET_OPS_MODE_RESP, node);
}
}
}
diff --git a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmService.java b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmService.java
index 19334ae..792484f 100644
--- a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmService.java
+++ b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmService.java
@@ -43,6 +43,23 @@
public interface RoadmService {
/**
+ * Attempts to manually switch working path to the one specified by {@code index}.
+ *
+ * @param deviceId DeviceId of the device to configure
+ * @param index working path index to switch to
+ */
+ void setProtectionSwitchWorkingPath(DeviceId deviceId, int index);
+
+ /**
+ * Retrieves protection switch specified port's service status.
+ *
+ * @param deviceId DeviceId of the device to configure
+ * @param portNumber the port
+ * @return port service status
+ */
+ String getProtectionSwitchPortState(DeviceId deviceId, PortNumber portNumber);
+
+ /**
* Set target power for a port if the port has configurable target power.
*
* @param deviceId DeviceId of the device to configure
@@ -69,8 +86,7 @@
* @param ochSignal channel to set attenuation for
* @param attenuation attenuation value to set to
*/
- void setAttenuation(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal,
- long attenuation);
+ void setAttenuation(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal, long attenuation);
/**
* Returns the attenuation of a connection.
@@ -99,8 +115,7 @@
* @param ochSignal channel to search for
* @return channel power if found, null otherwise
*/
- Long getCurrentChannelPower(DeviceId deviceId, PortNumber portNumber,
- OchSignal ochSignal);
+ Long getCurrentChannelPower(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal);
/**
* Returns the channels supported by a port.
@@ -117,7 +132,7 @@
* output port).
*
* Connections are represented as flows with an input port, output port, and
- * channel. Implementation of attenuation is up to the vendor.
+ * channel.
*
* @param deviceId DeviceId of the device to create this connection for
* @param priority priority of the flow
@@ -129,8 +144,7 @@
* @return FlowId of the FlowRule representing the connection
*/
FlowId createConnection(DeviceId deviceId, int priority, boolean isPermanent,
- int timeout, PortNumber inPort, PortNumber outPort,
- OchSignal ochSignal);
+ int timeout, PortNumber inPort, PortNumber outPort, OchSignal ochSignal);
/**
* Creates a new internal connection on a device with attenuation. This does
@@ -269,8 +283,7 @@
* @param ochSignal channel to check
* @return range if found, null otherwise
*/
- Range<Long> attenuationRange(DeviceId deviceId, PortNumber portNumber,
- OchSignal ochSignal);
+ Range<Long> attenuationRange(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal);
/**
* Returns the expected input power range for an input port.
diff --git a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmUtil.java b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmUtil.java
new file mode 100644
index 0000000..d125c77
--- /dev/null
+++ b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmUtil.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2016-present 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.roadm;
+
+import org.onlab.util.Frequency;
+import org.onosproject.net.Annotations;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+
+/**
+ * Roadm utilities.
+ */
+public final class RoadmUtil {
+
+ public static final String DEV_ID = "devId";
+ public static final String VALID = "valid";
+ public static final String MESSAGE = "message";
+ public static final String NA = "N/A";
+ public static final String UNKNOWN = "Unknown";
+ public static final String NONE = "(none)";
+ public static final String NO_ROWS_MESSAGE = "No items found";
+
+ public static final long GHZ = 1_000_000_000L;
+ public static final long THZ = 1_000_000_000_000L;
+
+ private RoadmUtil() {
+ }
+
+ /**
+ * Formats Hz to GHz.
+ *
+ * @param value Hz in string format
+ * @return GHz in string format
+ */
+ public static String asGHz(Frequency value) {
+ return value == null ? UNKNOWN : String.valueOf((double) value.asHz() / GHZ);
+ }
+
+ /**
+ * Formats Hz to THz.
+ *
+ * @param value Hz in string format
+ * @return THz in string format
+ */
+ public static String asTHz(Frequency value) {
+ return value == null ? UNKNOWN : String.valueOf((double) value.asHz() / THZ);
+ }
+
+ /**
+ * Gives a default value if the string is null or empty.
+ *
+ * @param value the string value
+ * @param defaultValue default value if null or empty
+ * @return processed string
+ */
+ public static String defaultString(String value, String defaultValue) {
+ return isNullOrEmpty(value) ? defaultValue : value;
+ }
+
+ /**
+ * Gives a default value if the object is null.
+ *
+ * @param object the object
+ * @param defaultValue default value if null
+ * @return processed string
+ */
+ public static String objectToString(Object object, String defaultValue) {
+ return object == null ? defaultValue : String.valueOf(object);
+ }
+
+ /**
+ * Gets value from annotations, if not exists, return default value.
+ *
+ * @param annotations the annotations
+ * @param key key value
+ * @param defaultValue default value
+ * @return value in string format
+ */
+ public static String getAnnotation(Annotations annotations, String key, String defaultValue) {
+ return defaultString(annotations.value(key), defaultValue);
+ }
+
+ /**
+ * Gets value from annotations, default value is NA.
+ *
+ * @param annotations the annotations
+ * @param key key value
+ * @return value in string format
+ */
+ public static String getAnnotation(Annotations annotations, String key) {
+ return getAnnotation(annotations, key, NA);
+ }
+}
\ No newline at end of file