Add initial schedule request handlers (#638)

This commit is contained in:
Karl Burtram
2018-06-18 10:18:23 -07:00
committed by GitHub
parent d2cc376b87
commit 29fb715ad5
10 changed files with 555 additions and 279 deletions

View File

@@ -114,6 +114,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.ServiceHost.SetRequestHandler(CreateAgentProxyRequest.Type, HandleCreateAgentProxyRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentProxyRequest.Type, HandleUpdateAgentProxyRequest);
this.ServiceHost.SetRequestHandler(DeleteAgentProxyRequest.Type, HandleDeleteAgentProxyRequest);
// Schedule request handlers
this.ServiceHost.SetRequestHandler(AgentSchedulesRequest.Type, HandleAgentSchedulesRequest);
this.ServiceHost.SetRequestHandler(CreateAgentScheduleRequest.Type, HandleCreateAgentScheduleRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentScheduleRequest.Type, HandleUpdateAgentScheduleRequest);
this.ServiceHost.SetRequestHandler(DeleteAgentScheduleRequest.Type, HandleDeleteAgentScheduleRequest);
}
#region "Jobs Handlers"
@@ -558,6 +564,61 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#endregion // "Proxy Handlers"
#region "Schedule Handlers"
internal async Task HandleAgentSchedulesRequest(AgentSchedulesParams parameters, RequestContext<AgentSchedulesResult> requestContext)
{
await requestContext.SendResult(null);
}
internal async Task HandleCreateAgentScheduleRequest(CreateAgentScheduleParams parameters, RequestContext<AgentScheduleResult> requestContext)
{
var result = await ConfigureAgentSchedule(
parameters.OwnerUri,
parameters.Schedule,
ConfigAction.Create,
RunType.RunNow);
await requestContext.SendResult(new AgentScheduleResult()
{
Success = result.Item1,
ErrorMessage = result.Item2,
Schedule = parameters.Schedule
});
}
internal async Task HandleUpdateAgentScheduleRequest(UpdateAgentScheduleParams parameters, RequestContext<AgentScheduleResult> requestContext)
{
var result = await ConfigureAgentSchedule(
parameters.OwnerUri,
parameters.Schedule,
ConfigAction.Update,
RunType.RunNow);
await requestContext.SendResult(new AgentScheduleResult()
{
Success = result.Item1,
ErrorMessage = result.Item2,
Schedule = parameters.Schedule
});
}
internal async Task HandleDeleteAgentScheduleRequest(DeleteAgentScheduleParams parameters, RequestContext<ResultStatus> requestContext)
{
var result = await ConfigureAgentSchedule(
parameters.OwnerUri,
parameters.Schedule,
ConfigAction.Drop,
RunType.RunNow);
await requestContext.SendResult(new ResultStatus()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
#endregion // "Schedule Handlers"
#region "Helpers"
@@ -720,7 +781,43 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
}
internal async Task<Tuple<bool, string>> ConfigureAgentSchedule(
string ownerUri,
AgentScheduleInfo schedule,
ConfigAction configAction,
RunType runType)
{
return await Task<bool>.Run(() =>
{
try
{
JobData jobData;
CDataContainer dataContainer;
CreateJobData(ownerUri, schedule.JobName, out dataContainer, out jobData);
const string UrnFormatStr = "Server[@Name='{0}']/JobServer[@Name='{0}']/Job[@Name='{1}']/Schedule[@Name='{2}']";
string serverName = dataContainer.Server.Name.ToUpper();
string scheduleUrn = string.Format(UrnFormatStr, serverName, jobData.Job.Name, schedule.Name);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("urn", scheduleUrn);
using (JobSchedulesActions actions = new JobSchedulesActions(dataContainer, jobData, schedule, configAction))
{
var executionHandler = new ExecutonHandler(actions);
executionHandler.RunNow(runType, this);
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
private void CreateJobData(
string ownerUri,

View File

@@ -29,14 +29,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts
public AgentProxyInfo[] Proxies { get; set; }
}
/// <summary>
/// SQL Agent Proxy result
/// </summary>
public class AgentProxyResult : ResultStatus
{
public AgentProxyInfo Proxy { get; set; }
}
/// <summary>
/// SQL Agent Proxy Accounts request type
/// </summary>
@@ -50,6 +42,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts
RequestType<AgentProxiesParams, AgentProxiesResult>.Create("agent/proxies");
}
/// <summary>
/// SQL Agent Proxy result
/// </summary>
public class AgentProxyResult : ResultStatus
{
public AgentProxyInfo Proxy { get; set; }
}
/// <summary>
/// SQL Agent create Proxy Account params
/// </summary>

View File

@@ -0,0 +1,68 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Collections.Generic;
using Microsoft.SqlTools.ServiceLayer.Agent;
namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts
{
[Flags]
public enum FrequencyTypes
{
Unknown = 0,
OneTime = 1,
Daily = 4,
Weekly = 8,
Monthly = 16,
MonthlyRelative = 32,
AutoStart = 64,
OnIdle = 128
}
[Flags]
public enum FrequencySubDayTypes
{
Unknown = 0,
Once = 1,
Second = 2,
Minute = 4,
Hour = 8
}
[Flags]
public enum FrequencyRelativeIntervals
{
First = 1,
Second = 2,
Third = 4,
Fourth = 8,
Last = 16
}
/// <summary>
/// a class for storing various properties of agent schedules
/// </summary>
public class AgentScheduleInfo
{
public int ID { get; set; }
public string Name { get; set; }
public string JobName { get; set; }
public bool IsEnabled { get; set; }
public FrequencyTypes FrequencyTypes { get; set; }
public FrequencySubDayTypes FrequencySubDayTypes { get; set; }
public int FrequencySubDayInterval { get; set; }
public FrequencyRelativeIntervals FrequencyRelativeIntervals { get; set; }
public int FrequencyRecurrenceFactor { get; set; }
public int FrequencyInterval { get; set; }
public DateTime DateCreated { get; set; }
public TimeSpan ActiveStartTimeOfDay { get; set; }
public DateTime ActiveStartDate { get; set; }
public TimeSpan ActiveEndTimeOfDay { get; set; }
public int JobCount { get; set; }
public DateTime ActiveEndDate { get; set; }
public Guid ScheduleUid { get; set; }
}
}

View File

@@ -0,0 +1,124 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts
{
/// <summary>
/// SQL Agent Schedules parameters
/// </summary>
public class AgentSchedulesParams : GeneralRequestDetails
{
public string OwnerUri { get; set; }
}
/// <summary>
/// SQL Agent Schedules result
/// </summary>
public class AgentSchedulesResult
{
public bool Success { get; set; }
public string ErrorMessage { get; set; }
public AgentScheduleInfo[] Schedules { get; set; }
}
/// <summary>
/// SQL Agent Schedules request type
/// </summary>
public class AgentSchedulesRequest
{
/// <summary>
/// Request definition
/// </summary>
public static readonly
RequestType<AgentSchedulesParams, AgentSchedulesResult> Type =
RequestType<AgentSchedulesParams, AgentSchedulesResult>.Create("agent/schedules");
}
/// <summary>
/// SQL Agent Schedule result
/// </summary>
public class AgentScheduleResult : ResultStatus
{
public AgentScheduleInfo Schedule { get; set; }
}
/// <summary>
/// SQL Agent create Schedules params
/// </summary>
public class CreateAgentScheduleParams : GeneralRequestDetails
{
public string OwnerUri { get; set; }
public AgentScheduleInfo Schedule { get; set; }
}
/// <summary>
/// SQL Agent create Schedule request type
/// </summary>
public class CreateAgentScheduleRequest
{
/// <summary>
/// Request definition
/// </summary>
public static readonly
RequestType<CreateAgentScheduleParams, AgentScheduleResult> Type =
RequestType<CreateAgentScheduleParams, AgentScheduleResult>.Create("agent/createschedule");
}
/// <summary>
/// SQL Agent update Schedule params
/// </summary>
public class UpdateAgentScheduleParams : GeneralRequestDetails
{
public string OwnerUri { get; set; }
public string OriginalScheduleName { get; set; }
public AgentScheduleInfo Schedule { get; set; }
}
/// <summary>
/// SQL Agent update Schedule request type
/// </summary>
public class UpdateAgentScheduleRequest
{
/// <summary>
/// Request definition
/// </summary>
public static readonly
RequestType<UpdateAgentScheduleParams, AgentScheduleResult> Type =
RequestType<UpdateAgentScheduleParams, AgentScheduleResult>.Create("agent/updateschedule");
}
/// <summary>
/// SQL Agent delete Schedule params
/// </summary>
public class DeleteAgentScheduleParams : GeneralRequestDetails
{
public string OwnerUri { get; set; }
public AgentScheduleInfo Schedule { get; set; }
}
/// <summary>
/// SQL Agent delete Schedule request type
/// </summary>
public class DeleteAgentScheduleRequest
{
/// <summary>
/// Request definition
/// </summary>
public static readonly
RequestType<DeleteAgentScheduleParams, ResultStatus> Type =
RequestType<DeleteAgentScheduleParams, ResultStatus>.Create("agent/deleteschedule");
}
}

View File

@@ -4,27 +4,61 @@
//
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlTools.ServiceLayer.Agent.Contracts;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Agent
{
/// <summary>
/// Summary description for JobSchedules.
/// Summary description for JobSchedulesActions.
/// </summary>
internal class JobSchedulesActions : ManagementActionBase
{
private bool sharedSchedulesSupported = false;
private JobData data;
private JobScheduleData scheduleData = null;
private AgentScheduleInfo scheduleInfo;
private ConfigAction configAction;
public JobSchedulesActions(CDataContainer dataContainer, JobData data)
public JobSchedulesActions(CDataContainer dataContainer, JobData data, AgentScheduleInfo scheduleInfo, ConfigAction configAction)
{
this.DataContainer = dataContainer;
this.data = data;
this.configAction = configAction;
this.scheduleInfo = scheduleInfo;
this.sharedSchedulesSupported = this.DataContainer.Server.Information.Version.Major >= 9;
if (configAction == ConfigAction.Create)
{
this.scheduleData = new JobScheduleData(this.data.Job);
this.scheduleData.SetJobSchedule(new JobSchedule());
}
else
{
// get the JobScheduleData from the urn
string urn = null;
STParameters parameters = new STParameters();
parameters.SetDocument(this.DataContainer.Document);
parameters.GetParam("urn", ref urn);
JobSchedule jobStep = this.data.Job.Parent.Parent.GetSmoObject(urn) as JobSchedule;
if (jobStep != null)
{
this.scheduleData = new JobScheduleData(jobStep);
}
if (configAction == ConfigAction.Update && this.scheduleData == null)
{
throw new Exception("Schedule urn parameter cannot be null");
}
}
// copy properties from AgentScheduelInfo
if (this.scheduleData != null)
{
this.scheduleData.Name = scheduleInfo.Name;
}
}
/// <summary>
@@ -38,263 +72,36 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
base.Dispose(disposing);
}
#region ui stuff
private void InitializeData()
{
if (this.data == null)
{
return;
}
// load the grid
//PopulateGrid(this.data.JobSchedules);
}
// private void PopulateGrid(JobSchedulesData schedules)
// {
// // add non-shared schedules
// for (int i = 0; i < schedules.Schedules.Count; i++)
// {
// JobScheduleData schedule = schedules.Schedules[i] as JobScheduleData;
// if (schedule != null)
// {
// // add rows to the grid
// GridCellCollection row = new GridCellCollection();
// GridCell cell;
// // ID
// cell = new GridCell(ConvertIdToDisplayName(schedule.ID));
// row.Add(cell);
// // Name
// cell = new GridCell(schedule.Name);
// row.Add(cell);
// // Enabled
// cell = new GridCell(schedule.Enabled ? JobSR.Yes : JobSR.No);
// row.Add(cell);
// // Description
// cell = new GridCell(schedule.Description);
// row.Add(cell);
// // Hyperlink 'Jobs in Schedule'
// if (this.sharedSchedulesSupported)
// {
// // don't add a hyperlink if the schedule has not yet been created
// cell = new GridCell(schedule.Created ? JobSR.ViewJobsInScheduleHyperlink : String.Empty);
// row.Add(cell);
// }
// this.scheduleList.AddRow(row);
// }
// }
// }
/// <summary>
/// Convert an id into a user friendly name. Converts new id to "new"
/// called by PreProcessExecution to enable derived classes to take over execution
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private string ConvertIdToDisplayName(int id)
/// <param name="runType"></param>
/// <param name="executionResult"></param>
/// <returns>
/// true if regular execution should take place, false if everything,
/// has been done by this function
/// </returns>
protected override bool DoPreProcessExecution(RunType runType, out ExecutionMode executionResult)
{
string rv;
// convert -1 into New
if (id < 0)
base.DoPreProcessExecution(runType, out executionResult);
if (this.scheduleData == null)
{
rv = "JobSR.New";
return false;
}
if (this.configAction == ConfigAction.Drop)
{
var jobSchedule = this.scheduleData.SourceSchedule;
if (jobSchedule != null)
{
jobSchedule.DropIfExists();
}
}
else
{
rv = Convert.ToString(id, System.Globalization.CultureInfo.CurrentCulture);
this.scheduleData.ApplyChanges();
}
return rv;
}
#endregion
#region ui event handlers
// private void addSchedule_Click(object sender, System.EventArgs e)
// {
// System.Diagnostics.Debug.Assert(this.DataContainer.Server.Information.Version.Major >= 9, "Shared Schedules supported only for Yukon - this button should be disabled if target server is Shiloh/Sphinx");
// StringBuilder excludedSchedules = this.BuildListOfScheduleId(this.data.JobSchedules.Schedules);
// StringBuilder removedSchedules = this.BuildListOfScheduleId(this.data.JobSchedules.RemovedSchedules);
// STParameters param = new STParameters();
// param.SetDocument(this.DataContainer.Document);
// param.SetParam("excludedschedules", excludedSchedules.ToString());
// if (this.data.Mode == JobData.DialogMode.Properties)
// {
// param.SetParam("removedschedules", removedSchedules.ToString());
// param.SetParam("joburn", this.data.Urn);
// }
// ManageSchedulesForm formPickUpSharedSchedule = new ManageSchedulesForm
// (
// this.DataContainer,
// ((this.data != null) && (this.data.Name != null)) ? this.data.Name : String.Empty,
// this.ServiceProvider
// );
// using (formPickUpSharedSchedule)
// {
// DialogResult dr = formPickUpSharedSchedule.ShowDialog();
// // cleanup the datacontainer
// param.SetParam("excludedschedules", String.Empty);
// if (this.data.Mode == JobData.DialogMode.Properties)
// {
// param.SetParam("removedschedules", String.Empty);
// param.SetParam("joburn", String.Empty);
// }
// if (dr == DialogResult.OK)
// {
// JobSchedule schedule = formPickUpSharedSchedule.SelectedSchedule;
// System.Diagnostics.Debug.Assert(schedule != null);
// System.Diagnostics.Debug.Assert(schedule.Name != null);
// bool scheduleAlreadyAdded = false;
// foreach (object o in this.data.JobSchedules.Schedules)
// {
// JobScheduleData jsd = o as JobScheduleData;
// System.Diagnostics.Debug.Assert(jsd != null, "non JobScheduleData found in this.data.Schedules");
// if ((jsd != null) && (jsd.ID == schedule.ID))
// {
// scheduleAlreadyAdded = true;
// break;
// }
// }
// if (scheduleAlreadyAdded == false)
// {
// JobScheduleData scheduleData = new JobScheduleData(schedule);
// this.data.JobSchedules.AddSchedule(scheduleData);
// this.scheduleList.DeleteAllRows();
// PopulateGrid(this.data.JobSchedules);
// UpdateControlStatus();
// }
// }
// }
// }
private void editSchedule_Click(object sender, System.EventArgs e)
{
// EditSelectedSchedule();
}
// private void deleteSchedule_Click(object sender, System.EventArgs e)
// {
// // check that a row is selected first
// STrace.Assert(this.scheduleList.SelectedCells.Count > 0, "there are no selected rows");
// if (this.scheduleList.SelectedCells.Count == 0)
// {
// return;
// }
// int row = (int)this.scheduleList.SelectedCells[0].Y;
// // check that this is a valid row
// STrace.Assert(row <= this.data.JobSchedules.Schedules.Count, "selected row does not exist in data structures");
// if (row > this.data.JobSchedules.Schedules.Count)
// {
// return;
// }
// JobScheduleData data = this.data.JobSchedules.Schedules[row] as JobScheduleData;
// if (data != null)
// {
// this.data.JobSchedules.DeleteSchedule(data); // if is non-shared it will be marked for deletion here
// this.scheduleList.DeleteAllRows();
// PopulateGrid(this.data.JobSchedules);
// }
// UpdateControlStatus();
// }
// private void EditSelectedSchedule()
// {
// // check that a row is selected first
// STrace.Assert(this.scheduleList.SelectedCells.Count > 0, "there are no selected rows");
// if (this.scheduleList.SelectedCells.Count == 0)
// {
// return;
// }
// int row = (int)this.scheduleList.SelectedCells[0].Y;
// // check that this is a valid row
// STrace.Assert(row <= this.data.JobSchedules.Schedules.Count, "selected row does not exist in data structures");
// if (row > this.data.JobSchedules.Schedules.Count)
// {
// return;
// }
// JobScheduleData data = this.data.JobSchedules.Schedules[row] as JobScheduleData;
// if (data != null)
// {
// try
// {
// using (ScheduleDialog jobSchedule = new ScheduleDialog(data,
// this.data.JobSchedules.Schedules,
// this.DataContainer,
// this.ServiceProvider))
// {
// jobSchedule.Text = JobSR.EditSchedule(data.Name);
// jobSchedule.SetSite(this.ServiceProvider);
// try
// {
// if (DialogResult.OK == jobSchedule.ShowDialog())
// {
// this.scheduleList.DeleteAllRows();
// PopulateGrid(this.data.JobSchedules);
// UpdateControlStatus();
// }
// }
// catch (ApplicationException error)
// {
// DisplayExceptionMessage(error);
// jobSchedule.DialogResult = DialogResult.None;
// }
// }
// }
// catch (ApplicationException error)
// {
// DisplayExceptionMessage(error);
// }
// }
// }
// }
#endregion
/// <summary>
/// enumerates schedules list and returns back as s string in format 1,2,3
/// </summary>
/// <param name="schedules"></param>
/// <returns></returns>
private StringBuilder BuildListOfScheduleId(List<JobScheduleData> schedules)
{
if (schedules == null)
{
throw new ArgumentNullException("schedules");
}
StringBuilder scheduleIdList = new StringBuilder();
foreach (JobScheduleData schedule in schedules)
{
if (schedule != null)
{
if (scheduleIdList.Length > 0)
{
scheduleIdList.AppendFormat(CultureInfo.InvariantCulture, ", {0}", schedule.ID);
}
else
{
scheduleIdList.Append(schedule.ID);
}
}
}
return scheduleIdList;
return false;
}
}
}

View File

@@ -305,10 +305,3 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
}
}
}

View File

@@ -801,6 +801,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.id = value;
}
}
public string Name
{
get
@@ -812,6 +813,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.currentName = value;
}
}
public bool Enabled
{
get
@@ -823,6 +825,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.enabled = value;
}
}
public bool AllowEnableDisable
{
get
@@ -830,6 +833,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return this.allowEnableDisable;
}
}
public string Description
{
get
@@ -837,6 +841,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return this.ToString();
}
}
public bool Created
{
get
@@ -848,6 +853,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.alreadyCreated = value;
}
}
public DateTime ActiveStartDate
{
get
@@ -859,6 +865,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.startDate = value;
}
}
public TimeSpan ActiveStartTime
{
get
@@ -870,6 +877,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.startTime = value;
}
}
public DateTime ActiveEndDate
{
get
@@ -883,6 +891,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
: value;
}
}
public TimeSpan ActiveEndTime
{
get
@@ -896,6 +905,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
: value;
}
}
public bool HasEndDate
{
get
@@ -903,6 +913,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return this.endDate < JobScheduleData.MaxAgentDateValue;
}
}
public bool HasEndTime
{
get
@@ -910,6 +921,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return this.endTime < JobScheduleData.MaxAgentTimeValue;
}
}
public FrequencyTypes FrequencyTypes
{
get
@@ -921,6 +933,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.frequencyType = value;
}
}
public int FrequencyInterval
{
get
@@ -932,6 +945,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.frequencyInterval = value;
}
}
public int FrequencyRecurranceFactor
{
get
@@ -943,6 +957,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.frequencyRecurranceFactor = value;
}
}
public FrequencyRelativeIntervals FrequencyRelativeIntervals
{
get
@@ -954,6 +969,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.frequencyRelativeInterval = value;
}
}
public int FrequencySubDayInterval
{
get
@@ -965,6 +981,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.frequencySubDayInterval = value;
}
}
public FrequencySubDayTypes FrequencySubDayTypes
{
get
@@ -976,6 +993,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.frequencySubDayTypes = value;
}
}
public JobSchedule SourceSchedule
{
get
@@ -983,6 +1001,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return this.source;
}
}
public bool IsReadOnly
{
get { return isReadOnly; }
@@ -1328,7 +1347,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
private void SetDefaults()
{
this.alreadyCreated = false;
currentName = originalName = String.Empty;
currentName = originalName = string.Empty;
this.enabled = true;
this.frequencyType = FrequencyTypes.Weekly; //SQL2K default value