blob: 67b50c9cf0cc6eef65efb6b806cdd9c4d98ec4f0 [file] [log] [blame]
xueliangcf527d12016-11-07 14:31:06 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
xueliangcf527d12016-11-07 14:31:06 +09003 *
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.fujitsu;
18
19import com.google.common.collect.ImmutableList;
20import org.apache.commons.configuration.HierarchicalConfiguration;
21import org.onosproject.drivers.utilities.XmlConfigParser;
Thomas Vachuska52f2cd12018-11-08 21:20:04 -080022import org.onosproject.alarm.Alarm;
23import org.onosproject.alarm.AlarmConsumer;
24import org.onosproject.alarm.AlarmEntityId;
25import org.onosproject.alarm.AlarmId;
26import org.onosproject.alarm.DefaultAlarm;
xueliangcf527d12016-11-07 14:31:06 +090027import org.onosproject.net.DeviceId;
28import org.onosproject.net.driver.AbstractHandlerBehaviour;
29import org.onosproject.net.driver.DriverHandler;
30import org.onosproject.netconf.NetconfController;
Yuta HIGUCHI234eaf32017-09-06 13:45:05 -070031import org.onosproject.netconf.NetconfException;
xueliangcf527d12016-11-07 14:31:06 +090032import org.onosproject.mastership.MastershipService;
33
34import org.slf4j.Logger;
35
xueliangcf527d12016-11-07 14:31:06 +090036import java.util.ArrayList;
37import java.util.List;
38import java.text.SimpleDateFormat;
39import java.text.ParseException;
40import java.util.Date;
41import java.util.TimeZone;
42
43import java.nio.charset.StandardCharsets;
44import java.io.ByteArrayInputStream;
45
Thomas Vachuska52f2cd12018-11-08 21:20:04 -080046import static org.onosproject.alarm.Alarm.SeverityLevel;
xueliangcf527d12016-11-07 14:31:06 +090047import static com.google.common.base.Preconditions.checkNotNull;
48import static org.onosproject.drivers.fujitsu.FujitsuVoltXmlUtility.*;
49import static org.slf4j.LoggerFactory.getLogger;
50
51/**
52 * Fujitsu vOLT specific implementation to provide a list of current alarms.
53 */
54public class FujitsuVoltAlarmConsumer extends AbstractHandlerBehaviour implements AlarmConsumer {
55 private final Logger log = getLogger(getClass());
56 private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
57
58 private static final TimeZone ZONE = TimeZone.getTimeZone("UTC");
59
60 private static final String VOLT_ALERTS = "volt-alerts";
61 private static final String OLT_ACTIVE_ALERTS = "olt-active-alerts";
62 private static final String ALERT_INFO = "alert-info";
63 private static final String ALERT_SEQNUM = "alert-seqnum";
64 private static final String ALERT_TYPE = "alert-type";
65 private static final String ALERT_TIME = "alert-time";
66 private static final String ALERT_CLEAR = "alert-clear";
67 private static final String RESOURCE_ID = "resource-id";
68 private static final String SEVERITY = "severity";
69 private static final String IP_ADDRESS = "ip-address";
70 private static final String DATE = "date";
71 private static final String TIME = "time";
72 private static final String OLT_ACTIVE_ALERTS_KEY =
73 "data." + VOLT_NE + ".volt-alerts.olt-active-alerts";
74 private static final String SLASH = "/";
75 private DeviceId ncDeviceId;
76
77 private enum AlertResourceType {
78 UNKNOWN,
79 PONLINK,
80 ONU,
81 SYSTEM
82 }
83
84 private enum AlertSeverity {
85 INFO("info", SeverityLevel.WARNING),
86 MINOR("minor", SeverityLevel.MINOR),
87 MAJOR("major", SeverityLevel.MAJOR),
88 CRITICAL("critical", SeverityLevel.CRITICAL);
89
90 private String text;
91 private SeverityLevel level;
92
93 AlertSeverity(String text, SeverityLevel level) {
94 this.text = text;
95 this.level = level;
96 }
97
98 public static SeverityLevel convertToAlarmSeverityLevel(String text) {
99 for (AlertSeverity severity : AlertSeverity.values()) {
100 if (text.equalsIgnoreCase(severity.text)) {
101 return severity.level;
102 }
103 }
104 return SeverityLevel.INDETERMINATE;
105 }
106 }
107
108 @Override
109 public List<Alarm> consumeAlarms() {
110 DriverHandler handler = handler();
111 NetconfController controller = handler.get(NetconfController.class);
112 MastershipService mastershipService = handler.get(MastershipService.class);
113 ncDeviceId = handler.data().deviceId();
114 checkNotNull(controller, "Netconf controller is null");
115
116 if (!mastershipService.isLocalMaster(ncDeviceId)) {
117 log.warn("Not master for {} Use {} to execute command",
118 ncDeviceId,
119 mastershipService.getMasterFor(ncDeviceId));
120 return null;
121 }
122
123 dateFormat.setTimeZone(ZONE);
124 List<Alarm> alarms = new ArrayList<>();
125 try {
126 StringBuilder request = new StringBuilder();
127 request.append(VOLT_NE_OPEN + VOLT_NE_NAMESPACE)
128 .append(ANGLE_RIGHT + NEW_LINE)
129 .append(buildStartTag(VOLT_ALERTS))
130 .append(buildEmptyTag(OLT_ACTIVE_ALERTS))
131 .append(buildEndTag(VOLT_ALERTS))
132 .append(VOLT_NE_CLOSE);
133
134 String reply = controller.getDevicesMap()
135 .get(ncDeviceId)
136 .getSession()
137 .get(request.toString(), null);
138 if (reply != null) {
139 alarms = parseVoltActiveAlerts(XmlConfigParser.
140 loadXml(new ByteArrayInputStream(reply.getBytes(StandardCharsets.UTF_8))));
141 }
Yuta HIGUCHI234eaf32017-09-06 13:45:05 -0700142 } catch (NetconfException e) {
xueliangcf527d12016-11-07 14:31:06 +0900143 log.error("Error reading alarms for device {} exception {}", ncDeviceId, e);
144 }
145
146 return ImmutableList.copyOf(alarms);
147 }
148
149 /**
150 * Parses XML string to get controller information.
151 *
152 * @param cfg a hierarchical configuration
153 * @return a list of alarms
154 */
155 private List<Alarm> parseVoltActiveAlerts(HierarchicalConfiguration cfg) {
156 List<Alarm> alarms = new ArrayList<>();
157 List<HierarchicalConfiguration> fields =
158 cfg.configurationsAt(OLT_ACTIVE_ALERTS_KEY);
159
160 for (HierarchicalConfiguration sub : fields) {
161 List<HierarchicalConfiguration> childFields =
162 sub.configurationsAt(ALERT_INFO);
163
164 for (HierarchicalConfiguration child : childFields) {
165 try {
166 int seqNum = Integer.parseInt(child.getString(ALERT_SEQNUM));
167 boolean cleared = Boolean.parseBoolean(child.getString(ALERT_CLEAR));
168 String alertType = child.getString(ALERT_TYPE);
169 String severity = child.getString(SEVERITY);
170
171 List<HierarchicalConfiguration> idFields =
172 child.configurationsAt(RESOURCE_ID);
173 if (idFields.isEmpty()) {
Laszlo Papp2d76a5f2018-03-28 17:55:58 +0100174 log.error("{} does not exist: SQ={}, TYPE={}, SEV={}, CLEARED={}",
xueliangcf527d12016-11-07 14:31:06 +0900175 RESOURCE_ID, seqNum, alertType, severity, cleared);
176 continue;
177 }
178 String alarmSrc = formAlarmSource(idFields);
179 if (alarmSrc == null) {
180 log.error("Cannot build description: SQ={}, TYPE={}, SEV={}, CLEARED={}",
181 seqNum, alertType, severity, cleared);
182 continue;
183 }
184 long timeRaised = getTimeRaised(child);
185 log.debug("VOLT: ACTIVE ALERT: SQ={}, TYPE={}, SEV={}, CLEARED={}, TIME={}",
186 seqNum, alertType, severity, cleared, timeRaised);
187
188 SeverityLevel alarmLevel =
189 AlertSeverity.convertToAlarmSeverityLevel(severity);
190 if (alarmLevel.equals(SeverityLevel.INDETERMINATE)) {
191 log.warn("Unknown severity: {}", severity);
192 }
193 DefaultAlarm.Builder alarmBuilder = new DefaultAlarm.Builder(
Ray Milkey0a1a0912018-02-15 11:35:58 -0800194 AlarmId.alarmId(ncDeviceId, Long.toString(timeRaised)),
xueliangcf527d12016-11-07 14:31:06 +0900195 ncDeviceId, alertType.toUpperCase(), alarmLevel, timeRaised)
196 .forSource(AlarmEntityId.alarmEntityId(alarmSrc));
197 alarms.add(alarmBuilder.build());
198 } catch (NumberFormatException e) {
199 log.error("Non-number exception {}", e);
200 } catch (Exception e) {
201 log.error("Exception {}", e);
202 }
203 }
204 }
205 return alarms;
206 }
207
208 /**
209 * Builds alarm source with resource information.
210 * @param idFields a hierarchical configuration
211 * @return formed alarm description
212 */
213 private String formAlarmSource(List<HierarchicalConfiguration> idFields) {
214 AlertResourceType resourceType = AlertResourceType.UNKNOWN;
215 StringBuilder alarmSrc = new StringBuilder();
216 String ipAddr = null;
217 int pon = ZERO;
218 int onu = ZERO;
219
220 for (HierarchicalConfiguration id : idFields) {
221 String value;
222 try {
223 value = id.getString(PONLINK_ID);
224 if (value == null) {
225 resourceType = AlertResourceType.SYSTEM;
226 ipAddr = id.getString(IP_ADDRESS);
227 } else {
228 pon = Integer.parseInt(value);
229 value = id.getString(ONU_ID);
230 if (value == null) {
231 resourceType = AlertResourceType.PONLINK;
232 } else {
233 resourceType = AlertResourceType.ONU;
234 onu = Integer.parseInt(value);
235 }
236 }
237 } catch (NumberFormatException e) {
238 log.error("Non-number resource-id exception {}", e);
239 return null;
240 }
241 }
242
243 alarmSrc.append("other:");
244 alarmSrc.append(resourceType.name()).append(SLASH);
245 switch (resourceType) {
246 case PONLINK:
247 alarmSrc.append(pon);
248 break;
249 case ONU:
250 alarmSrc.append(pon).append(HYPHEN).append(onu);
251 break;
252 case SYSTEM:
253 if (ipAddr != null) {
254 alarmSrc.append(ipAddr);
255 }
256 break;
257 default:
258 break;
259 }
260 return alarmSrc.toString();
261 }
262
263 /**
264 * Converts time and date information from device.
265 * @param cfg a hierarchical configuration
266 * @return converted time from device or system time
267 */
268 private long getTimeRaised(HierarchicalConfiguration cfg) {
269 String strDate;
270 String strTime;
271 long timeRaised;
272
273 List<HierarchicalConfiguration> timeFields =
274 cfg.configurationsAt(ALERT_TIME);
275 if (timeFields.isEmpty()) {
Laszlo Papp2d76a5f2018-03-28 17:55:58 +0100276 log.debug("{} does not exist", ALERT_TIME);
xueliangcf527d12016-11-07 14:31:06 +0900277 } else {
278 for (HierarchicalConfiguration child : timeFields) {
279 strDate = child.getString(DATE);
280 strTime = child.getString(TIME);
281 if ((strDate != null) && (strTime != null)) {
282 try {
283 Date date = dateFormat.parse(strDate + SPACE + strTime);
284 timeRaised = date.getTime();
Frank Wangd8ab0962017-08-11 11:09:30 +0800285 log.debug("{} {} converted to {}", strDate, strTime, timeRaised);
xueliangcf527d12016-11-07 14:31:06 +0900286 return timeRaised;
287 } catch (ParseException e) {
288 log.error("Cannot parse exception {} {} {}", strDate, strTime, e);
289 }
290 } else {
Laszlo Papp2d76a5f2018-03-28 17:55:58 +0100291 log.error("{} or {} does not exist", DATE, TIME);
xueliangcf527d12016-11-07 14:31:06 +0900292 }
293 }
294 }
295 // Use the system's time instead.
296 return System.currentTimeMillis();
297 }
298
299}