Agent configuration support classes (WIP) (#632)

* Additional SQL Agent config classes (WIP)

* Fix build breaks

* Clean up job step code

* Add VS Code build files

* Move changes to other machine

* More of the action execution classes

* More execution processing refactors

* More refactoring

* Disable tests for WIP merge

* Fix break on Release config

* Stage changes to other machine.
This commit is contained in:
Karl Burtram
2018-06-07 12:08:24 -07:00
committed by GitHub
parent 35b19320d4
commit 372ca0cbe8
73 changed files with 12650 additions and 374 deletions

View File

@@ -17,6 +17,7 @@ using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Agent.Contracts;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.Agent
@@ -26,13 +27,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// </summary>
public class AgentService
{
internal enum AgentConfigAction
{
Create,
Update,
Drop
}
private Dictionary<Guid, JobProperties> jobs = null;
private ConnectionService connectionService = null;
private static readonly Lazy<AgentService> instance = new Lazy<AgentService>(() => new AgentService());
@@ -88,10 +82,21 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
public void InitializeService(ServiceHost serviceHost)
{
this.ServiceHost = serviceHost;
// Jobs request handlers
this.ServiceHost.SetRequestHandler(AgentJobsRequest.Type, HandleAgentJobsRequest);
this.ServiceHost.SetRequestHandler(AgentJobHistoryRequest.Type, HandleJobHistoryRequest);
this.ServiceHost.SetRequestHandler(AgentJobActionRequest.Type, HandleJobActionRequest);
this.ServiceHost.SetRequestHandler(CreateAgentJobRequest.Type, HandleCreateAgentJobRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentJobRequest.Type, HandleUpdateAgentJobRequest);
this.ServiceHost.SetRequestHandler(DeleteAgentJobRequest.Type, HandleDeleteAgentJobRequest);
// Job Steps request handlers
this.ServiceHost.SetRequestHandler(CreateAgentJobStepRequest.Type, HandleCreateAgentJobStepRequest);
this.ServiceHost.SetRequestHandler(UpdateAgentJobStepRequest.Type, HandleUpdateAgentJobStepRequest);
this.ServiceHost.SetRequestHandler(DeleteAgentJobStepRequest.Type, HandleDeleteAgentJobStepRequest);
// Alerts request handlers
this.ServiceHost.SetRequestHandler(AgentAlertsRequest.Type, HandleAgentAlertsRequest);
this.ServiceHost.SetRequestHandler(CreateAgentAlertRequest.Type, HandleCreateAgentAlertRequest);
@@ -112,7 +117,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
}
#region "Jobs Handlers"
/// <summary>
/// Handle request to get Agent job activities
/// </summary>
@@ -138,7 +143,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
var agentJobs = new List<AgentJobInfo>();
if (this.jobs != null)
{
foreach (var job in this.jobs.Values)
{
agentJobs.Add(JobUtilities.ConvertToAgentJobInfo(job));
@@ -154,17 +159,17 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{
await requestContext.SendError(e);
}
});
});
}
/// <summary>
/// Handle request to get Agent Job history
/// </summary>
internal async Task HandleJobHistoryRequest(AgentJobHistoryParams parameters, RequestContext<AgentJobHistoryResult> requestContext)
internal async Task HandleJobHistoryRequest(AgentJobHistoryParams parameters, RequestContext<AgentJobHistoryResult> requestContext)
{
await Task.Run(async () =>
{
try
try
{
var result = new AgentJobHistoryResult();
ConnectionInfo connInfo;
@@ -179,7 +184,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
ServerConnection connection = tuple.Item3;
int count = dt.Rows.Count;
List<AgentJobHistoryInfo> jobHistories = new List<AgentJobHistoryInfo>();
if (count > 0)
if (count > 0)
{
var job = dt.Rows[0];
string jobName = Convert.ToString(job[JobUtilities.UrnJobName], System.Globalization.CultureInfo.InvariantCulture);
@@ -198,11 +203,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
await requestContext.SendResult(result);
}
}
catch (Exception e)
catch (Exception e)
{
await requestContext.SendError(e);
}
});
});
}
/// <summary>
@@ -213,7 +218,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
await Task.Run(async () =>
{
var result = new AgentJobActionResult();
try
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
@@ -222,7 +227,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
if (connInfo != null)
{
var sqlConnection = ConnectionService.OpenSqlConnection(connInfo);
var serverConnection = new ServerConnection(sqlConnection);
var serverConnection = new ServerConnection(sqlConnection);
var jobHelper = new JobHelper(serverConnection);
jobHelper.JobName = parameters.JobName;
switch(parameters.Action)
@@ -249,7 +254,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
await requestContext.SendResult(result);
}
}
catch (Exception e)
catch (Exception e)
{
result.Succeeded = false;
result.ErrorMessage = e.Message;
@@ -261,22 +266,171 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
private Tuple<SqlConnectionInfo, DataTable, ServerConnection> CreateSqlConnection(ConnectionInfo connInfo, String jobId)
{
var sqlConnection = ConnectionService.OpenSqlConnection(connInfo);
var serverConnection = new ServerConnection(sqlConnection);
var server = new Server(serverConnection);
var filter = new JobHistoryFilter();
var serverConnection = new ServerConnection(sqlConnection);
var server = new Server(serverConnection);
var filter = new JobHistoryFilter();
filter.JobID = new Guid(jobId);
var dt = server.JobServer.EnumJobHistory(filter);
var sqlConnInfo = new SqlConnectionInfo(serverConnection, SqlServer.Management.Common.ConnectionType.SqlConnection);
return new Tuple<SqlConnectionInfo, DataTable, ServerConnection>(sqlConnInfo, dt, serverConnection);
}
internal async Task HandleCreateAgentJobRequest(CreateAgentJobParams parameters, RequestContext<CreateAgentJobResult> requestContext)
{
var result = await ConfigureAgentJob(
parameters.OwnerUri,
parameters.Job,
ConfigAction.Create,
ManagementUtils.asRunType(parameters.TaskExecutionMode));
await requestContext.SendResult(new CreateAgentJobResult()
{
Succeeded = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task HandleUpdateAgentJobRequest(UpdateAgentJobParams parameters, RequestContext<UpdateAgentJobResult> requestContext)
{
var result = await ConfigureAgentJob(
parameters.OwnerUri,
parameters.Job,
ConfigAction.Update,
ManagementUtils.asRunType(parameters.TaskExecutionMode));
await requestContext.SendResult(new UpdateAgentJobResult()
{
Succeeded = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task HandleDeleteAgentJobRequest(DeleteAgentJobParams parameters, RequestContext<DeleteAgentJobResult> requestContext)
{
var result = await ConfigureAgentJob(
parameters.OwnerUri,
parameters.Job,
ConfigAction.Drop,
ManagementUtils.asRunType(parameters.TaskExecutionMode));
await requestContext.SendResult(new DeleteAgentJobResult()
{
Succeeded = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task HandleCreateAgentJobStepRequest(CreateAgentJobStepParams parameters, RequestContext<CreateAgentJobStepResult> requestContext)
{
Tuple<bool, string> result = await ConfigureAgentJobStep(
parameters.OwnerUri,
parameters.Step,
ConfigAction.Create);
await requestContext.SendResult(new CreateAgentJobStepResult()
{
Succeeded = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task HandleUpdateAgentJobStepRequest(UpdateAgentJobStepParams parameters, RequestContext<UpdateAgentJobStepResult> requestContext)
{
UpdateAgentJobStepResult result = new UpdateAgentJobStepResult();
await requestContext.SendResult(result);
}
internal async Task HandleDeleteAgentJobStepRequest(DeleteAgentJobStepParams parameters, RequestContext<DeleteAgentJobStepResult> requestContext)
{
DeleteAgentJobStepResult result = new DeleteAgentJobStepResult();
await requestContext.SendResult(result);
}
internal async Task<Tuple<bool, string>> ConfigureAgentJob(
string ownerUri,
AgentJobInfo jobInfo,
ConfigAction configAction,
RunType runType)
{
return await Task<Tuple<bool, string>>.Run(() =>
{
try
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
ownerUri,
out connInfo);
CDataContainer dataContainer = AdminService.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("job", string.Empty);
param.SetParam("jobid", jobInfo.JobId);
var jobData = new JobData(dataContainer, jobInfo);
using (JobActions jobActions = new JobActions(dataContainer, jobData, configAction))
{
var executionHandler = new ExecutonHandler(jobActions);
executionHandler.RunNow(runType, this);
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
internal async Task<Tuple<bool, string>> ConfigureAgentJobStep(
string ownerUri,
AgentJobStepInfo stepInfo,
ConfigAction configAction)
{
return await Task<Tuple<bool, string>>.Run(() =>
{
try
{
if (string.IsNullOrWhiteSpace(stepInfo.JobId))
{
return new Tuple<bool, string>(false, "JobId cannot be null");
}
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
ownerUri,
out connInfo);
CDataContainer dataContainer = AdminService.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("job", string.Empty);
param.SetParam("jobid", stepInfo.JobId);
param.SetParam("script", stepInfo.Script);
param.SetParam("scriptName", stepInfo.ScriptName);
var jobData = new JobData(dataContainer);
using (var jobStep = new JobStepsActions(dataContainer, jobData))
{
jobStep.CreateJobStep();
}
return new Tuple<bool, string>(true, string.Empty);
}
catch (Exception ex)
{
// log exception here
return new Tuple<bool, string>(false, ex.ToString());
}
});
}
#endregion // "Jobs Handlers"
#region "Alert Handlers"
/// <summary>
/// Handle request to get the alerts list
/// </summary>
/// </summary>
internal async Task HandleAgentAlertsRequest(AgentAlertsParams parameters, RequestContext<AgentAlertsResult> requestContext)
{
await Task.Run(async () =>
@@ -293,8 +447,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{
CDataContainer dataContainer = AdminService.CreateDataContainer(connInfo, databaseExists: true);
AlertCollection alerts = dataContainer.Server.JobServer.Alerts;
}
await requestContext.SendResult(result);
@@ -309,7 +461,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// <summary>
/// Handle request to create an alert
/// </summary>
/// </summary>
internal async Task HandleCreateAgentAlertRequest(CreateAgentAlertParams parameters, RequestContext<CreateAgentAlertResult> requestContext)
{
await Task.Run(async () =>
@@ -328,7 +480,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// <summary>
/// Handle request to update an alert
/// </summary>
/// </summary>
internal async Task HandleUpdateAgentAlertRequest(UpdateAgentAlertParams parameters, RequestContext<UpdateAgentAlertResult> requestContext)
{
await Task.Run(async () =>
@@ -353,7 +505,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("alert", alert.JobName);
using (AgentAlert agentAlert = new AgentAlert(dataContainer, alert))
using (AgentAlertActions agentAlert = new AgentAlertActions(dataContainer, alert))
{
agentAlert.CreateOrUpdate();
}
@@ -362,7 +514,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// <summary>
/// Handle request to delete an alert
/// </summary>
/// </summary>
internal async Task HandleDeleteAgentAlertRequest(DeleteAgentAlertParams parameters, RequestContext<DeleteAgentAlertResult> requestContext)
{
await Task.Run(async () =>
@@ -380,7 +532,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("alert", alert.JobName);
using (AgentAlert agentAlert = new AgentAlert(dataContainer, alert))
using (AgentAlertActions agentAlert = new AgentAlertActions(dataContainer, alert))
{
agentAlert.Drop();
}
@@ -447,10 +599,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{
bool succeeded = await ConfigureAgentProxy(
parameters.OwnerUri,
parameters.Proxy.AccountName,
parameters.Proxy,
AgentConfigAction.Create);
parameters.Proxy.AccountName,
parameters.Proxy,
ConfigAction.Create);
await requestContext.SendResult(new CreateAgentProxyResult()
{
Succeeded = succeeded
@@ -461,9 +613,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{
bool succeeded = await ConfigureAgentProxy(
parameters.OwnerUri,
parameters.OriginalProxyName,
parameters.OriginalProxyName,
parameters.Proxy,
AgentConfigAction.Update);
ConfigAction.Update);
await requestContext.SendResult(new UpdateAgentProxyResult()
{
@@ -475,9 +627,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{
bool succeeded = await ConfigureAgentProxy(
parameters.OwnerUri,
parameters.Proxy.AccountName,
parameters.Proxy.AccountName,
parameters.Proxy,
AgentConfigAction.Drop);
ConfigAction.Drop);
await requestContext.SendResult(new DeleteAgentProxyResult()
{
@@ -489,7 +641,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
string ownerUri,
string accountName,
AgentProxyInfo proxy,
AgentConfigAction configAction)
ConfigAction configAction)
{
return await Task<bool>.Run(() =>
{
@@ -506,15 +658,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
using (AgentProxyAccount agentProxy = new AgentProxyAccount(dataContainer, proxy))
{
if (configAction == AgentConfigAction.Create)
if (configAction == ConfigAction.Create)
{
return agentProxy.Create();
}
else if (configAction == AgentConfigAction.Update)
else if (configAction == ConfigAction.Update)
{
return agentProxy.Update();
}
else if (configAction == AgentConfigAction.Drop)
else if (configAction == ConfigAction.Drop)
{
return agentProxy.Drop();
}