Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 1 | /* |
| 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 | */ |
| 16 | |
| 17 | package org.onosproject.drivers.fujitsu; |
| 18 | |
| 19 | import com.google.common.collect.ImmutableSet; |
| 20 | import org.onosproject.mastership.MastershipService; |
| 21 | import org.onosproject.net.DeviceId; |
| 22 | import org.onosproject.drivers.fujitsu.behaviour.VoltOnuConfig; |
| 23 | import org.onosproject.net.driver.AbstractHandlerBehaviour; |
| 24 | import org.onosproject.net.driver.DriverHandler; |
| 25 | import org.onosproject.netconf.NetconfController; |
| 26 | import org.slf4j.Logger; |
| 27 | |
| 28 | import java.io.IOException; |
| 29 | import java.util.Set; |
| 30 | |
| 31 | import static com.google.common.base.Preconditions.checkNotNull; |
| 32 | import static org.onosproject.drivers.fujitsu.FujitsuVoltXmlUtility.*; |
| 33 | import static org.slf4j.LoggerFactory.getLogger; |
| 34 | |
| 35 | /** |
| 36 | * Implementation to get and set parameters available in vOLT |
| 37 | * through the Netconf protocol. |
| 38 | */ |
| 39 | public class FujitsuVoltOnuConfig extends AbstractHandlerBehaviour |
| 40 | implements VoltOnuConfig { |
| 41 | |
| 42 | private final Logger log = getLogger(FujitsuVoltOnuConfig.class); |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 43 | private static final String ADMIN_STATE = "admin-state"; |
| 44 | private static final String PASSWORD = "password"; |
| 45 | private static final Set<String> ONUCONFIGPARAMS = |
| 46 | ImmutableSet.of(ADMIN_STATE, "pm-enable", "fec-enable", "security-enable", PASSWORD); |
| 47 | private static final Set<String> ADMINSTATES = |
| 48 | ImmutableSet.of("enable", "disable"); |
| 49 | private static final Set<String> ENABLES = |
| 50 | ImmutableSet.of("true", "false"); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 51 | private static final String VOLT_ONUS = "volt-onus"; |
| 52 | private static final String ONUS_PERLINK = "onus-perlink"; |
| 53 | private static final String ONUS_LIST = "onus-list"; |
| 54 | private static final String ONU_INFO = "onu-info"; |
| 55 | private static final String ONU_SET_CONFIG = "onu-set-config"; |
| 56 | private static final String CONFIG_INFO = "config-info"; |
| 57 | private static final String VOLT_STATISTICS = "volt-statistics"; |
| 58 | private static final String ONU_STATISTICS = "onu-statistics"; |
| 59 | private static final String ONU_ETH_STATS = "onu-eth-stats"; |
| 60 | private static final String ETH_STATS = "eth-stats"; |
| 61 | private static final String ONU_GEM_STATS = "onu-gem-stats"; |
| 62 | private static final String GEM_STATS = "gem-stats"; |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 63 | private static final String PASSWORD_PATTERN = "^[a-zA-Z0-9]+$"; |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 64 | |
| 65 | @Override |
| 66 | public String getOnus(String target) { |
| 67 | DriverHandler handler = handler(); |
| 68 | NetconfController controller = handler.get(NetconfController.class); |
| 69 | MastershipService mastershipService = handler.get(MastershipService.class); |
| 70 | DeviceId ncDeviceId = handler.data().deviceId(); |
| 71 | checkNotNull(controller, "Netconf controller is null"); |
| 72 | String reply = null; |
| 73 | String[] onuId = null; |
| 74 | |
| 75 | if (!mastershipService.isLocalMaster(ncDeviceId)) { |
| 76 | log.warn("Not master for {} Use {} to execute command", |
| 77 | ncDeviceId, |
| 78 | mastershipService.getMasterFor(ncDeviceId)); |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 79 | return null; |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 80 | } |
| 81 | |
| 82 | if (target != null) { |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 83 | onuId = checkIdString(target); |
| 84 | if (onuId == null) { |
| 85 | log.error("Invalid ONU identifier {}", target); |
| 86 | return null; |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 87 | } |
| 88 | } |
| 89 | |
| 90 | try { |
| 91 | StringBuilder request = new StringBuilder(); |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 92 | request.append(VOLT_NE_OPEN + VOLT_NE_NAMESPACE); |
| 93 | request.append(ANGLE_RIGHT + NEW_LINE); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 94 | if (onuId != null) { |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 95 | request.append(buildStartTag(VOLT_ONUS)) |
| 96 | .append(buildStartTag(ONUS_PERLINK)) |
| 97 | .append(buildStartTag(PONLINK_ID, false)) |
| 98 | .append(onuId[FIRST_PART]) |
| 99 | .append(buildEndTag(PONLINK_ID)); |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 100 | if (onuId.length > ONE) { |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 101 | request.append(buildStartTag(ONUS_LIST)) |
| 102 | .append(buildStartTag(ONU_INFO)) |
| 103 | .append(buildStartTag(ONU_ID, false)) |
| 104 | .append(onuId[SECOND_PART]) |
| 105 | .append(buildEndTag(ONU_ID)) |
| 106 | .append(buildEndTag(ONU_INFO)) |
| 107 | .append(buildEndTag(ONUS_LIST)); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 108 | } |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 109 | request.append(buildEndTag(ONUS_PERLINK)) |
| 110 | .append(buildEndTag(VOLT_ONUS)); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 111 | } else { |
| 112 | request.append(buildEmptyTag(VOLT_ONUS)); |
| 113 | } |
| 114 | request.append(VOLT_NE_CLOSE); |
| 115 | |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 116 | reply = controller |
| 117 | .getDevicesMap() |
| 118 | .get(ncDeviceId) |
| 119 | .getSession() |
| 120 | .get(request.toString(), REPORT_ALL); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 121 | } catch (IOException e) { |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 122 | log.error("Cannot communicate to device {} exception {}", ncDeviceId, e); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 123 | } |
| 124 | return reply; |
| 125 | } |
| 126 | |
| 127 | @Override |
| 128 | public String setOnu(String target) { |
| 129 | DriverHandler handler = handler(); |
| 130 | NetconfController controller = handler.get(NetconfController.class); |
| 131 | MastershipService mastershipService = handler.get(MastershipService.class); |
| 132 | DeviceId ncDeviceId = handler.data().deviceId(); |
| 133 | checkNotNull(controller, "Netconf controller is null"); |
| 134 | String reply = null; |
| 135 | |
| 136 | if (!mastershipService.isLocalMaster(ncDeviceId)) { |
| 137 | log.warn("Not master for {} Use {} to execute command", |
| 138 | ncDeviceId, |
| 139 | mastershipService.getMasterFor(ncDeviceId)); |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 140 | return null; |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 141 | } |
| 142 | |
| 143 | String[] data = target.split(COLON); |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 144 | if (data.length != THREE) { |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 145 | log.error("Invalid number of arguments"); |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 146 | return null; |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 147 | } |
| 148 | |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 149 | String[] onuId = checkIdString(data[FIRST_PART]); |
| 150 | if ((onuId == null) || (onuId.length != TWO)) { |
| 151 | log.error("Invalid ONU identifier {}", target); |
| 152 | return null; |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 153 | } |
| 154 | |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 155 | if (!checkSetParam(data[SECOND_PART], |
| 156 | data[THIRD_PART])) { |
| 157 | log.error("Failed to check input {}", target); |
| 158 | return null; |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 159 | } |
| 160 | |
| 161 | try { |
| 162 | StringBuilder request = new StringBuilder(); |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 163 | request.append(ANGLE_LEFT + ONU_SET_CONFIG + SPACE); |
| 164 | request.append(VOLT_NE_NAMESPACE + ANGLE_RIGHT + NEW_LINE); |
| 165 | request.append(buildStartTag(PONLINK_ID, false)) |
| 166 | .append(onuId[FIRST_PART]) |
| 167 | .append(buildEndTag(PONLINK_ID)) |
| 168 | .append(buildStartTag(ONU_ID, false)) |
| 169 | .append(onuId[SECOND_PART]) |
| 170 | .append(buildEndTag(ONU_ID)) |
| 171 | .append(buildStartTag(CONFIG_INFO)) |
| 172 | .append(buildStartTag(data[SECOND_PART], false)) |
| 173 | .append(data[THIRD_PART]) |
| 174 | .append(buildEndTag(data[SECOND_PART])) |
| 175 | .append(buildEndTag(CONFIG_INFO)) |
| 176 | .append(buildEndTag(ONU_SET_CONFIG)); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 177 | |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 178 | reply = controller |
| 179 | .getDevicesMap() |
| 180 | .get(ncDeviceId) |
| 181 | .getSession() |
| 182 | .doWrappedRpc(request.toString()); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 183 | } catch (IOException e) { |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 184 | log.error("Cannot communicate to device {} exception {}", ncDeviceId, e); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 185 | } |
| 186 | return reply; |
| 187 | } |
| 188 | |
| 189 | @Override |
| 190 | public String getOnuStatistics(String target) { |
| 191 | DriverHandler handler = handler(); |
| 192 | NetconfController controller = handler.get(NetconfController.class); |
| 193 | MastershipService mastershipService = handler.get(MastershipService.class); |
| 194 | DeviceId ncDeviceId = handler.data().deviceId(); |
| 195 | checkNotNull(controller, "Netconf controller is null"); |
| 196 | String reply = null; |
| 197 | String[] onuId = null; |
| 198 | |
| 199 | if (!mastershipService.isLocalMaster(ncDeviceId)) { |
| 200 | log.warn("Not master for {} Use {} to execute command", |
| 201 | ncDeviceId, |
| 202 | mastershipService.getMasterFor(ncDeviceId)); |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 203 | return null; |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 204 | } |
| 205 | |
| 206 | if (target != null) { |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 207 | onuId = checkIdString(target); |
| 208 | if (onuId == null) { |
| 209 | log.error("Failed to check ID: {}", target); |
| 210 | return null; |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 211 | } |
| 212 | } |
| 213 | |
| 214 | try { |
| 215 | StringBuilder request = new StringBuilder(); |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 216 | request.append(VOLT_NE_OPEN + VOLT_NE_NAMESPACE); |
| 217 | request.append(ANGLE_RIGHT + NEW_LINE); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 218 | request.append(buildStartTag(VOLT_STATISTICS)); |
| 219 | if (onuId != null) { |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 220 | request.append(buildStartTag(ONU_STATISTICS)) |
| 221 | .append(buildStartTag(ONU_GEM_STATS)) |
| 222 | .append(buildStartTag(GEM_STATS)) |
| 223 | .append(buildStartTag(PONLINK_ID, false)) |
| 224 | .append(onuId[FIRST_PART]) |
| 225 | .append(buildEndTag(PONLINK_ID)); |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 226 | if (onuId.length > ONE) { |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 227 | request.append(buildStartTag(ONU_ID, false)) |
| 228 | .append(onuId[SECOND_PART]) |
| 229 | .append(buildEndTag(ONU_ID)); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 230 | } |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 231 | request.append(buildEndTag(GEM_STATS)) |
| 232 | .append(buildEndTag(ONU_GEM_STATS)); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 233 | |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 234 | request.append(buildStartTag(ONU_ETH_STATS)) |
| 235 | .append(buildStartTag(ETH_STATS)) |
| 236 | .append(buildStartTag(PONLINK_ID, false)) |
| 237 | .append(onuId[FIRST_PART]) |
| 238 | .append(buildEndTag(PONLINK_ID)); |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 239 | if (onuId.length > ONE) { |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 240 | request.append(buildStartTag(ONU_ID, false)) |
| 241 | .append(onuId[SECOND_PART]) |
| 242 | .append(buildEndTag(ONU_ID)); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 243 | } |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 244 | request.append(buildEndTag(ETH_STATS)) |
| 245 | .append(buildEndTag(ONU_ETH_STATS)) |
| 246 | .append(buildEndTag(ONU_STATISTICS)); |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 247 | } else { |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 248 | request.append(buildEmptyTag(ONU_STATISTICS)); |
| 249 | } |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 250 | request.append(buildEndTag(VOLT_STATISTICS)) |
| 251 | .append(VOLT_NE_CLOSE); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 252 | |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 253 | reply = controller |
| 254 | .getDevicesMap() |
| 255 | .get(ncDeviceId) |
| 256 | .getSession() |
| 257 | .get(request.toString(), REPORT_ALL); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 258 | } catch (IOException e) { |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 259 | log.error("Cannot communicate to device {} exception {}", ncDeviceId, e); |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 260 | } |
| 261 | return reply; |
| 262 | } |
| 263 | |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 264 | /** |
| 265 | * Verifies input string for ponlink-id{-onu-id}. |
| 266 | * |
| 267 | * @param target input data in string |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 268 | * @return String array containing IDs; may be null if an error is detected |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 269 | */ |
| 270 | private String[] checkIdString(String target) { |
| 271 | String[] onuId = target.split(HYPHEN); |
| 272 | int pon; |
| 273 | int onu; |
| 274 | |
| 275 | if (onuId.length > TWO) { |
| 276 | log.error("Invalid number of arguments for id:{}", onuId.length); |
| 277 | return null; |
| 278 | } |
| 279 | try { |
| 280 | pon = Integer.parseInt(onuId[FIRST_PART]); |
| 281 | if (pon <= ZERO) { |
| 282 | log.error("Invalid integer for ponlink-id:{}", onuId[FIRST_PART]); |
| 283 | return null; |
| 284 | } |
| 285 | if (onuId.length > ONE) { |
| 286 | onu = Integer.parseInt(onuId[SECOND_PART]); |
| 287 | if (onu <= ZERO) { |
| 288 | log.error("Invalid integer for onu-id:{}", onuId[SECOND_PART]); |
| 289 | return null; |
| 290 | } |
| 291 | } |
| 292 | } catch (NumberFormatException e) { |
| 293 | log.error("Non-number input for id:{}", target); |
| 294 | return null; |
| 295 | } |
| 296 | return onuId; |
| 297 | } |
| 298 | |
| 299 | /** |
| 300 | * Verifies input string for valid options. |
| 301 | * |
| 302 | * @param name input data in string |
| 303 | * @param value input data in string |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 304 | * @return true/false if the parameter is valid/invalid |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 305 | */ |
| 306 | private boolean checkSetParam(String name, String value) { |
| 307 | if (!ONUCONFIGPARAMS.contains(name)) { |
| 308 | log.error("Unsupported parameter: {}", name); |
| 309 | return false; |
| 310 | } |
| 311 | |
| 312 | switch (name) { |
| 313 | case ADMIN_STATE: |
| 314 | if (!validState(ADMINSTATES, name, value)) { |
| 315 | return false; |
| 316 | } |
| 317 | break; |
| 318 | case PASSWORD: |
| 319 | if (!value.matches(PASSWORD_PATTERN)) { |
| 320 | log.error("Invalid value for Name {} : Value {}.", name, value); |
| 321 | return false; |
| 322 | } |
| 323 | break; |
| 324 | default: |
| 325 | if (!validState(ENABLES, name, value)) { |
| 326 | return false; |
| 327 | } |
| 328 | break; |
| 329 | } |
| 330 | return true; |
| 331 | } |
| 332 | |
| 333 | /** |
| 334 | * Verifies input string for valid options. |
| 335 | * |
| 336 | * @param states input data in string for parameter state |
| 337 | * @param name input data in string for parameter name |
| 338 | * @param value input data in string for parameter value |
xueliang | c6e47e2 | 2016-10-20 16:37:24 +0900 | [diff] [blame] | 339 | * @return true/false if the parameter is valid/invalid |
xueliang | 5b3d3444 | 2016-09-23 10:37:33 +0900 | [diff] [blame] | 340 | */ |
| 341 | private boolean validState(Set<String> states, String name, String value) { |
| 342 | if (!states.contains(value)) { |
| 343 | log.error("Invalid value for Name {} : Value {}.", name, value); |
| 344 | return false; |
| 345 | } |
| 346 | return true; |
| 347 | } |
| 348 | |
Akihiro Yamanouchi | 8d3a9d3 | 2016-07-12 11:41:44 +0900 | [diff] [blame] | 349 | } |