Example #1
0
        internal static Contracts.StartSerialResponse StartBladeSerialSession(int bladeId, int timeoutInSecs)
        {
            Contracts.StartSerialResponse response = new Contracts.StartSerialResponse();
            response.completionCode     = Contracts.CompletionCode.Failure;
            response.serialSessionToken = null;
            Tracer.WriteInfo("BladeSerialSessionMetadata StartBladeSerialSession({0})", bladeId);

            // If there is an already existing Blade serial session (indicated by a valid bladeId and a valid sessionToken), return failure with appropriate completion code
            if (CompareAndSwapMetadata(ConfigLoaded.InactiveBladePortId, ConfigLoaded.InactiveBladeSerialSessionToken, ConfigLoaded.InactiveBladePortId, ConfigLoaded.InactiveBladeSerialSessionToken) != CompletionCode.Success)
            {
                Tracer.WriteError("StartBladeSerialSession({0}): Start failed because of already active session.", bladeId);
                response.completionCode = Contracts.CompletionCode.SerialSessionActive;
                return(response);
            }

            // Ipmi command to indicate start of serial session
            // This has to be executed before Enabling comm. dev. safe mode otherwise this will fail
            Ipmi.SerialMuxSwitch sms = WcsBladeFacade.SetSerialMuxSwitch((byte)bladeId, Ipmi.MuxSwtich.SwitchSystem);

            // If set serial mux fails - reverse all operations
            if (sms.CompletionCode != (byte)CompletionCode.Success)
            {
                Tracer.WriteError("BladeSerialSessionMetadata.StartBladeSerialSession({0}): Ipmi SetSerialMuxSwitch Failed", bladeId);
                if (!CommunicationDevice.DisableSafeMode())
                {
                    Tracer.WriteError("BladeSerialSessionMetadata.StartBladeSerialSession({0}): Unable to disable comm.dev. safe mode", bladeId);
                }
                // Whenever we disable safe mode, make sure that no more serial session activity may be performed - by reseting metadata
                if (!BladeSerialSessionMetadata.ResetMetadata())
                {
                    Tracer.WriteError("BladeSerialSessionMetadata.StopBladeSerialSession({0}): Unable to reset metadata", bladeId);
                }
                return(response);
            }

            byte[] randomNumber = new byte[8];
            new System.Security.Cryptography.RNGCryptoServiceProvider().GetNonZeroBytes(randomNumber);

            // Initialize Blade Serial Session MetaData - Init function does this automically
            // This function acts as a serialization point - only one active thread can proceed beyond this
            if (CompareAndSwapMetadata(ConfigLoaded.InactiveBladePortId, ConfigLoaded.InactiveBladeSerialSessionToken, bladeId, BitConverter.ToString(randomNumber), DateTime.Now) != CompletionCode.Success)
            {
                response.completionCode = Contracts.CompletionCode.SerialSessionActive;
                return(response);
            }

            response.completionCode     = Contracts.CompletionCode.Success;
            response.serialSessionToken = BitConverter.ToString(randomNumber);
            // Initializing TimeoutBladeSerialSessionInSecs with user defined session timeout
            ConfigLoaded.TimeoutBladeSerialSessionInSecs = timeoutInSecs;
            return(response);
        }
        public Contracts.StartSerialResponse StartSerialPortConsole(int portID, int clientSessionInactivityTimeoutInSecs, int serialdeviceCommunicationTimeoutInMsecs)
        {
            Contracts.StartSerialResponse response = new Contracts.StartSerialResponse();
            response.completionCode = Contracts.CompletionCode.Failure;
            response.serialSessionToken = null;
            this.portId = portID;

            Tracer.WriteInfo("Received StartSerialPortConsole({0})", this.portId);

            int clientInactivityTimeoutInSecs = ConfigLoaded.SerialPortConsoleClientSessionInactivityTimeoutInSecs;
            if (clientSessionInactivityTimeoutInSecs < 0 || clientSessionInactivityTimeoutInSecs > 0)
            {
                clientInactivityTimeoutInSecs = clientSessionInactivityTimeoutInSecs;
            }

            byte[] randomNumber = new byte[8];
            new System.Security.Cryptography.RNGCryptoServiceProvider().GetNonZeroBytes(randomNumber);
            Tracer.WriteInfo("StartSerialPortConsole: Random string is " + BitConverter.ToString(randomNumber));

            // Initialize Serial Session MetaData including the client inactivity timeout - this function does this automically
            // This function acts as a serialization point - only one active thread can proceed beyond this
            if (this.CompareAndSwapMetadata(ConfigLoaded.InactiveSerialPortSessionToken, BitConverter.ToString(randomNumber), DateTime.Now, clientInactivityTimeoutInSecs) != CompletionCode.Success)
            {
                response.completionCode = Contracts.CompletionCode.SerialSessionActive;
                return response;
            }

            SerialPortConsole currConsole = new SerialPortConsole((byte)portId);
            SerialStatusPacket serialStatus = new SerialStatusPacket();

            // TODO: Baudrate is hard coded here since it is not exposed to user in this V1.1 hotfix. 
            // We should later take the default value from app.config and include this as parameter in REST API
            BaudRate portBaudRate = BaudRate.Rate_9600;

            // Negative timeout values will be interpreted as infinite timeout by the device layer open serial port function
            int communicationDeviceTimeoutIn1ms = ConfigLoaded.SerialPortConsoleDeviceCommunicationTimeoutInMsecs;
            if (serialdeviceCommunicationTimeoutInMsecs < 0 || serialdeviceCommunicationTimeoutInMsecs > 0)
            {
                communicationDeviceTimeoutIn1ms = serialdeviceCommunicationTimeoutInMsecs;
                if (communicationDeviceTimeoutIn1ms > 0 && communicationDeviceTimeoutIn1ms < Constants.MinimumSerialDeviceTimeoutInMsecs)
                {
                    communicationDeviceTimeoutIn1ms = Constants.MinimumSerialDeviceTimeoutInMsecs;
                }
            }

            serialStatus = currConsole.openSerialPortConsole(communicationDeviceTimeoutIn1ms, portBaudRate);
            Tracer.WriteInfo("After calling comm dev open serial port");
            if (serialStatus.completionCode != CompletionCode.Success)
            {
                Tracer.WriteError("Error in Open Serial Port ({0})", portId);
                if (!this.ResetMetadata())
                {
                    Tracer.WriteError("StartSerialPortConsole Error: Unable to reset metadata");
                }
                return response;
            }

            response.completionCode = Contracts.CompletionCode.Success;
            response.serialSessionToken = BitConverter.ToString(randomNumber);
            return response;
        }
        internal static Contracts.StartSerialResponse StartBladeSerialSession(int bladeId, int timeoutInSecs)
        {
            Contracts.StartSerialResponse response = new Contracts.StartSerialResponse();
            response.completionCode = Contracts.CompletionCode.Failure;
            response.serialSessionToken = null;
            Tracer.WriteInfo("BladeSerialSessionMetadata StartBladeSerialSession({0})", bladeId);

            // If there is an already existing Blade serial session (indicated by a valid bladeId and a valid sessionToken), return failure with appropriate completion code
            if (CompareAndSwapMetadata(ConfigLoaded.InactiveBladePortId, ConfigLoaded.InactiveBladeSerialSessionToken, ConfigLoaded.InactiveBladePortId, ConfigLoaded.InactiveBladeSerialSessionToken) != CompletionCode.Success)
            {
                Tracer.WriteError("StartBladeSerialSession({0}): Start failed because of already active session.", bladeId);
                response.completionCode = Contracts.CompletionCode.SerialSessionActive;
                return response;
            }

            // Ipmi command to indicate start of serial session
            // This has to be executed before Enabling comm. dev. safe mode otherwise this will fail
            Ipmi.SerialMuxSwitch sms = WcsBladeFacade.SetSerialMuxSwitch((byte)bladeId, Ipmi.MuxSwtich.SwitchSystem);

            // If set serial mux fails - reverse all operations
            if (sms.CompletionCode != (byte)CompletionCode.Success)
            {
                Tracer.WriteError("BladeSerialSessionMetadata.StartBladeSerialSession({0}): Ipmi SetSerialMuxSwitch Failed", bladeId);
                if (!CommunicationDevice.DisableSafeMode())
                {
                    Tracer.WriteError("BladeSerialSessionMetadata.StartBladeSerialSession({0}): Unable to disable comm.dev. safe mode", bladeId);
                }
                // Whenever we disable safe mode, make sure that no more serial session activity may be performed - by reseting metadata
                if (!BladeSerialSessionMetadata.ResetMetadata())
                {
                    Tracer.WriteError("BladeSerialSessionMetadata.StopBladeSerialSession({0}): Unable to reset metadata", bladeId);
                }
                return response;
            }

            byte[] randomNumber = new byte[8];
            new System.Security.Cryptography.RNGCryptoServiceProvider().GetNonZeroBytes(randomNumber);

            // Initialize Blade Serial Session MetaData - Init function does this automically
            // This function acts as a serialization point - only one active thread can proceed beyond this
            if (CompareAndSwapMetadata(ConfigLoaded.InactiveBladePortId, ConfigLoaded.InactiveBladeSerialSessionToken, bladeId, BitConverter.ToString(randomNumber), DateTime.Now) != CompletionCode.Success)
            {
                response.completionCode = Contracts.CompletionCode.SerialSessionActive;
                return response;
            }

            response.completionCode = Contracts.CompletionCode.Success;
            response.serialSessionToken = BitConverter.ToString(randomNumber);
            // Initializing TimeoutBladeSerialSessionInSecs with user defined session timeout
            ConfigLoaded.TimeoutBladeSerialSessionInSecs = timeoutInSecs;
            return response;
        }
        public Contracts.StartSerialResponse StartSerialPortConsole(int portID, int clientSessionInactivityTimeoutInSecs, int serialdeviceCommunicationTimeoutInMsecs)
        {
            Contracts.StartSerialResponse response = new Contracts.StartSerialResponse();
            response.completionCode     = Contracts.CompletionCode.Failure;
            response.serialSessionToken = null;
            this.portId = portID;

            Tracer.WriteInfo("Received StartSerialPortConsole({0})", this.portId);

            int clientInactivityTimeoutInSecs = ConfigLoaded.SerialPortConsoleClientSessionInactivityTimeoutInSecs;

            if (clientSessionInactivityTimeoutInSecs < 0 || clientSessionInactivityTimeoutInSecs > 0)
            {
                clientInactivityTimeoutInSecs = clientSessionInactivityTimeoutInSecs;
            }

            byte[] randomNumber = new byte[8];
            new System.Security.Cryptography.RNGCryptoServiceProvider().GetNonZeroBytes(randomNumber);
            Tracer.WriteInfo("StartSerialPortConsole: Random string is " + BitConverter.ToString(randomNumber));

            // Initialize Serial Session MetaData including the client inactivity timeout - this function does this automically
            // This function acts as a serialization point - only one active thread can proceed beyond this
            if (this.CompareAndSwapMetadata(ConfigLoaded.InactiveSerialPortSessionToken, BitConverter.ToString(randomNumber), DateTime.Now, clientInactivityTimeoutInSecs) != CompletionCode.Success)
            {
                response.completionCode = Contracts.CompletionCode.SerialSessionActive;
                return(response);
            }

            SerialPortConsole  currConsole  = new SerialPortConsole((byte)portId);
            SerialStatusPacket serialStatus = new SerialStatusPacket();

            // TODO: Baudrate is hard coded here since it is not exposed to user in this V1.1 hotfix.
            // We should later take the default value from app.config and include this as parameter in REST API
            BaudRate portBaudRate = BaudRate.Rate_9600;

            // Negative timeout values will be interpreted as infinite timeout by the device layer open serial port function
            int communicationDeviceTimeoutIn1ms = ConfigLoaded.SerialPortConsoleDeviceCommunicationTimeoutInMsecs;

            if (serialdeviceCommunicationTimeoutInMsecs < 0 || serialdeviceCommunicationTimeoutInMsecs > 0)
            {
                communicationDeviceTimeoutIn1ms = serialdeviceCommunicationTimeoutInMsecs;
                if (communicationDeviceTimeoutIn1ms > 0 && communicationDeviceTimeoutIn1ms < Constants.MinimumSerialDeviceTimeoutInMsecs)
                {
                    communicationDeviceTimeoutIn1ms = Constants.MinimumSerialDeviceTimeoutInMsecs;
                }
            }

            serialStatus = currConsole.openSerialPortConsole(communicationDeviceTimeoutIn1ms, portBaudRate);
            Tracer.WriteInfo("After calling comm dev open serial port");
            if (serialStatus.completionCode != CompletionCode.Success)
            {
                Tracer.WriteError("Error in Open Serial Port ({0})", portId);
                if (!this.ResetMetadata())
                {
                    Tracer.WriteError("StartSerialPortConsole Error: Unable to reset metadata");
                }
                return(response);
            }

            response.completionCode     = Contracts.CompletionCode.Success;
            response.serialSessionToken = BitConverter.ToString(randomNumber);
            return(response);
        }
        internal static Contracts.StartSerialResponse StartBladeSerialSession(int bladeId, int timeoutInSecs)
        {
            Contracts.StartSerialResponse response = new Contracts.StartSerialResponse();
            response.completionCode = Contracts.CompletionCode.Failure;
            response.serialSessionToken = null;
            Tracer.WriteInfo("BladeSerialSessionMetadata StartBladeSerialSession({0})", bladeId);

            // If there is an already existing Blade serial session (indicated by a valid bladeId and a valid sessionToken), return failure with appropriate completion code
            if (CompareAndSwapMetadata(ConfigLoaded.InactiveBladePortId, ConfigLoaded.InactiveBladeSerialSessionToken,
                ConfigLoaded.InactiveBladePortId, ConfigLoaded.InactiveBladeSerialSessionToken) != CompletionCode.Success)
            {
                Tracer.WriteError("StartBladeSerialSession({0}): Start failed because of already active session.", bladeId);
                response.completionCode = Contracts.CompletionCode.SerialSessionActive;
                return response;
            }

            // Ipmi command to indicate start of serial session
            // This will automatically enable safe mode in the communication device layer (reject all COM4 commands except for blade console)
            // Only the first call to SetSerialMuxSwitch will succeed, subsequent calls will be rejected (see above statement)
            DateTime startTime = DateTime.Now;
            Ipmi.SerialMuxSwitch sms = WcsBladeFacade.SetSerialMuxSwitch((byte)bladeId);

            // MuxSetToSystem is expected to be true
            Tracer.WriteInfo(string.Format("StartBladeSerialSession SetSerialMuxSwitch Completion Code: 0x{0:X}.  MuxSetToSystem: {1}.  Execution Time: {2} seconds",
                sms.CompletionCode, sms.MuxSetToSystem, DateTime.Now.Subtract(startTime).TotalSeconds));

            // If set serial mux fails
            if (sms.CompletionCode != (byte)CompletionCode.Success)
            {
                Tracer.WriteError("BladeSerialSessionMetadata.StartBladeSerialSession({0}): Ipmi SetSerialMuxSwitch Failed", bladeId);
                // If the failure is not because of an already existing safe mode - reverse the enable safe mode that may have been performed as part of the SetSerialMuxSwitch call above
                // If the failure is because of an already existing safe mode - we should NOT disable safe mode since that would kill the existing blade console session
                if (sms.CompletionCode != (byte)CompletionCode.CannotExecuteRequestInSafeMode)
                {
                    if (!CommunicationDevice.DisableSafeMode())
                    {
                        Tracer.WriteError("BladeSerialSessionMetadata.StartBladeSerialSession({0}): Unable to disable comm.dev. safe mode", bladeId);
                    }

                    // Whenever we disable safe mode, make sure that no more serial session activity may be performed - by reseting metadata
                    if (!BladeSerialSessionMetadata.ResetMetadata())
                    {
                        Tracer.WriteError("BladeSerialSessionMetadata.StopBladeSerialSession({0}): Unable to reset metadata", bladeId);
                    }
                }
                return response;
            }

            byte[] randomNumber = new byte[8];
            new System.Security.Cryptography.RNGCryptoServiceProvider().GetNonZeroBytes(randomNumber);

            // Initialize Blade Serial Session MetaData - this function does this ATOMICally
            // This function acts as a serialization point - only one active thread can proceed beyond this
            // If there is an already existing Blade serial session (indicated by a valid bladeId and a valid sessionToken), return failure with appropriate completion code
            if (CompareAndSwapMetadata(ConfigLoaded.InactiveBladePortId, ConfigLoaded.InactiveBladeSerialSessionToken, bladeId, BitConverter.ToString(randomNumber), DateTime.Now) != CompletionCode.Success)
            {
                Tracer.WriteError("StartBladeSerialSession({0}): Start failed because of already active session.", bladeId);
                response.completionCode = Contracts.CompletionCode.SerialSessionActive;
                return response;
            }

            response.completionCode = Contracts.CompletionCode.Success;
            response.serialSessionToken = BitConverter.ToString(randomNumber);
            // Initializing TimeoutBladeSerialSessionInSecs with user defined session timeout
            ConfigLoaded.TimeoutBladeSerialSessionInSecs = timeoutInSecs;
            return response;
        }
        /// <summary>
        /// Starts the blade serial session.
        /// </summary>
        /// <param name="bladeId">The blade identifier.</param>
        /// <param name="timeoutInSecs">The timeout in secs.</param>
        /// <returns></returns>
        internal Contracts.StartSerialResponse StartBladeSerialSession(int bladeId, int timeoutInSecs)
        {
            Contracts.StartSerialResponse response = new Contracts.StartSerialResponse();
            response.completionCode = Contracts.CompletionCode.Failure;
            response.serialSessionToken = null;
            Tracer.WriteInfo("BladeSerialSessionMetadata StartBladeSerialSession(bladeId: {0})", bladeId);

            // If there is an existing Blade serial session (indicated by a valid sessionToken),
            // return failure with appropriate completion code
            if (CompareAndSwapMetadata(inactiveBladeSerialSessionToken,
                inactiveBladeSerialSessionToken) != CompletionCode.Success)
            {
                Tracer.WriteError("BladeSerialSessionMetadata. StartBladeSerialSession(bladeId: {0}): " +
                    "Start failed because of existing active session.", bladeId);
                response.completionCode = Contracts.CompletionCode.SerialSessionActive;
                return response;
            }

            // Add the blade to the serial session active blades list if the capacity is not violated
            if (UpdateBladeToSerialSessionBladeList(this.bladeId, UpdateListOption.Add) == -1)
            {
                // Check if maximum number of serial sessions have been reached
                int numSessions = UpdateBladeToSerialSessionBladeList(this.bladeId, UpdateListOption.DoNothing);
                if (numSessions >= maxParallelBladeSerialSessions)
                {
                    Tracer.WriteError("BladeSerialSessionMetadata. StartBladeSerialSession: " +
                        "Max sessions reached. Number of sessions: " + numSessions +
                        ". Could not add Blade " + this.bladeId + " to serial session active blades list. ", this.bladeId);
                    response.completionCode = Contracts.CompletionCode.MaxSerialSessionReached;
                }
                else
                {
                    Tracer.WriteError("BladeSerialSessionMetadata. StartBladeSerialSession: " +
                        "Could not add Blade {0} to serial session active blades list.", this.bladeId);
                    response.completionCode = Contracts.CompletionCode.SerialSessionActive;
                }
                return response;
            }

            // Start the serial session. Use default timeout in app.config if user specified value is zero.
            int adjustedTimeout = (timeoutInSecs == 0) ? (int)ConfigLoaded.BladeSerialTimeout : timeoutInSecs;
            Ipmi.StartSerialSession startSession = WcsBladeFacade.StartSerialSession((byte)bladeId, true, adjustedTimeout);

            if (startSession.CompletionCode != (byte)CompletionCode.Success)
            {
                Tracer.WriteError("BladeSerialSessionMetadata.StartBladeSerialSession(bladeId: {0}): StartSerialSession Failed", bladeId);

                if (startSession.CompletionCode == sessionAlreadyActive)
                    response.completionCode = Contracts.CompletionCode.SerialSessionActive;
            }
            else
            {
                byte[] randomNumber = new byte[8];
                new System.Security.Cryptography.RNGCryptoServiceProvider().GetNonZeroBytes(randomNumber);

                // Initialize Blade Serial Session MetaData - this function does this ATOMICally
                // If there is an already existing Blade serial session (indicated by a valid bladeId and a valid sessionToken), return failure with appropriate completion code
                if (CompareAndSwapMetadata(inactiveBladeSerialSessionToken,
                    BitConverter.ToString(randomNumber), DateTime.Now) != CompletionCode.Success)
                {
                    Tracer.WriteError("BladeSerialSessionMetadata. StartBladeSerialSession(bladeId: {0}): " +
                        "Start failed because of existing active session.", bladeId);
                    response.completionCode = Contracts.CompletionCode.SerialSessionActive;
                }
                else
                {
                    response.serialSessionToken = BitConverter.ToString(randomNumber);
                    // Initialize TimeoutBladeSerialSessionInSecs with user defined session timeout
                    TimeoutBladeSerialSessionInSecs = timeoutInSecs;
                    response.completionCode = Contracts.CompletionCode.Success;
                }
            }

            if (response.completionCode != Contracts.CompletionCode.Success)
            {
                // Remove the blade from the list since serial session is not successfully established
                if (UpdateBladeToSerialSessionBladeList(this.bladeId, UpdateListOption.Remove) == -1)
                    Tracer.WriteError("BladeSerialSessionMetadata.StartBladeSerialSession: " +
                        "Could not remove Blade {0} from the serial session active blades list.", this.bladeId);
            }

            return response;
        }