/// <summary>
        /// Gets called when a partition is disabled for a pariticular policy.
        /// </summary>
        internal async Task DisablePolicyAsync(BackupPolicy backupPolicy, string partitionId, BackupMapping inheritedBackupMapping, TimeSpan timeout, CancellationToken cancellationToken, ITransaction transaction)
        {
            /**
             * Cases:
             * 1. Partition has different policy inherited and storage is different, cleanup wont impact the same storage.
             *    ---> Check whether the timercallback is finished or not.
             * 2. Partition has different inherited policy and storage and container are same.
             *    --> NO Cleanup
             * **/

            // Since, you have disabled the policy now look for the backup mapping on the partition.
            var backupPolicyStore = await BackupPolicyStore.CreateOrGetBackupPolicyStore(this.StatefulService);

            if (inheritedBackupMapping == null)
            {
                await AddPartitionToCleanUpStore(partitionId, backupPolicy, cancellationToken, transaction);

                Task cleanUpTask = CleanUpTaskUtil(partitionId, backupPolicy);
            }
            else
            {
                var inheritedPolicy = await backupPolicyStore.GetValueAsync(inheritedBackupMapping.BackupPolicyName);

                if (!backupPolicy.Storage.CompareStorage(inheritedPolicy.Storage))
                {
                    BackupRestoreTrace.TraceSource.WriteWarning(TraceType, "Inherited Policy for partition:{0} is having same storage, so, cleanup is skipped.");
                }
                else
                {
                    await AddPartitionToCleanUpStore(partitionId, backupPolicy, cancellationToken, transaction);

                    Task cleanUpTask = CleanUpTaskUtil(partitionId, backupPolicy);
                }
            }
        }
        internal async override Task InitializeAsync()
        {
            this.BackupMappingStore = await BackupMappingStore.CreateOrGetBackupMappingStore(this.StatefulService).ConfigureAwait(false);

            this.BackupPolicyStore = await BackupPolicyStore.CreateOrGetBackupPolicyStore(this.StatefulService).ConfigureAwait(false);

            this.WorkItemQueue = await WorkItemQueue.CreateOrGetWorkItemQueue(this.StatefulService).ConfigureAwait(false);
        }
        private async Task UpdateSecretsAsync(string thumbprintFromManifest, string x509StoreNameFromManifest, CancellationToken cancellationToken)
        {
            BackupRestoreTrace.TraceSource.WriteInfo(TraceType, String.Format("Updating secrets using the new thumbprint {0}", thumbprintFromManifest));
            using (var transaction = this.StateManager.CreateTransaction())
            {
                try
                {
                    var policyStore = await BackupPolicyStore.CreateOrGetBackupPolicyStore(this);

                    var workItemQueue = await WorkItemQueue.CreateOrGetWorkItemQueue(this);

                    var policies = await policyStore.GetValuesAsync(Common.Constants.StoreTimeOut, cancellationToken, transaction);

                    foreach (var policy in policies)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        var updatedStorage = this.UpdateSecretInStorage(policy.Storage, thumbprintFromManifest, x509StoreNameFromManifest, cancellationToken);
                        var newPolicy      = policy.ToBuilder()
                                             .WithBackupStorage(updatedStorage)
                                             .UpdateUniqueId()
                                             .Build();

                        if (!await policyStore.UpdateValueAsync(policy.Name, policy, newPolicy, Common.Constants.StoreTimeOut, cancellationToken, transaction))
                        {
                            throw new InvalidOperationException(String.Format("Failed to update secret for policy with name {0}", newPolicy.Name));
                        }

                        if (newPolicy.BackupEnabledSet.Count > 0)
                        {
                            await workItemQueue.AddWorkItem(
                                new UpdateEnablementWorkItem(newPolicy.BackupEnabledSet.ToList(),
                                                             new WorkItemInfo
                            {
                                WorkItemType = WorkItemPropogationType.UpdateBackupPolicy,
                                BackupPolicyUpdateGuid = newPolicy.UniqueId
                            }), Common.Constants.StoreTimeOut, cancellationToken, transaction);
                        }
                    }

                    // Update the config store
                    var configStore = await ConfigStore.CreateOrGetConfigStore(this);

                    await configStore.UpdateValueAsync(Common.Constants.SecretUpdateInProgress, String.Empty, Common.Constants.StoreTimeOut, cancellationToken, transaction);

                    await configStore.UpdateValueAsync(Common.Constants.EncryptionCertThumbprintKey, thumbprintFromManifest, Common.Constants.StoreTimeOut, cancellationToken, transaction);

                    await transaction.CommitAsync();

                    BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "All secrets updated with manifest {0}", thumbprintFromManifest);
                    FabricEvents.Events.BRSSecretsUpdated(TraceType, thumbprintFromManifest);
                }
                catch (Exception ex)
                {
                    BackupRestoreTrace.TraceSource.WriteExceptionAsWarning(TraceType, ex, "Exception encountered while updating secrets");
                    throw;
                }
            }
        }
        internal async Task DisablePolicyAsync(string fabricUri, BackupMapping currentBackupMapping, TimeSpan timeout, CancellationToken cancellationToken, ITransaction transaction)
        {
            BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " In DisablePolicyAsync for fabricUri : {0}", fabricUri);
            string        applicationNameUri       = null;
            string        serviceNameUri           = null;
            string        partitionID              = null;
            var           fabricBackupResourceType = UtilityHelper.GetApplicationAndServicePartitionUri(fabricUri, out applicationNameUri, out serviceNameUri, out partitionID);
            List <string> filteredPartitionList    = new List <string>();
            var           backupMappingStore       = await BackupMappingStore.CreateOrGetBackupMappingStore(this.StatefulService);

            var backupPolicyStore = await BackupPolicyStore.CreateOrGetBackupPolicyStore(this.StatefulService);

            var currentBackupPolicy = await backupPolicyStore.GetValueAsync(currentBackupMapping.BackupPolicyName, transaction);

            BackupMapping inheritedBackupMapping = null;

            switch (fabricBackupResourceType)
            {
            case FabricBackupResourceType.ApplicationUri:
                filteredPartitionList = await FilterPartitionListToDisableForFabricURI(await GetPartitionsForServiceOrApplication(fabricUri,
                                                                                                                                  FabricBackupResourceType.ApplicationUri, timeout, cancellationToken), timeout, cancellationToken, FabricBackupResourceType.ServiceUri);

                break;

            case FabricBackupResourceType.ServiceUri:
                filteredPartitionList = await FilterPartitionListToDisableForFabricURI(await GetPartitionsForServiceOrApplication(fabricUri,
                                                                                                                                  FabricBackupResourceType.ServiceUri, timeout, cancellationToken), timeout, cancellationToken, FabricBackupResourceType.ServiceUri);

                inheritedBackupMapping = await backupMappingStore.GetValueAsync(applicationNameUri, transaction);

                break;

            case FabricBackupResourceType.PartitionUri:
                inheritedBackupMapping = await backupMappingStore.GetValueAsync(serviceNameUri, transaction);

                if (inheritedBackupMapping == null)
                {
                    inheritedBackupMapping = await backupMappingStore.GetValueAsync(applicationNameUri, transaction);
                }
                filteredPartitionList.Add(partitionID);
                break;
            }
            foreach (var partitionId in filteredPartitionList)
            {
                // there can be only one inherited backup policy for a single URI.
                BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " Trying to start DisablePolicyTask for partitionId : {0}", partitionId);
                await DisablePolicyAsync(currentBackupPolicy, partitionId, inheritedBackupMapping, timeout, cancellationToken, transaction);

                BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " Succesfully started DisablePolicyTask for partitionId : {0}", partitionId);
            }
        }
        internal async Task InitialiseRetentionManager()
        {
            this.RetentionStore = await RetentionStore.CreateOrGetRetentionStore(StatefulService);

            this.CleanupStore = await CleanupStore.CreateOrGetCleanupStore(StatefulService);

            // Initialise RetentionSchedulerDict using RetentionStore and retention schedulers
            BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "Intialising Retention Manager");
            using (ITransaction transaction = this.StatefulService.StateManager.CreateTransaction())
            {
                BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "Recreating RetentionSchedulerDict.");
                List <Tuple <string, RetentionMetadata> > listOfTuple = await this.RetentionStore.GetTupleListAsyncUtils(transaction, this.tokenSource.Token);

                foreach (var tuple in listOfTuple)
                {
                    if (!this.RetentionSchedulerDict.TryAdd(tuple.Item1,
                                                            new RetentionScheduler(tuple.Item1, tuple.Item2.CurrentRetentionPolicy, timerCallback)))
                    {
                        BackupRestoreTrace.TraceSource.WriteError(TraceType, "Not able to add retention scheduler for backupPolicy : {0}", tuple.Item1);
                        throw new InvalidOperationException(string.Format("{0}: Key already exists ", tuple.Item1));
                    }
                }

                // Start all the cleanUp Tasks again.
                BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "Starting all the previous cleanup tasks.");
                List <Tuple <string, List <string> > > listOfTuple2 = await this.CleanupStore.GetTupleListAsyncUtils(transaction, this.tokenSource.Token);

                int counter = 0;
                foreach (var tuple in listOfTuple2)
                {
                    var backupPolicyStore = await BackupPolicyStore.CreateOrGetBackupPolicyStore(this.StatefulService);

                    var backupPolicy = await backupPolicyStore.GetValueAsync(tuple.Item1, transaction);

                    if (tuple.Item2 != null && tuple.Item2.Count > 0)
                    {
                        counter += tuple.Item2.Count;
                        tuple.Item2.ForEach((partition =>
                        {
                            BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "Starting cleanUp task for partition : {0} and backupPolicy : {1}", partition, backupPolicy.Name);

                            Task task = CleanUpTaskUtil(partition, backupPolicy);
                        }));
                    }
                }
                BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "Number of cleanup Tasks started : {0}", counter);
            }
        }
        /// <summary>
        /// Gets called when a policy is updated
        /// </summary>
        internal async Task UpdatePolicyAsync(string backupPolicyName, TimeSpan timeout, CancellationToken cancellationToken, ITransaction transaction)
        {
            /**
             * Cases:
             * 1. UpdateRetention ----> Re-arm the timer.
             *    0. Add Retention.
             *    a. Remove retention --> dispose the timer.
             *    b. update the retention.
             * 2. UpdateStorage ---->
             * 3. Update Backup Schedule. --> no need to do anything/
             *
             */
            try
            {
                BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " In UpdatePolicyAsync of Retention Manager for Backup policy: {0}", backupPolicyName);
                var backupPolicyStore = await BackupPolicyStore.CreateOrGetBackupPolicyStore(this.StatefulService);

                RetentionMetadata retentionMetadata = await this.RetentionStore.GetValueAsync(backupPolicyName, timeout, cancellationToken, transaction);

                BackupPolicy backupPolicy = await backupPolicyStore.GetValueAsync(backupPolicyName, timeout, cancellationToken, transaction);

                if (retentionMetadata == null)
                {
                    if (backupPolicy.RetentionPolicy != null)
                    {
                        retentionMetadata = new RetentionMetadata(backupPolicy.RetentionPolicy);
                        await this.RetentionStore.AddAsync(backupPolicyName, retentionMetadata, timeout, cancellationToken, transaction);

                        RetentionScheduler retentionScheduler = new RetentionScheduler(backupPolicy.Name, backupPolicy.RetentionPolicy, timerCallback);

                        // Here we have updated the policy to introduce retention.
                        retentionScheduler.ArmTimer(retentionMetadata, true);
                        if (!RetentionSchedulerDict.TryAdd(backupPolicyName, retentionScheduler))
                        {
                            // If we are not able to add retention in RetentionSchedulerDict then, stop timer in retention scheduler
                            retentionScheduler.Stop();
                            BackupRestoreTrace.TraceSource.WriteWarning(TraceType, "UpdatePolicyAsync, Not able to add retentionScheduler to dict for policy : {0} ", backupPolicyName);
                            throw new InvalidOperationException(string.Format("{0}: Key already exists.", backupPolicyName));
                        }
                    }
                }
                else if (backupPolicy.RetentionPolicy == null)
                {
                    // need to remove the retentionScheduler from RetentionStore.
                    Func <bool> condition = () =>
                    {
                        if (retentionMetadata.LastRetentionCompletionTime > retentionMetadata.LastRetentionStartTime || retentionMetadata.LastRetentionStartTime == DateTime.MinValue)
                        {
                            return(true);
                        }
                        return(false);
                    };

                    bool disposeComplete = await BackupRestoreUtility.TryPerformOperationWithWaitAsync(
                        (policyName, token) =>
                    {
                        return(DisposeRetentionScheduler(policyName, timeout, token, transaction));
                    },
                        condition,
                        backupPolicyName,
                        cancellationToken,
                        minimumWaitTimeForRetryOperationInMs,
                        maxRetryCountForDisposingRetention,
                        minimumWaitTimeForRetryOperationInMs);

                    if (!disposeComplete)
                    {
                        BackupRestoreTrace.TraceSource.WriteError(TraceType, "Dispose retention did not complete for {0}", backupPolicyName);
                        throw new FabricBackupRestoreLocalRetryException();
                    }
                }
                else
                {
                    if (retentionMetadata.UpdateRetentionPolicyMetadata(backupPolicy.RetentionPolicy))
                    {
                        // Update the retention Scheduler store and arm the timer.
                        RetentionScheduler retentionScheduler;
                        if (!RetentionSchedulerDict.TryGetValue(backupPolicyName, out retentionScheduler))
                        {
                            BackupRestoreTrace.TraceSource.WriteError(TraceType, "UpdateBackupPolicy: Not able to get retention scheduler for backupPolicy {0}", backupPolicyName);
                            throw new KeyNotFoundException();
                        }

                        retentionScheduler.RearmTimer(false, retentionMetadata);
                        await this.RetentionStore.UpdateValueAsync(backupPolicyName, retentionMetadata, timeout, cancellationToken, transaction);
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException)
                {
                    BackupRestoreTrace.TraceSource.WriteWarning(TraceType, " DisposeRetentionScheduler ended with Timeout as the operation was cencelled: {0}", backupPolicyName);
                    BackupRestoreTrace.TraceSource.WriteWarning(TraceType, " It could be because the retention was in progress and user tried to remove the retention policy during UpdatePolicy: {0}", backupPolicyName);
                }
                else
                {
                    // Check for the exceptions of DisposeRetentionScheduler Timeout Retries.
                    BackupRestoreTrace.TraceSource.WriteError(TraceType, " UpdateBackupPolicy resulted in the exception : {0}", backupPolicyName);
                }
                throw;
            }
        }
        internal async Task <HashSet <string> > FindParititionsEnabledByPolicy(BackupPolicy backupPolicy)
        {
            BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " Finding all the partitions enabled for the backupPolicy : {0}", backupPolicy.Name);

            HashSet <string> partitionsEnabledByPolicy = new HashSet <string>();
            var backupPolicyStore = await BackupPolicyStore.CreateOrGetBackupPolicyStore(this.StatefulService);

            var backupMappingStore = await BackupMappingStore.CreateOrGetBackupMappingStore(this.StatefulService);

            var backupEnabledSet = backupPolicy.BackupEnabledSet.ToList();

            foreach (var backupedUri in backupEnabledSet)
            {
                string applicationName = null;
                string serviceName     = null;
                string partitionId     = null;
                FabricBackupResourceType fabricBackupResourceType =
                    UtilityHelper.GetApplicationAndServicePartitionUri(backupedUri, out applicationName, out serviceName,
                                                                       out partitionId);

                switch (fabricBackupResourceType)
                {
                case FabricBackupResourceType.PartitionUri:
                    partitionsEnabledByPolicy.Add(partitionId);
                    break;

                default:
                    var partitionIDList = await GetPartitionsForServiceOrApplication(backupedUri, fabricBackupResourceType, this.timeout, this.tokenSource.Token);

                    foreach (var partitionID in partitionIDList)
                    {
                        partitionsEnabledByPolicy.Add(partitionID);
                        this.tokenSource.Token.ThrowIfCancellationRequested();
                    }
                    break;
                }
            }

            List <string> partitionListToRemove = new List <string>();

            foreach (var partitionId in partitionsEnabledByPolicy)
            {
                this.tokenSource.Token.ThrowIfCancellationRequested();
                string serviceNameUri = await FabricClientHelper.GetFabricServiceUriFromPartitionId(partitionId, timeout, tokenSource.Token);

                string applicationNameUri = await FabricClientHelper.GetFabricApplicationUriFromServiceUri(serviceNameUri, timeout, tokenSource.Token);

                string partitionUri = await UtilityHelper.GetFabricUriFromPartitionId(partitionId, this.timeout, this.tokenSource.Token);

                var backupMapping = (await backupMappingStore.GetValueAsync(partitionUri, timeout, this.tokenSource.Token) ??
                                     await backupMappingStore.GetValueAsync(serviceNameUri, this.timeout, tokenSource.Token)) ??
                                    await backupMappingStore.GetValueAsync(applicationNameUri, this.timeout, tokenSource.Token);

                if (backupMapping.BackupPolicyName != backupPolicy.Name)
                {
                    partitionListToRemove.Add(partitionId);
                }
            }

            foreach (var partitionId in partitionListToRemove)
            {
                partitionsEnabledByPolicy.Remove(partitionId);
            }

            return(partitionsEnabledByPolicy);
        }
        /// <summary>
        /// Gets invoked when the RetentionScheduler's timer's time is elapsed
        /// </summary>
        internal void timerCallback(string backupPolicyName)
        {
            RetentionScheduler retentionScheduler;

            if (!RetentionSchedulerDict.TryGetValue(backupPolicyName, out retentionScheduler))
            {
                BackupRestoreTrace.TraceSource.WriteWarning(TraceType, "RetentionScheduler object is not found in retentionScheduler dict for policy: {0}", backupPolicyName);
                return;
            }
            bool toRearm = true;
            RetentionMetadata retentionMetadata = this.RetentionStore.GetValueAsync(backupPolicyName, this.timeout, this.tokenSource.Token).GetAwaiter().GetResult();

            try
            {
                BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " TimerCallback running for backupPolicy : {0}", backupPolicyName);

                var          backupPolicyStore = BackupPolicyStore.CreateOrGetBackupPolicyStore(this.StatefulService).GetAwaiter().GetResult();
                BackupPolicy backupPolicy      = backupPolicyStore.GetValueAsync(backupPolicyName, this.timeout, this.tokenSource.Token).GetAwaiter().GetResult();
                if (backupPolicy == null)
                {
                    /**
                     * This is used to garbage collect the retention scheduler. It could happen while deleting\updating policy retention scheduler object was not
                     * stopped properly. So, timer will call its callback again just to find that the backup policy does not exists.
                     * In this case, we should stop the retentionScheduler.
                     * **/
                    RetentionScheduler retentionSchedulerToDelete;
                    if (RetentionSchedulerDict.TryRemove(backupPolicyName, out retentionSchedulerToDelete))
                    {
                        retentionSchedulerToDelete.Stop();
                    }
                    else
                    {
                        BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "TimerCallback TryRemove retentionSchedulerDict failed of policy {0}. It could happen" +
                                                                 " when residual callback already scheduled on threadpool thread is getting invoked.", backupPolicyName);
                    }
                    toRearm = false;
                    return;
                }
                HashSet <string> partitionsEnabledByPolicy = FindParititionsEnabledByPolicy(backupPolicy).GetAwaiter().GetResult();

                retentionMetadata.UpdateLastRetentionStartTime();

                this.RetentionStore.UpdateValueAsync(backupPolicyName, retentionMetadata, this.timeout, this.tokenSource.Token, null).GetAwaiter().GetResult();

                var      derivedRetentionPolicy = (BasicRetentionPolicy)retentionMetadata.CurrentRetentionPolicy;
                TimeSpan retentionDuration      = derivedRetentionPolicy.RetentionDuration;
                int      minimumNumberOfBackups = derivedRetentionPolicy.MinimumNumberOfBackups;

                foreach (var partitionId in partitionsEnabledByPolicy)
                {
                    BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " Deleting backups for partitionId : {0}", partitionId);
                    List <string> partitionList = this.CleanupStore.GetValueAsync(backupPolicyName, this.timeout, this.tokenSource.Token).GetAwaiter().GetResult();
                    if (!(partitionList == null || partitionList.Count == 0) && partitionList.Contains(partitionId))
                    {
                        // Cleanup is going on for this partition.
                        continue;
                    }
                    DateTime      endDateFilter = DateTime.UtcNow - retentionDuration;
                    BackupStorage storage       = backupPolicy.Storage;
                    DeleteFilesForPartition(partitionId, endDateFilter, minimumNumberOfBackups, storage, backupPolicyName).GetAwaiter().GetResult();
                    this.tokenSource.Token.ThrowIfCancellationRequested();
                }

                // --> Introduce some wait time here so that CompletionTime is never equal to StartTime.
                retentionMetadata.UpdateLastRetentionCompletionTime();
                this.RetentionStore.UpdateValueAsync(backupPolicyName, retentionMetadata).GetAwaiter().GetResult();

                retentionScheduler.ArmTimer(retentionMetadata);
                toRearm = false;
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException)
                {
                    // Since, timercallback was cancelled, therefore, there is no need to rearm the timer.
                    BackupRestoreTrace.TraceSource.WriteWarning(TraceType, " TimerCallback for backupPolicy : {0} was cancelled ", backupPolicyName);
                    toRearm = false;
                }
                else
                {
                    BackupRestoreTrace.TraceSource.WriteWarning(TraceType, " TimerCallback for backupPolicy : {0} has thrown an exception : {1}", backupPolicyName, ex);
                }
            }
            finally
            {
                if (toRearm)
                {
                    retentionScheduler.RearmTimer(true, retentionMetadata);
                }
            }
        }
