/// <summary> /// Attempts to retrieve the Psu Power. This method /// calls down to the Chassis Manager with SendReceive /// </summary> private PsuPowerPacket GetPsuPower(byte psuId) { // Initialize return packet PsuPowerPacket returnPacket = new PsuPowerPacket(); returnPacket.CompletionCode = CompletionCode.UnspecifiedError; returnPacket.PsuPower = 0; byte[] powerValue = new byte[2]; try { PsuPowerResponse myResponse = new PsuPowerResponse(); myResponse = (PsuPowerResponse)this.SendReceive(this.PsuDeviceType, this.PsuId, new PsuRequest((byte)PmBusCommand.READ_POUT, (byte)PmBusResponseLength.READ_POUT), typeof(PsuPowerResponse)); if (myResponse.CompletionCode != 0) { returnPacket.CompletionCode = (CompletionCode)myResponse.CompletionCode; } else { returnPacket.CompletionCode = CompletionCode.Success; powerValue = myResponse.PsuPower; byte[] convertedPowerValue = null; PmBus.PmBusLinearDataFormatConverter(ref powerValue, out convertedPowerValue); powerValue = convertedPowerValue; returnPacket.PsuPower = System.BitConverter.ToInt32(powerValue, 0); } } catch (System.Exception ex) { returnPacket.CompletionCode = CompletionCode.UnspecifiedError; returnPacket.PsuPower = 0; Tracer.WriteError(this.PsuId, DeviceType.Psu, ex); } return(returnPacket); }
/// <summary> /// Attempts to retrieve the Psu Power. This method /// calls down to the Chassis Manager with SendReceive /// </summary> private PsuPowerPacket GetPsuPower(byte psuId) { // Initialize return packet PsuPowerPacket returnPacket = new PsuPowerPacket(); returnPacket.CompletionCode = CompletionCode.UnspecifiedError; returnPacket.PsuPower = 0; byte[] powerValue = new byte[2]; try { PsuPowerResponse myResponse = new PsuPowerResponse(); myResponse = (PsuPowerResponse)this.SendReceive(this.PsuDeviceType, this.PsuId, new PsuRequest((byte)PmBusCommand.READ_POUT,(byte)PmBusResponseLength.READ_POUT), typeof(PsuPowerResponse)); if (myResponse.CompletionCode != 0) { returnPacket.CompletionCode = (CompletionCode)myResponse.CompletionCode; } else { returnPacket.CompletionCode = CompletionCode.Success; powerValue = myResponse.PsuPower; byte[] convertedPowerValue = null; PmBus.PmBusLinearDataFormatConverter(ref powerValue, out convertedPowerValue); powerValue = convertedPowerValue; returnPacket.PsuPower = System.BitConverter.ToInt32(powerValue, 0); } } catch (System.Exception ex) { returnPacket.CompletionCode = CompletionCode.UnspecifiedError; returnPacket.PsuPower = 0; Tracer.WriteError(this.PsuId, DeviceType.Psu, ex); } return returnPacket; }
/// <summary> /// Attempt to resolve Psu Faults /// </summary> private static Dictionary <byte, PsuAlertFaultStatus> PsuAlertRemediate(Dictionary <byte, PsuAlertFaultType> psuFailures) { Dictionary <byte, PsuAlertFaultStatus> failedPsu = new Dictionary <byte, PsuAlertFaultStatus>(); foreach (KeyValuePair <byte, PsuAlertFaultType> psu in psuFailures) { // If firmware update is in progress, skip this PSU if (ChassisState.PsuFwUpdateInProgress[psu.Key - 1]) { continue; } lock (ChassisState.psuLock[psu.Key - 1]) { // Log PSU faults ChassisState.Psu[psu.Key - 1].LogPsuFaultStatus(); // Clear PSU faults, which will clear PSU_ALERT CompletionCode clearAlert = ClearPsuFault(psu.Key); if (clearAlert != CompletionCode.Success) { // PSU clear faults failed. Log failure and continue to next PSU. failedPsu.Add(psu.Key, PsuAlertFaultStatus.PsuClearFaultFailed); Tracer.WriteError("PsuAlertRemediate: ClearPsuFault failed on PsuId: {0}", psu.Key); continue; } if (psu.Value == PsuAlertFaultType.PsuFailure) { // Check that the PSU is on PsuStatusPacket psuStatus = ChassisState.Psu[psu.Key - 1].GetPsuStatus(); if (psuStatus.CompletionCode != CompletionCode.Success) { failedPsu.Add(psu.Key, PsuAlertFaultStatus.PsuFault); Tracer.WriteError("PsuAlertRemediate: GetPsuStatus on PSU ({0}) failed with return code {1}", psu.Key, psuStatus.CompletionCode); } else { if (psuStatus.PsuStatus == (byte)Contracts.PowerState.ON) { // Check PSU power output PsuPowerPacket power = ChassisState.Psu[psu.Key - 1].GetPsuPower(); if ((power.CompletionCode == CompletionCode.Success) && (power.PsuPower != 0)) { Tracer.WriteInfo("PsuStatus clear faults succeeded. Psu: {0} drawing power: {1} Watts", psu.Key, power.PsuPower); } else { // PSU is not outputting power. failedPsu.Add(psu.Key, PsuAlertFaultStatus.PsuNoOutputPower); Tracer.WriteError("PsuAlertRemediate failed Psu. PsuId: {0} Psu Error State: {1}", psu.Key, PsuAlertFaultStatus.PsuNoOutputPower.ToString()); } } else { // PSU is turned off. failedPsu.Add(psu.Key, PsuAlertFaultStatus.PsuPowerOff); Tracer.WriteError("PsuAlertRemediate failed Psu. PsuId: {0} Psu Error State: {1}", psu.Key, PsuAlertFaultStatus.PsuPowerOff.ToString()); } } } else if ((ConfigLoaded.BatteryMonitoringEnabled) && (ChassisState.Psu[(psu.Key - 1)] is EmersonPsu)) { // convert psu from base class object EmersonPsu emersonPsu = (EmersonPsu)ChassisState.Psu[(psu.Key - 1)]; if (psu.Value == PsuAlertFaultType.BatteryFault) { // clear battery fault status CompletionCode clearFault = emersonPsu.ClearBatteryFaultIndicator(); if (clearFault == CompletionCode.Success) { EmersonPsu.BatteryFaultIndicatorPacket faultIndicator = emersonPsu.GetBatteryFaultIndicator(); if (faultIndicator.BatteryFault == 1) { if (!failedPsu.ContainsKey(emersonPsu.PsuId)) { // Psu Clear faults did not succeed. failedPsu.Add(psu.Key, PsuAlertFaultStatus.BatteryFault); } Tracer.WriteError("PsuAlertRemediate failed to clear battery fault. PsuId: {0} Battery Error State: {1}", psu.Key, PsuAlertFaultStatus.BatteryFault.ToString()); } } } else if (psu.Value == PsuAlertFaultType.OnBattery && ConfigLoaded.NumBatteries > 0) { // Check if we need to trigger delegate to process battery status if (ConfigLoaded.ProcessBatteryStatus) { double sumBatteryChargeLevel = 0; ChassisEnergyStorageStatus status = null; // list to store battery charge levels List <string> batteryStates = new List <string>(); // battery present or not, set to true if even one battery is present. // default to false bool isBatteryPresent = false; // Calculate average battery charge level for (int index = 1; index <= ConfigLoaded.NumBatteries; index++) { status = ChassisState.GetEnergyStorageStatus((byte)index); // Add to the list battery charge levels batteryStates.Add(status.State.ToString()); // If even one battery is present, set flag to true if (status.Present) { isBatteryPresent = true; } // If battery state is not unknown, add up the charge level. if (status.State != EnergyStorageState.Unknown) { sumBatteryChargeLevel += status.PercentCharge; } } double avgChargeLevel = (sumBatteryChargeLevel / ConfigLoaded.NumBatteries); // Process battery status if battery discharge time is greater than the allowed discharge time // from app.config( default 35 seconds) or Average battery charge level is below a given threshold value. if (BatteryDischargeTimer.Elapsed > new System.TimeSpan(0, 0, ConfigLoaded.BatteryDischargeTimeInSecs) || avgChargeLevel < ConfigLoaded.BatteryChargeLevelThreshold) { // Invoke method to trigger NVDIMM backup for critical battery status ThreadPool.QueueUserWorkItem(new WaitCallback(ChassisManagerInternal.ProcessCriticalBatteryStatus)); } // Calculate backup energy available per blade and per NVDIMM double bladeEnergy = (ConfigLoaded.NumPsus * BATT_POUT_MAX * BATT_OP_TIME_100_LOAD * avgChargeLevel) / ConfigLoaded.Population; double nvdimmEnergy = (ConfigLoaded.NumPsus * BATT_POUT_EXTENDED * BATT_OP_TIME_75W_LOAD) / (ConfigLoaded.Population * ConfigLoaded.NvDimmPerBlade); // Scale the values bladeEnergy = bladeEnergy / ENERGY_STORAGE_SCALING_JOULES; nvdimmEnergy = nvdimmEnergy / ENERGY_STORAGE_SCALING_JOULES; // Send battery status to BMC, check returned completion code for success Dictionary <byte, CompletionCode> results = WcsBladeFacade.BroadcastSetEnergyStorage (isBatteryPresent, GetBatteryStateToBroadcast(batteryStates), ENERGY_STORAGE_SCALING_JOULES, (ushort)bladeEnergy, (byte)nvdimmEnergy); // Check if broadcast failed for any blade, if yes log error. for (int index = 1; index <= ConfigLoaded.Population; index++) { CompletionCode code; if (results.TryGetValue((byte)index, out code)) { // If completion code returned is not success if (code != CompletionCode.Success) { Tracer.WriteError("PsuMonitor: ProcessBatteryStatus: " + "Failed to update battery status to BMC for blade: " + index + ", completion code returned: " + code); } } else { // If blade entry does not exist. Tracer.WriteError("PsuMonitor: ProcessBatteryStatus : " + "Failed to update battery status to BMC for blade: " + index); } } } } } } // lock... } // foreach... return(failedPsu); }