/// <summary>
        /// Thread functions to run the set commands
        /// </summary>
        private static void RunSetDeviceCommands()
        {
            while (true)
            {
                try
                {
                    if (ChassisState.ShutDown)
                    {
                        return;
                    }

                    if (ConfigLoaded.EnableFan)
                    {
                        // Step 1. Set All Fan Speeds if EnableFan is set.
                        SetAllFanSpeeds();
                    }

                    // Step 2. Check Serial Console Inactivity.
                    CheckBladeConsoleInactivity();

                    // Step 3. Reset Watch Dog Timer
                    ResetWatchDog();

                    // Step 4. Set Attention Leds
                    SetAttentionLeds();
                }
                catch (Exception ex)
                {
                    Tracer.WriteWarning("Chassis Manager RunSetDeviceCommands thread encountered an exception " + ex);
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Write to Chassis Fru - (Important) note that this function enables write to any offset
        /// Offset checks ensures that we are within permissible limits, but cannot enforce semantics within those limits
        /// Length checks validity of packet, however empty fields in packet are responsibility of writing function
        /// User level priority since this is not an internal call
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="length"></param>
        /// <param name="packet"></param>
        /// <returns></returns>
        public byte writeChassisFru(ushort offset, ushort length, byte[] packet)
        {
            byte deviceId = 1;

            ChassisFruWriteResponse response = new ChassisFruWriteResponse();

            try
            {
                response = (ChassisFruWriteResponse)this.SendReceive(DeviceType.ChassisFruEeprom, deviceId, new ChassisFruWriteRequest(offset, length, packet),
                                                                     typeof(ChassisFruWriteResponse), (byte)PriorityLevel.User);
            }
            catch (Exception ex)
            {
                Tracer.WriteWarning("ChassisFru write had an exception", ex);
            }

            if (response.CompletionCode != (byte)CompletionCode.Success)
            {
                Tracer.WriteError("Fru Write failed with completion code {0:X}", response.CompletionCode);
            }
            else
            {
                Tracer.WriteInfo("Fru Write succeeded");
            }

            return((byte)response.CompletionCode);
        }
        /// <summary>
        /// Checks the validity of the current blade id passed
        /// </summary>
        /// <param name="bladeId"></param>
        /// <returns></returns>
        public static bool checkBladeTypeValidity(byte bladeId)
        {
            try
            {
                // Open the request message using an xml reader
                XmlReader xr = OperationContext.Current.IncomingMessageHeaders.GetReaderAtHeader(0);

                // Split the URL at the API name--Parameters junction indicated by the '?' character - taking the first string will ignore all parameters
                string[] urlSplit = xr.ReadElementContentAsString().Split('/');
                // Extract just the API name and rest of the URL, which will be the last item in the split using '/'
                string[] apiSplit = urlSplit[3].Split('?');

                BladeType val = BladeType.Unknown;
                invalidBladeFunction.TryGetValue(apiSplit[0], out val);

                // If the blade type does not support this function, return false, so we can send back useful info to user
                if ((byte)val == ChassisState.GetBladeType(bladeId))
                {
                    Tracer.WriteWarning("Command {0} not valid for Blade id {1}, Blade Type {2}",
                                        apiSplit[0], bladeId, ChassisState.GetBladeTypeName((byte)val));

                    return(false);
                }
            }
            catch (Exception ex)
            {
                Tracer.WriteError("Checking Blade Type validity encountered an exception" + ex);
                // We decide to go ahead and issue the command to the blade if the blade type check fails with exception,
                // This is done in order to not penalize a user command based on some failure in checking
                // The command might fail eventually, but with an unhelpful error message
            }
            return(true);
        }
Esempio n. 4
0
        /// <summary>
        /// Reads raw CM information - can be called individually if needed
        /// User level priority since this is not an internal call
        /// </summary>
        public ChassisFruReadResponse readRawChassisFru(ushort offset, ushort length)
        {
            byte deviceId = 1;
            ChassisFruReadResponse response = new ChassisFruReadResponse();

            try
            {
                response = (ChassisFruReadResponse)this.SendReceive(DeviceType.ChassisFruEeprom, deviceId, new ChassisFruReadRequest(offset, length),
                                                                    typeof(ChassisFruReadResponse), (byte)PriorityLevel.User);
            }
            catch (Exception ex)
            {
                Tracer.WriteWarning("Chassis Fru read had an exception", ex);
            }

            if (response.CompletionCode != (byte)CompletionCode.Success)
            {
                Tracer.WriteError("Fru read failed with completion code {0:X}", response.CompletionCode);
            }
            else
            {
                Tracer.WriteInfo("Chassis Fru info read: {0:X}", response.DataReturned.ToString());
            }
            return(response);
        }
        // Returns the most privileged role this user belongs to
        static internal authorizationRole GetCurrentUserMostPrivilegedRole()
        {
            try
            {
                ServiceSecurityContext context         = OperationContext.Current.ServiceSecurityContext;
                WindowsIdentity        windowsIdentity = context.WindowsIdentity;
                var principal = new WindowsPrincipal(windowsIdentity);

                // Extract domain + role names to check for access privilege
                // The first item before '\' is the domain name - extract it
                string[] usernameSplit = windowsIdentity.Name.Split('\\');
                // Apend role names after the domain name
                string wcscmadminRole    = usernameSplit[0] + "\\" + "WcsCmAdmin";
                string wcscmoperatorRole = usernameSplit[0] + "\\" + "WcsCmOperator";
                string wcscmuserRole     = usernameSplit[0] + "\\" + "WcsCmUser";

                if (principal.IsInRole("Administrators"))
                {
                    Tracer.WriteUserLog("User({0}) belongs to Administrators group and hence belongs to WcsCmAdmin privilege role", windowsIdentity.Name);
                    return(authorizationRole.WcsCmAdmin);
                }

                // Is user in local WcsCmAdmin group or domain's WcsCmAdmin group?
                if (principal.IsInRole("WcsCmAdmin") || principal.IsInRole(wcscmadminRole))
                {
                    Tracer.WriteUserLog("User({0}) belongs to WcsCmAdmin privilege role", windowsIdentity.Name);
                    return(authorizationRole.WcsCmAdmin);
                }

                // Is user in local WcsCmOperator group or domain's WcsCmOperator group?
                if (principal.IsInRole("WcsCmOperator") || principal.IsInRole(wcscmoperatorRole))
                {
                    Tracer.WriteUserLog("User({0}) belongs to WcsCmOperator privilege role", windowsIdentity.Name);
                    return(authorizationRole.WcsCmOperator);
                }

                // Is user in local WcsCmUser group or domain's WcsCmUser group?
                if (principal.IsInRole("WcsCmUser") || principal.IsInRole(wcscmuserRole))
                {
                    Tracer.WriteUserLog("User({0}) belongs to WcsCmUser privilege role", windowsIdentity.Name);
                    return(authorizationRole.WcsCmUser);
                }
                // User not mapped to any standard roles
                Tracer.WriteWarning("GetCurrentUserMostPrivilegedRole: Current user({0}) not mapped to the standard WCS roles", windowsIdentity.Name);
                Tracer.WriteUserLog("GetCurrentUserMostPrivilegedRole: Current user({0}) not mapped to the standard WCS roles", windowsIdentity.Name);
            }
            catch (Exception ex)
            {
                Tracer.WriteError("User Authorization check exception  was thrown: " + ex);
            }

            // Return as unauthorized if the user do not belong to any of the category or if there is an exception
            return(authorizationRole.WcsCmUnAuthorized);
        }
Esempio n. 6
0
        /// <summary>
        /// Identifies the PSU vendor at each psu slot using the modelnumber API of the PsuBase class
        /// (Assumes all PSU vendors implement the MFR_MODEL Pmbus command)
        /// Based on the model number, we bind the Psu class object to the corresponding child (vendor) class object
        /// </summary>
        private static void PsuInitialize()
        {
            for (uint psuIndex = 0; psuIndex < ConfigLoaded.NumPsus; psuIndex++)
            {
                // Initially create instance of the base class
                // Later.. based on the psu model number, we create the appropriate psu class object
                Psu[psuIndex] = new PsuBase((byte)(psuIndex + 1));

                PsuModelNumberPacket modelNumberPacket = new PsuModelNumberPacket();
                modelNumberPacket = Psu[psuIndex].GetPsuModel();
                string   psuModelNumber = modelNumberPacket.ModelNumber;
                PsuModel model          = ConvertPsuModelNumberToPsuModel(psuModelNumber);

                switch (model)
                {
                case PsuModel.Delta:
                    Psu[psuIndex] = new DeltaPsu((byte)(psuIndex + 1));
                    Tracer.WriteInfo("Delta PSU identified at slot-{0}, Model Number: {1}", psuIndex + 1, psuModelNumber);
                    break;

                case PsuModel.EmersonWithLes:
                    Psu[psuIndex] = new EmersonPsu((byte)(psuIndex + 1), true);
                    Tracer.WriteInfo("Emerson with LES PSU identified at slot-{0}, Model Number: {1}", psuIndex + 1, psuModelNumber);
                    break;

                case PsuModel.EmersonNonLes:
                    Psu[psuIndex] = new EmersonPsu((byte)(psuIndex + 1), false);
                    Tracer.WriteInfo("Emerson non-LES PSU identified at slot-{0}, Model Number: {1}", psuIndex + 1, psuModelNumber);
                    break;

                default:
                    // Unknown PSUs
                    if (ConfigLoaded.ForceEmersonPsu)
                    {
                        // Force to Emerson PSU without LES to enable FW update methods in the EmersonPsu class to be called.
                        // This is useful when a previous FW update did not complete successfully.
                        // The PSU stays in bootloader mode and does not recognize the
                        // MFR_MODEL command and will return all 0xFFs for this command.
                        Psu[psuIndex] = new EmersonPsu((byte)(psuIndex + 1), false);
                        Tracer.WriteWarning("Forcing PSU instantiation to Emerson non-LES PSU at slot-{0}, Model Number: {1}",
                                            psuIndex + 1, psuModelNumber);
                    }
                    else
                    {
                        Psu[psuIndex] = new PsuBase((byte)(psuIndex + 1));
                        Tracer.WriteInfo("Unidentified PSU at slot-{0}, Model Number: {1}. Default to base PSU class.", psuIndex + 1, psuModelNumber);
                    }
                    break;
                }

                // Enable/disable Battery Extended Operation Mode
                Psu[psuIndex].SetBatteryExtendedOperationMode(ConfigLoaded.DatasafeOperationsEnabled ? true: false);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Gets the PSU status for all PSUs
        /// </summary>
        private void GetAllPsuStatus()
        {
            int countStatus = 0;

            for (int numPsus = 0; numPsus < MaxPsuCount; numPsus++)
            {
                try
                {
                    PsuStatusPacket psuStatusPacket = new PsuStatusPacket();
                    psuStatusPacket = ChassisState.Psu[numPsus].GetPsuStatus();
                    if (psuStatusPacket.CompletionCode != CompletionCode.Success)
                    {
                        Tracer.WriteWarning("PSU ({0}) get status request failed with return code {1}", numPsus + 1, psuStatusPacket.CompletionCode);
                    }
                    else
                    {
                        if (psuStatusPacket.PsuStatus == (byte)Contracts.PowerState.ON)
                        {
                            countStatus++;
                        }
                        else
                        {
                            Tracer.WriteWarning("PSU ({0}) PowerGood signal is negated - check trace log for fault information", numPsus + 1);
                            CompletionCode clearFaultCompletionCode = ChassisState.Psu[numPsus].SetPsuClearFaults();
                            if (clearFaultCompletionCode != CompletionCode.Success)
                            {
                                Tracer.WriteError("PsuStatus clear fault (invoked upon negated power good signal) command failed. Completion code({0})", clearFaultCompletionCode);
                            }
                            else
                            {
                                Tracer.WriteWarning("PsuStatus clear fault (invoked upon negated power good signal) command succeeded.");
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Tracer.WriteError("PSU {0} status check failed with Exception: {1}", numPsus + 1, e);
                }
            }

            // Identify whether there is a PSU failure or not
            if (countStatus != MaxPsuCount)
            {
                ChassisState.PsuFailure = true;
            }
            else
            {
                ChassisState.PsuFailure = false;
            }
        }
        /// <summary>
        /// Attempts to retrieve the Psu Status. This method
        /// calls down to the Chassis Manager with SendReceive
        /// </summary>
        private PsuStatusPacket GetPsuStatus(byte psuId)
        {
            // Initialize return packet
            PsuStatusPacket returnPacket = new PsuStatusPacket();

            returnPacket.CompletionCode = CompletionCode.UnspecifiedError;
            returnPacket.PsuStatus      = 0;
            returnPacket.FaultPresent   = false;

            try
            {
                PsuStatusResponse myResponse = new PsuStatusResponse();
                myResponse = (PsuStatusResponse)this.SendReceive(this.PsuDeviceType, this.PsuId,
                                                                 new PsuRequest((byte)PmBusCommand.STATUS_WORD, (byte)PmBusResponseLength.STATUS_WORD), typeof(PsuStatusResponse));

                if (myResponse.CompletionCode != 0)
                {
                    returnPacket.CompletionCode = (CompletionCode)myResponse.CompletionCode;
                    Tracer.WriteWarning("GetPsuStatus Failure for PSU {0}: Completion Code: {1}", psuId, myResponse.CompletionCode);
                }
                else
                {
                    returnPacket.CompletionCode = CompletionCode.Success;
                    byte   varStatus;
                    byte[] psuStatus = myResponse.PsuStatus;

                    // If there are any other faults, indicate fault is present and log the full status word
                    if (!PmBus.ExtractPowerGoodFromPsuStatus(psuStatus, out varStatus))
                    {
                        Tracer.WriteWarning("GetPsuStatus: Psu ({0}) STATUS_WORD is non-zero: " +
                                            "(High Byte: {1} Low Byte: {2}) (See STATUS_WORD register in PmBusII Manual)",
                                            this.PsuId,
                                            System.Convert.ToString(psuStatus[1], 2).PadLeft(8, '0'),
                                            System.Convert.ToString(psuStatus[0], 2).PadLeft(8, '0'));

                        returnPacket.FaultPresent = true;
                    }

                    returnPacket.PsuStatus = varStatus;
                }
            }
            catch (System.Exception ex)
            {
                returnPacket.CompletionCode = CompletionCode.UnspecifiedError;
                returnPacket.PsuStatus      = 0;
                Tracer.WriteError("GetPsuStatus Exception: " + ex);
            }
            return(returnPacket);
        }
        /// <summary>
        /// Gets the current status of rear attention LED for the chassis
        /// </summary>
        /// <returns></returns>
        private static byte GetRearAttentionLedStatus()
        {
            // Gets the LED status response
            Contracts.LedStatusResponse ledStatus = new Contracts.LedStatusResponse();
            ledStatus = ChassisState.AttentionLed.GetLedStatus();

            if (ledStatus.completionCode != Contracts.CompletionCode.Success)
            {
                Tracer.WriteWarning("Internal getRearAttentionLedStatus - getting status failed with Completion Code {0:X}",
                                    ledStatus.completionCode);
                return((byte)LedStatus.NA);
            }
            else
            {
                return((byte)ledStatus.ledState);
            }
        }
Esempio n. 10
0
        // This function should be called before executing any service APIs
        // TODO: Add other checks that needs to be done before executing APIs - like check for chassis terminating etc
        internal static CompletionCode ApiGreenSignalling()
        {
            CompletionCode response = new CompletionCode();

            response = CompletionCode.UnspecifiedError;

            int currBladeId = bladeId;

            // Return Success if there is no active serial console session in progress
            if (!BladeSerialSessionMetadata.IsSerialConsoleSessionActive())
            {
                response = CompletionCode.Success;
                return(response);
            }

            // If App.config parameter, KillSerialConsoleSession, is enabled,
            // terminate existing serial console session and proceed executing incoming commmands.
            if (ConfigLoaded.KillSerialConsoleSession)
            {
                response = CompletionCode.UnspecifiedError;

                Tracer.WriteInfo("Kill serial console session is enabled to allow incoming commands to succeed.");
                Contracts.ChassisResponse sessionResponse = new Contracts.ChassisResponse();
                sessionResponse = StopBladeSerialSession(ConfigLoaded.InactiveBladePortId, ConfigLoaded.InactiveBladeSerialSessionToken, true);
                if (sessionResponse.completionCode != Contracts.CompletionCode.Success)
                {
                    Tracer.WriteError("BladeSerialSessionMetadata.ApiGreenSignalling:Error stopserialsession failed");
                    return(response);
                }

                response = CompletionCode.Success;
                return(response);
            }
            // If App.config parameter, KillSerialConsoleSession, is not  enabled, maintain existing serial console session,
            // and ignore incoming commands, with explicit failure message output as warning in trace, since it will not
            // affect service correctness.
            else
            {
                response = CompletionCode.SerialPortOtherErrors;
                Tracer.WriteWarning("Serial console session in progress. Ignore incoming command with message:{0}", response);

                // We are returning non-Success completion code (represented as SerialPortOtherErrors)
                // to indicate/trigger the failure of this incoming command.
                return(response);
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Internal operation to call both hard power on (soft power on is not exposed to the user)
        /// </summary>
        /// <param name="bladeId">Blade ID</param>
        /// <returns>True/false for success/failure</returns>
        internal static bool PowerOn(int bladeId)
        {
            Tracer.WriteInfo("Received poweron({0})", bladeId);
            bool powerOnStatus = false;

            BladePowerStatePacket bladePowerSwitchStatePacket = new BladePowerStatePacket();
            CompletionCode        status;

            // Hard Power enable
            // Serialize setting of state and actual code logic
            lock (ChassisState.locker[bladeId - 1])
            {
                BladePowerStatePacket currState = ChassisState.BladePower[bladeId - 1].GetBladePowerState();

                if (currState.CompletionCode != CompletionCode.Success ||
                    (currState.BladePowerState == (byte)Contracts.PowerState.OFF))
                {
                    // No return here, because we still want to return a BMC state on the fall through,
                    // if Blade enable read fails for whatever reason
                    Tracer.WriteWarning("PowerOn: Blade {0} Power Enable state read failed (Completion Code: {1:X})", bladeId, currState.CompletionCode);

                    bladePowerSwitchStatePacket = ChassisState.BladePower[bladeId - 1].SetBladePowerState((byte)PowerState.ON);
                    status = bladePowerSwitchStatePacket.CompletionCode;
                    Tracer.WriteInfo("Hard poweron status " + status);

                    if (status == CompletionCode.Success)
                    {
                        // Hard power on status is true, so Blade should be set to Initialization state on success
                        Tracer.WriteInfo("PowerOn: State Transition for blade {0}: {1} -> Initialization", bladeId,
                                         ChassisState.GetStateName((byte)bladeId));

                        ChassisState.SetBladeState((byte)bladeId, (byte)BladeState.Initialization);
                        powerOnStatus = true;
                    }
                    else
                    {
                        Tracer.WriteWarning("PowerOn: Hard Power On failed for BladeId {0} with code {1:X}", bladeId, status);
                    }
                }
                else
                {
                    powerOnStatus = true; // the blade was already powered on, so we dont power it on again
                }
            }
            return(powerOnStatus);
        }
Esempio n. 12
0
        /// <summary>
        /// The code that is executed by the worker thread
        /// 1. Wait for a new work item
        /// 2. Generate a data packet using the request information
        /// 3. Send the generated packet over the port
        /// 4. Receive the response from the target hardware device
        /// 5. Generate/copy a response packet
        /// 6. Signal the waiting user-level thread
        /// 7. Repeat above
        /// Note: For serviceability purpose, continue to execute
        /// the main loop even with an unhandled exception
        /// </summary>
        private void WorkerThreadFunction()
        {
            while (true)
            {
                try
                {
                    while (true)
                    {
                        WorkItem workItem;

                        // Get a new work item
                        workItem = GetWorkItem();

                        if (workItem != null)
                        {
                            Tracer.WriteInfo("[Worker] logicalPortId: {0}, Signaled", logicalPortId);
                            if (shouldTerminateWorkerThread == true)
                            {
                                Tracer.WriteWarning("[Worker] Draining the remaining work item before terminating CM");
                            }
                            SendReceive(ref workItem);
                        }
                        else
                        {
                            // If CM is about to gracefully terminate and there is no more work item in the
                            // queues (i.e., all the queues have been drained), stop this worker thread
                            // by exiting from the main loop
                            if (shouldTerminateWorkerThread == true)
                            {
                                Tracer.WriteInfo("[Worker] Stopping worker threads", logicalPortId);
                                return;
                            }
                            WaitForWorkItem();
                        }
                    }
                }
                catch (Exception e)
                {
                    Tracer.WriteError("Unhandled Exception in PortManager worker thread main loop");
                    Tracer.WriteError(e);
                }
            }
        }
Esempio n. 13
0
        /// <summary>
        /// BladeOff commands switches off blade through IPMI (soft blade off)
        /// </summary>
        /// <param name="bladeId"></param>
        /// <returns></returns>
        internal static bool BladeOff(int bladeId)
        {
            bool powerOffStatus = false;

            // Soft power enable
            byte softStatus = WcsBladeFacade.SetPowerState((byte)bladeId, Ipmi.IpmiPowerState.Off);

            Tracer.WriteInfo("Soft poweroff status " + softStatus);

            if (softStatus != (byte)CompletionCode.Success)
            {
                Tracer.WriteWarning("Blade Soft Power Off Failed with Completion Code {0:X}", softStatus);
            }
            else
            {
                powerOffStatus = true;
            }
            return(powerOffStatus);
        }
        /// <summary>
        /// Converts inlet temperature to PWM value
        /// </summary>
        /// <param name="temperature"></param>
        /// <returns></returns>
        private static byte GetPwmFromTemperature(double temperature, double lowThreshold, double highThreshold)
        {
            byte PWM = (byte)ConfigLoaded.MinPWM; // set to min as default

            if (lowThreshold >= highThreshold)
            {
                Tracer.WriteWarning("Low Threshold Temperature is greater or equal compared to high threshold");
                return(PWM);
            }
            // PWM should never be higher or lower than the threshold.
            if (temperature < lowThreshold || temperature > highThreshold)
            {
                Tracer.WriteWarning("Temperature value {0} is out of range (lowThreshold {1} - highThreshold {2})",
                                    temperature, lowThreshold, highThreshold);
                return(PWM);
            }

            // Find PWM corresponding to temperature value from low threshold and range value
            // Linear extrapolation requires current value, range for consideration and the low-threshold so that
            // we can compute the PWM (as a value between 20-100)
            if (temperature <= highThreshold)
            {
                // These thresholds are read from threshold values in SDR record
                double range = highThreshold - lowThreshold;
                double value = ConfigLoaded.MinPWM + ((temperature - lowThreshold) / range) * (MaxPWM - ConfigLoaded.MinPWM);
                PWM = (byte)value;

                // Reset to MinPWM if calculated PWM is lower than MinPWM
                if (PWM < ConfigLoaded.MinPWM)
                {
                    PWM = (byte)ConfigLoaded.MinPWM;
                }

                // Set PWM to MaxPWM if calculated PWM is more than MaxPWM
                if (PWM > MaxPWM)
                {
                    PWM = MaxPWM;
                }
            }

            return(PWM);
        }
        /// <summary>
        /// Sets the rear attention LED to on or off based on ledState param (0 - off, 1 - on)
        /// </summary>
        /// <param name="ledState"></param>
        private static byte SetRearAttentionLedStatus(byte ledState)
        {
            byte completionCode = (byte)CompletionCode.UnspecifiedError;

            if (ledState == (byte)LedStatus.On)
            {
                completionCode = ChassisState.AttentionLed.TurnLedOn();
                Tracer.WriteInfo("Internal setRearAttentionLEDStatus - LEDOn Return: {0:X}", completionCode);
            }
            if (ledState == (byte)LedStatus.Off)
            {
                completionCode = ChassisState.AttentionLed.TurnLedOff();
                Tracer.WriteInfo("Internal setRearAttentionLEDStatus - LEDOff Return: {0:X}", completionCode);
            }
            if (completionCode != (byte)CompletionCode.Success)
            {
                Tracer.WriteWarning("Internal setRearAttentionLEDStatus error - completion code: {0:X}", completionCode);
            }
            return(completionCode);
        }
Esempio n. 16
0
        /// <summary>
        /// Attempts to retrieve the Psu Status. This method
        /// calls down to the Chassis Manager with SendReceive
        /// </summary>
        private PsuStatusPacket GetPsuStatus(byte psuId)
        {
            // Initialize return packet
            PsuStatusPacket returnPacket = new PsuStatusPacket();

            returnPacket.CompletionCode = CompletionCode.UnspecifiedError;
            returnPacket.PsuStatus      = 0;

            try
            {
                PsuStatusResponse myResponse = new PsuStatusResponse();
                myResponse = (PsuStatusResponse)this.SendReceive(this.PsuDeviceType, this.PsuId, new PsuRequest((byte)PmBusCommand.STATUS_WORD, (byte)PmBusResponseLength.STATUS_WORD), typeof(PsuStatusResponse));

                if (myResponse.CompletionCode != 0)
                {
                    returnPacket.CompletionCode = (CompletionCode)myResponse.CompletionCode;
                    Tracer.WriteWarning("GetPsuStatus Failure: status({0})", returnPacket.PsuStatus);
                }
                else
                {
                    returnPacket.CompletionCode = CompletionCode.Success;
                    byte   varStatus;
                    byte[] psuStatus = myResponse.PsuStatus;

                    // If there are any other faults, print the full status word
                    if (!PmBus.ExtractPowerGoodFromPsuStatus(psuStatus, out varStatus))
                    {
                        Tracer.WriteWarning("Psu({0}) PowerGood Negated ({1} {2}) in/out curr/volt faults (See StatusWord in PmBusII Manual)", this.PsuId, System.Convert.ToString(psuStatus[0], 2).PadLeft(8, '0'), System.Convert.ToString(psuStatus[1], 2).PadLeft(8, '0'));
                    }

                    returnPacket.PsuStatus = varStatus;
                }
            }
            catch (System.Exception ex)
            {
                returnPacket.CompletionCode = CompletionCode.UnspecifiedError;
                returnPacket.PsuStatus      = 0;
                Tracer.WriteError("GetPsuStatus Exception: " + ex);
            }
            return(returnPacket);
        }
        /// <summary>
        /// Initialize Communication Device
        /// </summary>
        /// <returns>status byte which indicates whether initialization was successful or not</returns>
        private static byte CommunicationDeviceInitialize()
        {
            byte status = (byte)CompletionCode.UnspecifiedError;

            Tracer.WriteInfo("Initializing Communication Device");
            CompletionCode completionCode = CommunicationDevice.Init();

            #region Comm. Device Initialization Retry
            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);
                }
            }
            #endregion

            if (CompletionCodeChecker.Succeeded(completionCode))
            {
                Tracer.WriteInfo("Communication Device Initialization successful..");
            }

            return((byte)CompletionCode.Success);
        }
 // Returns the least privileged role with access to this API
 static internal authorizationRole GetCurrentApiLeastPrivilegedRole(string apiName)
 {
     try
     {
         authorizationRole val = authorizationRole.WcsCmUnAuthorized;
         // If api name do not map to any of the mapped roles, then by default make it accessible only by WcsCmAdmin role
         if (!apiNameLeastPrivilegeRoleMap.TryGetValue(apiName, out val))
         {
             Tracer.WriteWarning("GetCurrentApiLeastPrivilegedRole: There is no role mapping for the api " + apiName);
             return(authorizationRole.WcsCmAdmin);
         }
         Tracer.WriteInfo("Requested API's minimum privilege requirement: " + val);
         return(val);
     }
     catch (Exception ex)
     {
         Tracer.WriteError("Api-to-Role Mapping Exception was thrown: " + ex);
         // Return as UnAuthorized if there is an exception, then by default make this API accessible only by WcsCmAdmin role
         Tracer.WriteInfo("Requested API's minimum privilege requirement (after exception):  " + authorizationRole.WcsCmAdmin);
         return(authorizationRole.WcsCmAdmin);
     }
 }
Esempio n. 19
0
        private SerialDataPacket receiveSerialData(byte id)
        {
            // Initialize return packet
            SerialDataPacket returnPacket = new SerialDataPacket();

            returnPacket.completionCode = CompletionCode.UnspecifiedError;
            returnPacket.data           = null;

            try
            {
                // Call device layer below
                SerialConsolePortReceiveResponse serialResponse =
                    (SerialConsolePortReceiveResponse)this.SendReceive(this.SerialPortConsoleDeviceType, translateSerialPortId(this.PortId),
                                                                       new SerialConsolePortReceiveRequest(), typeof(SerialConsolePortReceiveResponse), (byte)PriorityLevel.User);

                // check for completion code
                if (serialResponse.CompletionCode != 0)
                {
                    returnPacket.completionCode = (CompletionCode)serialResponse.CompletionCode;
                }
                else
                {
                    returnPacket.completionCode = CompletionCode.Success;
                    if (serialResponse.ReceiveData == null)
                    {
                        Tracer.WriteWarning("Data is empty in SerialPortConsole.receiveSerialData");
                    }
                    returnPacket.data = serialResponse.ReceiveData;
                }
            }
            catch (System.Exception ex)
            {
                returnPacket.completionCode = CompletionCode.UnspecifiedError;
                returnPacket.data           = null;
                Tracer.WriteError(this.PortId, DeviceType.SerialPortConsole, ex);
            }

            return(returnPacket);
        }
Esempio n. 20
0
        /// <summary>
        /// Add a work item into a work queue.
        /// Return fail if the parameter is not valid and/or
        /// the target queue is currently full
        /// The caller must check the return value
        /// </summary>
        /// <param name="priorityLevel"></param>
        /// <param name="workItem"></param>
        /// <returns></returns>
        internal bool SendReceive(PriorityLevel priorityLevel, WorkItem workItem)
        {
            Queue workQueue = GetWorkQueue(priorityLevel);

            // Invalid priority level
            if (workQueue == null)
            {
                return(false);
            }

            // Must be thread-safe as other user-level thread or the device-level thread
            // can concurrently access the queue
            lock (workQueue.SyncRoot)
            {
                if (workQueue.Count > maxQueueLength)
                {
                    // Invalid execution path: should not reach here
                    Tracer.WriteError("[Error, PortManager: {0}, priorityLevel: {1}] Queue (size: {2}) overflowed",
                                      logicalPortId, priorityLevel, workQueue.Count);
                    return(false);
                }
                else if (workQueue.Count == maxQueueLength)
                {
                    // The work queue is current full and cannot serve the request
                    Tracer.WriteWarning("[PortManager: {0}, priorityLevel: {1}] Full", logicalPortId, priorityLevel);
                    return(false);
                }

                // Insert the work item
                workQueue.Enqueue(workItem);
            }

            // Signal the worker thread to process the work item that has been just inserted
            autoEvent.Set();

            // The work item has been successfully inserted
            return(true);
        }
        /// <summary>
        /// Thread function for running get blade requirement continuously
        /// </summary>
        private static void RunGetAllBladeRequirements()
        {
            while (true)
            {
                try
                {
                    while (true)
                    {
                        if (ChassisState.ShutDown)
                        {
                            return;
                        }

                        // Get Blade Pwm requirements.
                        GetAllBladePwmRequirements();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.WriteWarning("Chassis Manager RunGetAllBladeRequirements thread encountered an exception " + ex);
                }
            }
        }
        /// <summary>
        /// Monitors PSU and takes remedial actions.  Called by PSU_ALERT thread.
        /// </summary>
        internal static void MonitorPsuAlert()
        {
            if (ConfigLoaded.NumPsus > 0)
            {
                try
                {
                    while (true)
                    {
                        if (ChassisState.ShutDown)
                        {
                            Tracer.WriteWarning("Psu Monitoring Thread Exiting");
                            return;
                        }

                        // Monitor PSU
                        MonitorPsuAlertHelper();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.WriteWarning("Chassis Manager MonitorPsuAlert thread encountered an exception " + ex);
                }
            }
        }
        /// <summary>
        /// Attempts to retrieve the Psu fault status registers. This method
        /// calls down to the Chassis Manager with SendReceive
        /// </summary>
        private PsuResponseBasePacket LogPsuFaultStatus(byte psuId)
        {
            // Initialize return packet
            PsuResponseBasePacket returnPacket = new PsuResponseBasePacket();

            returnPacket.CompletionCode = CompletionCode.Success;

            try
            {
                PsuCommandByteResponse response = new PsuCommandByteResponse();

                // STATUS_VOUT
                response = (PsuCommandByteResponse)this.SendReceive(this.PsuDeviceType, this.PsuId,
                                                                    new PsuRequest((byte)PmBusCommand.STATUS_VOUT, (byte)PmBusResponseLength.STATUS_VOUT), typeof(PsuCommandByteResponse));
                if (response.CompletionCode != 0)
                {
                    returnPacket.CompletionCode = (CompletionCode)response.CompletionCode;
                    Tracer.WriteWarning("LogPsuFaultStatus: Failed to read STATUS_VOUT on PSU {0}: Completion Code: {1}", psuId, response.CompletionCode);
                }
                else
                {
                    Tracer.WriteWarning("LogPsuFaultStatus: PSU {0} STATUS_VOUT: {1}", psuId, System.Convert.ToString(response.PsuByteResponse, 2).PadLeft(8, '0'));
                }

                // STATUS_IOUT
                response = (PsuCommandByteResponse)this.SendReceive(this.PsuDeviceType, this.PsuId,
                                                                    new PsuRequest((byte)PmBusCommand.STATUS_IOUT, (byte)PmBusResponseLength.STATUS_IOUT), typeof(PsuCommandByteResponse));
                if (response.CompletionCode != 0)
                {
                    returnPacket.CompletionCode = (CompletionCode)response.CompletionCode;
                    Tracer.WriteWarning("LogPsuFaultStatus: Failed to read STATUS_IOUT on PSU {0}: Completion Code: {1}", psuId, response.CompletionCode);
                }
                else
                {
                    Tracer.WriteWarning("LogPsuFaultStatus: PSU {0} STATUS_IOUT: {1}", psuId, System.Convert.ToString(response.PsuByteResponse, 2).PadLeft(8, '0'));
                }

                // STATUS_INPUT
                response = (PsuCommandByteResponse)this.SendReceive(this.PsuDeviceType, this.PsuId,
                                                                    new PsuRequest((byte)PmBusCommand.STATUS_INPUT, (byte)PmBusResponseLength.STATUS_INPUT), typeof(PsuCommandByteResponse));
                if (response.CompletionCode != 0)
                {
                    returnPacket.CompletionCode = (CompletionCode)response.CompletionCode;
                    Tracer.WriteWarning("LogPsuFaultStatus: Failed to read STATUS_INPUT on PSU {0}: Completion Code: {1}", psuId, response.CompletionCode);
                }
                else
                {
                    Tracer.WriteWarning("LogPsuFaultStatus: PSU {0} STATUS_INPUT: {1}", psuId, System.Convert.ToString(response.PsuByteResponse, 2).PadLeft(8, '0'));
                }

                // STATUS_TEMPERATURE
                response = (PsuCommandByteResponse)this.SendReceive(this.PsuDeviceType, this.PsuId,
                                                                    new PsuRequest((byte)PmBusCommand.STATUS_TEMPERATURE, (byte)PmBusResponseLength.STATUS_TEMPERATURE), typeof(PsuCommandByteResponse));
                if (response.CompletionCode != 0)
                {
                    returnPacket.CompletionCode = (CompletionCode)response.CompletionCode;
                    Tracer.WriteWarning("LogPsuFaultStatus: Failed to read STATUS_TEMPERATURE on PSU {0}: Completion Code: {1}", psuId, response.CompletionCode);
                }
                else
                {
                    Tracer.WriteWarning("LogPsuFaultStatus: PSU {0} STATUS_TEMPERATURE: {1}", psuId, System.Convert.ToString(response.PsuByteResponse, 2).PadLeft(8, '0'));
                }

                // STATUS_CML
                response = (PsuCommandByteResponse)this.SendReceive(this.PsuDeviceType, this.PsuId,
                                                                    new PsuRequest((byte)PmBusCommand.STATUS_CML, (byte)PmBusResponseLength.STATUS_CML), typeof(PsuCommandByteResponse));
                if (response.CompletionCode != 0)
                {
                    returnPacket.CompletionCode = (CompletionCode)response.CompletionCode;
                    Tracer.WriteWarning("LogPsuFaultStatus: Failed to read STATUS_CML on PSU {0}: Completion Code: {1}", psuId, response.CompletionCode);
                }
                else
                {
                    Tracer.WriteWarning("LogPsuFaultStatus: PSU {0} STATUS_CML: {1}", psuId, System.Convert.ToString(response.PsuByteResponse, 2).PadLeft(8, '0'));
                }
            }
            catch (System.Exception ex)
            {
                returnPacket.CompletionCode = CompletionCode.UnspecifiedError;
                Tracer.WriteError("LogPsuFaultStatus Exception: " + ex);
            }
            return(returnPacket);
        }
Esempio n. 24
0
        /// <summary>
        /// Class Constructor.
        /// </summary>
        static ConfigLoaded()
        {
            // check app.config for Population, if population is not found
            // in the app.config default the value to 24.
            int.TryParse(Config.AppSettings["Population"], out Population);
            Population = Population == 0 ? 24 : Population;

            // check app.config for MaxSerialConsolePorts, if MaxSerialConsolePorts is not found
            // in the app.config default the value to 1.
            int.TryParse(Config.AppSettings["MaxSerialConsolePorts"], out MaxSerialConsolePorts);
            MaxSerialConsolePorts = MaxSerialConsolePorts == 0 ? 1 : MaxSerialConsolePorts;

            int.TryParse(Config.AppSettings["InactiveSerialPortId"], out InactiveSerialPortId);
            InactiveSerialPortId = InactiveSerialPortId == 0 ? -1 : InactiveSerialPortId;

            InactiveSerialPortSessionToken = Config.AppSettings["InactiveSerialPortSessionToken"].ToString();
            InactiveSerialPortSessionToken = InactiveSerialPortSessionToken == string.Empty ? "-1" : InactiveSerialPortSessionToken;

            SecretSerialPortSessionToken = Config.AppSettings["SecretSerialPortSessionToken"].ToString();
            SecretSerialPortSessionToken = SecretSerialPortSessionToken == string.Empty ? "-99" : SecretSerialPortSessionToken;

            int.TryParse(Config.AppSettings["SerialPortConsoleClientSessionInactivityTimeoutInSecs"], out SerialPortConsoleClientSessionInactivityTimeoutInSecs);
            SerialPortConsoleClientSessionInactivityTimeoutInSecs = SerialPortConsoleClientSessionInactivityTimeoutInSecs == 0 ? 120 : SerialPortConsoleClientSessionInactivityTimeoutInSecs;

            int.TryParse(Config.AppSettings["SerialPortConsoleDeviceCommunicationTimeoutInMsecs"], out SerialPortConsoleDeviceCommunicationTimeoutInMsecs);
            SerialPortConsoleDeviceCommunicationTimeoutInMsecs = SerialPortConsoleDeviceCommunicationTimeoutInMsecs == 0 ? 100 : SerialPortConsoleDeviceCommunicationTimeoutInMsecs;

            int.TryParse(Config.AppSettings["InactiveBladePortId"], out InactiveBladePortId);
            InactiveBladePortId = InactiveBladePortId == 0 ? -1 : InactiveBladePortId;

            InactiveBladeSerialSessionToken = Config.AppSettings["InactiveBladeSerialSessionToken"].ToString();
            InactiveBladeSerialSessionToken = InactiveBladeSerialSessionToken == string.Empty ? "-1" : InactiveBladeSerialSessionToken;

            int.TryParse(Config.AppSettings["SecretBladePortId"], out SecretBladePortId);
            SecretBladePortId = SecretBladePortId == 0 ? -99 : SecretBladePortId;

            SecretBladeSerialSessionToken = Config.AppSettings["SecretBladeSerialSessionToken"].ToString();
            SecretBladeSerialSessionToken = SecretBladeSerialSessionToken == string.Empty ? "-99" : SecretBladeSerialSessionToken;

            int.TryParse(Config.AppSettings["bladeSerialTimeout"], out bladeSerialTimeout);
            bladeSerialTimeout = bladeSerialTimeout == 0 ? 2 : bladeSerialTimeout;

            int.TryParse(Config.AppSettings["SerialTimeout"], out SerialTimeout);
            SerialTimeout = SerialTimeout == 0 ? 100 : SerialTimeout;

            int.TryParse(Config.AppSettings["GpioErrorLimit"], out GpioErrorLimit);
            GpioErrorLimit = GpioErrorLimit == 0 ? 3 : GpioErrorLimit;

            // check app.config for BmcSessionTime.  if not found, the default value
            // is 6.
            int.TryParse(Config.AppSettings["BmcSessionTime"], out BmcSessionTime);
            BmcSessionTime = BmcSessionTime == 0 ? 6 : BmcSessionTime;

            // check app.config for BmcUserName, if BmcUserName is not found
            // in the app.config default the value to root.
            BmcUserName = Config.AppSettings["BmcUserName"].ToString();
            BmcUserName = BmcUserName == string.Empty ? "root" : BmcUserName;

            // check app.config for BmcUserKey, if BmcUserName is not found
            // in the app.config default the value to root.
            BmcUserKey = Config.AppSettings["BmcUserKey"].ToString();
            BmcUserKey = BmcUserKey == string.Empty ? "root" : BmcUserKey;

            // check app.config for NumFans, if NumFans is not found
            // in the app.config default the value to 6.
            int.TryParse(Config.AppSettings["NumFans"], out NumFans);
            NumFans = NumFans == 0 ? 6 : NumFans;

            // check app.config for NumPsus, if NumPsus is not found
            // in the app.config default the value to 6.
            int.TryParse(Config.AppSettings["NumPsus"], out NumPsus);
            NumPsus = NumPsus == 0 ? 6 : NumPsus;

            // check app.config for NumNicsPerBlade, if not found
            // in the app.config default the value to 2.
            int.TryParse(Config.AppSettings["NumNicsPerBlade"], out NumNicsPerBlade);
            NumNicsPerBlade = NumNicsPerBlade == 0 ? 2 : NumNicsPerBlade;

            // check app.config for NumPowerSwitches, if NumPowerSwitches is not found
            // in the app.config default the value to 2.
            int.TryParse(Config.AppSettings["NumPowerSwitches"], out NumPowerSwitches);
            NumPowerSwitches = NumPowerSwitches == 0 ? 2 : NumPowerSwitches;

            // check app.config for WaitTimeAfterACSocketPowerOffInMsecs, if not found
            // in the app.config default the value to 1000 ms.
            int.TryParse(Config.AppSettings["WaitTimeAfterACSocketPowerOffInMsecs"], out WaitTimeAfterACSocketPowerOffInMsecs);
            WaitTimeAfterACSocketPowerOffInMsecs = WaitTimeAfterACSocketPowerOffInMsecs == 0 ? 1000 : WaitTimeAfterACSocketPowerOffInMsecs;

            // check app.config for WaitTimeAfterBladeHardPowerOffInMsecs, if not found
            // in the app.config default the value to 100 ms.
            int.TryParse(Config.AppSettings["WaitTimeAfterBladeHardPowerOffInMsecs"], out WaitTimeAfterBladeHardPowerOffInMsecs);
            WaitTimeAfterBladeHardPowerOffInMsecs = WaitTimeAfterBladeHardPowerOffInMsecs == 0 ? 100 : WaitTimeAfterBladeHardPowerOffInMsecs;

            // check app.config for ChassisManagerTraceFilePath, if not found
            // in the app.config default the value to C:\ChassisManagerTrace.txt.
            TraceLogFilePath = Config.AppSettings["TraceLogFilePath"].ToString();
            TraceLogFilePath = TraceLogFilePath == string.Empty ? @"C:\ChassisManagerTrace.txt" : TraceLogFilePath;

            // check app.config for ChassisManagerTraceFileSize, if not found
            // in the app.config default the value to 100 KB.
            int.TryParse(Config.AppSettings["TraceLogFileSize"], out TraceLogFileSize);
            TraceLogFileSize = TraceLogFileSize == 0 ? 100 : TraceLogFileSize;

            // check app.config for ChassisManagerTraceFilePath, if not found
            // in the app.config default the value to C:\ChassisManagerTrace.txt.
            UserLogFilePath = Config.AppSettings["UserLogFilePath"].ToString();
            UserLogFilePath = UserLogFilePath == string.Empty ? @"C:\ChassisManagerUserLog.txt" : UserLogFilePath;

            // check app.config for ChassisManagerUserFileSize, if not found
            // in the app.config default the value to 100 KB.
            int.TryParse(Config.AppSettings["UserLogFileSize"], out UserLogFileSize);
            UserLogFileSize = UserLogFileSize == 0 ? 100 : UserLogFileSize;

            // check app.config for GetTimePeriod, if it is not found
            // in the app.config default the value to 30000.
            int.TryParse(Config.AppSettings["GetTimePeriod"], out GetTimePeriod);
            GetTimePeriod = GetTimePeriod == 0 ? 30000 : GetTimePeriod;

            // check app.config for SetTimePeriod, if it is not found
            // in the app.config default the value to 30000.
            int.TryParse(Config.AppSettings["SetTimePeriod"], out SetTimePeriod);
            SetTimePeriod = SetTimePeriod == 0 ? 30000 : SetTimePeriod;

            // check app.config for MaxPWM, if it is not found
            // in the app.config default the value to 100.
            int.TryParse(Config.AppSettings["MaxPWM"], out MaxPWM);
            MaxPWM = MaxPWM == 0 ? 100 : MaxPWM;

            // check app.config for MinPWM, if it is not found
            // in the app.config default the value to 20.
            int.TryParse(Config.AppSettings["MinPWM"], out MinPWM);
            MinPWM = MinPWM == 0 ? 20 : MinPWM;

            // check app.config for StepPWM, if it is not found
            // in the app.config default the value to 10.
            int.TryParse(Config.AppSettings["StepPWM"], out StepPWM);
            StepPWM = StepPWM == 0 ? 10 : StepPWM;

            // check app.config for InputSensor, if it is not found
            // in the app.config default the value to 1.
            int.TryParse(Config.AppSettings["InputSensor"], out InputSensor);
            InputSensor = InputSensor == 0 ? 1 : InputSensor;

            // check app.config for SensorLowThreshold, if it is not found
            // in the app.config default the value to 0.
            int.TryParse(Config.AppSettings["SensorLowThreshold"], out SensorLowThreshold);
            SensorLowThreshold = SensorLowThreshold == 0 ? 0 : SensorLowThreshold;

            // check app.config for SensorHighThreshold, if it is not found
            // in the app.config default the value to 100.
            int.TryParse(Config.AppSettings["SensorHighThreshold"], out SensorHighThreshold);
            SensorHighThreshold = SensorHighThreshold == 0 ? 100 : SensorHighThreshold;

            // check app.config for AltitudeCorrectionFactor, if it is not found
            // in the app.config default the value to 0.032 (3.2%).
            float.TryParse(Config.AppSettings["AltitudeCorrectionFactor"], out AltitudeCorrectionFactor);
            AltitudeCorrectionFactor = AltitudeCorrectionFactor == 0 ? (float)0.032 : AltitudeCorrectionFactor;

            // check app.config for Altitude, if it is not found
            // in the app.config default the value to 0 (0 feet above sea level).
            int.TryParse(Config.AppSettings["Altitude"], out Altitude);
            Altitude = Altitude == 0 ? 0 : Altitude;

            // check app.config for MaxRetries, if it is not found
            // in the app.config default the value to 3.
            int.TryParse(Config.AppSettings["MaxRetries"], out MaxRetries);
            MaxRetries = MaxRetries == 0 ? 3 : MaxRetries;

            // check app.config for LEDHigh, if it is not found
            // in the app.config default the value to 255.
            int.TryParse(Config.AppSettings["LEDHigh"], out LEDHigh);
            LEDHigh = LEDHigh == 0 ? 255 : LEDHigh;

            // check app.config for LEDLow, if it is not found
            // in the app.config default the value to 0.
            int.TryParse(Config.AppSettings["LEDLow"], out LEDLow);
            LEDLow = LEDLow == 0 ? 0 : LEDLow;

            // check app.config for MinPowerLimit, if it is not found
            // in the app.config default the value to 120W.
            int.TryParse(Config.AppSettings["MinPowerLimit"], out MinPowerLimit);
            MinPowerLimit = MinPowerLimit == 0 ? 120 : MinPowerLimit;

            // check app.config for MaxPowerLimit, if it is not found
            // in the app.config default the value to 1000W.
            int.TryParse(Config.AppSettings["MaxPowerLimit"], out MaxPowerLimit);
            MaxPowerLimit = MaxPowerLimit == 0 ? 1000 : MaxPowerLimit;

            // check app.config for MaxFailCount, if it is not found
            // in the app.config default the value to 0.
            int.TryParse(Config.AppSettings["MaxFailCount"], out MaxFailCount);
            MaxFailCount = MaxFailCount == 0 ? 0 : MaxFailCount;

            // check app.config for CM Fru variables, if it is not found
            // in the app.config default the value FRU values found in Spec V1.0.
            int.TryParse(Config.AppSettings["CMStartingOffset"], out ChassisStartingOffset);
            ChassisStartingOffset = ChassisStartingOffset == 0 ? 0 : ChassisStartingOffset;

            int.TryParse(Config.AppSettings["CMFruLength"], out ChassisFruLength);
            ChassisFruLength = ChassisFruLength == 0 ? 256 : ChassisFruLength;

            int.TryParse(Config.AppSettings["InternalUseSize"], out InternalUseSize);
            InternalUseSize = InternalUseSize == 0 ? 72 : InternalUseSize;

            int.TryParse(Config.AppSettings["ChassisInfoSize"], out ChassisInfoSize);
            ChassisInfoSize = ChassisInfoSize == 0 ? 32 : ChassisInfoSize;

            int.TryParse(Config.AppSettings["BoardInfoSize"], out BoardInfoSize);
            BoardInfoSize = BoardInfoSize == 0 ? 64 : BoardInfoSize;

            int.TryParse(Config.AppSettings["ProductInfoSize"], out ProductInfoSize);
            ProductInfoSize = ProductInfoSize == 0 ? 80 : ProductInfoSize;

            // check app.config for Hard Disk Drive Sensor ids
            int.TryParse(Config.AppSettings["BladeDisk0"], out BladeDisk0);
            BladeDisk0 = BladeDisk0 == 0 ? 243 : BladeDisk0;

            int.TryParse(Config.AppSettings["BladeDisk1"], out BladeDisk1);
            BladeDisk1 = BladeDisk1 == 0 ? 244 : BladeDisk1;

            int.TryParse(Config.AppSettings["BladeDisk2"], out BladeDisk2);
            BladeDisk2 = BladeDisk2 == 0 ? 245 : BladeDisk2;

            int.TryParse(Config.AppSettings["BladeDisk3"], out BladeDisk3);
            BladeDisk3 = BladeDisk3 == 0 ? 246 : BladeDisk3;

            // check app.config for Health Diagnostics Sensor ids
            int.TryParse(Config.AppSettings["CPU0ProcHotSensor"], out CPU0ProcHotSensor);
            CPU0ProcHotSensor = CPU0ProcHotSensor == 0 ? 187 : CPU0ProcHotSensor;

            int.TryParse(Config.AppSettings["CPU1ProcHotSensor"], out CPU1ProcHotSensor);
            CPU1ProcHotSensor = CPU1ProcHotSensor == 0 ? 188 : CPU1ProcHotSensor;

            int.TryParse(Config.AppSettings["PCIeBusSensor"], out PCIeBusSensor);
            PCIeBusSensor = PCIeBusSensor == 0 ? 161 : PCIeBusSensor;

            int.TryParse(Config.AppSettings["SPSFWSensor"], out SPSFWSensor);
            SPSFWSensor = SPSFWSensor == 0 ? 23 : SPSFWSensor;

            // check app.config for MaxPortManagerWorkQueueLength, if it is not found
            // in the app.config default the value to 10.
            int.TryParse(Config.AppSettings["MaxPortManagerWorkQueueLength"], out MaxPortManagerWorkQueueLength);
            MaxPortManagerWorkQueueLength = MaxPortManagerWorkQueueLength == 0 ? 20 : MaxPortManagerWorkQueueLength;

            // check app.config for ServiceTimeoutInMinutes, if it is not found
            // in the app.config default the value to 2 minutes.
            double.TryParse(Config.AppSettings["ServiceTimeoutInMinutes"], out ServiceTimeoutInMinutes);
            ServiceTimeoutInMinutes = ServiceTimeoutInMinutes == 0 ? 2 : ServiceTimeoutInMinutes;

            // check app.config for CMServicePortNumber, if it is not found
            // in the app.config default the value to 8000.
            int.TryParse(Config.AppSettings["CmServicePortNumber"], out CmServicePortNumber);
            CmServicePortNumber = CmServicePortNumber < 1 ? 8000 : CmServicePortNumber;

            // check app.config for SslCertificateName, if not found
            // in the app.config default the value to "CMServiceServer".
            SslCertificateName = Config.AppSettings["SslCertificateName"].ToString();
            SslCertificateName = SslCertificateName == string.Empty ? @"CMServiceServer" : SslCertificateName;

            // check app.config for EnableSslEncryption, if not found
            // in the app.config default the value to true/enable.
            int tempSslEncrypt = 1;

            int.TryParse(Config.AppSettings["EnableSslEncryption"], out tempSslEncrypt);
            EnableSslEncryption = tempSslEncrypt == 0 ? false : true;

            // Check App.config for KillSerialConsoleSession, if not found, default to true/enable.
            int tempKillSerialConsoleSession = 1;

            int.TryParse(Config.AppSettings["KillSerialConsoleSession"], out tempKillSerialConsoleSession);
            KillSerialConsoleSession = tempKillSerialConsoleSession == 0 ? false : true;

            // Check App.config for EnableFan, if not found, default to true/enable.
            int tempEnableFan = 1;

            int.TryParse(Config.AppSettings["EnableFan"], out tempEnableFan);
            EnableFan = tempEnableFan == 0 ? false : true;

            // check app.config for EventLogXml, if not found
            // in the app.config default the value to EventDataStrings.xml
            string evtLogFile = string.Empty;

            evtLogFile = Config.AppSettings["EventLogXml"].ToString();
            evtLogFile = evtLogFile == string.Empty ? @"EventDataStrings.xml" : evtLogFile;

            // format event log strings dictionary
            Dictionary <string, string> formatStrings = new Dictionary <string, string>();

            try
            {
                FileStream fs = new FileStream(evtLogFile, FileMode.Open, FileAccess.Read);

                XmlDocument XmlEventLogDoc = new XmlDocument();

                // load xml document
                XmlEventLogDoc.Load(fs);

                // convert xml document into class objects
                EventStrings = XmlToObject("EventLogTypeCode", XmlEventLogDoc);

                // populate format event log strings dictionary
                XmlFormatStrings("EventLogStrings", formatStrings, XmlEventLogDoc);
            }
            catch (System.Exception ex)
            {
                Tracer.WriteWarning(string.Format("ERROR: Could not load Event Log Strings from {0}", evtLogFile));
                Tracer.WriteError(ex);

                // set event strings to default empty list.
                EventStrings = new List <EventLogData>();
            }

            if (formatStrings.ContainsKey("ErrorCode"))
            {
                EventLogStrError = formatStrings["ErrorCode"].ToString();
            }
            else
            {
                EventLogStrError = string.Empty;
            }

            if (formatStrings.ContainsKey("Separator"))
            {
                EventLogStrSeparator = formatStrings["Separator"].ToString();
            }
            else
            {
                EventLogStrSeparator = string.Empty;
            }

            if (formatStrings.ContainsKey("Space"))
            {
                EventLogStrSpacer = formatStrings["Space"].ToString();
            }
            else
            {
                EventLogStrSpacer = string.Empty;
            }

            if (formatStrings.ContainsKey("SensorType"))
            {
                EventLogStrSensor = formatStrings["SensorType"].ToString();
            }
            else
            {
                EventLogStrSensor = string.Empty;
            }

            if (formatStrings.ContainsKey("Unknown"))
            {
                Unknown = formatStrings["Unknown"].ToString();
            }
            else
            {
                Unknown = string.Empty;
            }
        }
        /// <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);
            }
        }
Esempio n. 26
0
        private static List <EventLogData> XmlToObject(string xmlTag, XmlDocument xmlEventLogDoc)
        {
            List <EventLogData> response = new List <EventLogData>();

            try
            {
                XmlNodeList rootNodeList = xmlEventLogDoc.GetElementsByTagName(xmlTag);

                if (rootNodeList.Count > 0)
                {
                    // root level node: EventLogTypeCode
                    foreach (XmlNode root in rootNodeList)
                    {
                        // GenericEvent/SensorSpecificEvent
                        foreach (XmlNode node in root.ChildNodes)
                        {
                            EventLogMsgType clasification = GetEventLogClass(node.Name.ToString());

                            XmlNodeList firstTierNodes = node.ChildNodes;

                            // enumerate first level child nodes
                            foreach (XmlNode firstNode in firstTierNodes)
                            {
                                int    number      = Convert.ToInt32(firstNode.Attributes["Number"].Value.ToString());
                                string description = firstNode.Attributes["ReadingClass"].Value.ToString();

                                XmlNodeList secondTierNodes = firstNode.ChildNodes;

                                // enumerate second level xml nodes
                                foreach (XmlNode secondNode in secondTierNodes)
                                {
                                    int    offset  = Convert.ToInt32(secondNode.Attributes["Number"].Value.ToString());
                                    string message = secondNode.Attributes["Description"].Value.ToString();

                                    EventLogData respObj = new EventLogData(number, offset, clasification, message, description);

                                    XmlNodeList thirdTierNodes = secondNode.ChildNodes;

                                    if (thirdTierNodes.Count > 0)
                                    {
                                        // enumerate third level xml nodes
                                        foreach (XmlNode extension in thirdTierNodes)
                                        {
                                            int    id     = Convert.ToInt32(extension.Attributes["Number"].Value.ToString());
                                            string detail = extension.Attributes["Description"].Value.ToString();

                                            respObj.AddExtension(id, detail);
                                        } // enumerate third level xml nodes
                                    }

                                    response.Add(respObj);
                                } // enumerate second level xml nodes
                            }     // enumerate first level child nodes
                        }         // GenericEvent/SensorSpecificEvent
                    }
                }
                else
                {
                    Tracer.WriteWarning("ERROR: Could not load Event Log Strings, could not find xml root node in file");
                }
            }
            catch (Exception ex)
            {
                Tracer.WriteError(string.Format("ERROR: Could not load Event Log Strings. Error: {0}", ex.ToString()));
            }

            return(response);
        }
Esempio n. 27
0
        /// <summary>
        /// Class Constructor.
        /// </summary>
        static ConfigLoaded()
        {
            // check app.config for Join Timeout in seconds
            int joinTimeout;

            int.TryParse(Config.AppSettings["JoinTimeout"], out joinTimeout);
            ThreadJoinTimeout = joinTimeout == 0 ? TimeSpan.FromSeconds(10) : TimeSpan.FromSeconds(joinTimeout);

            // check app.config for Population, if population is not found
            // in the app.config default the value to 24.
            int.TryParse(Config.AppSettings["Population"], out Population);
            Population = Population == 0 ? 24 : Population;

            // check app.config for MaxSerialConsoleSessions, if MaxSerialConsoleSessions is not found
            // in the app.config default the value to 12.
            uint.TryParse(Config.AppSettings["MaxSerialConsoleSessions"], out MaxSerialConsoleSessions);
            MaxSerialConsoleSessions = MaxSerialConsoleSessions == 0 ? 12 : MaxSerialConsoleSessions;

            // check app.config for MaxSerialConsolePorts, if MaxSerialConsolePorts is not found
            // in the app.config default the value to 1.
            int.TryParse(Config.AppSettings["MaxSerialConsolePorts"], out MaxSerialConsolePorts);
            MaxSerialConsolePorts = MaxSerialConsolePorts == 0 ? 1 : MaxSerialConsolePorts;

            // Time for BMC to decompress firmware and start responding after power on.
            // This is the firmware decompression time.
            int.TryParse(Config.AppSettings["FirmwareDecompressionTime"], out FirmwareDecompressionTime);
            FirmwareDecompressionTime = FirmwareDecompressionTime == 0 ? 28 : FirmwareDecompressionTime;

            int manufacturerId;

            int.TryParse(Config.AppSettings["MultiRecordFruManufacturerId"], out manufacturerId);
            manufacturerId = manufacturerId == 0 ? 311 : manufacturerId;
            ConvertIanaManufactureId(manufacturerId);

            int fruWritesRemaining = 0;

            int.TryParse(Config.AppSettings["ResetMultiRecordFruWritesRemaining"], out fruWritesRemaining);
            ResetMultiRecordFruWritesRemaining = fruWritesRemaining == 0 ? false : true;

            int.TryParse(Config.AppSettings["SerialPortConsoleClientSessionInactivityTimeoutInSecs"], out SerialPortConsoleClientSessionInactivityTimeoutInSecs);
            SerialPortConsoleClientSessionInactivityTimeoutInSecs = SerialPortConsoleClientSessionInactivityTimeoutInSecs == 0 ? 120 : SerialPortConsoleClientSessionInactivityTimeoutInSecs;

            int.TryParse(Config.AppSettings["SerialPortConsoleDeviceCommunicationTimeoutInMsecs"], out SerialPortConsoleDeviceCommunicationTimeoutInMsecs);
            SerialPortConsoleDeviceCommunicationTimeoutInMsecs = SerialPortConsoleDeviceCommunicationTimeoutInMsecs == 0 ? 100 : SerialPortConsoleDeviceCommunicationTimeoutInMsecs;

            // Default to 300 seconds if app.config setting is 0, negative or an invalid string
            uint.TryParse(Config.AppSettings["BladeSerialTimeout"], out BladeSerialTimeout);
            BladeSerialTimeout = BladeSerialTimeout == 0 ? 300 : BladeSerialTimeout;

            int.TryParse(Config.AppSettings["SerialTimeout"], out SerialTimeout);
            SerialTimeout = SerialTimeout == 0 ? 100 : SerialTimeout;

            int.TryParse(Config.AppSettings["GpioErrorLimit"], out GpioErrorLimit);
            GpioErrorLimit = GpioErrorLimit == 0 ? 3 : GpioErrorLimit;

            // check app.config for BmcSessionTime.  if not found, the default value
            // is 6.
            int.TryParse(Config.AppSettings["BmcSessionTime"], out BmcSessionTime);
            BmcSessionTime = BmcSessionTime == 0 ? 6 : BmcSessionTime;

            // check app.config for BmcUserName, if BmcUserName is not found
            // in the app.config default the value to root.
            BmcUserName = Config.AppSettings["BmcUserName"];
            BmcUserName = string.IsNullOrEmpty(BmcUserName) ? "root" : BmcUserName;

            // check app.config for BmcUserKey, if BmcUserName is not found
            // in the app.config default the value to root.
            BmcUserKey = Config.AppSettings["BmcUserKey"];
            BmcUserKey = string.IsNullOrEmpty(BmcUserKey) ? "root" : BmcUserKey;

            // check app.config for NumFans, if NumFans is not found
            // in the app.config default the value to 6.
            int.TryParse(Config.AppSettings["NumFans"], out NumFans);
            NumFans = NumFans < 0 ? 6 : NumFans;

            // check app.config for NumPsus, if NumPsus is not found
            // in the app.config default the value to 6.
            int.TryParse(Config.AppSettings["NumPsus"], out NumPsus);
            NumPsus = NumPsus < 0 ? 6 : NumPsus;

            // check app.config for NumBatteries, if NumBatteries is not found
            // in the app.config default the value to 6.
            int.TryParse(Config.AppSettings["NumBatteries"], out NumBatteries);
            NumBatteries = NumBatteries < 0 ? 6 : NumBatteries;

            // check app.config for NumNicsPerBlade, if not found
            // in the app.config default the value to 2.
            int.TryParse(Config.AppSettings["NumNicsPerBlade"], out NumNicsPerBlade);
            NumNicsPerBlade = NumNicsPerBlade == 0 ? 2 : NumNicsPerBlade;

            // check app.config for NumPowerSwitches, if NumPowerSwitches is not found
            // in the app.config default the value to 2.
            int.TryParse(Config.AppSettings["NumPowerSwitches"], out NumPowerSwitches);
            NumPowerSwitches = NumPowerSwitches < 0 ? 0 : NumPowerSwitches;

            // check app.config for WaitTimeAfterACSocketPowerOffInMsecs, if not found
            // in the app.config default the value to 1000 ms.
            int.TryParse(Config.AppSettings["WaitTimeAfterACSocketPowerOffInMsecs"], out WaitTimeAfterACSocketPowerOffInMsecs);
            WaitTimeAfterACSocketPowerOffInMsecs = WaitTimeAfterACSocketPowerOffInMsecs == 0 ? 1000 : WaitTimeAfterACSocketPowerOffInMsecs;

            // check app.config for WaitTimeAfterBladeHardPowerOffInMsecs, if not found
            // in the app.config default the value to 100 ms.
            int.TryParse(Config.AppSettings["WaitTimeAfterBladeHardPowerOffInMsecs"], out WaitTimeAfterBladeHardPowerOffInMsecs);
            WaitTimeAfterBladeHardPowerOffInMsecs = WaitTimeAfterBladeHardPowerOffInMsecs == 0 ? 100 : WaitTimeAfterBladeHardPowerOffInMsecs;

            // check app.config for ChassisManagerTraceFilePath, if not found
            // in the app.config default the value to C:\ChassisManagerTrace.txt.
            TraceLogFilePath = Config.AppSettings["TraceLogFilePath"];
            TraceLogFilePath = string.IsNullOrEmpty(TraceLogFilePath) ? @"C:\ChassisManagerTrace.txt" : TraceLogFilePath;

            // check app.config for ChassisManagerTraceFileSize, if not found
            // in the app.config default the value to 100 KB.
            int.TryParse(Config.AppSettings["TraceLogFileSize"], out TraceLogFileSize);
            TraceLogFileSize = TraceLogFileSize == 0 ? 100 : TraceLogFileSize;

            // check app.config for ChassisManagerTraceFilePath, if not found
            // in the app.config default the value to C:\ChassisManagerTrace.txt.
            UserLogFilePath = Config.AppSettings["UserLogFilePath"];
            UserLogFilePath = string.IsNullOrEmpty(UserLogFilePath) ? @"C:\ChassisManagerUserLog.txt" : UserLogFilePath;

            // check app.config for ChassisManagerUserFileSize, if not found
            // in the app.config default the value to 100 KB.
            int.TryParse(Config.AppSettings["UserLogFileSize"], out UserLogFileSize);
            UserLogFileSize = UserLogFileSize == 0 ? 100 : UserLogFileSize;

            // check app.config for UserLogMaxEntries, if not found
            // in the app.config default the value to 50 entries.
            int.TryParse(Config.AppSettings["UserLogMaxEntries"], out UserLogMaxEntries);
            UserLogMaxEntries = UserLogMaxEntries == 0 ? 50 : UserLogMaxEntries;

            // check app.config for MaxPWM, if it is not found
            // in the app.config default the value to 100.
            int.TryParse(Config.AppSettings["MaxPWM"], out MaxPWM);
            MaxPWM = MaxPWM == 0 ? 100 : MaxPWM;

            // check app.config for MinPWM, if it is not found
            // in the app.config default the value to 20.
            int.TryParse(Config.AppSettings["MinPWM"], out MinPWM);
            MinPWM = MinPWM == 0 ? 20 : MinPWM;

            // check app.config for StepPWM, if it is not found
            // in the app.config default the value to 10.
            int.TryParse(Config.AppSettings["StepPWM"], out StepPWM);
            StepPWM = StepPWM == 0 ? 10 : StepPWM;

            // check app.config for InputSensor, if it is not found
            // in the app.config default the value to 1.
            int.TryParse(Config.AppSettings["InputSensor"], out InputSensor);
            InputSensor = InputSensor == 0 ? 1 : InputSensor;

            // check app.config for Inlet, if it is not found
            // in the app.config default the value to 176.
            int.TryParse(Config.AppSettings["InletSensor"], out InletSensor);
            InletSensor = InletSensor == 0 ? 176 : InletSensor;

            // check app.config for Inlet Offset, if it is not found
            // in the app.config default the value to false.
            int InletOffSet = 0;

            int.TryParse(Config.AppSettings["EnableInletOffSet"], out InletOffSet);
            EnableInletOffSet = InletOffSet == 0 ? false : true;

            // check app.config for SensorLowThreshold, if it is not found
            // in the app.config default the value to 0.
            int.TryParse(Config.AppSettings["SensorLowThreshold"], out SensorLowThreshold);
            SensorLowThreshold = SensorLowThreshold == 0 ? 0 : SensorLowThreshold;

            // check app.config for SensorHighThreshold, if it is not found
            // in the app.config default the value to 100.
            int.TryParse(Config.AppSettings["SensorHighThreshold"], out SensorHighThreshold);
            SensorHighThreshold = SensorHighThreshold == 0 ? 100 : SensorHighThreshold;

            // check app.config for AltitudeCorrectionFactor, if it is not found
            // in the app.config default the value to 0.032 (3.2%).
            float.TryParse(Config.AppSettings["AltitudeCorrectionFactor"], out AltitudeCorrectionFactor);
            AltitudeCorrectionFactor = AltitudeCorrectionFactor == 0 ? (float)0.032 : AltitudeCorrectionFactor;

            // check app.config for Altitude, if it is not found
            // in the app.config default the value to 0 (0 feet above sea level).
            int.TryParse(Config.AppSettings["Altitude"], out Altitude);
            Altitude = Altitude == 0 ? 0 : Altitude;

            // check app.config for MaxRetries, if it is not found
            // in the app.config default the value to 3.
            int.TryParse(Config.AppSettings["MaxRetries"], out MaxRetries);
            MaxRetries = MaxRetries == 0 ? 3 : MaxRetries;

            // check app.config for LEDHigh, if it is not found
            // in the app.config default the value to 255.
            int.TryParse(Config.AppSettings["LEDHigh"], out LEDHigh);
            LEDHigh = LEDHigh == 0 ? 255 : LEDHigh;

            // check app.config for MinPowerLimit, if it is not found
            // in the app.config default the value to 120W.
            int.TryParse(Config.AppSettings["MinPowerLimit"], out MinPowerLimit);
            MinPowerLimit = MinPowerLimit == 0 ? 120 : MinPowerLimit;

            // check app.config for MaxPowerLimit, if it is not found
            // in the app.config default the value to 1000W.
            int.TryParse(Config.AppSettings["MaxPowerLimit"], out MaxPowerLimit);
            MaxPowerLimit = MaxPowerLimit == 0 ? 1000 : MaxPowerLimit;

            // check app.config for SetPowerLimitCorrectionTimeInMilliseconds, if it is not found
            // in the app.config default the value to 6000ms.
            int.TryParse(Config.AppSettings["SetPowerLimitCorrectionTimeInMilliseconds"], out SetPowerLimitCorrectionTimeInMilliseconds);
            SetPowerLimitCorrectionTimeInMilliseconds = SetPowerLimitCorrectionTimeInMilliseconds == 0 ? 6000 : SetPowerLimitCorrectionTimeInMilliseconds;

            // check app.config for MaxFailCount, if it is not found
            // in the app.config default the value to 0.
            int.TryParse(Config.AppSettings["MaxFailCount"], out MaxFailCount);
            MaxFailCount = MaxFailCount == 0 ? 0 : MaxFailCount;

            // check app.config for MaxPortManagerWorkQueueLength, if it is not found
            // in the app.config default the value to 10.
            int.TryParse(Config.AppSettings["MaxPortManagerWorkQueueLength"], out MaxPortManagerWorkQueueLength);
            MaxPortManagerWorkQueueLength = MaxPortManagerWorkQueueLength == 0 ? 20 : MaxPortManagerWorkQueueLength;

            // check app.config for ServiceTimeoutInMinutes, if it is not found
            // in the app.config default the value to 2 minutes.
            double.TryParse(Config.AppSettings["ServiceTimeoutInMinutes"], out ServiceTimeoutInMinutes);
            ServiceTimeoutInMinutes = ServiceTimeoutInMinutes == 0 ? 2 : ServiceTimeoutInMinutes;

            // check app.config for CMServicePortNumber, if it is not found
            // in the app.config default the value to 8000.
            int.TryParse(Config.AppSettings["CmServicePortNumber"], out CmServicePortNumber);
            CmServicePortNumber = CmServicePortNumber < 1 ? 8000 : CmServicePortNumber;

            // check app.config for SslCertificateName, if not found
            // in the app.config default the value to "CMServiceServer".
            SslCertificateName = Config.AppSettings["SslCertificateName"];
            SslCertificateName = string.IsNullOrEmpty(SslCertificateName) ? @"CMServiceServer" : SslCertificateName;

            // check app.config for EnableSslEncryption, if not found
            // in the app.config default the value to true/enable.
            int tempSslEncrypt = 1;

            int.TryParse(Config.AppSettings["EnableSslEncryption"], out tempSslEncrypt);
            EnableSslEncryption = tempSslEncrypt == 0 ? false : true;

            // Check App.config for EnableFan, if not found, default to true/enable.
            int tempEnableFan = 1;

            int.TryParse(Config.AppSettings["EnableFan"], out tempEnableFan);
            EnableFan = tempEnableFan == 0 ? false : true;

            // Check App.config for EnableBatteryMonitoring
            int batteryMonitoring;

            int.TryParse(Config.AppSettings["EnableBatteryMonitoring"], out batteryMonitoring);
            BatteryMonitoringEnabled = (batteryMonitoring == 0 ? false : true);

            // Check App.config for EnablePsuAlert
            int psuAlert;

            int.TryParse(Config.AppSettings["EnablePsuAlertMonitoring"], out psuAlert);
            PsuAlertMonitorEnabled = (psuAlert == 0 ? false : true);

            // Check App.config for EnableDatasafeAPIs
            int datasafeOperations;

            int.TryParse(Config.AppSettings["EnableDatasafeAPIs"], out datasafeOperations);
            DatasafeOperationsEnabled = (datasafeOperations == 0 ? false : true);

            // Check App.config for EnablePowerAlertDrivenPowerCapAPIs
            int powerAlertAPIs;

            int.TryParse(Config.AppSettings["EnablePowerAlertDrivenPowerCapAPIs"], out powerAlertAPIs);
            PowerAlertDrivenPowerCapAPIsEnabled = (powerAlertAPIs == 0 ? false : true);

            // Check App.config for DpcAutoDeassert
            int dpcAuto;

            int.TryParse(Config.AppSettings["DpcAutoDeassert"], out dpcAuto);
            DpcAutoDeassert = (dpcAuto == 0 ? false : true);

            int.TryParse(Config.AppSettings["PsuAlertPollInterval"], out PsuAlertPollInterval);
            PsuAlertPollInterval = PsuAlertPollInterval < 3 ? 3 : PsuAlertPollInterval;

            int.TryParse(Config.AppSettings["PsuPollInterval"], out PsuPollInterval);
            PsuPollInterval = PsuPollInterval < 10 ? 10 : PsuPollInterval;

            // Flag for forcing instantiation of unknown PSUs to Emerson PSUs.
            int forceEmersonPsuFlag = 0;

            int.TryParse(Config.AppSettings["ForceEmersonPsu"], out forceEmersonPsuFlag);
            ForceEmersonPsu = forceEmersonPsuFlag == 0 ? false : true;

            int.TryParse(Config.AppSettings["NvDimmPerBlade"], out NvDimmPerBlade);
            NvDimmPerBlade = NvDimmPerBlade == 0 ? 2 : NvDimmPerBlade;

            int.TryParse(Config.AppSettings["NvDimmTriggerFailureCount"], out NvDimmTriggerFailureCount);
            NvDimmTriggerFailureCount = NvDimmTriggerFailureCount < 1 ? 1 : NvDimmTriggerFailureCount;

            int.TryParse(Config.AppSettings["NvDimmTriggerFailureAction"], out NvDimmTriggerFailureAction);
            NvDimmTriggerFailureAction = NvDimmTriggerFailureAction < 0 ? 0 : NvDimmTriggerFailureAction;

            int.TryParse(Config.AppSettings["AdrCompleteDelay"], out AdrCompleteDelay);
            AdrCompleteDelay = AdrCompleteDelay == 0 ? 5 : AdrCompleteDelay;

            int.TryParse(Config.AppSettings["NvDDimmPresentPowerOffDelay"], out NvDimmPresentPowerOffDelay);
            NvDimmPresentPowerOffDelay = NvDimmPresentPowerOffDelay == 0 ? 160 : NvDimmPresentPowerOffDelay;

            // check app.config for ProcessBatteryStatus
            // if not found in the app.config default the value to false.
            int tempProcessBatteryStatus = 0;

            int.TryParse(Config.AppSettings["ProcessBatteryStatus"], out tempProcessBatteryStatus);
            ProcessBatteryStatus = tempProcessBatteryStatus == 0 ? false : true;

            // check app.config for BatteryChargeLevelThreshold
            // if not found in the app.config default the value to 50 percent.
            double.TryParse(Config.AppSettings["BatteryChargeLevelThreshold"], out BatteryChargeLevelThreshold);
            BatteryChargeLevelThreshold = BatteryChargeLevelThreshold == 0 ? 50 : BatteryChargeLevelThreshold;

            // check app.config for BatteryDischargeTimeInSecs
            // if not found in the app.config default the value to 35 seconds.
            int.TryParse(Config.AppSettings["BatteryDischargeTimeInSecs"], out BatteryDischargeTimeInSecs);
            BatteryDischargeTimeInSecs = BatteryDischargeTimeInSecs == 0 ? 35 : BatteryDischargeTimeInSecs;

            // check app.config for SerialSessionPowerOnWait
            // if not found in the app.config default the value to 5000 ms.
            int.TryParse(Config.AppSettings["SerialSessionPowerOnWait"], out SerialSessionPowerOnWait);
            SerialSessionPowerOnWait = SerialSessionPowerOnWait == 0 ? 5000 : SerialSessionPowerOnWait;

            // check app.config for SerialSessionPowerOnRetry
            // if not found in the app.config default the value to 10.
            int.TryParse(Config.AppSettings["SerialSessionPowerOnRetry"], out SerialSessionPowerOnRetry);
            SerialSessionPowerOnRetry = SerialSessionPowerOnRetry == 0 ? 10 : SerialSessionPowerOnRetry;

            // check app.config for EventLogXml, if not found
            // in the app.config default the value to EventDataStrings.xml
            string evtLogFile = string.Empty;

            evtLogFile = Config.AppSettings["EventLogXml"];
            evtLogFile = string.IsNullOrEmpty(evtLogFile) ? @"EventDataStrings.xml" : evtLogFile;

            // format event log strings dictionary
            Dictionary <string, string> formatStrings = new Dictionary <string, string>();

            try
            {
                FileStream fs = new FileStream(evtLogFile, FileMode.Open, FileAccess.Read);

                XmlDocument XmlEventLogDoc = new XmlDocument();

                // load xml document
                XmlEventLogDoc.Load(fs);

                // convert xml document into class objects
                EventStrings = XmlToObject("EventLogTypeCode", XmlEventLogDoc);

                // populate format event log strings dictionary
                XmlFormatStrings("EventLogStrings", formatStrings, XmlEventLogDoc);
            }
            catch (System.Exception ex)
            {
                Tracer.WriteWarning(string.Format("ERROR: Could not load Event Log Strings from {0}", evtLogFile));
                Tracer.WriteError(0, "ConfigLoaded.Configloaded", ex);

                // set event strings to default empty list.
                EventStrings = new List <EventLogData>();
            }

            if (formatStrings.ContainsKey("EventData"))
            {
                EventData = formatStrings["EventData"];
            }
            else
            {
                EventData = string.Empty;
            }

            if (formatStrings.ContainsKey("Separator"))
            {
                EventLogStrSeparator = formatStrings["Separator"];
            }
            else
            {
                EventLogStrSeparator = string.Empty;
            }

            if (formatStrings.ContainsKey("Space"))
            {
                EventLogStrSpacer = formatStrings["Space"];
            }
            else
            {
                EventLogStrSpacer = string.Empty;
            }

            if (formatStrings.ContainsKey("SensorType"))
            {
                EventLogStrSensor = formatStrings["SensorType"];
            }
            else
            {
                EventLogStrSensor = string.Empty;
            }

            if (formatStrings.ContainsKey("Unknown"))
            {
                Unknown = formatStrings["Unknown"];
            }
            else
            {
                Unknown = string.Empty;
            }
        }
        /// <summary>
        /// Every component in the higher level of the stack should call this method
        /// to send/receive data to/from actual hardware devices
        /// </summary>
        /// <param name="priorityLevel"></param>
        /// <param name="deviceType"></param>
        /// <param name="deviceId"></param>
        /// <param name="request">
        /// Input
        /// [0]: function code
        /// [1:2]: byte count (N)
        /// [3:N+2]: payload
        /// </param>
        /// <param name="response">
        /// Output
        /// [0]: completion code
        /// [1:2]: byte count (N)
        /// [3:N+2]: payload
        /// Note: response can be null
        /// </param>
        static internal void SendReceive(PriorityLevel priorityLevel, byte deviceType, byte deviceId, byte[] request, out byte[] response)
        {
            Tracer.WriteInfo("CommunicationDevice.SendReceive({0})", deviceType);
            ushort sessionId = IncrementTimeStampAndGetSessionId();
            byte   physicalId;

            // If CM is terminating, do not accept any more new requests
            if (isTerminating == true)
            {
                ResponsePacketUtil.GenerateResponsePacket(CompletionCode.ServiceTerminating, out response);
                return;
            }

            if (IsValidRequest(deviceType, deviceId, ref request) == false)
            {
                ResponsePacketUtil.GenerateResponsePacket(CompletionCode.InvalidCommand, out response);
                return;
            }

            physicalId = GetPhysicalIdFromLogicalId(deviceType, deviceId);
            Tracer.WriteInfo("CommunicationDevice.SendReceive PhysicalID ({0})", physicalId);

            using (WorkItem workItem = new WorkItem(deviceType, physicalId, request, sessionId))
            {
                byte logicalPortId = (byte)LogicalPortId.InvalidLogicalPortId;
                byte functionCode  = RequestPacketUtil.GetFunctionCode(ref request);

                switch (deviceType)
                {
                case (byte)DeviceType.Server:
                // Fall through
                case (byte)DeviceType.BladeConsole:
                    logicalPortId = (byte)LogicalPortId.SerialPortServers;
                    break;

                case (byte)DeviceType.SerialPortConsole:
                    // TODO: Extend the code for more serial consoles
                    if (deviceId == 1)
                    {
                        logicalPortId = (byte)LogicalPortId.SerialPortConsole1;
                    }
                    else if (deviceId == 2)
                    {
                        logicalPortId = (byte)LogicalPortId.SerialPortConsole2;
                    }
                    else if (deviceId == 3)
                    {
                        logicalPortId = (byte)LogicalPortId.SerialPortConsole3;
                    }
                    else if (deviceId == 4)
                    {
                        logicalPortId = (byte)LogicalPortId.SerialPortConsole4;
                    }
                    break;

                default:
                    logicalPortId = (byte)LogicalPortId.SerialPortOtherDevices;
                    break;
                }

                if (logicalPortId == (byte)LogicalPortId.InvalidLogicalPortId)
                {
                    ResponsePacketUtil.GenerateResponsePacket(CompletionCode.InvalidCommand, out response);
                    return;
                }

                // If currently in safe mode, reject all the requests routed to COM4 except for BladeConsole commands
                if ((isSafeModeEnabled == true) &&
                    (logicalPortId == (byte)LogicalPortId.SerialPortServers) &&
                    (deviceType != (byte)DeviceType.BladeConsole))
                {
                    ResponsePacketUtil.GenerateResponsePacket(CompletionCode.CannotExecuteRequestInSafeMode, out response);
                    return;
                }

                if (portManagers[logicalPortId].SendReceive(priorityLevel, workItem) == true)
                {
                    // Successfully added the request in the work queue
                    Tracer.WriteInfo("[logicalPortId: {0}, priorityLevel: {1}] SendReceive succeeded and wait", logicalPortId, priorityLevel);

                    // Sleep until signaled by the device worker thread
                    // Wait time: wait time in the queue + worker thread processing time
                    workItem.Wait();

                    // Copy the response to the output buffer
                    workItem.GetResponse(out response);
                }
                else
                {
                    // Could not add the reuqest in the work queue
                    Tracer.WriteWarning("[logicalPortId: {0}, priorityLevel: {1}] SendReceive failed", logicalPortId, priorityLevel);
                    ResponsePacketUtil.GenerateResponsePacket(CompletionCode.OutOfSpace, out response);
                }
            }
        }
        /// <summary>
        /// Function that gets fan speed requirements
        /// from all blades. It also updates the blade states.
        /// </summary>
        private static void GetAllBladePwmRequirements()
        {
            // Rate is required to timestep over each individual Blade call
            double rate     = (double)getBladePwmReqtTimePeriodInMilliseconds / (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));
                }

                Tracer.WriteInfo("GetBladeRequirement called at {0} for BladeId {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)
                {
                    CheckPowerEnableState(blade);
                }

                // Log Start time
                DateTime startTime = DateTime.Now;

                #region Check fail State -> Initialize

                // 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 blade could be reinitialized
                        Tracer.WriteInfo("GetAllBladePwmRequirements: State Transition for blade {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.
                        // do not allow retries on Get System Guid
                        DeviceGuid guid = WcsBladeFacade.GetSystemGuid(blade, false);
                        if (guid.CompletionCode == (byte)CompletionCode.Success)
                        {
                            Tracer.WriteInfo("GetAllBladePwmRequirements: GUID present for blade {0}, GUID: {1}", blade, guid.Guid.ToString());

                            DeviceGuid cachedGuid = WcsBladeFacade.GetCachedGuid(blade);

                            if (guid.Guid == cachedGuid.Guid)
                            {
                                // Change state to Probation and assume the system was in fail due to timeout.
                                Tracer.WriteInfo("GetAllBladePwmRequirements: State Transition for blade {0}: {1} -> Probation", blade,
                                                 ChassisState.GetStateName(blade));
                                ChassisState.SetBladeState(blade, (byte)BladeState.Probation);
                            }
                            else
                            {
                                // Change state to Initialization as the device has changed.
                                Tracer.WriteInfo("GetAllBladePwmRequirements: State Transition for blade {0}: {1} -> Probation", blade,
                                                 ChassisState.GetStateName(blade));
                                ChassisState.SetBladeState(blade, (byte)BladeState.Initialization);
                            }
                        }
                        else
                        {
                            Tracer.WriteInfo("GetAllBladePwmRequirements: 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]++;
                }

                #endregion

                #region Move Initialize -> Probation

                // Handles Initialization
                if (ChassisState.GetBladeState(blade) == (byte)BladeState.Initialization)
                {
                    BladePowerStatePacket powerstate = ChassisState.BladePower[blade - 1].GetCachedBladePowerState();

                    if (powerstate.CompletionCode == 0)
                    {
                        if (powerstate.DecompressionTime == 0)
                        {
                            // Will result in Hard Power off or Probation
                            ReInitialize(blade);
                        }
                    }
                }

                #endregion


                // Normal operation - possible states are probation or healthy
                if (ChassisState.GetBladeState(blade) == (byte)BladeState.Probation ||
                    ChassisState.GetBladeState(blade) == (byte)BladeState.Healthy)
                {
                    #region Jbod (no sensor reading)

                    if (ChassisState.GetBladeType(blade) == (byte)BladeType.Jbod)
                    {
                        // Do not allow retries on system guid.
                        DeviceGuid guid = WcsBladeFacade.GetSystemGuid(blade, false);
                        if (guid.CompletionCode == (byte)CompletionCode.Success)
                        {
                            Tracer.WriteInfo("GetAllBladePwmRequirements: GUID present for JBOD {0}, GUID: {1}",
                                             blade, guid.Guid.ToString());

                            // Change state to Healthy
                            if (ChassisState.GetBladeState(blade) == (byte)BladeState.Probation)
                            {
                                Tracer.WriteInfo("GetAllBladePwmRequirements: State Transition for JBOD {0}: {1} -> Healthy",
                                                 blade, ChassisState.GetStateName(blade));
                                ChassisState.SetBladeState(blade, (byte)BladeState.Healthy);
                            }
                        }
                        else
                        {
                            Tracer.WriteInfo("GetAllBladePwmRequirements: 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("GetAllBladePwmRequirements: 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;
                    }

                    #endregion

                    #region Server -> Get PWM move to Healthy or move to Fail

                    // Call temperature reading list command
                    SensorReading Temps = WcsBladeFacade.GetSensorReading((byte)blade, (byte)ConfigLoaded.InputSensor, PriorityLevel.System);

                    if (Temps.CompletionCode != (byte)CompletionCode.Success)
                    {
                        Tracer.WriteWarning("GetAllBladePwmRequirements: BladeId: {0} - GetSensorReading for temperature failed with code {1:X}",
                                            blade, Temps.CompletionCode);

                        // Move to Fail state if no readings were obtained
                        Tracer.WriteInfo("GetAllBladePwmRequirements: State Transition for blade {0}: {1} -> Fail", blade,
                                         ChassisState.GetStateName(blade));

                        ChassisState.SetBladeState(blade, (byte)BladeState.Fail);
                    }
                    else
                    {
                        Tracer.WriteInfo("GetAllBladePwmRequirements: #### BladeId = " + 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("GetAllBladePwmRequirements: State Transition for blade {0}: {1} -> Healthy",
                                             blade, ChassisState.GetStateName(blade));

                            ChassisState.SetBladeState(blade, (byte)BladeState.Healthy);
                            ChassisState.FailCount[blade - 1] = 0; // reset the fail count

                            // When a blade transitions to 'Healthy' state, enable/disable default blade operations
                            EnableDisableDefaultBladeOperations(blade);
                        }

                        if (ConfigLoaded.InputSensor != 1) // Non-PWM sensor.
                        {
                            PWM = GetPwmFromTemperature(Temps.Reading,
                                                        ConfigLoaded.SensorLowThreshold,
                                                        ConfigLoaded.SensorHighThreshold);
                        }
                        else
                        {
                            // PWM should never be higher or lower than the threshold.
                            if (Temps.Reading < ConfigLoaded.MinPWM || Temps.Reading > ConfigLoaded.MaxPWM)
                            {
                                Tracer.WriteWarning("PWM value " + Temps.Reading + " on blade " + blade +
                                                    " is out of range (lowThreshold: " + ConfigLoaded.MinPWM +
                                                    " - highThreshold: " + ConfigLoaded.MaxPWM);

                                PWM = (byte)ConfigLoaded.MinPWM;
                            }
                            else
                            {
                                PWM = (byte)Temps.Reading;
                            }
                        }

                        Tracer.WriteInfo("PWM value on blade {0} for Sensor {1} = {2}", blade, InputSensor, PWM);
                    }

                    #endregion
                }

                // 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 static void SetAllFanSpeeds()
        {
            // rate limiter for setting thread
            Thread.Sleep(TimeSpan.FromMilliseconds(setTimePeriodInMilliseconds));

            // Get max requirement from the bladerequirement table
            byte maxFanRequest = GetMaxRequirement();

            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. Scaling fan speed up proportionally to handle one fan failure.");

                // 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;
        }