blob: 05df59a8c7b7d9f51697e1fbe4e97c34c5faa1ae [file] [log] [blame]
Laszlo Papp8b3a5f62017-10-05 13:32:00 +01001/*
2 * Copyright 2017 Open Networking Foundation
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 */
16
17package org.onosproject.drivers.polatis.netconf;
18
19import com.google.common.collect.Range;
20import org.apache.commons.configuration.HierarchicalConfiguration;
21import org.onosproject.net.Direction;
22import org.onosproject.net.OchSignal;
23import org.onosproject.net.PortNumber;
24import org.onosproject.net.behaviour.PowerConfig;
25import org.onosproject.net.driver.AbstractHandlerBehaviour;
26import org.slf4j.Logger;
27
Laszlo Papp8cd61fb2017-10-13 16:45:00 +010028import java.util.ArrayList;
29import java.util.List;
Laszlo Papp8b87a192017-10-19 18:47:12 +010030import java.util.NoSuchElementException;
Laszlo Papp8b3a5f62017-10-05 13:32:00 +010031import java.util.Optional;
32
33import static org.onosproject.drivers.polatis.netconf.PolatisOpticalUtility.POWER_MULTIPLIER;
Laszlo Papp8b87a192017-10-19 18:47:12 +010034import static org.onosproject.drivers.polatis.netconf.PolatisOpticalUtility.VOA_MULTIPLIER;
Laszlo Papp8b3a5f62017-10-05 13:32:00 +010035import static org.onosproject.drivers.polatis.netconf.PolatisOpticalUtility.POWER_RANGE;
Laszlo Papp81cc6422017-10-18 02:24:09 +010036import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.netconfGet;
Laszlo Papp8b87a192017-10-19 18:47:12 +010037import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.netconfEditConfig;
Laszlo Papp81cc6422017-10-18 02:24:09 +010038import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.configAt;
39import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.configsAt;
Laszlo Papp8b87a192017-10-19 18:47:12 +010040import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.xml;
Laszlo Papp81cc6422017-10-18 02:24:09 +010041import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.xmlOpen;
42import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.xmlClose;
43import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_PORT;
44import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_PORTID;
45import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_OPM;
46import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_OPM_XMLNS;
47import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_DATA_OPM;
48import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_DATA_OPM_PORT;
Laszlo Papp8b87a192017-10-19 18:47:12 +010049import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_VOA;
50import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_VOA_XMLNS;
51import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_DATA_VOA_PORT;
52import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.CFG_MODE_MERGE;
Laszlo Papp81cc6422017-10-18 02:24:09 +010053
Laszlo Papp8b3a5f62017-10-05 13:32:00 +010054import static org.slf4j.LoggerFactory.getLogger;
55
56/**
57 * Get current or target port/channel power from a Polatis optical netconf device.
58 * Set target port power or channel attenuation to an optical netconf device.
59 */
60public class PolatisPowerConfig<T> extends AbstractHandlerBehaviour
Andrea Campanelladadf6402019-08-07 15:24:11 +020061 implements PowerConfig<T> {
Laszlo Papp8b3a5f62017-10-05 13:32:00 +010062
Laszlo Papp81cc6422017-10-18 02:24:09 +010063 private static final String KEY_POWER = "power";
Laszlo Papp8b87a192017-10-19 18:47:12 +010064 private static final String KEY_ATTEN_LEVEL = "atten-level";
65 private static final String KEY_ATTEN_MODE = "atten-mode";
66 private static final String VALUE_ATTEN_MODE = "VOA_MODE_ABSOLUTE";
Laszlo Papp81cc6422017-10-18 02:24:09 +010067
Laszlo Papp8b3a5f62017-10-05 13:32:00 +010068 private static final Logger log = getLogger(PolatisPowerConfig.class);
69
70 @Override
Andrea Campanelladadf6402019-08-07 15:24:11 +020071 public Optional<Double> getTargetPower(PortNumber port, T component) {
72 Long power = acquireCurrentPower(port, component);
73 if (power == null) {
74 return Optional.empty();
75 }
76 return Optional.of(power.doubleValue());
Laszlo Papp8b3a5f62017-10-05 13:32:00 +010077 }
78
79 @Override
Andrea Campanelladadf6402019-08-07 15:24:11 +020080 public void setTargetPower(PortNumber port, T component, double power) {
Laszlo Papp8b3a5f62017-10-05 13:32:00 +010081 if (component instanceof OchSignal) {
82 log.warn("Channel power is not applicable.");
83 return;
84 }
Andrea Campanelladadf6402019-08-07 15:24:11 +020085 setPortTargetPower(port, (long) power);
Laszlo Papp8b3a5f62017-10-05 13:32:00 +010086 }
87
88 @Override
Andrea Campanelladadf6402019-08-07 15:24:11 +020089 public Optional<Double> currentPower(PortNumber port, T component) {
90 Long power = acquireCurrentPower(port, component);
91 if (power == null) {
92 return Optional.empty();
93 }
94 return Optional.of(power.doubleValue());
Laszlo Papp8b3a5f62017-10-05 13:32:00 +010095 }
96
97 @Override
Andrea Campanelladadf6402019-08-07 15:24:11 +020098 public Optional<Range<Double>> getTargetPowerRange(PortNumber port, T component) {
99 Range<Long> power = getTxPowerRange(port, component);
100 if (power == null) {
101 return Optional.empty();
102 }
103 return Optional.of(Range.closed((double) power.lowerEndpoint(), (double) power.upperEndpoint()));
Laszlo Papp8b3a5f62017-10-05 13:32:00 +0100104 }
105
106 @Override
Andrea Campanelladadf6402019-08-07 15:24:11 +0200107 public Optional<Range<Double>> getInputPowerRange(PortNumber port, T component) {
108 Range<Long> power = getRxPowerRange(port, component);
109 if (power == null) {
110 return Optional.empty();
111 }
112 return Optional.of(Range.closed((double) power.lowerEndpoint(), (double) power.upperEndpoint()));
Laszlo Papp8b3a5f62017-10-05 13:32:00 +0100113 }
114
Laszlo Papp8cd61fb2017-10-13 16:45:00 +0100115 @Override
116 public List<PortNumber> getPorts(T component) {
117 if (component instanceof OchSignal) {
118 log.warn("Channel component is not applicable.");
119 return new ArrayList<PortNumber>();
120 }
121 log.debug("Get port config ports...");
122 return acquirePorts();
123 }
124
125 private List<PortNumber> acquirePorts() {
126 String filter = getPortPowerFilter(null);
127 String reply = netconfGet(handler(), filter);
128 List<HierarchicalConfiguration> subtrees = configsAt(reply, KEY_DATA_OPM);
129 List<PortNumber> ports = new ArrayList<PortNumber>();
130 for (HierarchicalConfiguration portConfig : subtrees) {
131 ports.add(PortNumber.portNumber(portConfig.getLong(KEY_PORTID)));
132 }
133 return ports;
134 }
135
136 /**
137 * Get the filter string for the OPM power NETCONF request.
138 *
139 * @param port the port, null to return all the opm ports
140 * @return filter string
141 */
Laszlo Papp8b3a5f62017-10-05 13:32:00 +0100142 private String getPortPowerFilter(PortNumber port) {
Laszlo Papp8cd61fb2017-10-13 16:45:00 +0100143 StringBuilder filter = new StringBuilder(xmlOpen(KEY_OPM_XMLNS))
Laszlo Papp8b3a5f62017-10-05 13:32:00 +0100144 .append(xmlOpen(KEY_PORT))
Laszlo Papp8cd61fb2017-10-13 16:45:00 +0100145 .append(xmlOpen(KEY_PORTID));
146 if (port != null) {
147 filter.append(port.toLong());
148 }
149 return filter.append(xmlClose(KEY_PORTID))
Laszlo Papp8b3a5f62017-10-05 13:32:00 +0100150 .append(xmlClose(KEY_PORT))
151 .append(xmlClose(KEY_OPM))
152 .toString();
153 }
154
155 private Long acquireTargetPower(PortNumber port, T component) {
156 if (component instanceof OchSignal) {
157 log.warn("Channel power is not applicable.");
158 return null;
159 }
160 log.debug("Get port{} target power...", port);
Laszlo Papp8b87a192017-10-19 18:47:12 +0100161 return acquirePortAttenuation(port);
162 }
163
164 /**
165 * Get the filter string for the attenuation NETCONF request.
166 *
167 * @param port the port, null to return all the attenuation ports
168 * @return filter string
169 */
170 private String getPortAttenuationFilter(PortNumber port) {
171 StringBuilder filter = new StringBuilder(xmlOpen(KEY_VOA_XMLNS))
172 .append(xmlOpen(KEY_PORT))
173 .append(xmlOpen(KEY_PORTID));
174 if (port != null) {
175 filter.append(port.toLong());
176 }
177 return filter.append(xmlClose(KEY_PORTID))
178 .append(xmlOpen(KEY_ATTEN_LEVEL))
179 .append(xmlClose(KEY_ATTEN_LEVEL))
180 .append(xmlClose(KEY_PORT))
181 .append(xmlClose(KEY_VOA))
182 .toString();
183 }
184
185 private Long acquirePortAttenuation(PortNumber port) {
186 String filter = getPortAttenuationFilter(port);
187 String reply = netconfGet(handler(), filter);
188 HierarchicalConfiguration info = configAt(reply, KEY_DATA_VOA_PORT);
189 if (info == null) {
190 return null;
191 }
192 long attenuation = 0;
193 try {
194 attenuation = (long) (info.getDouble(KEY_ATTEN_LEVEL) * VOA_MULTIPLIER);
195 } catch (NoSuchElementException e) {
196 log.debug("Could not find atten-level for port {}", port);
197 }
198
199 return attenuation;
Laszlo Papp8b3a5f62017-10-05 13:32:00 +0100200 }
201
202 private Long acquireCurrentPower(PortNumber port, T component) {
203 if (component instanceof OchSignal) {
204 log.warn("Channel power is not applicable.");
205 return null;
206 }
207 log.debug("Get port{} current power...", port);
208 return acquirePortPower(port);
209 }
210
211 private Long acquirePortPower(PortNumber port) {
212 String filter = getPortPowerFilter(port);
213 String reply = netconfGet(handler(), filter);
214 HierarchicalConfiguration info = configAt(reply, KEY_DATA_OPM_PORT);
215 if (info == null) {
216 return null;
217 }
218 return (long) (info.getDouble(KEY_POWER) * POWER_MULTIPLIER);
219 }
220
221 private boolean setPortTargetPower(PortNumber port, long power) {
222 log.debug("Set port{} target power...", port);
Laszlo Papp8b87a192017-10-19 18:47:12 +0100223 String cfg = new StringBuilder(xmlOpen(KEY_VOA_XMLNS))
224 .append(xmlOpen(KEY_PORT))
225 .append(xml(KEY_PORTID, Long.toString(port.toLong())))
226 .append(xml(KEY_ATTEN_MODE, VALUE_ATTEN_MODE))
Laszlo Pappda059e72017-10-23 11:39:31 +0100227 .append(xml(KEY_ATTEN_LEVEL, Double.toString((double) power / VOA_MULTIPLIER)))
Laszlo Papp8b87a192017-10-19 18:47:12 +0100228 .append(xmlClose(KEY_PORT))
Laszlo Pappda059e72017-10-23 11:39:31 +0100229 .append(xmlClose(KEY_VOA))
Laszlo Papp8b87a192017-10-19 18:47:12 +0100230 .toString();
231 return netconfEditConfig(handler(), CFG_MODE_MERGE, cfg);
Laszlo Papp8b3a5f62017-10-05 13:32:00 +0100232 }
233
234 private Range<Long> getPowerRange() {
235 return POWER_RANGE;
236 }
237
238 private Range<Long> getTxPowerRange(PortNumber port, T component) {
239 if (component instanceof Direction) {
240 log.debug("Get target port{} power range...", port);
241 return getPowerRange();
242 } else {
Laszlo Papp8b3a5f62017-10-05 13:32:00 +0100243 log.warn("Channel power is not applicable.");
244 return null;
245 }
246 }
247
248 private Range<Long> getRxPowerRange(PortNumber port, T component) {
249 log.debug("Get input port{} power range...", port);
250 return getPowerRange();
251 }
252}