Exemple #9
0
    public async Task <BackupPolicy> GetBackupSchedulingPolicyAsync(BackupPartitionInfo backupPartitionInfo,
                                                                    TimeSpan timeout,
                                                                    CancellationToken cancellationToken)
    {
        BackupPolicy backupPolicy;

        BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "{0} GetBackupPolicy invoked", backupPartitionInfo.PartitionId);

        var backupMappingStore = await BackupMappingStore.CreateOrGetBackupMappingStore(this.statefulService);

        var backupPolicyStore = await BackupPolicyStore.CreateOrGetBackupPolicyStore(this.statefulService);

        var suspendStore = await SuspendStore.CreateOrGetSuspendStatusStore(this.statefulService);

        var serviceNameUri = await UtilityHelper.GetCustomServiceUri(backupPartitionInfo.ServiceName, timeout, cancellationToken);

        var backupMappingKey = UtilityHelper.GetBackupMappingKey(serviceNameUri, backupPartitionInfo.PartitionId.ToString());

        var backupMappingModel = (await backupMappingStore.GetValueAsync(backupMappingKey) ??
                                  await backupMappingStore.GetValueAsync(serviceNameUri)) ??
                                 await backupMappingStore.GetValueAsync(UtilityHelper.GetApplicationNameFromService(serviceNameUri));

        bool isPartitionSuspended = await suspendStore.GetValueAsync(backupMappingKey) != null;

        if (backupMappingModel == null || isPartitionSuspended)
        {
            BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "{0} Backup protection not enabled", backupPartitionInfo.PartitionId);
            throw new FabricPeriodicBackupNotEnabledException();
        }

        var backupPolicyName  = backupMappingModel.BackupPolicyName;
        var backupPolicyModel = await backupPolicyStore.GetValueAsync(backupPolicyName);

        switch (backupPolicyModel.BackupSchedule.BackupScheduleType)
        {
        case BackupScheduleType.FrequencyBased:
            backupPolicy = new FrequencyBasedBackupPolicy();
            var frequencyBasedSchedulePolicy = (System.Fabric.BackupRestore.Common.Model.FrequencyBasedBackupSchedule)backupPolicyModel.BackupSchedule;
            backupPolicy.PolicyType = BackupPolicyType.FrequencyBased;
            var freqBackupPolicy = (FrequencyBasedBackupPolicy)backupPolicy;

            freqBackupPolicy.RunFrequency = (ushort)frequencyBasedSchedulePolicy.Interval;

            if (frequencyBasedSchedulePolicy.IntervalType == BackupScheduleInterval.Hours)
            {
                freqBackupPolicy.RunFrequencyType = BackupPolicyRunFrequency.Hours;
            }

            if (frequencyBasedSchedulePolicy.IntervalType == BackupScheduleInterval.Minutes)
            {
                freqBackupPolicy.RunFrequencyType = BackupPolicyRunFrequency.Minutes;
            }

            break;

        case BackupScheduleType.TimeBased:
            backupPolicy = new ScheduleBasedBackupPolicy();
            var scheduleBasedSchedulePolicy = (System.Fabric.BackupRestore.Common.Model.TimeBasedBackupSchedule)backupPolicyModel.BackupSchedule;
            backupPolicy.PolicyType = BackupPolicyType.ScheduleBased;

            var schdBackupPolicy = (ScheduleBasedBackupPolicy)backupPolicy;
            if (scheduleBasedSchedulePolicy.ScheduleFrequencyType == BackupScheduleFrequency.Daily)
            {
                schdBackupPolicy.RunSchedule = BackupPolicyRunSchedule.Daily;
            }

            if (scheduleBasedSchedulePolicy.ScheduleFrequencyType == BackupScheduleFrequency.Weekly)
            {
                schdBackupPolicy.RunSchedule = BackupPolicyRunSchedule.Weekly;
            }

            schdBackupPolicy.RunDays  = new List <DayOfWeek>(scheduleBasedSchedulePolicy.RunDays);
            schdBackupPolicy.RunTimes = new List <TimeSpan>(scheduleBasedSchedulePolicy.RunTimes);

            break;

        default:
            throw new FabricPeriodicBackupNotEnabledException();
        }

        backupPolicy.MaxIncrementalBackups = Convert.ToByte(backupPolicyModel.MaxIncrementalBackup);
        backupPolicy.Name     = backupPolicyModel.Name;
        backupPolicy.PolicyId = backupPolicyModel.UniqueId;

        switch (backupPolicyModel.Storage.BackupStorageType)
        {
        case BackupStorageType.FileShare:
            var fileShareStorage = (System.Fabric.BackupRestore.Common.Model.FileShareBackupStorageInfo)backupPolicyModel.Storage;
            backupPolicy.StoreInformation = new FileShareBackupStore
            {
                AccessType          = String.IsNullOrEmpty(fileShareStorage.PrimaryUserName) ? FileShareAccessType.None : FileShareAccessType.DomainUser,
                FileSharePath       = Path.Combine(fileShareStorage.Path, UtilityHelper.GetBaseDirectoryPathForPartition(serviceNameUri, backupPartitionInfo.PartitionId.ToString())),
                PrimaryUserName     = fileShareStorage.PrimaryUserName,
                PrimaryPassword     = fileShareStorage.PrimaryPassword,
                SecondaryUserName   = fileShareStorage.SecondaryUserName,
                SecondaryPassword   = fileShareStorage.SecondaryPassword,
                IsPasswordEncrypted = fileShareStorage.IsPasswordEncrypted,
            };
            break;

        case BackupStorageType.AzureBlobStore:
            var azureStorage = (System.Fabric.BackupRestore.Common.Model.AzureBlobBackupStorageInfo)backupPolicyModel.Storage;
            backupPolicy.StoreInformation = new AzureBlobBackupStore
            {
                ConnectionString      = azureStorage.ConnectionString,
                ContainerName         = azureStorage.ContainerName,
                FolderPath            = UtilityHelper.GetBaseDirectoryPathForPartition(serviceNameUri, backupPartitionInfo.PartitionId.ToString()),
                IsAccountKeyEncrypted = azureStorage.IsConnectionStringEncrypted,
            };
            break;

        case BackupStorageType.DsmsAzureBlobStore:
            var dsmsAzureStorage = (System.Fabric.BackupRestore.Common.Model.DsmsAzureBlobBackupStorageInfo)backupPolicyModel.Storage;
            backupPolicy.StoreInformation = new DsmsAzureBlobBackupStore
            {
                StorageCredentialsSourceLocation = dsmsAzureStorage.StorageCredentialsSourceLocation,
                ContainerName = dsmsAzureStorage.ContainerName,
                FolderPath    = UtilityHelper.GetBaseDirectoryPathForPartition(serviceNameUri, backupPartitionInfo.PartitionId.ToString()),
            };
            break;
        }

        return(backupPolicy);
    }
