private static Activities ConvertToActivityRollback(ScheduledRules scheduledRule)
        {
            if (scheduledRule.Rolledback == null)
            //|| !scheduledRule.Rolledback.Value
            {
                return(null);
            }

            return(new Activities()
            {
                //if(scheduledRule.ExecutionStartTime != null)
                FIChaosStartedTime = scheduledRule.RollbackExecutionStartTime.Value,
                ResourceName = scheduledRule.ResourceName,
                ChaosStartedTime = scheduledRule.RollbackExecutionStartTime.HasValue
                    ? scheduledRule.RollbackExecutionStartTime.ToString()
                    : null,
                ChaosCompletedTime = scheduledRule.RollbackEventCompletedTime.HasValue ? scheduledRule.RollbackEventCompletedTime.ToString() : null,
                ChaosOperation = scheduledRule.FiOperation + " - " + ActionType.Start,
                InitialState = scheduledRule.RollbackInitialState,
                FinalState = scheduledRule.RollbackFinalState,
                Status = scheduledRule.RollbackExecutionStatus,
                Error = scheduledRule.RollbackError,
                Warning = scheduledRule.RollbackWarning
            });
        }
        public static ScheduledRules ConvertToScheduledRuleEntityForAvailabilityZone <T>(T entity, string sessionId,
                                                                                         ActionType action, string fiOperation, DateTime executionTime) where T : VirtualMachineCrawlerResponse
        {
            if (!Mappings.FunctionNameMap.ContainsKey(VirtualMachineGroup.AvailabilityZones.ToString()))
            {
                return(null);
            }

            var localGUID    = sessionId; // System.Guid.NewGuid().ToString();
            var scheduleRule = new ScheduledRules(localGUID, entity.RowKey)
                                          //return new ScheduledRules(localGUID, entity.RowKey)
            {
                ResourceType           = VirtualMachineGroup.AvailabilityZones.ToString(),
                ScheduledExecutionTime = executionTime,
                FiOperation            = fiOperation,
                ResourceName           = entity.ResourceName,
                CurrentAction          = action.ToString(),
                TriggerData            = GetTriggerData(entity, action, localGUID, entity.RowKey, VirtualMachineGroup.AvailabilityZones.ToString()),
                SchedulerSessionId     = sessionId,
                CombinationKey         = entity.RegionName + Delimeters.Exclamatory.ToString() + entity.AvailabilityZone,
                //Rolledback = false
            };

            if (fiOperation.Equals(AzureFiOperation.PowerCycle.ToString()))
            {
                scheduleRule.Rolledback = false;
            }

            return(scheduleRule);
        }
        public static ScheduledRules ConvertToScheduledRuleEntity <T>(T entity, string sessionId,
                                                                      ActionType action, string fiOperation, DateTime executionTime, VirtualMachineGroup virtualMachineGroup) where T : CrawlerResponse
        {
            if (entity == null || !Mappings.FunctionNameMap.ContainsKey(virtualMachineGroup.ToString()))
            {
                return(null);
            }
            var localGUID    = sessionId;// System.Guid.NewGuid().ToString();
            var scheduleRule = new ScheduledRules(localGUID, entity.RowKey)
            {
                ResourceType           = virtualMachineGroup.ToString(),
                ScheduledExecutionTime = executionTime,
                ResourceName           = entity.ResourceName,
                CurrentAction          = action.ToString(),
                FiOperation            = fiOperation,
                TriggerData            = GetTriggerData(entity, action, localGUID, entity.RowKey, virtualMachineGroup.ToString()),
                SchedulerSessionId     = sessionId
            };

            if (fiOperation.Equals(AzureFiOperation.PowerCycle.ToString()))
            {
                scheduleRule.Rolledback = false;
            }

            return(scheduleRule);
        }
 /// <summary>Set the initial property of the activity entity</summary>
 /// <param name="virtualMachine">The vm</param>
 /// <param name="scheduledRules">Event activity entity.</param>
 /// /// <param name="enableRollback">Event activity entity.</param>
 private static void SetInitialEventActivity(IVirtualMachine virtualMachine, ScheduledRules scheduledRules, bool enableRollback)
 {
     if (enableRollback)
     {
         scheduledRules.RollbackInitialState       = virtualMachine.PowerState.Value;
         scheduledRules.RollbackExecutionStartTime = DateTime.UtcNow;
     }
     else
     {
         scheduledRules.InitialState       = virtualMachine.PowerState.Value;
         scheduledRules.ExecutionStartTime = DateTime.UtcNow;
     }
 }
        private static Schedules ConvertToSchedule(ScheduledRules scheduledRule)
        {
            var triggerData = JsonConvert.DeserializeObject <InputObject>(scheduledRule.TriggerData);

            return(new Schedules()
            {
                ResourceName = scheduledRule.ResourceName,
                ScheduledTime = scheduledRule.ScheduledExecutionTime.ToString(),
                ChaosOperation = scheduledRule.FiOperation,
                IsRollbacked = scheduledRule.Rolledback,
                Status = (scheduledRule.FiOperation == "Restart") ? Status.Completed.ToString() : scheduledRule.Rolledback.HasValue && scheduledRule.Rolledback.Value ? scheduledRule.RollbackExecutionStatus : Status.Incomplete.ToString()
            });
        }
        private static Activities ConvertToActivity(ScheduledRules scheduledRule)
        {
            var triggerData = JsonConvert.DeserializeObject <InputObject>(scheduledRule.TriggerData);

            return(new Activities()
            {
                ResourceName = scheduledRule.ResourceName,
                ChaosStartedTime = scheduledRule.ExecutionStartTime.HasValue ? scheduledRule.ExecutionStartTime.ToString() : null,
                ChaosCompletedTime = scheduledRule.EventCompletedTime.HasValue ? scheduledRule.EventCompletedTime.ToString(): null,
                ChaosOperation = scheduledRule.FiOperation + " - " + triggerData.Action.ToString(),
                InitialState = scheduledRule.InitialState,
                FinalState = scheduledRule.FinalState,
                Status = scheduledRule.ExecutionStatus,
                Error = scheduledRule.Error,
                Warning = scheduledRule.Warning
            });
        }
        public static bool Run([OrchestrationTrigger] DurableOrchestrationContext context, TraceWriter log)
        {
            var inputData = context.GetInput <string>();

            if (!ValidateInput(inputData, log, out var inputObject))
            {
                return(false);
            }

            var azureClient = new AzureClient();

            var scheduleRule = new ScheduledRules(inputObject.PartitionKey, inputObject.RowKey);

            if (inputObject.EnableRollback)
            {
                scheduleRule.RollbackExecutionStatus = Status.Started.ToString();
            }
            else
            {
                scheduleRule.ExecutionStatus = Status.Started.ToString();
            }

            if (!azureClient.IsChaosEnabledByGroup(inputObject.ResourceType))
            {
                if (inputObject.EnableRollback)
                {
                    scheduleRule.RollbackWarning = Warnings.ChaosDisabledAfterRules;
                }
                else
                {
                    scheduleRule.Warning = Warnings.ChaosDisabledAfterRules;
                }

                StorageAccountProvider.InsertOrMerge(scheduleRule, StorageTableNames.ScheduledRulesTableName);
                return(false);
            }

            try
            {
                IVirtualMachine virtualMachine = GetVirtualMachine(azureClient.AzureInstance, inputObject);
                if (virtualMachine == null)
                {
                    log.Info($"VM Chaos : No resource found for the resource name : " + inputObject.ResourceId);
                    return(false);
                }

                log.Info($"VM Chaos received the action: " + inputObject.Action + " for the virtual machine: " + inputObject.ResourceId);

                if (!Enum.TryParse(virtualMachine.ProvisioningState, out ProvisioningState provisioningState) || provisioningState != ProvisioningState.Succeeded)
                {
                    log.Info($"VM Chaos :  The vm '" + inputObject.ResourceId + "' is in the state of " + virtualMachine.ProvisioningState + ", so cannont perform the same action " + inputObject.Action);
                    if (inputObject.EnableRollback)
                    {
                        scheduleRule.RollbackExecutionStatus = Status.Failed.ToString();
                        scheduleRule.RollbackWarning         = string.Format(Warnings.ProvisionStateCheck, provisioningState);
                    }
                    else
                    {
                        scheduleRule.ExecutionStatus = Status.Failed.ToString();
                        scheduleRule.Warning         = string.Format(Warnings.ProvisionStateCheck, provisioningState);
                    }

                    StorageAccountProvider.InsertOrMerge(scheduleRule, StorageTableNames.ScheduledRulesTableName);
                    return(false);
                }

                SetInitialEventActivity(virtualMachine, scheduleRule, inputObject.EnableRollback);

                // if its not valid chaos then update the event table with  warning message and return false
                bool isValidChaos = IsValidChaos(inputObject.Action, virtualMachine.PowerState);
                if (!isValidChaos)
                {
                    log.Info($"VM Chaos- Invalid action: " + inputObject.Action);
                    if (inputObject.EnableRollback)
                    {
                        scheduleRule.RollbackExecutionStatus = Status.Failed.ToString();
                        scheduleRule.RollbackWarning         = Warnings.ActionAndStateAreSame;
                    }
                    else
                    {
                        scheduleRule.ExecutionStatus = Status.Failed.ToString();
                        scheduleRule.Warning         = Warnings.ActionAndStateAreSame;
                    }

                    StorageAccountProvider.InsertOrMerge(scheduleRule, StorageTableNames.ScheduledRulesTableName);
                    return(false);
                }

                StorageAccountProvider.InsertOrMerge(scheduleRule, StorageTableNames.ScheduledRulesTableName);
                PerformChaosOnVirtualMachine(inputObject.Action, virtualMachine, scheduleRule, inputObject.EnableRollback);
                // Can we break from here to check the status later ?
                virtualMachine = GetVirtualMachine(azureClient.AzureInstance, inputObject);
                if (virtualMachine != null)
                {
                    if (inputObject.EnableRollback)
                    {
                        scheduleRule.Rolledback = true;
                        scheduleRule.RollbackEventCompletedTime = DateTime.UtcNow;
                        scheduleRule.RollbackFinalState         = virtualMachine.PowerState.Value;
                        scheduleRule.RollbackExecutionStatus    = Status.Completed.ToString();
                    }
                    else
                    {
                        scheduleRule.EventCompletedTime = DateTime.UtcNow;
                        scheduleRule.FinalState         = virtualMachine.PowerState.Value;
                        scheduleRule.ExecutionStatus    = Status.Completed.ToString();
                    }
                }

                StorageAccountProvider.InsertOrMerge(scheduleRule, StorageTableNames.ScheduledRulesTableName);
                log.Info($"VM Chaos Completed");
                return(true);
            }
            catch (Exception ex)
            {
                if (inputObject.EnableRollback)
                {
                    scheduleRule.RollbackError           = ex.Message;
                    scheduleRule.RollbackExecutionStatus = Status.Failed.ToString();
                }
                else
                {
                    scheduleRule.Error           = ex.Message;
                    scheduleRule.ExecutionStatus = Status.Failed.ToString();
                }

                StorageAccountProvider.InsertOrMerge(scheduleRule, StorageTableNames.ScheduledRulesTableName);

                // dont throw the error here just handle the error and return the false
                log.Error($"VM Chaos trigger function threw the exception ", ex, FunctionName);
                log.Info($"VM Chaos Completed with error");
            }

            return(false);
        }
        /// <summary>Perform the Chaos Operation</summary>
        /// <param name="actionType">Action type</param>
        /// <param name="virtualMachine">Virtual Machine</param>
        /// <param name="scheduledRules">Event activity entity</param>
        /// <returns></returns>
        private static void PerformChaosOnVirtualMachine(string action, IVirtualMachine virtualMachine, ScheduledRules scheduledRules, bool enableRollback)
        {
            ActionType actionType;

            if (!Enum.TryParse(action, out actionType))
            {
                return;
            }

            switch (actionType)
            {
            case ActionType.Start:
                virtualMachine.StartAsync();
                break;

            case ActionType.PowerOff:
            case ActionType.Stop:
                virtualMachine.PowerOffAsync();
                break;

            case ActionType.Restart:
                virtualMachine.RestartAsync();
                break;
            }

            if (enableRollback)
            {
                scheduledRules.RollbackExecutionStatus = Status.Executing.ToString();
            }
            else
            {
                scheduledRules.ExecutionStatus = Status.Executing.ToString();
            }
        }
 /// <summary>Set the initial property of the activity entity</summary>
 /// <param name="scaleSetVm">The vm</param>
 /// <param name="scheduleRule">Event activity entity.</param>
 /// /// <param name="enableRollback">Event activity entity.</param>
 private static void SetInitialEventActivity(IVirtualMachineScaleSetVM scaleSetVm, ScheduledRules scheduleRule, bool enableRollback)
 {
     if (enableRollback)
     {
         scheduleRule.RollbackInitialState       = scaleSetVm.PowerState.Value;
         scheduleRule.RollbackExecutionStartTime = DateTime.UtcNow;
     }
     else
     {
         scheduleRule.InitialState       = scaleSetVm.PowerState.Value;
         scheduleRule.ExecutionStartTime = DateTime.UtcNow;
     }
 }
        /// <summary>Perform the Chaos Operation</summary>
        /// <param name="actionType">Action type</param>
        /// <param name="scaleSetVm">Virtual Machine instance</param>
        /// <param name="scheduleRule">Event activity entity</param>
        /// <param name="enableRollback">Event activity entity</param>
        /// <returns></returns>
        private static async Task PerformChaos(string action, IVirtualMachineScaleSetVM scaleSetVm, ScheduledRules scheduleRule, bool enableRollback)
        {
            ActionType actionType;

            if (!Enum.TryParse(action, out actionType))
            {
                return;
            }

            switch (actionType)
            {
            case ActionType.Start:
                await scaleSetVm.StartAsync();

                break;

            case ActionType.PowerOff:
            case ActionType.Stop:
                await scaleSetVm.PowerOffAsync();

                break;

            case ActionType.Restart:
                await scaleSetVm.RestartAsync();

                break;
            }
            if (enableRollback)
            {
                scheduleRule.RollbackExecutionStatus = Status.Executing.ToString();
            }
            else
            {
                scheduleRule.ExecutionStatus = Status.Executing.ToString();
            }
        }
        public static async Task <bool> Run([OrchestrationTrigger] DurableOrchestrationContext context, TraceWriter log)
        {
            var input = context.GetInput <string>();

            if (!ValidateInput(input, log, out var inputObject))
            {
                return(false);
            }

            var azureClient  = new AzureClient();
            var scheduleRule = new ScheduledRules(inputObject.PartitionKey, inputObject.RowKey);

            if (inputObject.EnableRollback)
            {
                scheduleRule.RollbackExecutionStatus = Status.Started.ToString();
            }
            else
            {
                scheduleRule.ExecutionStatus = Status.Started.ToString();
            }
            try
            {
                var scaleSetVm = await GetVirtualMachineScaleSetVm(azureClient.AzureInstance, inputObject, log);

                if (scaleSetVm == null)
                {
                    log.Info($"VM Scaleset Chaos : No resource found for the  scale set id: " + inputObject.VirtualMachineScaleSetId);
                    return(false);
                }

                log.Info($"VM ScaleSet Chaos received the action: " + inputObject.Action +
                         " for the virtual machine: " + inputObject.ResourceId);

                SetInitialEventActivity(scaleSetVm, scheduleRule, inputObject.EnableRollback);

                // if its not valid chaos then update the event table with  warning message and return the bad request response
                bool isValidChaos = IsValidChaos(inputObject.Action, scaleSetVm.PowerState);
                if (!isValidChaos)
                {
                    log.Info($"VM ScaleSet- Invalid action: " + inputObject.Action);
                    if (inputObject.EnableRollback)
                    {
                        scheduleRule.RollbackExecutionStatus = Status.Failed.ToString();
                        scheduleRule.RollbackWarning         = Warnings.ActionAndStateAreSame;
                    }
                    else
                    {
                        scheduleRule.ExecutionStatus = Status.Failed.ToString();
                        scheduleRule.Warning         = Warnings.ActionAndStateAreSame;
                    }

                    StorageAccountProvider.InsertOrMerge(scheduleRule, StorageTableNames.ScheduledRulesTableName);
                    return(false);
                }

                if (inputObject.EnableRollback)
                {
                    scheduleRule.RollbackExecutionStatus = Status.Started.ToString();
                }
                else
                {
                    scheduleRule.ExecutionStatus = Status.Started.ToString();
                }

                StorageAccountProvider.InsertOrMerge(scheduleRule, StorageTableNames.ScheduledRulesTableName);
                await PerformChaos(inputObject.Action, scaleSetVm, scheduleRule, inputObject.EnableRollback);

                scaleSetVm = await scaleSetVm.RefreshAsync();

                if (scaleSetVm != null)
                {
                    if (inputObject.EnableRollback)
                    {
                        scheduleRule.Rolledback = true;
                        scheduleRule.RollbackEventCompletedTime = DateTime.UtcNow;
                        scheduleRule.RollbackFinalState         = scaleSetVm.PowerState.Value;
                        scheduleRule.RollbackExecutionStatus    = Status.Completed.ToString();
                    }
                    else
                    {
                        scheduleRule.EventCompletedTime = DateTime.UtcNow;
                        scheduleRule.FinalState         = scaleSetVm.PowerState.Value;
                        scheduleRule.ExecutionStatus    = Status.Completed.ToString();
                    }
                }

                StorageAccountProvider.InsertOrMerge(scheduleRule, StorageTableNames.ScheduledRulesTableName);
                log.Info($"VM ScaleSet Chaos Completed");
                return(true);
            }
            catch (Exception ex)
            {
                if (inputObject.EnableRollback)
                {
                    scheduleRule.RollbackError           = ex.Message;
                    scheduleRule.RollbackExecutionStatus = Status.Failed.ToString();
                }
                else
                {
                    scheduleRule.Error           = ex.Message;
                    scheduleRule.ExecutionStatus = Status.Failed.ToString();
                }
                StorageAccountProvider.InsertOrMerge(scheduleRule, StorageTableNames.ScheduledRulesTableName);

                // dont throw the error here just handle the error and return the false
                log.Error($"VM ScaleSet Chaos trigger function threw the exception ", ex, FunctionName);
                log.Info($"VM ScaleSet Chaos Completed with error");
            }

            return(false);
        }