blob: 97e2feec27ff7160b66cd8f2205877d6abb00101 [file] [log] [blame]
Jimmy Yanda878fc2016-09-02 16:32:01 -07001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.roadm;
17
18import com.fasterxml.jackson.databind.node.ObjectNode;
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Range;
21import org.onlab.osgi.ServiceDirectory;
MaoLu937cf422017-03-03 23:31:46 -080022import org.onlab.util.Frequency;
Jimmy Yanda878fc2016-09-02 16:32:01 -070023import org.onosproject.net.AnnotationKeys;
24import org.onosproject.net.DeviceId;
MaoLu937cf422017-03-03 23:31:46 -080025import org.onosproject.net.device.DeviceService;
26import org.onosproject.net.OchSignal;
Jimmy Yanda878fc2016-09-02 16:32:01 -070027import org.onosproject.net.Port;
28import org.onosproject.net.PortNumber;
Jimmy Yanda878fc2016-09-02 16:32:01 -070029import org.onosproject.ui.RequestHandler;
30import org.onosproject.ui.UiConnection;
31import org.onosproject.ui.UiMessageHandler;
32import org.onosproject.ui.table.TableModel;
33import org.onosproject.ui.table.TableRequestHandler;
34import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
36
37import java.util.Collection;
MaoLu937cf422017-03-03 23:31:46 -080038import java.util.Collections;
39import java.util.Comparator;
Jimmy Yanda878fc2016-09-02 16:32:01 -070040import java.util.List;
MaoLu937cf422017-03-03 23:31:46 -080041import java.util.Set;
42
43import static org.onosproject.net.Device.Type;
Jimmy Yanda878fc2016-09-02 16:32:01 -070044
45/**
46 * Table-View message handler for ROADM port view.
47 */
48public class RoadmPortViewMessageHandler extends UiMessageHandler {
49
50 private static final String ROADM_PORT_DATA_REQ = "roadmPortDataRequest";
51 private static final String ROADM_PORT_DATA_RESP = "roadmPortDataResponse";
52 private static final String ROADM_PORTS = "roadmPorts";
Jimmy Yanda878fc2016-09-02 16:32:01 -070053 private static final String ROADM_SET_TARGET_POWER_REQ = "roadmSetTargetPowerRequest";
54 private static final String ROADM_SET_TARGET_POWER_RESP = "roadmSetTargetPowerResponse";
MaoLu937cf422017-03-03 23:31:46 -080055 private static final String ROADM_SHOW_ITEMS_REQ = "roadmShowPortItemsRequest";
56 private static final String ROADM_SHOW_ITEMS_RESP = "roadmShowPortItemsResponse";
57 private static final String ROADM_SET_OPS_MODE_REQ = "roadmSetOpsModeRequest";
58 private static final String ROADM_SET_OPS_MODE_RESP = "roadmSetOpsModeResponse";
Jimmy Yanda878fc2016-09-02 16:32:01 -070059
60 private static final String ID = "id";
Jimmy Yanda878fc2016-09-02 16:32:01 -070061 private static final String NAME = "name";
MaoLu937cf422017-03-03 23:31:46 -080062 private static final String TYPE = "type";
Jimmy Yanda878fc2016-09-02 16:32:01 -070063 private static final String ENABLED = "enabled";
64 private static final String MIN_FREQ = "minFreq";
65 private static final String MAX_FREQ = "maxFreq";
66 private static final String GRID = "grid";
MaoLu2f7eadb2017-05-02 15:38:43 -070067 private static final String POWER_RANGE = "powerRange";
Jimmy Yanda878fc2016-09-02 16:32:01 -070068 private static final String CURRENT_POWER = "currentPower";
69 private static final String TARGET_POWER = "targetPower";
70 private static final String HAS_TARGET_POWER = "hasTargetPower";
MaoLu937cf422017-03-03 23:31:46 -080071 private static final String SERVICE_STATE = "serviceState";
Jimmy Yanda878fc2016-09-02 16:32:01 -070072
73 private static final String[] COLUMN_IDS = {
MaoLu2f7eadb2017-05-02 15:38:43 -070074 ID, TYPE, NAME, ENABLED, MIN_FREQ, MAX_FREQ, GRID, POWER_RANGE,
MaoLu937cf422017-03-03 23:31:46 -080075 CURRENT_POWER, SERVICE_STATE, TARGET_POWER, HAS_TARGET_POWER
Jimmy Yanda878fc2016-09-02 16:32:01 -070076 };
77
Jimmy Yanda878fc2016-09-02 16:32:01 -070078 private RoadmService roadmService;
MaoLu937cf422017-03-03 23:31:46 -080079 private DeviceService deviceService;
Jimmy Yanda878fc2016-09-02 16:32:01 -070080
81 private final Logger log = LoggerFactory.getLogger(getClass());
82
83 @Override
84 public void init(UiConnection connection, ServiceDirectory directory) {
85 super.init(connection, directory);
Jimmy Yanda878fc2016-09-02 16:32:01 -070086 roadmService = get(RoadmService.class);
MaoLu937cf422017-03-03 23:31:46 -080087 deviceService = get(DeviceService.class);
Jimmy Yanda878fc2016-09-02 16:32:01 -070088 }
89
90 @Override
91 protected Collection<RequestHandler> createRequestHandlers() {
MaoLu937cf422017-03-03 23:31:46 -080092 return ImmutableSet.of(new PortTableDataRequestHandler(),
93 new SetTargetPowerRequestHandler(),
94 new CreateShowItemsRequestHandler(),
95 new CreateOpsModeSetRequestHandler()
96 );
Jimmy Yanda878fc2016-09-02 16:32:01 -070097 }
98
99 // Handler for sample table requests
100 private final class PortTableDataRequestHandler extends TableRequestHandler {
101
102 private PortTableDataRequestHandler() {
103 super(ROADM_PORT_DATA_REQ, ROADM_PORT_DATA_RESP, ROADM_PORTS);
104 }
105
106 @Override
107 protected String[] getColumnIds() {
108 return COLUMN_IDS;
109 }
110
111 @Override
112 protected String noRowsMessage(ObjectNode payload) {
MaoLu937cf422017-03-03 23:31:46 -0800113 return RoadmUtil.NO_ROWS_MESSAGE;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700114 }
115
116 @Override
117 protected void populateTable(TableModel tm, ObjectNode payload) {
MaoLu937cf422017-03-03 23:31:46 -0800118 DeviceId deviceId = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
Jimmy Yanda878fc2016-09-02 16:32:01 -0700119 if (deviceService.isAvailable(deviceId)) {
120 List<Port> ports = deviceService.getPorts(deviceId);
121 for (Port port : ports) {
122 populateRow(tm.addRow(), port, deviceId);
123 }
124 }
125 }
126
127 private void populateRow(TableModel.Row row, Port port, DeviceId deviceId) {
MaoLu937cf422017-03-03 23:31:46 -0800128 PortNumber portNum = port.number();
129 getFrequencyLimit(deviceId, portNum);
130 row.cell(ID, portNum.toLong())
Jimmy Yanda878fc2016-09-02 16:32:01 -0700131 .cell(TYPE, port.type())
132 .cell(ENABLED, port.isEnabled())
MaoLu937cf422017-03-03 23:31:46 -0800133 .cell(NAME, RoadmUtil.getAnnotation(port.annotations(), AnnotationKeys.PORT_NAME))
134 .cell(MIN_FREQ, RoadmUtil.asTHz(minFreq))
135 .cell(MAX_FREQ, RoadmUtil.asTHz(maxFreq))
136 .cell(GRID, RoadmUtil.asGHz(channelSpacing))
MaoLu2f7eadb2017-05-02 15:38:43 -0700137 .cell(POWER_RANGE, getPowerRange(deviceId, portNum))
MaoLu937cf422017-03-03 23:31:46 -0800138 .cell(CURRENT_POWER, getCurrentPower(deviceId, portNum))
139 .cell(SERVICE_STATE, getPortServiceState(deviceId, portNum))
140 .cell(TARGET_POWER, getTargetPower(deviceId, portNum))
141 .cell(HAS_TARGET_POWER, roadmService.hasPortTargetPower(deviceId, portNum));
142 }
143
144 private String getPortServiceState(DeviceId deviceId, PortNumber portNumber) {
145 return RoadmUtil.defaultString(
146 roadmService.getProtectionSwitchPortState(deviceId, portNumber),
147 RoadmUtil.UNKNOWN);
148 }
149
150 private Frequency minFreq = null, maxFreq = null, channelSpacing = null;
151 // Gets min frequency, max frequency, channel spacing
152 private void getFrequencyLimit(DeviceId deviceId, PortNumber portNumber) {
153 Set<OchSignal> signals = roadmService.queryLambdas(deviceId, portNumber);
154 if (signals.isEmpty()) {
155 return;
156 }
157 Comparator<OchSignal> compare =
158 (OchSignal a, OchSignal b) -> a.spacingMultiplier() - b.spacingMultiplier();
159 OchSignal minOch = Collections.min(signals, compare);
160 OchSignal maxOch = Collections.max(signals, compare);
161 minFreq = minOch.centralFrequency();
162 maxFreq = maxOch.centralFrequency();
163 channelSpacing = minOch.channelSpacing().frequency();
Jimmy Yanda878fc2016-09-02 16:32:01 -0700164 }
165
MaoLu2f7eadb2017-05-02 15:38:43 -0700166 // Returns the power range as a string, N/A if the power range not exists.
167 // The power range would be input power range or target power range determined by port property.
168 // If the port is RX direction then acquire the input power range from driver.
169 // Otherwise there will be a TX direction port, thus acquire the target power range.
170 private String getPowerRange(DeviceId deviceId, PortNumber portNumber) {
MaoLu937cf422017-03-03 23:31:46 -0800171 Range<Long> range = roadmService.inputPortPowerRange(deviceId, portNumber);
MaoLu2f7eadb2017-05-02 15:38:43 -0700172 if (range == null) {
173 range = roadmService.targetPortPowerRange(deviceId, portNumber);
174 }
MaoLu937cf422017-03-03 23:31:46 -0800175 return RoadmUtil.objectToString(range, RoadmUtil.NA);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700176 }
177
178 // Returns the current power as a string, Unknown if no value can be found.
179 private String getCurrentPower(DeviceId deviceId, PortNumber portNumber) {
MaoLu937cf422017-03-03 23:31:46 -0800180 Long currentPower = roadmService.getCurrentPortPower(deviceId, portNumber);
181 return RoadmUtil.objectToString(currentPower, RoadmUtil.UNKNOWN);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700182 }
183
184 // Returns target power as a string, Unknown if target power is expected but
185 // cannot be found, N/A if port does not have configurable target power
186 private String getTargetPower(DeviceId deviceId, PortNumber portNumber) {
MaoLu937cf422017-03-03 23:31:46 -0800187 if (!roadmService.hasPortTargetPower(deviceId, portNumber)) {
188 return RoadmUtil.NA;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700189 }
MaoLu937cf422017-03-03 23:31:46 -0800190 Long targetPower = roadmService.getTargetPortPower(deviceId, portNumber);
191 return RoadmUtil.objectToString(targetPower, RoadmUtil.UNKNOWN);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700192 }
193 }
194
195
196 // Handler for setting port target power
197 private final class SetTargetPowerRequestHandler extends RequestHandler {
198
Jimmy Yanda878fc2016-09-02 16:32:01 -0700199 private static final String TARGET_POWER_ERR_MSG = "Target power range is %s.";
200
201 private SetTargetPowerRequestHandler() {
202 super(ROADM_SET_TARGET_POWER_REQ);
203 }
204
205 @Override
206 public void process(ObjectNode payload) {
MaoLu937cf422017-03-03 23:31:46 -0800207 DeviceId deviceId = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
Jimmy Yanda878fc2016-09-02 16:32:01 -0700208 PortNumber portNumber = PortNumber.portNumber(payload.get(ID).asLong());
MaoLu937cf422017-03-03 23:31:46 -0800209 Range<Long> range = roadmService.targetPortPowerRange(deviceId, portNumber);
210 if (range == null) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700211 log.warn("Unable to determine target power range for device {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800212 return;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700213 }
MaoLu937cf422017-03-03 23:31:46 -0800214 Long targetPower = payload.get(TARGET_POWER).asLong();
215 boolean validTargetPower = range.contains(targetPower);
216 if (validTargetPower) {
217 roadmService.setTargetPortPower(deviceId, portNumber, targetPower);
218 }
219 ObjectNode rootNode = objectNode();
220 rootNode.put(ID, payload.get(ID).asText());
221 rootNode.put(RoadmUtil.VALID, validTargetPower);
222 rootNode.put(RoadmUtil.MESSAGE, String.format(TARGET_POWER_ERR_MSG, range.toString()));
223 sendMessage(ROADM_SET_TARGET_POWER_RESP, rootNode);
224 }
225 }
226
227 private final class CreateShowItemsRequestHandler extends RequestHandler {
228 private static final String SHOW_TARGET_POWER = "showTargetPower";
229 private static final String SHOW_SERVICE_STATE = "showServiceState";
230 private static final String SHOW_FLOW_ICON = "showFlowIcon";
231
232 private CreateShowItemsRequestHandler() {
233 super(ROADM_SHOW_ITEMS_REQ);
234 }
235
236 @Override
237 public void process(ObjectNode payload) {
238 DeviceId did = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
239 Type devType = deviceService.getDevice(did).type();
240 // Build response
241 ObjectNode node = objectNode();
242 node.put(SHOW_TARGET_POWER, devType != Type.FIBER_SWITCH);
243 node.put(SHOW_SERVICE_STATE, devType == Type.FIBER_SWITCH);
244 node.put(SHOW_FLOW_ICON, devType == Type.ROADM);
245 sendMessage(ROADM_SHOW_ITEMS_RESP, node);
246 }
247 }
248
249 private final class CreateOpsModeSetRequestHandler extends RequestHandler {
250 private static final String OPS_SWITCH_INDEX = "index";
251 private static final String DEVICE_INVALID_ERR_MSG = "Apply failed: device is offline or unavailable.";
252 private static final String TYPE_INVALID_ERR_MSG = "Apply failed: invalid device type.";
253
254 private CreateOpsModeSetRequestHandler() {
255 super(ROADM_SET_OPS_MODE_REQ);
256 }
257
258 @Override
259 public void process(ObjectNode payload) {
260 DeviceId did = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
261 ObjectNode node = objectNode();
262 if (!deviceService.isAvailable(did)) {
263 node.put(RoadmUtil.VALID, false);
264 node.put(RoadmUtil.MESSAGE, DEVICE_INVALID_ERR_MSG);
265 sendMessage(ROADM_SET_OPS_MODE_RESP, node);
266 return;
267 }
268 Type devType = deviceService.getDevice(did).type();
269 if (devType != Type.FIBER_SWITCH) {
270 node.put(RoadmUtil.VALID, false);
271 node.put(RoadmUtil.MESSAGE, TYPE_INVALID_ERR_MSG);
272 sendMessage(ROADM_SET_OPS_MODE_RESP, node);
273 return;
274 }
275 // get virtual port and switch port from payload
276 roadmService.setProtectionSwitchWorkingPath(did, (int) number(payload, OPS_SWITCH_INDEX));
277 node.put(RoadmUtil.VALID, true);
278 sendMessage(ROADM_SET_OPS_MODE_RESP, node);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700279 }
280 }
281}