Skip to content

Commit 87f49bd

Browse files
committed
Merge pull request #187 from MabOneSdk/user/dev1-adit/rsjobs
Get and Wait implementation for Jobs
2 parents 109a74e + 1cd4c0e commit 87f49bd

File tree

15 files changed

+717
-16
lines changed

15 files changed

+717
-16
lines changed

src/ResourceManager/RecoveryServices.Backup/CmdletParameterHelpMessages.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,18 @@ internal static class Policy
4444
public const string SchedulePolicy = "Schedule Policy object for the policy.";
4545
public const string ProtectionPolicy = "Protection policy object.";
4646
}
47+
48+
internal static class Job
49+
{
50+
public const string FromFilter = "Beginning value of time range for which jobs have to be fetched.";
51+
public const string ToFilter = "Ending value of time range for which jobs have to be fetched.";
52+
public const string OperationFilter = "Filter value for type of job.";
53+
public const string StatusFilter = "Filter value for status of job.";
54+
public const string BackupManagementTypeFilter = "Filter value for Backup Management Type of job.";
55+
public const string JobIdFilter = "Filter value for Id of job.";
56+
public const string JobFilter = "Job whose latest object has to be fetched.";
57+
public const string WaitJobOrListFilter = "Job or List of jobs until end of which the cmdlet should wait.";
58+
public const string WaitJobTimeoutFilter = "Maximum time to wait before aborting wait in seconds.";
59+
}
4760
}
4861
}
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: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
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.Job.FromFilter)]
30+
[ValidateNotNull]
31+
public DateTime? From { get; set; }
32+
33+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.ToFilter)]
34+
[ValidateNotNull]
35+
public DateTime? To { get; set; }
36+
37+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.JobIdFilter)]
38+
[ValidateNotNullOrEmpty]
39+
public string JobId { get; set; }
40+
41+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.JobFilter)]
42+
[ValidateNotNull]
43+
public AzureRmRecoveryServicesJobBase Job { get; set; }
44+
45+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.BackupManagementTypeFilter)]
46+
[ValidateNotNullOrEmpty]
47+
public BackupManagementType BackupManagementType { get; set; }
48+
49+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.OperationFilter)]
50+
[ValidateNotNullOrEmpty]
51+
public JobOperation Operation { get; set; }
52+
53+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.StatusFilter)]
54+
[ValidateNotNullOrEmpty]
55+
public JobStatus Status { get; set; }
56+
57+
public override void ExecuteCmdlet()
58+
{
59+
ARSVault Vault = null;
60+
61+
ExecutionBlock(() =>
62+
{
63+
base.ExecuteCmdlet();
64+
65+
// initialize values to default
66+
DateTime rangeStart = DateTime.UtcNow.AddDays(-1);
67+
DateTime rangeEnd = DateTime.UtcNow;
68+
69+
if (From.HasValue)
70+
{
71+
rangeStart = From.Value;
72+
}
73+
74+
if (To.HasValue)
75+
{
76+
rangeEnd = To.Value;
77+
}
78+
79+
// validate filters
80+
if (rangeEnd >= rangeStart)
81+
{
82+
throw new Exception(CmdletWarningAndErrorMessages.Job.ToShouldBeLessThanFrom);
83+
}
84+
else if (rangeEnd.Subtract(rangeStart) > TimeSpan.FromDays(30))
85+
{
86+
throw new Exception(CmdletWarningAndErrorMessages.Job.AllowedDateTimeRangeExceeded);
87+
}
88+
89+
// validate JobId and Job objects
90+
if (!string.IsNullOrEmpty(JobId))
91+
{
92+
// if JobId and Job are provided together and they don't match then throw exception
93+
if (Job != null && JobId != Job.InstanceId)
94+
{
95+
throw new Exception(CmdletWarningAndErrorMessages.Job.JobIdAndJobMismatch);
96+
}
97+
}
98+
else if (Job != null)
99+
{
100+
JobId = Job.InstanceId;
101+
}
102+
103+
// TODO: Initialize Vault object from base cmdlet once support is added
104+
List<AzureRmRecoveryServicesJobBase> result = new List<AzureRmRecoveryServicesJobBase>();
105+
int resultCount = 0;
106+
var adapterResponse = HydraAdapter.GetJobs(Vault.ResouceGroupName, Vault.Name, JobId, Status.ToString(), Operation.ToString(), rangeStart, rangeEnd,
107+
BackupManagementType.ToString());
108+
JobConversions.AddHydraJobsToPSList(adapterResponse, result, ref resultCount);
109+
110+
while (!string.IsNullOrEmpty(adapterResponse.ItemList.NextLink))
111+
{
112+
if (resultCount >= JobConstants.MaximumJobsToFetch)
113+
{
114+
// trace a warning that there are more jobs and user has to refine filters.
115+
WriteWarning(CmdletWarningAndErrorMessages.Job.RefineFilters);
116+
break;
117+
}
118+
119+
string skipToken;
120+
HydraHelpers.GetSkipTokenFromNextLink(adapterResponse.ItemList.NextLink, out skipToken);
121+
if (skipToken != null)
122+
{
123+
adapterResponse = HydraAdapter.GetJobs(Vault.ResouceGroupName, Vault.Name, JobId, Status.ToString(), Operation.ToString(),
124+
rangeStart, rangeEnd, BackupManagementType.ToString(), null, skipToken);
125+
JobConversions.AddHydraJobsToPSList(adapterResponse, result, ref resultCount);
126+
}
127+
else
128+
{
129+
break;
130+
}
131+
}
132+
133+
if (resultCount != 1)
134+
{
135+
WriteObject(result);
136+
}
137+
else
138+
{
139+
WriteObject(result[0]);
140+
}
141+
});
142+
}
143+
}
144+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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", DefaultParameterSetName = JobFilterSet), OutputType(typeof(AzureRmRecoveryServicesJobBase))]
22+
public class GetAzureRmRecoveryServicesJobDetails : RecoveryServicesBackupCmdletBase
23+
{
24+
protected const string IdFilterSet = "IdFilterSet";
25+
protected const string JobFilterSet = "JobFilterSet";
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+
ARSVault Vault = null;
38+
39+
ExecutionBlock(() =>
40+
{
41+
base.ExecuteCmdlet();
42+
43+
if (ParameterSetName == JobFilterSet)
44+
{
45+
JobId = Job.InstanceId;
46+
}
47+
48+
// Initialize vault object from base cmdlet
49+
var adapterResponse = HydraAdapter.GetJob(Vault.ResouceGroupName, Vault.Name, JobId);
50+
WriteObject(JobConversions.GetPSJob(adapterResponse));
51+
});
52+
}
53+
}
54+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
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 = true, HelpMessage = ParamHelpMsg.Job.WaitJobOrListFilter)]
27+
[ValidateNotNull]
28+
public object Job { get; set; }
29+
30+
[Parameter(Mandatory = false, HelpMessage = ParamHelpMsg.Job.WaitJobTimeoutFilter)]
31+
public long? Timeout { get; set; }
32+
33+
public override void ExecuteCmdlet()
34+
{
35+
ARSVault Vault = null;
36+
ExecutionBlock(() =>
37+
{
38+
base.ExecuteCmdlet();
39+
40+
List<string> jobsToWaitOn = new List<string>();
41+
List<AzureRmRecoveryServicesJobBase> finalJobs = new List<AzureRmRecoveryServicesJobBase>();
42+
43+
// TODO: Validate the following code
44+
object castedObj;
45+
if (GetCastedObjFromPSObj(Job, typeof(AzureRmRecoveryServicesJobBase), out castedObj))
46+
{
47+
AzureRmRecoveryServicesJobBase justJob = castedObj as AzureRmRecoveryServicesJobBase;
48+
jobsToWaitOn.Add(justJob.InstanceId);
49+
}
50+
else if (GetCastedObjFromPSObj(Job, typeof(List<AzureRmRecoveryServicesJobBase>), out castedObj))
51+
{
52+
List<AzureRmRecoveryServicesJobBase> jobsList = castedObj as List<AzureRmRecoveryServicesJobBase>;
53+
foreach (var job in jobsList)
54+
{
55+
jobsToWaitOn.Add(job.InstanceId);
56+
}
57+
}
58+
else
59+
{
60+
// not a valid object. throw exception.
61+
throw new Exception(CmdletWarningAndErrorMessages.Job.WaitJobInvalidInput + Job.GetType().FullName);
62+
}
63+
64+
// now wait until timeout happens or all jobs complete execution
65+
DateTime waitBeginning = DateTime.UtcNow;
66+
67+
while (true)
68+
{
69+
if (Timeout.HasValue)
70+
{
71+
if (DateTime.UtcNow.Subtract(waitBeginning) >= TimeSpan.FromSeconds(Timeout.Value))
72+
{
73+
break;
74+
}
75+
}
76+
77+
bool hasUnfinishedJob = false;
78+
finalJobs.Clear();
79+
foreach (string jobId in jobsToWaitOn)
80+
{
81+
var updatedJob = JobConversions.GetPSJob(
82+
HydraAdapter.GetJob(Vault.ResouceGroupName, Vault.Name, jobId)
83+
);
84+
85+
if (IsJobInProgress(updatedJob))
86+
{
87+
hasUnfinishedJob = true;
88+
}
89+
90+
finalJobs.Add(updatedJob);
91+
}
92+
93+
if (!hasUnfinishedJob)
94+
{
95+
break;
96+
}
97+
}
98+
99+
if (finalJobs.Count == 1)
100+
{
101+
WriteObject(finalJobs[0]);
102+
}
103+
else
104+
{
105+
WriteObject(finalJobs);
106+
}
107+
});
108+
}
109+
110+
private bool GetCastedObjFromPSObj(object obj, Type objType, out object castedJob)
111+
{
112+
if (obj is PSObject)
113+
{
114+
obj = ((PSObject)obj).ImmediateBaseObject;
115+
}
116+
// try to cast the immediate object to base object
117+
try
118+
{
119+
castedJob = Convert.ChangeType(obj, objType);
120+
return true;
121+
}
122+
catch (InvalidCastException)
123+
{
124+
castedJob = null;
125+
return false;
126+
}
127+
}
128+
129+
// Move the following function to a common helper file later when
130+
// more functions of this type are required.
131+
private bool IsJobInProgress(AzureRmRecoveryServicesJobBase job)
132+
{
133+
if (job.Status.CompareTo("InProgress") == 0 ||
134+
job.Status.CompareTo("Cancelling") == 0)
135+
{
136+
return true;
137+
}
138+
return false;
139+
}
140+
}
141+
}

0 commit comments

Comments
 (0)