/// <summary> /// Function that gets all the fan speed requirements /// from the Blade. It also updates the balde state /// </summary> private void GetAllBladePwmRequirements() { // Rate is required to timestep over each individual Blade call double rate = (double)GetTimePeriod / (double)MaxSledCount; double timeDiff = 0; for (byte blade = 1; blade <= MaxSledCount; blade++) { // Handle shutdown state if (ChassisState.ShutDown) { return; } // default PWM setting byte PWM = (byte)ConfigLoaded.MinPWM; // Query blade type from IPMI layer ChassisState.BladeTypeCache[blade - 1] = (byte)WcsBladeFacade.clients[blade].BladeClassification; // wait for rate limiter which includes the previous time difference for sensor get, and then issue get fan requirement double sleepTime = rate - timeDiff; if (sleepTime > rate) { sleepTime = rate; } if (sleepTime > 0) { Thread.Sleep(TimeSpan.FromMilliseconds(sleepTime)); } if (CommunicationDevice.IsSafeMode()) { // Do not perform any sensor reading - continue in the for loop Tracer.WriteInfo("Monitoring thread: Safe Mode, Skipping sensor read"); continue; } Tracer.WriteInfo("GetBladeRequirement called at {0} for sledId {1} (state: {2})", DateTime.Now, blade, ChassisState.GetStateName(blade)); // Check for the condition where known state is hardpoweroff, but someone plugged a new blade in if (ChassisState.GetBladeState(blade) == (byte)BladeState.HardPowerOff) { ChassisState.PowerFailCount[blade - 1]++; // TODO: identify if this period is sufficient to do this check if (ChassisState.PowerFailCount[blade - 1] > (ConfigLoaded.MaxRetries * ConfigLoaded.Population)) { CheckPowerEnableState(blade); ChassisState.PowerFailCount[blade - 1] = 0; } } // Log Start time DateTime startTime = DateTime.Now; // If blade was in Fail state if (ChassisState.GetBladeState(blade) == (byte)BladeState.Fail) { // If failed count is greater than a maximum value, we move it to Initialization state if (ChassisState.FailCount[blade - 1] > ConfigLoaded.MaxFailCount) { // Move to Initialization state so that this sled could be reinitialized Tracer.WriteInfo("State Transition for Sled {0}: {1} -> Initialization", blade, ChassisState.GetStateName(blade)); ChassisState.SetBladeState(blade, (byte)BladeState.Initialization); } else { // Moving out of Fail state - First we use a light-weight get GUID to check whether the blade is there DeviceGuid guid = WcsBladeFacade.GetSystemGuid(blade); if (guid.CompletionCode == (byte)CompletionCode.Success) { Tracer.WriteInfo("GUID present for sled {0}, GUID: {1}", blade, guid.Guid.ToString()); // Change state to Probation Tracer.WriteInfo("State Transition for Sled {0}: {1} -> Probation", blade, ChassisState.GetStateName(blade)); ChassisState.SetBladeState(blade, (byte)BladeState.Probation); } else { Tracer.WriteInfo("Get System GUID returns a bad completion status: {0}", guid.CompletionCode); } } // Increase time spent in Fail state everytime we are in this state ChassisState.FailCount[blade - 1]++; } // Handles Initialization if (ChassisState.GetBladeState(blade) == (byte)BladeState.Initialization) { this.ReInitialize(blade); } // Normal operation - possible states are probation or healthy if (ChassisState.GetBladeState(blade) == (byte)BladeState.Probation || ChassisState.GetBladeState(blade) == (byte)BladeState.Healthy) { if (ChassisState.GetBladeType(blade) == (byte)BladeType.Jbod) { DeviceGuid guid = WcsBladeFacade.GetSystemGuid(blade); if (guid.CompletionCode == (byte)CompletionCode.Success) { Tracer.WriteInfo("GUID present for jbod {0}, GUID: {1}", blade, guid.Guid.ToString()); // Change state to Probation Tracer.WriteInfo("State Transition for jbod {0}: {1} -> Healthy", blade, ChassisState.GetStateName(blade)); ChassisState.SetBladeState(blade, (byte)BladeState.Healthy); } else { Tracer.WriteInfo("Get System GUID for jbod {0} failed with status {1}", blade, guid.CompletionCode); // Set it to failed state, where we will retry guids and reinitialize if needed Tracer.WriteInfo("State Transition for jbod {0}: {1} -> Fail", blade, ChassisState.GetStateName(blade)); ChassisState.SetBladeState(blade, (byte)BladeState.Fail); } // No need to check for sensor reading, just continue continue; } // Call temperature reading list command SensorReading Temps = WcsBladeFacade.GetSensorReading((byte)blade, (byte)ConfigLoaded.InputSensor, PriorityLevel.System); if (Temps.CompletionCode != (byte)CompletionCode.Success) { Tracer.WriteWarning("SledId: {0} - getTempSensorReading failed with code {1:X}", blade, Temps.CompletionCode); // Move to Fail state if no readings were obtained Tracer.WriteInfo("State Transition for Sled {0}: {1} -> Fail", blade, ChassisState.GetStateName(blade)); ChassisState.SetBladeState(blade, (byte)BladeState.Fail); } else { Tracer.WriteInfo("#### Sledid= " + blade + " Sensor id= " + ConfigLoaded.InputSensor + " Sensor reading= " + Temps.Reading + " Raw= " + Temps.RawReading + ", LowerNonCritical= " + ConfigLoaded.SensorLowThreshold + ", UpperNonCritical= " + ConfigLoaded.SensorHighThreshold); // Handle state logic if needed // Probation state should be shifted to Healthy since there was no timeout, & sensorread succeeded if (ChassisState.GetBladeState(blade) == (byte)BladeState.Probation) { // Change state to healthy Tracer.WriteInfo("State Transition for Sled {0}: {1} -> Healthy", blade, ChassisState.GetStateName(blade)); ChassisState.SetBladeState(blade, (byte)BladeState.Healthy); ChassisState.FailCount[blade - 1] = 0; // reset the fail count } PWM = GetPwmFromTemperature(Temps.Reading, ConfigLoaded.SensorLowThreshold, ConfigLoaded.SensorHighThreshold); Tracer.WriteInfo("PWM value for Sensor {0} = {1}", InputSensor, PWM); } } // write value into requirements table BladeRequirementTable[blade - 1] = PWM; // Log end time and capture time of execution for sensor get command DateTime endTime = DateTime.Now; timeDiff = endTime.Subtract(startTime).TotalMilliseconds; // convert time difference into milliseconds } }
/// <summary> /// Sets the chassis fan speed /// </summary> private void SetAllFanSpeeds() { // rate limiter for setting thread Thread.Sleep(TimeSpan.FromMilliseconds(SetTimePeriod)); // Get max requirement from the bladerequirement table byte maxFanRequest = this.GetMaxRequirement(); if (CommunicationDevice.IsSafeMode()) { // Set fan speed to maximum Tracer.WriteInfo("Safe mode: Setting Fan speed to max"); maxFanRequest = MaxPWM; } Tracer.WriteInfo("Max value got from Blade table = {0} (at {1})", maxFanRequest, DateTime.Now); // Check Fan Status and get number of working fans int numFansWorking = GetAllFanStatus(); // Handle one fan failure if (numFansWorking == MaxFanCount - 1) { // Alert that one fan has failed! Tracer.WriteError("Fan failure, applying conversion"); // Denote fan failure in chassis ChassisState.FanFailure = true; double conversion = (double)MaxFanCount / (double)(MaxFanCount - 1); maxFanRequest = (byte)(conversion * maxFanRequest); } else if (numFansWorking < MaxFanCount - 1) { // Set fan speed to max for fan failures more than N-1 maxFanRequest = MaxPWM; // this is to set at max speed Tracer.WriteError("More than 1 Fans failed"); // Denote that this is a fan failure in chassis ChassisState.FanFailure = true; } else { // All fans are working fine - check rear attention LED and if on, turn it off (by setting fanFailure to false) ChassisState.FanFailure = false; } // Do altitude correction maxFanRequest = (byte)((1 + ConfigLoaded.AltitudeCorrectionFactor * (int)(ConfigLoaded.Altitude / 1000)) * maxFanRequest); // Bound fan request to the maximum possible if (maxFanRequest > MaxPWM) { maxFanRequest = MaxPWM; } // Enable Ramp Down in smaller steps if (PrevFanPWM >= maxFanRequest + 2 * ConfigLoaded.StepPWM) { maxFanRequest = (byte)(PrevFanPWM - ConfigLoaded.StepPWM); } // Set fan speed for all fans - setting one fan device is enough, since setfanspeed is for all fan devices byte status = ChassisState.Fans[0].SetFanSpeed(maxFanRequest); // Trace the speed of fan Tracer.WriteInfo("Fan speed = " + ChassisState.Fans[0].GetFanSpeed()); if (status != (byte)CompletionCode.Success) { Tracer.WriteWarning("SetFanSpeed failed with Completion Code: {0:X}", status); } else { Tracer.WriteInfo("Fan Speed set to {0}", maxFanRequest); } // Store current fan PWM in PrevFanPWM for next iteration PrevFanPWM = maxFanRequest; }
/// <summary> /// Initialize Chassis constants and configs /// </summary> internal byte Initialize() { Tracer.WriteInfo("Initializing state"); byte status = (byte)CompletionCode.UnspecifiedError; ChassisState.Initialize(); Tracer.WriteInfo("Initializing Communication Device"); // Initializer lower layer communication device CompletionCode completionCode = CommunicationDevice.Init(); if (CompletionCodeChecker.Failed(completionCode)) { Tracer.WriteWarning("Initialization failed: {0}", completionCode); int loop = 0; // Retry 3 times before failing completely for (loop = 0; loop < ConfigLoaded.MaxRetries; loop++) { Tracer.WriteInfo("Initialization Retry: {0}", loop); completionCode = CommunicationDevice.Init(); if (CompletionCodeChecker.Succeeded(completionCode)) { break; } } if (loop == ConfigLoaded.MaxRetries) { Tracer.WriteError("Re-attempt at Communication Device Initialization failed with code: {0}", completionCode); return(status); } } if (CompletionCodeChecker.Succeeded(completionCode)) { Tracer.WriteInfo("Communication Device Initialized"); status = (byte)CompletionCode.Success; } // Get power status of enable pin for each blade and update blade state for (byte deviceId = 1; deviceId <= MaxSledCount; deviceId++) { CheckPowerEnableState(deviceId); } // Initialize Wcs Blade - TODO: This initialize should return some status WcsBladeFacade.Initialize(); // This method just creates IPMI Client Class for each blade. Tracer.WriteInfo("IPMI Facade Initialized, Number of blades initialized: {0}", WcsBladeFacade.Initialized); // check all client initialization status and update state Tracer.WriteInfo("Checking client status for {0} blades", MaxSledCount); for (byte deviceId = 1; deviceId <= MaxSledCount; deviceId++) { // TODO: How to check initialized status, now that this has become a function if (WcsBladeFacade.clients[deviceId].Initialize()) // This method logs on to an IPMI session. { // If initialized is true, change state to probation Tracer.WriteInfo("State Transition for Sled {0}: {1} -> Probation", deviceId, ChassisState.GetStateName(deviceId)); ChassisState.SetBladeState(deviceId, (byte)BladeState.Probation); } else { Tracer.WriteInfo("Blade not initialized: Blade ", +deviceId); } } Tracer.WriteInfo("Initializing Watchdog Timer"); // Initialize WatchDog Timer ChassisState.Wdt.EnableWatchDogTimer(); Tracer.WriteInfo("Watchdog timer initialized"); // Initialize internal chassis manager tables this.ChassisInternalInitialize(); return(status); }