Exemple #1
0
        private PlanExecutorEnv BuildPlanExecutorEnv(string planType, Int32 planId, bool resume)
        {
            ValidatePlanType(planType);

            string clientName = Commands.BuildClientName(planType, planId);

            PlanExecutorEnv env = new PlanExecutorEnv();

            env.Cwd  = GetExecutableDirectoryPath();
            env.Path = Path.Combine(env.Cwd, "Teltec.Everest.PlanExecutor.exe");

            StringBuilder sb = new StringBuilder(255);

            sb.AppendFormat(" --client-name={0}", clientName);
            sb.AppendFormat(" -t {0}", planType);
            sb.AppendFormat(" -p {0}", planId);
            if (resume)
            {
                sb.Append(" --resume");
            }

            env.Arguments = sb.ToString();

            return(env);
        }
Exemple #2
0
        private bool RunBackupPlan(Server.ClientContext context, Int32 planId, bool resume)
        {
            PlanExecutorEnv env    = BuildPlanExecutorEnv(PlanTypeEnum.BACKUP.ToString().ToLowerInvariant(), planId, resume);
            EventHandler    onExit = delegate(object sender, EventArgs e)
            {
                RunningBackups.Remove(planId);
                //Process process = (Process)sender;
                //if (process.ExitCode != 0)
                //{
                //	Handler.Send(context, Commands.ReportError("FAILED"));
                //}
            };

            try
            {
                Process process = ProcessUtils.StartSubProcess(env.Path, env.Arguments, env.Cwd, onExit, false, false, true);
                RunningBackups.Add(planId, process);
                return(true);
            }
            catch (Exception ex)
            {
                Handler.Send(context, Commands.ReportError(0, ex.Message));
                return(false);
            }
        }
Exemple #3
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);
                }
            }
        }