Skip to content

Commit c8464c0

Browse files
committed
Get and Wait implementation for Jobs
1 parent 143c608 commit c8464c0

File tree

12 files changed

+668
-6
lines changed

12 files changed

+668
-6
lines changed

src/ResourceManager/RecoveryServices.Backup/CmdletParameterHelpMessages.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,18 @@ internal static class Common
3434
{
3535
public const string Vault = "The Azure Backup vault object which is the parent resource.";
3636
}
37+
38+
internal static class Job
39+
{
40+
public const string FromFilter = "Beginning value of time range for which jobs have to be fetched.";
41+
public const string ToFilter = "Ending value of time range for which jobs have to be fetched.";
42+
public const string OperationFilter = "Filter value for type of job.";
43+
public const string StatusFilter = "Filter value for status of job.";
44+
public const string BackupManagementTypeFilter = "Filter value for Backup Management Type of job.";
45+
public const string JobIdFilter = "Filter value for Id of job.";
46+
public const string JobFilter = "Job whose latest object has to be fetched.";
47+
public const string WaitJobOrListFilter = "Job or List of jobs until end of which the cmdlet should wait.";
48+
public const string WaitJobTimeoutFilter = "Maximum time to wait before aborting wait in seconds.";
49+
}
3750
}
3851
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using System;
16+
using System.Collections.Generic;
17+
using System.Linq;
18+
using System.Text;
19+
using System.Threading.Tasks;
20+
21+
namespace Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlets
22+
{
23+
internal class CmdletWarningAndErrorMessages
24+
{
25+
internal class Job
26+
{
27+
public const string RefineFilters = "There are more than 1000 jobs for the filter combination you have provided. Kindly refine your filters to fetch the job you want.";
28+
public const string AllowedDateTimeRangeExceeded = "To filter should not be more than 30 days away from From filter.";
29+
public const string JobIdAndJobMismatch = "JobID and Job object provided don't match each other";
30+
public const string ToShouldBeLessThanFrom = "To filter should not less than From filter.";
31+
public const string WaitJobInvalidInput = "Please pass Job or List of Jobs as input. Your input is of type: ";
32+
}
33+
}
34+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using System;
16+
using System.Collections.Generic;
17+
using System.Management.Automation;
18+
using Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlets.Models;
19+
using Microsoft.Azure.Commands.RecoveryServices.Backup.Helpers;
20+
21+
namespace Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlets
22+
{
23+
/// <summary>
24+
/// Get list of jobs
25+
/// </summary>
26+
[Cmdlet(VerbsCommon.Get, "AzureRmBackupJob"), OutputType(typeof(List<AzureRmRecoveryServicesJobBase>), typeof(AzureRmRecoveryServicesJobBase))]
27+
public class GetAzureRmRecoveryServicesJob : RecoveryServicesBackupCmdletBase
28+
{
29+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Common.Vault, ValueFromPipeline = true)]
30+
public ARSVault Vault { get; set; }
31+
32+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.FromFilter)]
33+
[ValidateNotNull]
34+
public DateTime? From { get; set; }
35+
36+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.ToFilter)]
37+
[ValidateNotNull]
38+
public DateTime? To { get; set; }
39+
40+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.JobIdFilter)]
41+
[ValidateNotNullOrEmpty]
42+
public string JobId { get; set; }
43+
44+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.JobFilter)]
45+
[ValidateNotNull]
46+
public AzureRmRecoveryServicesJobBase Job { get; set; }
47+
48+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.BackupManagementTypeFilter)]
49+
[ValidateNotNullOrEmpty]
50+
public string BackupManagementType { get; set; }
51+
52+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.OperationFilter)]
53+
[ValidateNotNullOrEmpty]
54+
public string Operation { get; set; }
55+
56+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.StatusFilter)]
57+
[ValidateNotNullOrEmpty]
58+
public string Status { get; set; }
59+
60+
public override void ExecuteCmdlet()
61+
{
62+
ExecutionBlock(() =>
63+
{
64+
base.ExecuteCmdlet();
65+
66+
// initialize values to default
67+
DateTime rangeStart = DateTime.UtcNow.AddDays(-1);
68+
DateTime rangeEnd = DateTime.UtcNow;
69+
70+
if (From.HasValue)
71+
{
72+
rangeStart = From.Value;
73+
}
74+
75+
if (To.HasValue)
76+
{
77+
rangeEnd = To.Value;
78+
}
79+
80+
// validate filters
81+
if (rangeEnd >= rangeStart)
82+
{
83+
throw new Exception(CmdletWarningAndErrorMessages.Job.ToShouldBeLessThanFrom);
84+
}
85+
else if (rangeEnd.Subtract(rangeStart) > TimeSpan.FromDays(30))
86+
{
87+
throw new Exception(CmdletWarningAndErrorMessages.Job.AllowedDateTimeRangeExceeded);
88+
}
89+
90+
// validate JobId and Job objects
91+
if (!string.IsNullOrEmpty(JobId))
92+
{
93+
// if JobId and Job are provided together and they don't match then throw exception
94+
if (Job != null && JobId != Job.InstanceId)
95+
{
96+
throw new Exception(CmdletWarningAndErrorMessages.Job.JobIdAndJobMismatch);
97+
}
98+
}
99+
else if (Job != null)
100+
{
101+
JobId = Job.InstanceId;
102+
}
103+
104+
// TODO: Initialize Vault object from base cmdlet once support is added
105+
List<AzureRmRecoveryServicesJobBase> result = new List<AzureRmRecoveryServicesJobBase>();
106+
int resultCount = 0;
107+
var adapterResponse = HydraAdapter.GetJobs(Vault.ResouceGroupName, Vault.Name, JobId, Status, Operation, rangeStart, rangeEnd,
108+
BackupManagementType);
109+
JobConversions.AddHydraJobsToPSList(adapterResponse, result, ref resultCount);
110+
111+
while (!string.IsNullOrEmpty(adapterResponse.ItemList.NextLink))
112+
{
113+
if (resultCount >= JobConstants.MaximumJobsToFetch)
114+
{
115+
// trace a warning that there are more jobs and user has to refine filters.
116+
WriteWarning(CmdletWarningAndErrorMessages.Job.RefineFilters);
117+
break;
118+
}
119+
120+
string skipToken;
121+
HydraHelpers.GetSkipTokenFromNextLink(adapterResponse.ItemList.NextLink, out skipToken);
122+
if (skipToken != null)
123+
{
124+
adapterResponse = HydraAdapter.GetJobs(Vault.ResouceGroupName, Vault.Name, JobId, Status, Operation,
125+
rangeStart, rangeEnd, BackupManagementType, null, skipToken);
126+
JobConversions.AddHydraJobsToPSList(adapterResponse, result, ref resultCount);
127+
}
128+
else
129+
{
130+
break;
131+
}
132+
}
133+
134+
if (resultCount != 1)
135+
{
136+
WriteObject(result);
137+
}
138+
else
139+
{
140+
WriteObject(result[0]);
141+
}
142+
});
143+
}
144+
}
145+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using System.Management.Automation;
16+
using Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlets.Models;
17+
using Microsoft.Azure.Commands.RecoveryServices.Backup.Helpers;
18+
19+
namespace Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlets
20+
{
21+
[Cmdlet(VerbsCommon.Get, "AzureRmBackupJobDetails"), OutputType(typeof(AzureRmRecoveryServicesJobBase))]
22+
public class GetAzureRmRecoveryServicesJobDetails : RecoveryServicesBackupCmdletBase
23+
{
24+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Common.Vault, ValueFromPipeline = true)]
25+
public ARSVault Vault { get; set; }
26+
27+
[Parameter(Mandatory = true, HelpMessage = ParamHelpMsg.Job.JobIdFilter, ParameterSetName = "IdFilterSet")]
28+
[ValidateNotNullOrEmpty]
29+
public string JobId { get; set; }
30+
31+
[Parameter(Mandatory = true, HelpMessage = ParamHelpMsg.Job.JobFilter, ParameterSetName = "JobFilterSet")]
32+
[ValidateNotNull]
33+
public AzureRmRecoveryServicesJobBase Job { get; set; }
34+
35+
public override void ExecuteCmdlet()
36+
{
37+
ExecutionBlock(() =>
38+
{
39+
base.ExecuteCmdlet();
40+
41+
if (string.IsNullOrEmpty(JobId) && Job != null)
42+
{
43+
JobId = Job.InstanceId;
44+
}
45+
46+
// Initialize vault object from base cmdlet
47+
var adapterResponse = HydraAdapter.GetJob(Vault.ResouceGroupName, Vault.Name, JobId);
48+
WriteObject(JobConversions.GetPSJob(adapterResponse));
49+
});
50+
}
51+
}
52+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using System;
16+
using System.Collections.Generic;
17+
using System.Management.Automation;
18+
using Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlets.Models;
19+
using Microsoft.Azure.Commands.RecoveryServices.Backup.Helpers;
20+
21+
namespace Microsoft.Azure.Commands.RecoveryServices.Backup.Cmdlets
22+
{
23+
[Cmdlet("Wait", "AzureRmBackupJob"), OutputType(typeof(List<AzureRmRecoveryServicesJobBase>), typeof(AzureRmRecoveryServicesJobBase))]
24+
public class WaitAzureRmRecoveryServicesJob : RecoveryServicesBackupCmdletBase
25+
{
26+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Common.Vault)]
27+
public ARSVault Vault { get; set; }
28+
29+
[Parameter(Mandatory = true, HelpMessage = ParamHelpMsg.Job.WaitJobOrListFilter)]
30+
[ValidateNotNull]
31+
public object Job { get; set; }
32+
33+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.WaitJobTimeoutFilter)]
34+
public long? Timeout { get; set; }
35+
36+
public override void ExecuteCmdlet()
37+
{
38+
ExecutionBlock(() =>
39+
{
40+
base.ExecuteCmdlet();
41+
42+
List<string> jobsToWaitOn = new List<string>();
43+
List<AzureRmRecoveryServicesJobBase> finalJobs = new List<AzureRmRecoveryServicesJobBase>();
44+
45+
// TODO: Validate the following code
46+
object castedObj;
47+
if (GetCastedObjFromPSObj(Job, typeof(AzureRmRecoveryServicesJobBase), out castedObj))
48+
{
49+
AzureRmRecoveryServicesJobBase justJob = castedObj as AzureRmRecoveryServicesJobBase;
50+
jobsToWaitOn.Add(justJob.InstanceId);
51+
}
52+
else if (GetCastedObjFromPSObj(Job, typeof(List<AzureRmRecoveryServicesJobBase>), out castedObj))
53+
{
54+
List<AzureRmRecoveryServicesJobBase> jobsList = castedObj as List<AzureRmRecoveryServicesJobBase>;
55+
foreach (var job in jobsList)
56+
{
57+
jobsToWaitOn.Add(job.InstanceId);
58+
}
59+
}
60+
else
61+
{
62+
// not a valid object. throw exception.
63+
throw new Exception(CmdletWarningAndErrorMessages.Job.WaitJobInvalidInput + Job.GetType().FullName);
64+
}
65+
66+
// now wait until timeout happens or all jobs complete execution
67+
DateTime waitBeginning = DateTime.UtcNow;
68+
69+
while (true)
70+
{
71+
if (Timeout.HasValue)
72+
{
73+
if (DateTime.UtcNow.Subtract(waitBeginning) >= TimeSpan.FromSeconds(Timeout.Value))
74+
{
75+
break;
76+
}
77+
}
78+
79+
bool hasUnfinishedJob = false;
80+
finalJobs.Clear();
81+
foreach (string jobId in jobsToWaitOn)
82+
{
83+
var updatedJob = JobConversions.GetPSJob(
84+
HydraAdapter.GetJob(Vault.ResouceGroupName, Vault.Name, jobId)
85+
);
86+
87+
if (IsJobInProgress(updatedJob))
88+
{
89+
hasUnfinishedJob = true;
90+
}
91+
92+
finalJobs.Add(updatedJob);
93+
}
94+
95+
if (!hasUnfinishedJob)
96+
{
97+
break;
98+
}
99+
}
100+
101+
if (finalJobs.Count == 1)
102+
{
103+
WriteObject(finalJobs[0]);
104+
}
105+
else
106+
{
107+
WriteObject(finalJobs);
108+
}
109+
});
110+
}
111+
112+
private bool GetCastedObjFromPSObj(object obj, Type objType, out object castedJob)
113+
{
114+
if (obj is PSObject)
115+
{
116+
obj = ((PSObject)obj).ImmediateBaseObject;
117+
}
118+
// try to cast the immediate object to base object
119+
try
120+
{
121+
castedJob = Convert.ChangeType(obj, objType);
122+
return true;
123+
}
124+
catch (InvalidCastException)
125+
{
126+
castedJob = null;
127+
return false;
128+
}
129+
}
130+
131+
// Move the following function to a common helper file later when
132+
// more functions of this type are required.
133+
private bool IsJobInProgress(AzureRmRecoveryServicesJobBase job)
134+
{
135+
if (job.Status.CompareTo("InProgress") == 0 ||
136+
job.Status.CompareTo("Cancelling") == 0)
137+
{
138+
return true;
139+
}
140+
return false;
141+
}
142+
}
143+
}

0 commit comments

Comments
 (0)