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