Exemple #10
0
    public async Task <RestorePointDetails> GetRestorePointDetailsAsync(BackupPartitionInfo backupPartitionInfo, TimeSpan timeout,
                                                                        CancellationToken cancellationToken)
    {
        BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "GetRestorePointDetailsAsync invoked for partition {0}", backupPartitionInfo.PartitionId);

        var restoreStore = await RestoreStore.CreateOrGetRestoreStatusStore(this.statefulService);

        var backupMappingStore = await BackupMappingStore.CreateOrGetBackupMappingStore(this.statefulService);

        var backupPolicyStore = await BackupPolicyStore.CreateOrGetBackupPolicyStore(this.statefulService);

        bool                   userInitiatedOperation;
        BackupStorage          backupStorage;
        BackupStoreInformation backupStoreInformation = null;
        List <string>          backupLocations;
        string                 brsServiceUri = await UtilityHelper.GetCustomServiceUri(backupPartitionInfo.ServiceName, timeout, cancellationToken);

        var fabricUri     = UtilityHelper.GetBackupMappingKey(brsServiceUri, backupPartitionInfo.PartitionId.ToString());
        var restoreStatus = await restoreStore.GetValueAsync(fabricUri);

        if (restoreStatus != null && (
                restoreStatus.RestoreStatusState != RestoreState.Failure ||
                restoreStatus.RestoreStatusState != RestoreState.Invalid ||
                restoreStatus.RestoreStatusState != RestoreState.Success ||
                restoreStatus.RestoreStatusState != RestoreState.Timeout))
        {
            backupStorage          = restoreStatus.BackupStorage;
            userInitiatedOperation = true;
            backupLocations        = restoreStatus.BackupLocations.ToList();
        }
        else
        {
            var backupMappingKey = UtilityHelper.GetBackupMappingKey(brsServiceUri,
                                                                     backupPartitionInfo.PartitionId.ToString());
            var backupMappingModel = (await backupMappingStore.GetValueAsync(backupMappingKey) ??
                                      await backupMappingStore.GetValueAsync(brsServiceUri)) ??
                                     await backupMappingStore.GetValueAsync(UtilityHelper.GetApplicationNameFromService(brsServiceUri));

            if (backupMappingModel == null)
            {
                throw new FabricPeriodicBackupNotEnabledException();
            }

            var backupPolicy = await backupPolicyStore.GetValueAsync(backupMappingModel.BackupPolicyName);

            if (backupPolicy != null && backupPolicy.AutoRestore)
            {
                backupStorage          = backupPolicy.Storage;
                userInitiatedOperation = false;

                string applicationName, serviceName;
                UtilityHelper.GetApplicationAndServiceNameFromServiceUri(brsServiceUri,
                                                                         out applicationName, out serviceName);

                // Get the latest backup now
                var backups = await backupStorage.GetBackupEnumerationsTask(
                    applicationName,
                    serviceName,
                    backupPartitionInfo.PartitionId.ToString(),
                    DateTime.MinValue,
                    DateTime.MaxValue,
                    true,
                    cancellationToken);

                if (backups == null || backups.Count == 0)
                {
                    throw new ArgumentException(); // TODO: Change this with appropriate exception
                }

                var backupDetail = backups.First();

                var recoveryPointManager = RecoveryPointManagerFactory.GetRecoveryPointManager(backupStorage);
                backupLocations = await recoveryPointManager.GetBackupLocationsInBackupChainAsync(backupDetail.BackupLocation, cancellationToken);
            }
            else
            {
                throw new ArgumentException(); // TODO: Change with the OTher exception
            }
        }

        switch (backupStorage.BackupStorageType)
        {
        case BackupStorageType.FileShare:
            var fileShareStorage = (FileShareStorage)backupStorage;
            backupStoreInformation = new FileShareBackupStore
            {
                AccessType          = String.IsNullOrEmpty(fileShareStorage.PrimaryUserName) ? FileShareAccessType.None : FileShareAccessType.DomainUser,
                FileSharePath       = fileShareStorage.Path,
                PrimaryUserName     = fileShareStorage.PrimaryUserName,
                PrimaryPassword     = fileShareStorage.PrimaryPassword,
                SecondaryUserName   = fileShareStorage.SecondaryUserName,
                SecondaryPassword   = fileShareStorage.SecondaryPassword,
                IsPasswordEncrypted = fileShareStorage.IsPasswordEncrypted,
            };
            break;

        case BackupStorageType.AzureBlobStore:
            var azureStorage = (AzureStorage)backupStorage;
            backupStoreInformation = new AzureBlobBackupStore
            {
                ConnectionString      = azureStorage.ConnectionString,
                ContainerName         = azureStorage.ContainerName,
                FolderPath            = String.Empty,             // TODO: This should be constructed
                IsAccountKeyEncrypted = azureStorage.IsConnectionStringEncrypted,
            };
            break;

        case BackupStorageType.DsmsAzureBlobStore:
            var dsmsAzureStorage = (DsmsAzureStorage)backupStorage;
            backupStoreInformation = new DsmsAzureBlobBackupStore
            {
                StorageCredentialsSourceLocation = dsmsAzureStorage.StorageCredentialsSourceLocation,
                ContainerName = dsmsAzureStorage.ContainerName,
                FolderPath    = String.Empty,                     // TODO: This should be constructed
            };
            break;
        }

        Guid restoreOperationId = Guid.NewGuid();

        if (userInitiatedOperation)
        {
            await UtilityHelper.InvokeWithRetry(async() =>
            {
                using (ITransaction transaction = this.statefulService.StateManager.CreateTransaction())
                {
                    var currentRestoreStatus = await restoreStore.GetValueWithUpdateLockModeAsync(fabricUri, timeout, cancellationToken, transaction);
                    restoreOperationId       = currentRestoreStatus.RestoreRequestGuid;
                    if (currentRestoreStatus.RestoreStatusState == RestoreState.Accepted) //TODO Check for Guid
                    {
                        var toUpdateRestoreStatus = currentRestoreStatus.ToBuilder().WithState(RestoreState.RestoreInProgress).Build();
                        await
                        restoreStore.UpdateValueAsync(fabricUri, toUpdateRestoreStatus, timeout,
                                                      cancellationToken, transaction);
                        await transaction.CommitAsync();
                    }
                    else
                    {
                        transaction.Abort();
                    }
                }
            });
        }

        var restorePartitionDetails = new RestorePointDetails()
        {
            BackupLocations        = backupLocations,
            UserInitiatedOperation = userInitiatedOperation,
            StoreInformation       = backupStoreInformation,
            OperationId            = restoreOperationId
        };

        BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "GetRestorePointDetailsAsync invoked for partition {0} with Return Values {1}", backupPartitionInfo.PartitionId, restorePartitionDetails);
        return(restorePartitionDetails);
    }