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