diff --git a/src/RecoveryServices/RecoveryServices.Backup.Models/CommonModels/PolicyRetentionObjects.cs b/src/RecoveryServices/RecoveryServices.Backup.Models/CommonModels/PolicyRetentionObjects.cs index 3a5f3096b04f..2845f30b9654 100644 --- a/src/RecoveryServices/RecoveryServices.Backup.Models/CommonModels/PolicyRetentionObjects.cs +++ b/src/RecoveryServices/RecoveryServices.Backup.Models/CommonModels/PolicyRetentionObjects.cs @@ -219,14 +219,64 @@ public override void Validate() /// public new void Validate(ScheduleRunType ScheduleRunFrequency = 0) { - base.Validate(ScheduleRunFrequency); - int MinDurationCountInDays = 1, MaxDurationCountInDays = PolicyConstants.AfsSnapshotRetentionDaysMax; if (SnapshotRetentionInDays < MinDurationCountInDays || SnapshotRetentionInDays > MaxDurationCountInDays) { throw new ArgumentException(Resources.SnapshotRetentionInDaysInvalidException); } + + if (IsDailyScheduleEnabled) + { + if (DailySchedule == null) + { + throw new ArgumentException(Resources.DailyScheduleEnabledButScheduleIsNullException); + } + else + { + DailySchedule.BackupManagementType = BackupManagementType; + DailySchedule.Validate(ScheduleRunFrequency, PolicyConstants.AfsDailyRetentionDaysMin, PolicyConstants.AfsVaultDailyRetentionDaysMax); + } + } + + if (IsWeeklyScheduleEnabled) + { + if (WeeklySchedule == null) + { + throw new ArgumentException(Resources.WeeklyScheduleEnabledButScheduleIsNullException); + } + else + { + WeeklySchedule.BackupManagementType = BackupManagementType; + WeeklySchedule.Validate(ScheduleRunFrequency, PolicyConstants.AfsWeeklyRetentionMin, PolicyConstants.AfsVaultWeeklyRetentionMax); + } + } + + if (IsMonthlyScheduleEnabled) + { + if (MonthlySchedule == null) + { + throw new ArgumentException(Resources.MonthlyScheduleEnabledButScheduleIsNullException); + } + else + { + MonthlySchedule.BackupManagementType = BackupManagementType; + MonthlySchedule.Validate(ScheduleRunFrequency, PolicyConstants.AfsMonthlyRetentionMin, PolicyConstants.AfsVaultMonthlyRetentionMax); + } + } + + if (IsYearlyScheduleEnabled) + { + if (YearlySchedule == null) + { + throw new ArgumentException(Resources.YearlyScheduleEnabledButScheduleIsNullException); + } + else + { + YearlySchedule.BackupManagementType = BackupManagementType; + YearlySchedule.Validate(ScheduleRunFrequency, PolicyConstants.AfsYearlyRetentionMin, PolicyConstants.AfsVaultYearlyRetentionMax); + } + } } public override string ToString() @@ -308,17 +358,26 @@ public class DailyRetentionSchedule : RetentionScheduleBase public int DurationCountInDays { get; set; } // no extra fields - public override void Validate(ScheduleRunType ScheduleRunFrequency = 0) + public void Validate(ScheduleRunType ScheduleRunFrequency = 0, int MinDuration = 0, int MaxDuration = 0) { int MinDurationCountInDays = 7, MaxDurationCountInDays = PolicyConstants.MaxAllowedRetentionDurationCount; if(BackupManagementType == Management.RecoveryServices.Backup.Models.BackupManagementType.AzureStorage) { - MinDurationCountInDays = PolicyConstants.AfsDailyRetentionDaysMin; - MaxDurationCountInDays = PolicyConstants.AfsVaultDailyRetentionDaysMax; + if (MinDuration != 0 && MaxDuration != 0) + { + MinDurationCountInDays = MinDuration; + MaxDurationCountInDays = MaxDuration; + } + else + { + MinDurationCountInDays = PolicyConstants.AfsDailyRetentionDaysMin; + MaxDurationCountInDays = PolicyConstants.AfsDailyRetentionDaysMax; + } } + if (DurationCountInDays < MinDurationCountInDays || DurationCountInDays > MaxDurationCountInDays) { - throw new ArgumentException(Resources.RetentionDurationCountInDaysInvalidException); + throw new ArgumentException(string.Format(Resources.RetentionDurationCountInvalidException, "Days", MinDurationCountInDays, MaxDurationCountInDays)); } base.Validate(ScheduleRunFrequency); @@ -345,17 +404,26 @@ public class WeeklyRetentionSchedule : RetentionScheduleBase /// public List DaysOfTheWeek { get; set; } - public override void Validate(ScheduleRunType ScheduleRunFrequency = 0) + public void Validate(ScheduleRunType ScheduleRunFrequency = 0, int MinDuration = 0, int MaxDuration = 0) { int MinDurationCountInWeeks = 1, MaxDurationCountInWeeks = PolicyConstants.MaxAllowedRetentionDurationCountWeekly; if(BackupManagementType == Management.RecoveryServices.Backup.Models.BackupManagementType.AzureStorage) { - MinDurationCountInWeeks = PolicyConstants.AfsWeeklyRetentionMin; - MaxDurationCountInWeeks = PolicyConstants.AfsVaultWeeklyRetentionMax; + if (MinDuration != 0 && MaxDuration != 0) + { + MinDurationCountInWeeks = MinDuration; + MaxDurationCountInWeeks = MaxDuration; + } + else + { + MinDurationCountInWeeks = PolicyConstants.AfsWeeklyRetentionMin; + MaxDurationCountInWeeks = PolicyConstants.AfsWeeklyRetentionMax; + } } + if (DurationCountInWeeks < MinDurationCountInWeeks || DurationCountInWeeks > MaxDurationCountInWeeks) { - throw new ArgumentException(Resources.RetentionDurationCountInvalidException); + throw new ArgumentException(string.Format(Resources.RetentionDurationCountInvalidException, "Weeks", MinDurationCountInWeeks, MaxDurationCountInWeeks)); } if (DaysOfTheWeek == null || DaysOfTheWeek.Count == 0 || DaysOfTheWeek.Count != DaysOfTheWeek.Distinct().Count()) @@ -403,20 +471,28 @@ public MonthlyRetentionSchedule() { } - public override void Validate(ScheduleRunType ScheduleRunFrequency = 0) + public void Validate(ScheduleRunType ScheduleRunFrequency = 0, int MinDuration = 0, int MaxDuration = 0) { base.Validate(ScheduleRunFrequency); int MinDurationCountInMonths = 1, MaxDurationCountInMonths = PolicyConstants.MaxAllowedRetentionDurationCountMonthly; if (BackupManagementType == Management.RecoveryServices.Backup.Models.BackupManagementType.AzureStorage) { - MinDurationCountInMonths = PolicyConstants.AfsMonthlyRetentionMin; - MaxDurationCountInMonths = PolicyConstants.AfsVaultMonthlyRetentionMax; + if (MinDuration != 0 && MaxDuration != 0) + { + MinDurationCountInMonths = MinDuration; + MaxDurationCountInMonths = MaxDuration; + } + else + { + MinDurationCountInMonths = PolicyConstants.AfsMonthlyRetentionMin; + MaxDurationCountInMonths = PolicyConstants.AfsMonthlyRetentionMax; + } } if (DurationCountInMonths < MinDurationCountInMonths || DurationCountInMonths > MaxDurationCountInMonths) { - throw new ArgumentException(Resources.RetentionDurationCountInvalidException); + throw new ArgumentException(string.Format(Resources.RetentionDurationCountInvalidException, "Months", MinDurationCountInMonths, MaxDurationCountInMonths)); } if (RetentionScheduleFormatType == RetentionScheduleFormat.Daily) @@ -487,19 +563,28 @@ public YearlyRetentionSchedule() } - public override void Validate(ScheduleRunType ScheduleRunFrequency = 0) +public void Validate(ScheduleRunType ScheduleRunFrequency = 0, int MinDuration = 0, int MaxDuration = 0) { base.Validate(ScheduleRunFrequency); int MinDurationCountInYears = 1, MaxDurationCountInYears = PolicyConstants.MaxAllowedRetentionDurationCountYearly; if (BackupManagementType == Management.RecoveryServices.Backup.Models.BackupManagementType.AzureStorage) { - MinDurationCountInYears = PolicyConstants.AfsYearlyRetentionMin; - MaxDurationCountInYears = PolicyConstants.AfsVaultYearlyRetentionMax; + if (MinDuration != 0 && MaxDuration != 0) + { + MinDurationCountInYears = MinDuration; + MaxDurationCountInYears = MaxDuration; + } + else + { + MinDurationCountInYears = PolicyConstants.AfsYearlyRetentionMin; + MaxDurationCountInYears = PolicyConstants.AfsYearlyRetentionMax; + } } + if (DurationCountInYears < MinDurationCountInYears || DurationCountInYears > MaxDurationCountInYears) { - throw new ArgumentException(Resources.RetentionDurationCountInvalidException); + throw new ArgumentException(string.Format(Resources.RetentionDurationCountInvalidException, "Years", MinDurationCountInYears, MaxDurationCountInYears)); } if (MonthsOfYear == null || MonthsOfYear.Count == 0 || MonthsOfYear.Count != MonthsOfYear.Distinct().Count()) diff --git a/src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.Designer.cs b/src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.Designer.cs index 2a196f70b45b..542c39b2059e 100644 --- a/src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.Designer.cs +++ b/src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.Designer.cs @@ -1392,7 +1392,7 @@ public static string RetentionDurationCountInDaysInvalidException } /// - /// Looks up a localized string similar to RetentionDuration in Days/Weeks/Months/Years should be from 1 - 9999. + /// Looks up a localized string similar to RetentionDuration in {0} should be from {1} - {2}. /// public static string RetentionDurationCountInvalidException { @@ -2755,7 +2755,7 @@ public static string CRRAccessTokenCouldNotBeFetchedException } /// - /// Looks up a localized string similar to Modifying existing policies to stop data transfer to the vault and retain backups only as snapshots is not supported. Please create a new policy to opt-out of the data transfer to the recovery services vault. + /// Switching the backup tier from vaulted backup to snapshot is not possible. Please create a new policy for snapshot-only backups. /// public static string AFSPolicyUpdateNotAllowed { diff --git a/src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.resx b/src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.resx index f31727bca925..5b4c324cbb0c 100644 --- a/src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.resx +++ b/src/RecoveryServices/RecoveryServices.Backup.Models/Properties/Resources.resx @@ -226,7 +226,7 @@ In Monthly and Yearly retention schedules, RetentionFormatType cannot be 'Daily' if Weekly BackupSchedule is selected - RetentionDuration in Days/Weeks/Months/Years should be from 1 - 9999 + RetentionDuration in {0} should be from {1} - {2} If Weekly backup schedule is enabled, then IsDailyScheduleEnabled should be false and Weekly retention schedule should not be null, IsWeeklyScheduleEnabled should be true @@ -860,7 +860,7 @@ Please contact Microsoft for further assistance. Unable to fetch CRR access token. Please retry the operation or contact Microsoft support if issue persists - Modifying existing policies to stop data transfer to the vault and retain backups only as snapshots is not supported. Please create a new policy to opt-out of the data transfer to the recovery services vault. + Switching the backup tier from vaulted backup to snapshot is not possible. Please create a new policy for snapshot-only backups. Changing the backup tier keeps current snapshots as-is under the existing policy. Future backups will be stored in the vault with new retention settings. This action is irreversible and incurs additional costs. Switching from vault to snapshot requires reconfiguration. Learn more at https://learn.microsoft.com/en-us/azure/backup/azure-file-share-backup-overview?tabs=snapshot. diff --git a/src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/AzureFiles/ItemTests.ps1 b/src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/AzureFiles/ItemTests.ps1 index 7d7e2ff3526a..3591d986517f 100644 --- a/src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/AzureFiles/ItemTests.ps1 +++ b/src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/AzureFiles/ItemTests.ps1 @@ -495,7 +495,7 @@ function Test-AzureFSVaultRestore -VaultId $vault.ID ` -Policy $snapshotPolicy ` -Item $item - } "Modifying existing policies to stop data transfer to the vault and retain backups only as snapshots is not supported. Please create a new policy to opt-out of the data transfer to the recovery services vault." + } "Switching the backup tier from vaulted backup to snapshot is not possible. Please create a new policy for snapshot-only backups." $item = Get-AzRecoveryServicesBackupItem -VaultId $vault.ID -BackupManagementType AzureStorage -WorkloadType AzureFiles diff --git a/src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/AzureFiles/PolicyTests.ps1 b/src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/AzureFiles/PolicyTests.ps1 index 00c0de9f6513..df669aa434f3 100644 --- a/src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/AzureFiles/PolicyTests.ps1 +++ b/src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/AzureFiles/PolicyTests.ps1 @@ -95,7 +95,7 @@ function Test-AzureFSVaultPolicy -RetentionPolicy $retentionPolicy ` -SchedulePolicy $schedulePolicy ` -Policy $policy } ` - "Modifying existing policies to stop data transfer to the vault and retain backups only as snapshots is not supported. Please create a new policy to opt-out of the data transfer to the recovery services vault." + "Switching the backup tier from vaulted backup to snapshot is not possible. Please create a new policy for snapshot-only backups." # Delete policy Remove-AzRecoveryServicesBackupProtectionPolicy `