示例#1
0
        private Models.ISchedulablePlan LoadPlan(Options options)
        {
            Models.ISchedulablePlan result = null;

            switch (options.PlanType)
            {
            case PlanTypeEnum.Backup:
                result = _daoBackupPlan.Get(options.PlanIdentifier);
                break;

            case PlanTypeEnum.Restore:
                result = _daoRestorePlan.Get(options.PlanIdentifier);
                break;
            }

            return(result);
        }
示例#2
0
        private IBaseOperation CreateOperation(Models.ISchedulablePlan plan, Options options)
        {
            IBaseOperation result = null;

            switch (options.PlanType)
            {
            case PlanTypeEnum.Backup:
                result = CreateBackupOperation(plan as Models.BackupPlan);
                //result = CreateBackupOperation(plan as Models.BackupPlan);
                break;

            case PlanTypeEnum.Restore:
                result = CreateRestoreOperation(plan as Models.RestorePlan);
                //result = CreateRestoreOperation(plan as Models.RestorePlan);
                break;
            }

            return(result);
        }
示例#3
0
 public BaseOperationHelper(Models.ISchedulablePlan plan)
 {
     Plan = plan;
     Plan.Config.WireUpActions();             // IMPORTANT: Must be invoked before raising any plan event.
 }
示例#4
0
        private void Run()
        {
            // Load informed plan
            Models.ISchedulablePlan plan = LoadPlan(Options);
            if (plan == null)
            {
                logger.Fatal("The {0} plan with id {1} does not exist.",
                             Options.PlanType.ToString().ToLowerInvariant(), Options.PlanIdentifier);
                ExitShowingHelpText(1);
            }

            Model = plan;

            if (Options.Verbose)
            {
                logger.Info("Running {0} plan #{1}", Options.PlanType.ToString().ToLowerInvariant(), Options.PlanIdentifier);
            }

#if !DEBUG
            try
#endif
            {
                RunningOperation = CreateOperation(plan, Options);

                RunningOperation.Start();

                while (true)
                {
                    if (!IsReleaseVersion && System.Environment.UserInteractive)
                    {
                        if (ConsoleAppHelper.TerminationRequestedEvent.WaitOne(1))
                        {
                            if (RunningOperation != null && RunningOperation.IsRunning)
                            {
                                RunningOperation.Cancel();
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    if (RunningOperationEndedEvent.WaitOne(100))
                    {
                        break;
                    }

                    RunningOperation.DoEvents();
                }

                logger.Info("Operation finished.");

                Handler.Client.WaitUntilDone();

                RunningOperation.SendReport();
            }
#if !DEBUG
            catch (Exception ex)
            {
                string message = ex.Message;

                Handler.Send(Commands.ReportError(0, message));
                logger.Error(message);

                if (RunningOperation != null)
                {
                    BaseOperationReport report = RunningOperation.GetReport() as BaseOperationReport;
                    report.OperationStatus = OperationStatus.FAILED;
                    report.AddErrorMessage(message);
                    RunningOperation.SendReport();
                }

                Environment.Exit(1);
            }
#endif

#if DEBUG
            // Wait 10 seconds before exiting, only for debugging purposes.
            Thread.Sleep(10000);
#endif
        }
示例#5
0
        private void SchedulePlanExecution(Models.ISchedulablePlan plan, bool reschedule = false)
        {
            string taskName = BuildTaskName(plan);

            // Get the service on the local machine
            using (TaskService ts = new TaskService())
            {
                // Find if there's already a task for the informed plan.
                Task existingTask = ts.FindTask(taskName, false);

                if (existingTask != null)
                {
                    // Check if the plan changed after the existing task was scheduled.
                    // It's important to convert the DateTime's to the same TimeZone before comparing them.
                    bool changed = plan.UpdatedAt.ToLocalTime() > existingTask.Definition.RegistrationInfo.Date.ToLocalTime();
                    if (!changed)
                    {
                        return;
                    }

                    if (plan.IsRunManually)
                    {
                        Info("{0} is already scheduled - Deleting schedule because it's now Manual.", taskName);

                        // Remove the task we found.
                        ts.RootFolder.DeleteTask(taskName);
                        return;
                    }
                    else
                    {
                        Info("{0} is already scheduled - {1}", taskName,
                             reschedule ? "rescheduling..." : "rescheduling was not requested");

                        // If we're not rescheduling, stop now.
                        if (!reschedule)
                        {
                            return;
                        }

                        // Do NOT delete the task we found - it will be updated by `RegisterTaskDefinition`.
                        //ts.RootFolder.DeleteTask(taskName);
                    }
                }
                else
                {
                    if (plan.IsRunManually)
                    {
                        // Do not schedule anything.
                        return;
                    }
                }

                Info("Scheduling task {0} (plan last changed at {1})", taskName,
                     plan.UpdatedAt.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:ssK"));

                // If the task doesn't exist yet, create a new task definition and assign properties
                // This task will require Task Scheduler 2.0 (Windows >= Vista or Server >= 2008) or newer.
                TaskDefinition td = existingTask != null
                                        ? existingTask.Definition
                                        : ts.NewTask();

                // Run this task even if the user is NOT logged on.
                if (td.LowestSupportedVersion == TaskCompatibility.V1)
                {
                    td.Settings.RunOnlyIfLoggedOn = false;
                }

                // When running this task, use the System user account, if we have elevated privileges.
                if (IsElevated)
                {
                    td.Principal.LogonType = TaskLogonType.InteractiveTokenOrPassword;
                }

                //td.Principal.RequiredPrivileges = new TaskPrincipalPrivilege[] {
                //	TaskPrincipalPrivilege.SeBackupPrivilege,
                //	TaskPrincipalPrivilege.SeRestorePrivilege,
                //	TaskPrincipalPrivilege.SeChangeNotifyPrivilege,
                //	TaskPrincipalPrivilege.SeCreateSymbolicLinkPrivilege,
                //	TaskPrincipalPrivilege.SeManageVolumePrivilege,
                //	TaskPrincipalPrivilege.SeCreateSymbolicLinkPrivilege,
                //};

                // Run with highest privileges, if we have elevated privileges.
                if (IsElevated)
                {
                    td.Principal.RunLevel = TaskRunLevel.Highest;
                }

                // If the task is not scheduled to run again, delete it after 24 hours -- This seem to require `EndBoundary` to be set.
                //td.Settings.DeleteExpiredTaskAfter = TimeSpan.FromHours(24);

                // Don't allow multipe instances of the task to run simultaneously.
                td.Settings.MultipleInstances = TaskInstancesPolicy.IgnoreNew;

                // Only run when a network is available.
                td.Settings.RunOnlyIfNetworkAvailable = true;

                td.RegistrationInfo.Author = string.Format(@"{0}\{1}", Environment.UserDomainName, Environment.UserName);

                // We identify the Scheduled task needs an update if this Date is older than `SchedulablePlan.UpdatedAt`.
                td.RegistrationInfo.Date = DateTime.UtcNow;

                string description = string.Format(
                    "This task was automatically {0} by the {1} service at {2}",
                    existingTask != null ? "updated" : "created",
                    typeof(Teltec.Everest.Scheduler.Service).Namespace,
                    td.RegistrationInfo.Date.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:ssK"));
                td.RegistrationInfo.Description = description;

                // Create triggers to fire the task when planned.
                td.Triggers.Clear();
                td.Triggers.AddRange(BuildTriggers(plan));

                bool isBackup  = plan is Models.BackupPlan;
                bool isRestore = plan is Models.RestorePlan;
                if (!isBackup && !isRestore)
                {
                    throw new InvalidOperationException("Unhandled plan type");
                }

                // Create an action that will launch the PlanExecutor
                string planType = isBackup
                                        ? PlanTypeEnum.BACKUP.ToString().ToLowerInvariant()
                                        : isRestore
                                                ? PlanTypeEnum.RESTORE.ToString().ToLowerInvariant()
                                                : string.Empty;

                PlanExecutorEnv env = BuildPlanExecutorEnv(planType, plan.ScheduleParamId, false);
                td.Actions.Clear();
                td.Actions.Add(new ExecAction(env.Path, env.Arguments, env.Cwd));

                // Register the task in the root folder
                const string        username  = "******";
                const string        password  = null;
                const TaskLogonType logonType = TaskLogonType.ServiceAccount;
                try
                {
                    ts.RootFolder.RegisterTaskDefinition(taskName, td, TaskCreation.CreateOrUpdate, username, password, logonType);
                }
                catch (Exception ex)
                {
                    logger.Error("Failed to create/update scheduled task ({0}): {1}", taskName, ex.Message);
                }
            }
        }
示例#6
0
 private bool HasScheduledTask(Models.ISchedulablePlan plan)
 {
     return(HasScheduledTask(BuildTaskName(plan)));
 }
示例#7
0
 private Task FindScheduledTask(Models.ISchedulablePlan plan)
 {
     return(FindScheduledTask(BuildTaskName(plan)));
 }
示例#8
0
        private Trigger[] BuildTriggers(Models.ISchedulablePlan plan)
        {
            List <Trigger> triggers = new List <Trigger>();

            Models.PlanSchedule schedule = plan.Schedule;
            switch (schedule.ScheduleType)
            {
            case Models.ScheduleTypeEnum.RUN_MANUALLY:
            {
                break;
            }

            case Models.ScheduleTypeEnum.SPECIFIC:
            {
                DateTime?optional = schedule.OccursSpecificallyAt;
                if (!optional.HasValue)
                {
                    break;
                }

                DateTime whenToStart = optional.Value;

                Trigger tr = Trigger.CreateTrigger(TaskTriggerType.Time);

                // When to start?
                tr.StartBoundary = whenToStart.ToLocalTime();

                triggers.Add(tr);
                break;
            }

            case Models.ScheduleTypeEnum.RECURRING:
            {
                if (!schedule.RecurrencyFrequencyType.HasValue)
                {
                    break;
                }

                Trigger tr = null;

                switch (schedule.RecurrencyFrequencyType.Value)
                {
                case Models.FrequencyTypeEnum.DAILY:
                {
                    tr = Trigger.CreateTrigger(TaskTriggerType.Daily);

                    if (schedule.IsRecurrencyDailyFrequencySpecific)
                    {
                        // Repetition - Occurs every day
                        tr.Repetition.Interval = TimeSpan.FromDays(1);
                    }

                    break;
                }

                case Models.FrequencyTypeEnum.WEEKLY:
                {
                    if (schedule.OccursAtDaysOfWeek == null || schedule.OccursAtDaysOfWeek.Count == 0)
                    {
                        break;
                    }

                    tr = Trigger.CreateTrigger(TaskTriggerType.Weekly);

                    WeeklyTrigger wt = tr as WeeklyTrigger;

                    // IMPORTANT: The default constructed `WeeklyTrigger` sets Sunday.
                    wt.DaysOfWeek = 0;

                    Models.PlanScheduleDayOfWeek matchDay = null;

                    matchDay = schedule.OccursAtDaysOfWeek.SingleOrDefault(p => p.DayOfWeek == DayOfWeek.Monday);
                    if (matchDay != null)
                    {
                        wt.DaysOfWeek |= DaysOfTheWeek.Monday;
                    }

                    matchDay = schedule.OccursAtDaysOfWeek.SingleOrDefault(p => p.DayOfWeek == DayOfWeek.Tuesday);
                    if (matchDay != null)
                    {
                        wt.DaysOfWeek |= DaysOfTheWeek.Tuesday;
                    }

                    matchDay = schedule.OccursAtDaysOfWeek.SingleOrDefault(p => p.DayOfWeek == DayOfWeek.Wednesday);
                    if (matchDay != null)
                    {
                        wt.DaysOfWeek |= DaysOfTheWeek.Wednesday;
                    }

                    matchDay = schedule.OccursAtDaysOfWeek.SingleOrDefault(p => p.DayOfWeek == DayOfWeek.Thursday);
                    if (matchDay != null)
                    {
                        wt.DaysOfWeek |= DaysOfTheWeek.Thursday;
                    }

                    matchDay = schedule.OccursAtDaysOfWeek.SingleOrDefault(p => p.DayOfWeek == DayOfWeek.Friday);
                    if (matchDay != null)
                    {
                        wt.DaysOfWeek |= DaysOfTheWeek.Friday;
                    }

                    matchDay = schedule.OccursAtDaysOfWeek.SingleOrDefault(p => p.DayOfWeek == DayOfWeek.Saturday);
                    if (matchDay != null)
                    {
                        wt.DaysOfWeek |= DaysOfTheWeek.Saturday;
                    }

                    matchDay = schedule.OccursAtDaysOfWeek.SingleOrDefault(p => p.DayOfWeek == DayOfWeek.Sunday);
                    if (matchDay != null)
                    {
                        wt.DaysOfWeek |= DaysOfTheWeek.Sunday;
                    }

                    break;
                }

                case Models.FrequencyTypeEnum.MONTHLY:
                {
                    if (!schedule.MonthlyOccurrenceType.HasValue || !schedule.OccursMonthlyAtDayOfWeek.HasValue)
                    {
                        break;
                    }

                    tr = Trigger.CreateTrigger(TaskTriggerType.MonthlyDOW);

                    MonthlyDOWTrigger mt = tr as MonthlyDOWTrigger;

                    switch (schedule.MonthlyOccurrenceType.Value)
                    {
                    case Models.MonthlyOccurrenceTypeEnum.FIRST:
                        mt.WeeksOfMonth = WhichWeek.FirstWeek;
                        break;

                    case Models.MonthlyOccurrenceTypeEnum.SECOND:
                        mt.WeeksOfMonth = WhichWeek.SecondWeek;
                        break;

                    case Models.MonthlyOccurrenceTypeEnum.THIRD:
                        mt.WeeksOfMonth = WhichWeek.ThirdWeek;
                        break;

                    case Models.MonthlyOccurrenceTypeEnum.FOURTH:
                        mt.WeeksOfMonth = WhichWeek.FourthWeek;
                        break;

                    case Models.MonthlyOccurrenceTypeEnum.PENULTIMATE:
                        mt.WeeksOfMonth = WhichWeek.ThirdWeek;
                        break;

                    case Models.MonthlyOccurrenceTypeEnum.LAST:
                        mt.WeeksOfMonth = WhichWeek.LastWeek;
                        break;
                    }

                    switch (schedule.OccursMonthlyAtDayOfWeek.Value)
                    {
                    case DayOfWeek.Monday:
                        mt.DaysOfWeek = DaysOfTheWeek.Monday;
                        break;

                    case DayOfWeek.Tuesday:
                        mt.DaysOfWeek = DaysOfTheWeek.Tuesday;
                        break;

                    case DayOfWeek.Wednesday:
                        mt.DaysOfWeek = DaysOfTheWeek.Wednesday;
                        break;

                    case DayOfWeek.Thursday:
                        mt.DaysOfWeek = DaysOfTheWeek.Thursday;
                        break;

                    case DayOfWeek.Friday:
                        mt.DaysOfWeek = DaysOfTheWeek.Friday;
                        break;

                    case DayOfWeek.Saturday:
                        mt.DaysOfWeek = DaysOfTheWeek.Saturday;
                        break;

                    case DayOfWeek.Sunday:
                        mt.DaysOfWeek = DaysOfTheWeek.Sunday;
                        break;
                    }

                    break;
                }

                case Models.FrequencyTypeEnum.DAY_OF_MONTH:
                {
                    if (!schedule.OccursAtDayOfMonth.HasValue)
                    {
                        break;
                    }

                    tr = Trigger.CreateTrigger(TaskTriggerType.Monthly);

                    MonthlyTrigger mt = tr as MonthlyTrigger;

                    //
                    // TODO: What happens if the specified day is >=29 and we are in February?
                    //
                    mt.DaysOfMonth = new int[] { schedule.OccursAtDayOfMonth.Value };

                    break;
                }
                }

                if (tr == null)
                {
                    break;
                }

                // When to start?
                DateTime now = DateTime.UtcNow;
                if (schedule.IsRecurrencyDailyFrequencySpecific)
                {
                    TimeSpan?optional = schedule.RecurrencySpecificallyAtTime;
                    if (!optional.HasValue)
                    {
                        break;
                    }

                    TimeSpan time = optional.Value;
                    tr.StartBoundary = new DateTime(now.Year, now.Month, now.Day, time.Hours, time.Minutes, time.Seconds);
                }
                else
                {
                    tr.StartBoundary = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0);                                     // Start of day.
                }

                // Repetition - Occurs every interval
                if (!schedule.IsRecurrencyDailyFrequencySpecific)
                {
                    switch (schedule.RecurrencyTimeUnit.Value)
                    {
                    case Models.TimeUnitEnum.HOURS:
                        tr.Repetition.Interval = TimeSpan.FromHours(schedule.RecurrencyTimeInterval.Value);
                        break;

                    case Models.TimeUnitEnum.MINUTES:
                        tr.Repetition.Interval = TimeSpan.FromMinutes(schedule.RecurrencyTimeInterval.Value);
                        break;
                    }
                }

                // Window limits
                if (!schedule.IsRecurrencyDailyFrequencySpecific)
                {
                    if (schedule.RecurrencyWindowStartsAtTime.HasValue && schedule.RecurrencyWindowEndsAtTime.HasValue)
                    {
                        tr.Repetition.StopAtDurationEnd = false;

                        TimeSpan window = schedule.RecurrencyWindowEndsAtTime.Value - schedule.RecurrencyWindowStartsAtTime.Value;

                        tr.Repetition.Duration = window;
                        //tr.ExecutionTimeLimit = window;
                    }
                }

                triggers.Add(tr);
                break;
            }
            }

            if (triggers.Count == 0)
            {
                Warn("No task was created for {0}", BuildTaskName(plan));
            }

            return(triggers.ToArray());
        }
示例#9
0
 private string BuildTaskName(Models.ISchedulablePlan plan)
 {
     return(plan.ScheduleParamName);
 }