/// <summary> /// Read blade log, for given blade number /// </summary> /// <param name="bladeId">Blade ID(1-48)</param> /// <returns>returns logPacket structure poluated. If null then failure</returns> public ChassisLogResponse ReadBladeLog(int bladeId) { Tracer.WriteInfo("Received Readbladelog({0})", bladeId); Tracer.WriteUserLog("Invoked ReadBladelog(bladeId: {0})", bladeId); // Blade spec limits number of SEL entries to 226 uint maxSelEntries = 226; // Initialize response ChassisLogResponse selLog = new ChassisLogResponse(); selLog.logEntries = new List<LogEntry>(); selLog.completionCode = Contracts.CompletionCode.Unknown; selLog.statusDescription = String.Empty; Contracts.ChassisResponse varResponse = ValidateRequest("ReadBladeLog", bladeId); if (varResponse.completionCode != Contracts.CompletionCode.Success) { selLog.completionCode = varResponse.completionCode; selLog.statusDescription = varResponse.statusDescription; return selLog; } Ipmi.SystemEventLog selRecord = WcsBladeFacade.GetSel((byte)bladeId); Tracer.WriteInfo("Blade {0} ReadBladeLog Return: {1}", bladeId, selRecord.CompletionCode); if (selRecord.CompletionCode != 0 && selRecord.CompletionCode != 0xCB) { Tracer.WriteWarning("ReadBladeLog on blade {0} failed with completion code {1:X}", bladeId, selRecord.CompletionCode); selLog.completionCode = ChassisManagerUtil.GetContractsCompletionCodeMapping((byte)selRecord.CompletionCode); selLog.statusDescription = selLog.completionCode.ToString(); } else { try { // Event time and description lists List<DateTime> eventTimeList = new List<DateTime>(); List<string> eventDescriptionList = new List<string>(); int startingIndex = 0; ushort minRecordId = ushort.MaxValue; Ipmi.SystemEventLogMessage eventLog; string eventDescription; string spacer = ConfigLoaded.EventLogStrSpacer + ConfigLoaded.EventLogStrSeparator + ConfigLoaded.EventLogStrSpacer; // Separate log entries into time and description arrays for (int index = 0; index < selRecord.EventLog.Count; index++) { if (index >= maxSelEntries) { break; } // Extract event data eventLog = selRecord.EventLog[index]; EventLogData eventLogData = ExtractEventMessage(eventLog); // Format event description according to record type if (eventLog.EventFormat == Ipmi.EventMessageFormat.SystemEvent) { // Get sensor details. string sensor = string.Format(ConfigLoaded.EventLogStrSensor, eventLog.SensorType.ToString(), WcsBladeFacade.GetSensorDescription((byte)bladeId, eventLog.GeneratorId[0], eventLog.SensorNumber), eventLog.SensorNumber); // Get Event Data Message string eventData = string.Format(ConfigLoaded.EventData, eventLog.EventPayload); // Add entry to array eventDescription = ( // Record ID and Type "RecordID: " + eventLog.RecordId + " Record Type: " + string.Format("0x{0:X}", eventLog.RecordType) + spacer + // Generator ID "GenID: " + Ipmi.IpmiSharedFunc.ByteArrayToHexString(eventLog.GeneratorId) + spacer + // Description and message eventLogData.Description + spacer + eventLogData.EventMessage + spacer + // Sensor Type and Number sensor + spacer + eventLog.EventDir.ToString() + spacer + // Event Data eventData); } else if (eventLog.EventFormat == Ipmi.EventMessageFormat.OemTimeStamped) { // Add entry to array eventDescription = ( // Record ID and Type "RecordID: " + eventLog.RecordId + " Record Type: " + string.Format("0x{0:X}", eventLog.RecordType) + spacer + // Description and message eventLogData.Description + spacer + eventLogData.EventMessage); } else if (eventLog.EventFormat == Ipmi.EventMessageFormat.OemNonTimeStamped) { // Add entry to array eventDescription = ( // Record ID and Type "RecordID: " + eventLog.RecordId + " Record Type: " + string.Format("0x{0:X}", eventLog.RecordType) + spacer + // Description and message eventLogData.Description + spacer + eventLogData.EventMessage); } else { eventDescription = string.Empty; } // Track starting index of the entry with the smallest Record ID if (eventLog.RecordId < minRecordId) { minRecordId = eventLog.RecordId; startingIndex = index; } // Add event time to list eventTimeList.Add(eventLog.EventDate); eventDescriptionList.Add(eventDescription); } // Add SEL entries to response starting with the one with the smallest Record ID int entryIdx = startingIndex; for (int entryAdded = 0; entryAdded < eventTimeList.Count; entryAdded++) { LogEntry logEntry = new LogEntry(); logEntry.eventTime = eventTimeList[entryIdx]; logEntry.eventDescription = eventDescriptionList[entryIdx]; selLog.logEntries.Add(logEntry); // Go to next entry and handle wraparound entryIdx++; if (entryIdx == eventTimeList.Count) entryIdx = 0; } selLog.completionCode = Contracts.CompletionCode.Success; Tracer.WriteInfo("ReadBladeLog on blade " + bladeId + " returned " + selLog.logEntries.Count() + " entries out of " + selRecord.EventLog.Count + " found on BMC"); } catch (Exception ex) { Tracer.WriteError("ReadBladeLog on blade " + bladeId + " failed with exception: " + ex); selLog.completionCode = Contracts.CompletionCode.Failure; selLog.statusDescription = selLog.completionCode.ToString() + ": " + ex.Message; } } return selLog; }
/// <summary> /// Unified API for querying user chassis audit logs - both timestamp and maxEntries used as input /// </summary> /// <param name="filterStartTime"></param> /// <param name="filterEndTime"></param> /// <param name="maxEntries"></param> /// <returns>Returns list of user log when success else returns null.</returns> public static List<LogEntry> GetFilteredLogEntries(DateTime filterStartTime, DateTime filterEndTime, int maxEntries) { if (Tracer.GetCurrentUserLogFilePath() == null) return null; try { List<LogEntry> timestampFilteredEntries = new List<LogEntry>(); // Parse the log entries from each user log file // Note that these files could simultaneously be modified (switch primary, delete content etc) foreach (string filepath in Tracer.GetAllUserLogFilePaths()) { if (!File.Exists(filepath)) { Tracer.WriteInfo("UserLogXmllinqHelper.GetFilteredLogEntries(): Skipping file ({0}) since it does not exist."); continue; } using (FileStream fileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (BufferedStream bstream = new BufferedStream(fileStream)) using (StreamReader reader = new StreamReader(bstream)) { int index = 0; const int count = 2048; // Reading 2K characters at a time to alleviate memory pressure // Splitting file with arbitrary chunks size may result in chopped 'partial' XML data which is saved in this variable // This data will be merged with the subsequent (consecutive) XML data string prevEntry = null; while (!reader.EndOfStream) { char[] localbuffer = new char[count]; reader.Read(localbuffer, index, count); string myData = new string(localbuffer); myData = prevEntry + myData; string[] subStrings = System.Text.RegularExpressions.Regex.Split(myData, @"ApplicationData>"); if (subStrings.Length < 1) break; prevEntry = subStrings[subStrings.Length - 1]; for (int i = 0; i < subStrings.Length - 1; i++) { string str = subStrings[i]; if (str.Length > 2 && str.Trim().EndsWith("</")) { string currentEntry = (str.Remove(str.Length - 2)); string[] tokens = currentEntry.Trim().Split(new char[] { ',' }); LogEntry timestampFilteredEntry = new LogEntry(); if (DateTime.TryParse(tokens[0], out timestampFilteredEntry.eventTime)) { timestampFilteredEntry.eventTime = DateTime.ParseExact(tokens[0], "yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture); timestampFilteredEntry.eventDescription = currentEntry.Replace(tokens[0] + ",", ""); // Add this entry to the list only when the timestamp falls withing the parameter input range if(timestampFilteredEntry.eventTime >= filterStartTime && timestampFilteredEntry.eventTime <= filterEndTime) timestampFilteredEntries.Add(timestampFilteredEntry); } else { Tracer.WriteWarning("GetFilteredLogEntries(): Reading Chassis user log - ignoring entry '({0})' due to unparse-able date ", tokens[0]); // Skipping the entry since date is not parse-able } } } prevEntry = subStrings[subStrings.Length - 1]; } } } timestampFilteredEntries.Reverse(); return timestampFilteredEntries.Take(maxEntries).ToList(); } catch (Exception e) { Tracer.WriteError("GetFilteredLogEntries(): Reading Chassis user log exception " + e.Message); return null; } }
/// <summary> /// Read blade log, for given blade number /// </summary> /// <param name="bladeId">Blade ID(1-48)</param> /// <returns>returns logPacket structure poluated. If null then failure</returns> public ChassisLogResponse ReadBladeLog(int bladeId) { Tracer.WriteInfo("Received Readbladelog({0})", bladeId); Tracer.WriteUserLog("Invoked ReadBladelog(bladeId: {0})", bladeId); uint noEntries = 100; ChassisLogResponse selLog = new ChassisLogResponse(); selLog.logEntries = new List<LogEntry>(); selLog.completionCode = Contracts.CompletionCode.Unknown; selLog.statusDescription = String.Empty; Contracts.ChassisResponse varResponse = ValidateRequest("ReadBladeLog", bladeId); if (varResponse.completionCode != Contracts.CompletionCode.Success) { selLog.completionCode = varResponse.completionCode; selLog.statusDescription = varResponse.statusDescription; return selLog; } Ipmi.SystemEventLog selRecord = WcsBladeFacade.GetSel((byte)bladeId); // Code added to write output to the console window. Tracer.WriteInfo("Blade {0} ReadBladeLog Return: {1}", bladeId, selRecord.CompletionCode); if (selRecord.CompletionCode != 0) { Tracer.WriteWarning("blade Get SEL Failed with Completion code {0:X}", selRecord.CompletionCode); selLog.completionCode = ChassisManagerUtil.GetContractsCompletionCodeMapping((byte)selRecord.CompletionCode); selLog.statusDescription = selLog.completionCode.ToString(); } else { try { string spacer = ConfigLoaded.EventLogStrSpacer + ConfigLoaded.EventLogStrSeparator + ConfigLoaded.EventLogStrSpacer; foreach (Ipmi.SystemEventLogMessage eventLog in selRecord.EventLog) { if (selLog.logEntries.Count() >= noEntries) { break; } EventLogData eventData = ExtractEventMessage(eventLog); // Get sensor details. string sensor = string.Format(ConfigLoaded.EventLogStrSensor, eventLog.SensorType.ToString(), WcsBladeFacade.GetSensorDescription((byte)bladeId, (byte)eventLog.SensorNumber), eventLog.SensorNumber); // Get Event Error Message string error = string.Format(ConfigLoaded.EventLogStrError, eventLog.EventPayload); LogEntry logEntry = new LogEntry(); logEntry.eventTime = eventLog.EventDate; logEntry.eventDescription = (eventLog.EventDir.ToString() + spacer + eventData.Description + spacer + eventData.EventMessage + spacer + sensor + spacer + error); selLog.logEntries.Add(logEntry); } selLog.completionCode = Contracts.CompletionCode.Success; Tracer.WriteInfo("Readbladelog returned " + selLog.logEntries.Count() + " entries."); } catch (Exception ex) { Tracer.WriteError("ReadBladeLog failed with exception: " + ex); selLog.completionCode = Contracts.CompletionCode.Failure; selLog.statusDescription = selLog.completionCode.ToString() + ": " + ex.Message; } } return selLog; }
/// <summary> /// Read blade log, for given blade number /// </summary> /// <param name="bladeId">Blade ID(1-48)</param> /// <returns>returns logPacket structure poluated. If null then failure</returns> public ChassisLogResponse ReadBladeLog(int bladeId) { Tracer.WriteInfo("Received Readbladelog({0})", bladeId); Tracer.WriteUserLog("Invoked ReadBladelog(bladeId: {0})", bladeId); // Blade spec limits number of SEL entries to 226 uint noSelEntries = 226; // Initialize response ChassisLogResponse selLog = new ChassisLogResponse(); selLog.logEntries = new List<LogEntry>(); selLog.completionCode = Contracts.CompletionCode.Unknown; selLog.statusDescription = String.Empty; Contracts.ChassisResponse varResponse = ValidateRequest("ReadBladeLog", bladeId); if (varResponse.completionCode != Contracts.CompletionCode.Success) { selLog.completionCode = varResponse.completionCode; selLog.statusDescription = varResponse.statusDescription; return selLog; } Ipmi.SystemEventLog selRecord = WcsBladeFacade.GetSel((byte)bladeId); Tracer.WriteInfo("Blade {0} ReadBladeLog Return: {1}", bladeId, selRecord.CompletionCode); if (selRecord.CompletionCode != 0 && selRecord.CompletionCode != 0xCB) { Tracer.WriteWarning("blade Get SEL Failed with Completion code {0:X}", selRecord.CompletionCode); selLog.completionCode = ChassisManagerUtil.GetContractsCompletionCodeMapping((byte)selRecord.CompletionCode); selLog.statusDescription = selLog.completionCode.ToString(); } else { try { DateTime[] eventTime = new DateTime[selRecord.EventLog.Count]; string[] eventDescription = new string[selRecord.EventLog.Count]; Ipmi.SystemEventLogMessage eventLog; string spacer = ConfigLoaded.EventLogStrSpacer + ConfigLoaded.EventLogStrSeparator + ConfigLoaded.EventLogStrSpacer; // Separate log entries into time and description arrays for (int index = 0; index < selRecord.EventLog.Count; index++) { if (index >= noSelEntries) { break; } // Extract event data eventLog = selRecord.EventLog[index]; EventLogData eventData = ExtractEventMessage(eventLog); // Get sensor details. string sensor = string.Format(ConfigLoaded.EventLogStrSensor, eventLog.SensorType.ToString(), WcsBladeFacade.GetSensorDescription((byte)bladeId, eventLog.GeneratorId[0], eventLog.SensorNumber), eventLog.SensorNumber); // Get Event Error Message string error = string.Format(ConfigLoaded.EventLogStrError, eventLog.EventPayload); // Add entry to array eventTime[index] = eventLog.EventDate; eventDescription[index] = ("GenID: " + Ipmi.IpmiSharedFunc.ByteArrayToHexString(eventLog.GeneratorId) + spacer + eventLog.EventDir.ToString() + spacer + eventData.Description + spacer + eventData.EventMessage + spacer + sensor + spacer + error); } // Sort log entries by time Array.Sort<DateTime, string>(eventTime, eventDescription); // Convert array elements into list for response for (int index = 0; index < eventTime.Length; index++) { LogEntry logEntry = new LogEntry(); logEntry.eventTime = eventTime[index]; logEntry.eventDescription = eventDescription[index]; selLog.logEntries.Add(logEntry); } selLog.completionCode = Contracts.CompletionCode.Success; Tracer.WriteInfo("Readbladelog returned " + selLog.logEntries.Count() + " entries. Of " + selRecord.EventLog.Count + " found on BMC"); } catch (Exception ex) { Tracer.WriteError("ReadBladeLog failed with exception: " + ex); selLog.completionCode = Contracts.CompletionCode.Failure; selLog.statusDescription = selLog.completionCode.ToString() + ": " + ex.Message; } } return selLog; }
/// <summary> /// Read Chassis Log /// </summary> /// <returns>returns logPacket structure poluated. If null then failure</returns> public ChassisLogResponse ReadChassisLog() { ChassisLogResponse response = new ChassisLogResponse(); response.completionCode = Contracts.CompletionCode.Unknown; response.statusDescription = String.Empty; Tracer.WriteUserLog("Invoked ReadChassisLog()"); try { if (Tracer.GetCurrentUserLogFilePath() != null) { // Open a filestream to read the user log FileStream fileStream = new FileStream( Tracer.GetCurrentUserLogFilePath(), FileMode.Open, FileAccess.Read, FileShare.ReadWrite); List<string> entries = new List<string>(); //Read each log entry XmlReaderSettings settings = new XmlReaderSettings(); settings.ConformanceLevel = ConformanceLevel.Fragment; XmlReader reader = XmlReader.Create(fileStream, settings); const int MAX_ENTRIES = 500; int traceEventCount = 0; while (reader.Read() && traceEventCount < MAX_ENTRIES) { try { if (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "E2ETraceEvent") { // Read each sub-entry in E2ETraceEvent XmlReader subReader = reader.ReadSubtree(); while (subReader.Read() && traceEventCount < MAX_ENTRIES) { reader.ReadToFollowing("ApplicationData"); if (reader.Read()) { entries.Add(reader.Value.Trim()); } } } } } catch (System.Xml.XmlException xm) { Tracer.WriteInfo("ReadChassisLog XML exception - ignoring it: " + xm.Message); } } // dispose the filestream. dispose internally calls Close(). fileStream.Dispose(); response.logEntries = new List<LogEntry>(); // For each entry get the timestamp and description int loopCount = 0; foreach (string entry in entries) { System.DateTime timeStamp = new System.DateTime(); string[] tokens = entry.Split(new char[] { ',' }); if (DateTime.TryParse(tokens[0], out timeStamp)) { LogEntry lg = new LogEntry(); lg.eventTime = timeStamp; lg.eventDescription = entry.Replace(tokens[0] + ",", ""); response.logEntries.Add(lg); } loopCount++; } response.completionCode = Contracts.CompletionCode.Success; } else { Tracer.WriteError("ReadChassisLog: Unable to get current trace file path"); response.completionCode = Contracts.CompletionCode.Failure; response.statusDescription = "ReadChassisLog: Unable to get current trace file path"; } } catch (Exception e) { Tracer.WriteError(e.Message); response.completionCode = Contracts.CompletionCode.Failure; response.statusDescription = String.Format("ReadChassisLog failed with exception:{0} ", e.Message); } return response; }