blob: 2aa80f70c613abab810fc015b294ebb241c7fe89 [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";
67 private static final String INPUT_POWER_RANGE = "inputPowerRange";
68 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 = {
74 ID, TYPE, NAME, ENABLED, MIN_FREQ, MAX_FREQ, GRID, INPUT_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))
137 .cell(INPUT_POWER_RANGE, getInputPowerRange(deviceId, portNum))
138 .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
166 // Returns the input power range as a string, N/A if the port is not an
167 // input port
168 private String getInputPowerRange(DeviceId deviceId, PortNumber portNumber) {
MaoLu937cf422017-03-03 23:31:46 -0800169 Range<Long> range = roadmService.inputPortPowerRange(deviceId, portNumber);
170 return RoadmUtil.objectToString(range, RoadmUtil.NA);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700171 }
172
173 // Returns the current power as a string, Unknown if no value can be found.
174 private String getCurrentPower(DeviceId deviceId, PortNumber portNumber) {
MaoLu937cf422017-03-03 23:31:46 -0800175 Long currentPower = roadmService.getCurrentPortPower(deviceId, portNumber);
176 return RoadmUtil.objectToString(currentPower, RoadmUtil.UNKNOWN);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700177 }
178
179 // Returns target power as a string, Unknown if target power is expected but
180 // cannot be found, N/A if port does not have configurable target power
181 private String getTargetPower(DeviceId deviceId, PortNumber portNumber) {
MaoLu937cf422017-03-03 23:31:46 -0800182 if (!roadmService.hasPortTargetPower(deviceId, portNumber)) {
183 return RoadmUtil.NA;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700184 }
MaoLu937cf422017-03-03 23:31:46 -0800185 Long targetPower = roadmService.getTargetPortPower(deviceId, portNumber);
186 return RoadmUtil.objectToString(targetPower, RoadmUtil.UNKNOWN);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700187 }
188 }
189
190
191 // Handler for setting port target power
192 private final class SetTargetPowerRequestHandler extends RequestHandler {
193
Jimmy Yanda878fc2016-09-02 16:32:01 -0700194 private static final String TARGET_POWER_ERR_MSG = "Target power range is %s.";
195
196 private SetTargetPowerRequestHandler() {
197 super(ROADM_SET_TARGET_POWER_REQ);
198 }
199
200 @Override
201 public void process(ObjectNode payload) {
MaoLu937cf422017-03-03 23:31:46 -0800202 DeviceId deviceId = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
Jimmy Yanda878fc2016-09-02 16:32:01 -0700203 PortNumber portNumber = PortNumber.portNumber(payload.get(ID).asLong());
MaoLu937cf422017-03-03 23:31:46 -0800204 Range<Long> range = roadmService.targetPortPowerRange(deviceId, portNumber);
205 if (range == null) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700206 log.warn("Unable to determine target power range for device {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800207 return;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700208 }
MaoLu937cf422017-03-03 23:31:46 -0800209 Long targetPower = payload.get(TARGET_POWER).asLong();
210 boolean validTargetPower = range.contains(targetPower);
211 if (validTargetPower) {
212 roadmService.setTargetPortPower(deviceId, portNumber, targetPower);
213 }
214 ObjectNode rootNode = objectNode();
215 rootNode.put(ID, payload.get(ID).asText());
216 rootNode.put(RoadmUtil.VALID, validTargetPower);
217 rootNode.put(RoadmUtil.MESSAGE, String.format(TARGET_POWER_ERR_MSG, range.toString()));
218 sendMessage(ROADM_SET_TARGET_POWER_RESP, rootNode);
219 }
220 }
221
222 private final class CreateShowItemsRequestHandler extends RequestHandler {
223 private static final String SHOW_TARGET_POWER = "showTargetPower";
224 private static final String SHOW_SERVICE_STATE = "showServiceState";
225 private static final String SHOW_FLOW_ICON = "showFlowIcon";
226
227 private CreateShowItemsRequestHandler() {
228 super(ROADM_SHOW_ITEMS_REQ);
229 }
230
231 @Override
232 public void process(ObjectNode payload) {
233 DeviceId did = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
234 Type devType = deviceService.getDevice(did).type();
235 // Build response
236 ObjectNode node = objectNode();
237 node.put(SHOW_TARGET_POWER, devType != Type.FIBER_SWITCH);
238 node.put(SHOW_SERVICE_STATE, devType == Type.FIBER_SWITCH);
239 node.put(SHOW_FLOW_ICON, devType == Type.ROADM);
240 sendMessage(ROADM_SHOW_ITEMS_RESP, node);
241 }
242 }
243
244 private final class CreateOpsModeSetRequestHandler extends RequestHandler {
245 private static final String OPS_SWITCH_INDEX = "index";
246 private static final String DEVICE_INVALID_ERR_MSG = "Apply failed: device is offline or unavailable.";
247 private static final String TYPE_INVALID_ERR_MSG = "Apply failed: invalid device type.";
248
249 private CreateOpsModeSetRequestHandler() {
250 super(ROADM_SET_OPS_MODE_REQ);
251 }
252
253 @Override
254 public void process(ObjectNode payload) {
255 DeviceId did = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
256 ObjectNode node = objectNode();
257 if (!deviceService.isAvailable(did)) {
258 node.put(RoadmUtil.VALID, false);
259 node.put(RoadmUtil.MESSAGE, DEVICE_INVALID_ERR_MSG);
260 sendMessage(ROADM_SET_OPS_MODE_RESP, node);
261 return;
262 }
263 Type devType = deviceService.getDevice(did).type();
264 if (devType != Type.FIBER_SWITCH) {
265 node.put(RoadmUtil.VALID, false);
266 node.put(RoadmUtil.MESSAGE, TYPE_INVALID_ERR_MSG);
267 sendMessage(ROADM_SET_OPS_MODE_RESP, node);
268 return;
269 }
270 // get virtual port and switch port from payload
271 roadmService.setProtectionSwitchWorkingPath(did, (int) number(payload, OPS_SWITCH_INDEX));
272 node.put(RoadmUtil.VALID, true);
273 sendMessage(ROADM_SET_OPS_MODE_RESP, node);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700274 }
275 }
276}