Пример #1
0
        /// <summary>
        /// This method communicates with policystorage service and gets the backupstorage details
        /// </summary>
        /// <param name="policy">Policy which is to be restored</param>
        /// <returns>BackupStorage details</returns>
        public async Task <BackupStorage> GetBackupStorageDetails(string policy)
        {
            IPolicyStorageService policyStorageClient = ServiceProxy.Create <IPolicyStorageService>(new Uri("fabric:/StandByApplication/PolicyStorageService"));
            BackupStorage         backupStorage       = await policyStorageClient.GetPolicyStorageDetails(policy);

            return(backupStorage);
        }
 public virtual void Setup()
 {
     _backupProcess = A.Fake<BackupProcess>();
     _backupStorage = A.Fake<BackupStorage>();
     _backupNotifier = A.Fake<BackupNotifier>();
     _backupCleanUp = A.Fake<BackupCleanUp>();
 }
        private async Task <PolicyStorageEntity> GetPolicyDetails(string httpConnectionString, string thumbprint, string policyName)
        {
            PolicyStorageEntity policyStorageEntity = new PolicyStorageEntity
            {
                policy = policyName
            };
            string URL           = httpConnectionString + "/";
            string URLParameters = "BackupRestore/BackupPolicies/" + policyName + "?api-version=6.4";

            HttpResponseMessage response = await Utility.HTTPGetAsync(URL, URLParameters, thumbprint);

            if (response.IsSuccessStatusCode)
            {
                // Parse the response body. Blocking!
                var           content       = response.Content.ReadAsAsync <JObject>().Result;
                JObject       objectData    = (JObject)content["Storage"];
                BackupStorage backupStorage = JsonConvert.DeserializeObject <BackupStorage>(objectData.ToString());
                policyStorageEntity.backupStorage = backupStorage;
                return(policyStorageEntity);
            }
            else
            {
                Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
                return(null);
            }
        }
        // This encapsulates a restore task which triggers the restore and returns the restore result accordingly.
        public async Task <RestoreResult> RestoreWorkFlow(JToken latestbackupInfo, string policy, PartitionWrapper partition, String clusterConnectionString, String clusterThumbprint)
        {
            string URL           = clusterConnectionString + "/";
            string URLParameters = "Partitions/" + partition.partitionId + "/$/Restore" + "?api-version=6.4";

            BackupStorage backupStorage = await GetBackupStorageDetails(policy);

            if (backupStorage == null)
            {
                ServiceEventSource.Current.ServiceMessage(this.Context, "backupstorage is null");
                return(null);
            }

            BackupInfo backupInfo = new BackupInfo(latestbackupInfo["BackupId"].ToString(), latestbackupInfo["BackupLocation"].ToString(), backupStorage, (DateTime)latestbackupInfo["CreationTimeUtc"]);

            HttpResponseMessage response = await Utility.HTTPPostAsync(URL, URLParameters, backupInfo, clusterThumbprint);

            if (response.IsSuccessStatusCode || response.StatusCode == System.Net.HttpStatusCode.Conflict) // As calling Restore multiple times results in 409/Conflict Error, when in progress
            {
                string restoreState = "";
                restoreState = GetRestoreState(partition, clusterConnectionString, clusterThumbprint);
                return(new RestoreResult(backupInfo, restoreState));
            }
            else
            {
                Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
                return(null);
            }
        }
 public BackupInfo(string backupId, string backupLocation, BackupStorage backupStorage, DateTime backupTime)
 {
     this.backupId       = backupId;
     this.backupLocation = backupLocation;
     this.backupStorage  = backupStorage;
     this.backupTime     = backupTime;
 }
 public GetRestorePointsWithBackupStorageOperationWithinDates(BackupStorage backupStorage, string fabricRequestHeader, DateTime startDateTime, DateTime endDateTime
                                                              , string serviceName, string apiVersion, StatefulService statefulService)
     : base(fabricRequestHeader, serviceName, apiVersion, statefulService)
 {
     this.backupStorage = backupStorage;
     this.startDateTime = startDateTime;
     this.endDateTime   = endDateTime;
 }
Пример #7
0
 internal BackupPartitionWorkItem(string serviceUri, string partitionId, BackupStorage backupStorage, Guid backupRequestGuid, int backupTimeoutinMinutes)
 {
     this.ServiceUri        = serviceUri;
     this.PartitionId       = partitionId;
     this.BackupRequestGuid = backupRequestGuid;
     this.BackupStorage     = backupStorage;
     this.RequestDateTime   = DateTime.UtcNow;
     this.BackupTimeout     = TimeSpan.FromMinutes(backupTimeoutinMinutes);
 }
 public BackupController(
     BackupProcess backupProcess, 
     BackupStorage backupStorage, 
     BackupCleanUp backupCleanUp, 
     BackupNotifier backupNotifier)
 {
     _backupProcess = backupProcess;
     _backupStorage = backupStorage;
     _backupCleanUp = backupCleanUp;
     _backupNotifier = backupNotifier;
 }
Пример #9
0
        // This encapsulates a restore task which triggers the restore and returns the restore result accordingly.
        public async Task <RestoreResult> RestoreWorkFlow(JToken latestbackupInfo, string policy, PartitionWrapper partition, String clusterConnectionString, String clusterThumbprint, String partitionDictionary)
        {
            IReliableDictionary <Guid, PartitionWrapper> myDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <Guid, PartitionWrapper> >(partitionDictionary);

            string URL           = clusterConnectionString + "/";
            string urlParameters = "Partitions/" + partition.partitionId + "/$/Restore" + "?api-version=6.2-preview";


            X509Certificate2  clientCert     = GetClientCertificate(clusterThumbprint);
            WebRequestHandler requestHandler = new WebRequestHandler();

            requestHandler.ClientCertificates.Add(clientCert);
            requestHandler.ServerCertificateValidationCallback = this.MyRemoteCertificateValidationCallback;


            HttpClient client = new HttpClient(requestHandler)
            {
                BaseAddress = new Uri(URL)
            };

            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            BackupStorage backupStorage = await GetBackupStorageDetails(policy);

            if (backupStorage == null)
            {
                ServiceEventSource.Current.ServiceMessage(this.Context, "backupstorage is null");
                return(null);
            }

            BackupInfo backupInfo = new BackupInfo(latestbackupInfo["BackupId"].ToString(), latestbackupInfo["BackupLocation"].ToString(), backupStorage, (DateTime)latestbackupInfo["CreationTimeUtc"]);

            HttpResponseMessage response = await client.PostAsJsonAsync(urlParameters, backupInfo);        // Blocking call!

            if (response.IsSuccessStatusCode || response.StatusCode == System.Net.HttpStatusCode.Conflict) // As calling Restore multiple times results in 409/Conflict Error, when in progress
            {
                string restoreState = "";
                //do
                //{
                //    await Task.Delay(10000);
                //    restoreState = GetRestoreState(partition, clusterConnectionString, clusterThumbprint);
                //} while (restoreState.Equals("Accepted") || restoreState.Equals("RestoreInProgress"));
                restoreState = GetRestoreState(partition, clusterConnectionString, clusterThumbprint);
                return(new RestoreResult(backupInfo, restoreState));
            }
            else
            {
                Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
                return(null);
            }
        }
Пример #10
0
        private BackupStoreInformation  GetBackupStoreInformationFromBackupStorage(BackupStorage backupStorage)
        {
            BackupStoreInformation storeInformation;

            switch (backupStorage.BackupStorageType)
            {
            case BackupStorageType.AzureBlobStore:
                var azureStorage = (AzureBlobBackupStorageInfo)backupStorage;
                storeInformation = new AzureBlobBackupStore
                {
                    ConnectionString      = azureStorage.ConnectionString,
                    ContainerName         = azureStorage.ContainerName,
                    FolderPath            = UtilityHelper.GetBaseDirectoryPathForPartition(this.ServiceUri, this.PartitionId),             // TODO: This should be constructed
                    IsAccountKeyEncrypted = azureStorage.IsConnectionStringEncrypted,
                };
                break;

            case BackupStorageType.DsmsAzureBlobStore:
                var dsmsAzureStorage = (DsmsAzureBlobBackupStorageInfo)backupStorage;
                storeInformation = new DsmsAzureBlobBackupStore
                {
                    StorageCredentialsSourceLocation = dsmsAzureStorage.StorageCredentialsSourceLocation,
                    ContainerName = dsmsAzureStorage.ContainerName,
                    FolderPath    = UtilityHelper.GetBaseDirectoryPathForPartition(this.ServiceUri, this.PartitionId),
                };
                break;

            case BackupStorageType.FileShare:
                var fileShareStorage = (FileShareBackupStorageInfo)backupStorage;
                storeInformation = new FileShareBackupStore
                {
                    AccessType          = String.IsNullOrEmpty(fileShareStorage.PrimaryUserName) ? FileShareAccessType.None : FileShareAccessType.DomainUser,
                    FileSharePath       = Path.Combine(fileShareStorage.Path, UtilityHelper.GetBaseDirectoryPathForPartition(this.ServiceUri, this.PartitionId)),
                    PrimaryUserName     = fileShareStorage.PrimaryUserName,
                    PrimaryPassword     = fileShareStorage.PrimaryPassword,
                    SecondaryUserName   = fileShareStorage.SecondaryUserName,
                    SecondaryPassword   = fileShareStorage.SecondaryPassword,
                    IsPasswordEncrypted = fileShareStorage.IsPasswordEncrypted,
                };
                break;

            default:
                throw new ArgumentException(string.Format("{0} not supported.", backupStorage.BackupStorageType));
            }

            return(storeInformation);
        }
Пример #11
0
        string DownloadPackageBackup(
            string id,
            string version,
            string hash)
        {
            var blobClient = BackupStorage.CreateCloudBlobClient();
            var packageBackupsBlobContainer = Util.GetPackageBackupsBlobContainer(blobClient);
            var packageBackupFileName       = Util.GetPackageBackupFileName(
                id,
                version,
                hash);
            var packageBackupBlob = packageBackupsBlobContainer.GetBlockBlobReference(packageBackupFileName);
            var downloadPath      = Path.Combine(_tempFolder, packageBackupFileName);

            packageBackupBlob.DownloadToFile(downloadPath);
            return(downloadPath);
        }
        internal override async Task <HttpResponseMessage> RunAsync(TimeSpan timeout, CancellationToken cancellationToken)
        {
            string applicationNameUri;
            string serviceNameUri;
            string partitionId;
            string fabricUri = await UtilityHelper.GetFabricUriFromRequstHeaderForPartitions(this.fabricRequestHeader, timeout, cancellationToken);

            UtilityHelper.GetApplicationAndServicePartitionUri(fabricUri, out applicationNameUri, out serviceNameUri, out partitionId);
            BackupStorage backupStorageModel;

            if (this.backupStorage == null)
            {
                var backupMapping = (await this.BackupMappingStore.GetValueAsync(fabricUri) ??
                                     await this.BackupMappingStore.GetValueAsync(serviceNameUri)) ??
                                    await this.BackupMappingStore.GetValueAsync(UtilityHelper.GetApplicationNameFromService(applicationNameUri));

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

                var backupPolicy = await this.BackupPolicyStore.GetValueAsync(backupMapping.BackupPolicyName, timeout, cancellationToken);

                backupStorageModel = backupPolicy.Storage;
            }
            else
            {
                backupStorageModel = BackupStorage.FromBackupStorageView(this.backupStorage);
            }

            var backupRequestGuid     = Guid.NewGuid();
            var backupPartitionStatus = new BackupPartitionStatus(fabricUri, backupRequestGuid);
            var sendBackupPartitionToServiceNodeWorkItem = new BackupPartitionWorkItem(serviceNameUri, partitionId, backupStorageModel, backupRequestGuid, this.backupTimeoutinMinutes);

            using (var transaction = this.StatefulService.StateManager.CreateTransaction())
            {
                await this.CheckForEitherBackupOrRestoreInProgress(fabricUri, timeout, cancellationToken, transaction);

                await this.WorkItemQueue.AddWorkItem(sendBackupPartitionToServiceNodeWorkItem, timeout, cancellationToken, transaction);

                await this.BackupPartitionStore.AddOrUpdateAsync(fabricUri, backupPartitionStatus, (fabricUriKey, backupPartitionStatusUpdate) => backupPartitionStatus, timeout, cancellationToken, transaction);

                await transaction.CommitAsync();
            }
            return(new HttpResponseMessage(HttpStatusCode.Accepted));
        }
Пример #13
0
        private async Task <PolicyStorageEntity> getPolicyDetails(string cs, string policyName)
        {
            PolicyStorageEntity policyStorageEntity = new PolicyStorageEntity();

            policyStorageEntity.policy = policyName;
            string URL           = "https://" + cs + "/";
            string urlParameters = "BackupRestore/BackupPolicies/" + policyName + "?api-version=6.2-preview";


            X509Certificate2  clientCert     = GetClientCertificate();
            WebRequestHandler requestHandler = new WebRequestHandler();

            requestHandler.ClientCertificates.Add(clientCert);
            requestHandler.ServerCertificateValidationCallback = this.MyRemoteCertificateValidationCallback;


            HttpClient client = new HttpClient(requestHandler)
            {
                BaseAddress = new Uri(URL)
            };

            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            // List data response.
            HttpResponseMessage response = await client.GetAsync(urlParameters);  // Blocking call!

            if (response.IsSuccessStatusCode)
            {
                // Parse the response body. Blocking!
                var           content       = response.Content.ReadAsAsync <JObject>().Result;
                JObject       objectData    = (JObject)content["Storage"];
                BackupStorage backupStorage = JsonConvert.DeserializeObject <BackupStorage>(objectData.ToString());
                policyStorageEntity.backupStorage = backupStorage;
                return(policyStorageEntity);
            }
            else
            {
                Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
                return(null);
            }
        }
Пример #14
0
        // This encapsulates a restore task which triggers the restore and returns the restore result accordingly.
        public async Task <RestoreResult> RestoreWorkFlow(JToken latestbackupInfo, string policy, PartitionWrapper partition, String clusterConnectionString, String partitionDictionary)
        {
            IReliableDictionary <Guid, PartitionWrapper> myDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <Guid, PartitionWrapper> >(partitionDictionary);

            HttpClient client        = new HttpClient();
            string     URL           = clusterConnectionString + "/Partitions/" + partition.partitionId + "/$/Restore";
            string     urlParameters = "?api-version=6.2-preview";

            client.BaseAddress = new Uri(URL);
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            BackupStorage backupStorage = await GetBackupStorageDetails(policy);

            if (backupStorage == null)
            {
                ServiceEventSource.Current.ServiceMessage(this.Context, "backupstorage is null");
                return(null);
            }

            BackupInfo backupInfo = new BackupInfo(latestbackupInfo["BackupId"].ToString(), latestbackupInfo["BackupLocation"].ToString(), backupStorage, (DateTime)latestbackupInfo["CreationTimeUtc"]);

            HttpResponseMessage response = await client.PostAsJsonAsync(urlParameters, backupInfo);  // Blocking call!

            if (response.IsSuccessStatusCode)
            {
                string restoreState = "";
                do
                {
                    await Task.Delay(10000);

                    restoreState = GetRestoreState(partition, clusterConnectionString);
                } while (restoreState.Equals("Accepted") || restoreState.Equals("RestoreInProgress"));
                return(new RestoreResult(backupInfo, restoreState));
            }
            else
            {
                Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
                return(null);
            }
        }
        public async Task <IActionResult> GetPolicies(String cs, [FromBody] List <string> applications)
        {
            List <PolicyStorageEntity> policyDetails = new List <PolicyStorageEntity>();
            List <string> policyNames = new List <string>();

            foreach (string application in applications)
            {
                string     URL           = "http://" + cs + "/Applications/" + application + "/$/GetBackupConfigurationInfo";
                string     urlParameters = "?api-version=6.2-preview";
                HttpClient client        = new HttpClient
                {
                    BaseAddress = new Uri(URL)
                };
                client.DefaultRequestHeaders.Accept.Add(
                    new MediaTypeWithQualityHeaderValue("application/json"));

                HttpResponseMessage response = await client.GetAsync(urlParameters);

                if (response.IsSuccessStatusCode)
                {
                    var    content = response.Content.ReadAsAsync <JObject>().Result;
                    JArray array   = (JArray)content["Items"];
                    foreach (var item in array)
                    {
                        string policy = item["PolicyName"].ToString();
                        if (!policyNames.Contains(policy))
                        {
                            policyNames.Add(policy);
                        }
                    }
                }
                else
                {
                    Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
                    return(null);
                }

                foreach (string policyName in policyNames)
                {
                    PolicyStorageEntity policyStorageEntity = new PolicyStorageEntity();
                    policyStorageEntity.policy = policyName;
                    URL           = "http://" + cs + "/BackupRestore/BackupPolicies/" + policyName;
                    urlParameters = "?api-version=6.2-preview";
                    client        = new HttpClient
                    {
                        BaseAddress = new Uri(URL)
                    };
                    client.DefaultRequestHeaders.Accept.Add(
                        new MediaTypeWithQualityHeaderValue("application/json"));

                    // List data response.
                    response = await client.GetAsync(urlParameters);  // Blocking call!

                    if (response.IsSuccessStatusCode)
                    {
                        // Parse the response body. Blocking!
                        var           content       = response.Content.ReadAsAsync <JObject>().Result;
                        JObject       objectData    = (JObject)content["Storage"];
                        BackupStorage backupStorage = JsonConvert.DeserializeObject <BackupStorage>(objectData.ToString());
                        policyStorageEntity.backupStorage = backupStorage;
                        policyDetails.Add(policyStorageEntity);
                    }
                    else
                    {
                        Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
                        return(null);
                    }
                }
            }
            return(this.Json(policyDetails));
        }
Пример #16
0
        private BackupStorage UpdateSecretInStorage(BackupStorage storage, string thumbprintFromManifest, string x509StoreNameFromManifest, CancellationToken cancellationToken)
        {
            if (storage.BackupStorageType == BackupStorageType.AzureBlobStore)
            {
                var azureStorage = (AzureBlobBackupStorageInfo)storage;
                if (!azureStorage.IsConnectionStringEncrypted && String.IsNullOrEmpty(thumbprintFromManifest))
                {
                    return(storage);
                }
                if (azureStorage.IsConnectionStringEncrypted)
                {
                    return(azureStorage.ToBuilder()
                           .WithConnectionString(UtilityHelper.ConvertToUnsecureString(EncryptionUtility.DecryptText(azureStorage.ConnectionString)))
                           .SetIsConnectionStringEncrypted(false)
                           .Build());
                }

                if (!String.IsNullOrEmpty(thumbprintFromManifest))
                {
                    return(azureStorage.ToBuilder()
                           .WithConnectionString(EncryptionUtility.EncryptText(azureStorage.ConnectionString, thumbprintFromManifest, x509StoreNameFromManifest))
                           .SetIsConnectionStringEncrypted(true)
                           .Build());
                }
            }
            else if (storage.BackupStorageType == BackupStorageType.FileShare)
            {
                var fileShareStorage = (FileShareBackupStorageInfo)storage;
                if (!fileShareStorage.IsPasswordEncrypted && String.IsNullOrEmpty(thumbprintFromManifest))
                {
                    return(storage);
                }
                if (fileShareStorage.IsPasswordEncrypted)
                {
                    var builder = fileShareStorage.ToBuilder()
                                  .SetIsPasswordEncrypted(false);
                    if (!String.IsNullOrEmpty(fileShareStorage.PrimaryPassword))
                    {
                        builder.WithPrimaryPassword(UtilityHelper.ConvertToUnsecureString(EncryptionUtility.DecryptText(fileShareStorage.PrimaryPassword)));
                    }

                    if (!String.IsNullOrEmpty(fileShareStorage.SecondaryPassword))
                    {
                        builder.WithSecondaryPassword(UtilityHelper.ConvertToUnsecureString(EncryptionUtility.DecryptText(fileShareStorage.SecondaryPassword)));
                    }

                    return(builder.Build());
                }

                if (!String.IsNullOrEmpty(thumbprintFromManifest))
                {
                    var builder = fileShareStorage.ToBuilder()
                                  .SetIsPasswordEncrypted(true);
                    if (!String.IsNullOrEmpty(fileShareStorage.PrimaryPassword))
                    {
                        builder.WithPrimaryPassword(EncryptionUtility.EncryptText(fileShareStorage.PrimaryPassword, thumbprintFromManifest, x509StoreNameFromManifest));
                    }

                    if (!String.IsNullOrEmpty(fileShareStorage.SecondaryPassword))
                    {
                        builder.WithSecondaryPassword(EncryptionUtility.EncryptText(fileShareStorage.SecondaryPassword, thumbprintFromManifest, x509StoreNameFromManifest));
                    }

                    return(builder.Build());
                }
            }
            else if (storage.BackupStorageType == BackupStorageType.DsmsAzureBlobStore)
            {
                // DsmsAzureBlobStorage doesn't contain any encrypted strings, return the original value.
                return(storage);
            }

            throw new ArgumentException("Invalid storage type");
        }
Пример #17
0
        public override void ExecuteCommand()
        {
            Log.Info(
                "Backing up '{0}/packages' -> '{1}/package-backups'.",
                StorageAccount.Credentials.AccountName,
                BackupStorage.Credentials.AccountName);

            var client       = CreateBlobClient();
            var backupClient = BackupStorage.CreateCloudBlobClient();

            // Get the state file object
            var  state         = GetStateFile(backupClient);
            var  lastId        = state.LastBackedUpId;
            bool forcedRecheck = false;

            if (state.LastBackupCompletedUtc.HasValue && ((DateTimeOffset.UtcNow - state.LastBackupCompletedUtc.Value) > TimeSpan.FromDays(1)))
            {
                // Do a "full" backup (check every package file) every day
                lastId        = null;
                forcedRecheck = true;
            }

            var packagesToBackUp = GetPackagesToBackUp(lastId, forcedRecheck);

            var processedCount = 0;

            var backupBlobs  = backupClient.GetContainerReference("package-backups");
            var packageBlobs = client.GetContainerReference("packages");

            if (!WhatIf)
            {
                backupBlobs.CreateIfNotExists();
            }
            Parallel.ForEach(packagesToBackUp, new ParallelOptions {
                MaxDegreeOfParallelism = SingleThreaded ? 1 : 10
            }, package =>
            {
                try
                {
                    var packageBlob = packageBlobs.GetBlockBlobReference(Util.GetPackageFileName(package.Id, package.Version));
                    var backupBlob  = backupBlobs.GetBlockBlobReference(Util.GetPackageBackupFileName(package.Id, package.Version, package.Hash));
                    if (packageBlob.Exists())
                    {
                        bool shouldCopy = backupBlob.Exists();

                        // Verify the package, if it exists
                        if (shouldCopy)
                        {
                            packageBlob.FetchAttributes();
                            backupBlob.FetchAttributes();
                            shouldCopy =
                                String.IsNullOrEmpty(packageBlob.Properties.ContentMD5) ||
                                String.IsNullOrEmpty(backupBlob.Properties.ContentMD5) ||
                                !String.Equals(packageBlob.Properties.ContentMD5, backupBlob.Properties.ContentMD5, StringComparison.Ordinal);
                        }

                        if (!shouldCopy && !WhatIf)
                        {
                            backupBlob.StartCopyFromBlob(packageBlob);
                        }

                        Interlocked.Increment(ref processedCount);
                        Log.Trace(
                            "[{2:000000}/{3:000000} {4:00.0}%] {5} Backup of '{0}@{1}'.",
                            package.Id,
                            package.Version,
                            processedCount,
                            packagesToBackUp.Count,
                            (double)processedCount / (double)packagesToBackUp.Count,
                            shouldCopy ? "Skipped" : "Started");
                    }
                    else
                    {
                        Log.Warn(
                            "[{2:000000}/{3:000000} {4:00.0}%] Package File not found in source: '{0}@{1}'",
                            package.Id,
                            package.Version,
                            processedCount,
                            packagesToBackUp.Count,
                            (double)processedCount / (double)packagesToBackUp.Count);
                    }
                }
                catch (Exception ex)
                {
                    Interlocked.Increment(ref processedCount);
                    Log.Error(
                        "[{2:000000}/{3:000000} {4:00.0}%] Error Starting Backup of '{0}@{1}': {5}",
                        package.Id,
                        package.Version,
                        processedCount,
                        packagesToBackUp.Count,
                        (double)processedCount / (double)packagesToBackUp.Count,
                        ex.Message);
                }
            });

            Log.Info("Backed up {0} packages from {1} to {2}", processedCount, StorageAccount.Credentials.AccountName, BackupStorage.Credentials.AccountName);

            state.LastBackupCompletedUtc = DateTimeOffset.UtcNow;
            state.LastBackedUpId         = packagesToBackUp.Max(p => p.Key);

            WriteStateFile(backupClient, state);
        }
Пример #18
0
        /// <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);
                }
            }
        }
Пример #19
0
        private async Task DeleteFilesForPartition(string partitionId, DateTime endDateFilter, int minimumNumberOfBackups, BackupStorage storage, string backupPolicyName, bool isCleanupTask = false)
        {
            // Design:

            /**
             * Need out Two API's from Azure share and file share
             * 1. List of all backups before a certain date for the partition
             * 2. Start deleting the files one by one.(one file at a time with some random wait time.)
             *
             **/

            BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " In DeleteFilesForPartition for partitionId : {0} with endDateFilter {1}", partitionId, endDateFilter);
            string applicationName = null;
            string serviceName     = null;
            string partitionID     = null;
            string fabricUri       = await UtilityHelper.GetFabricUriFromPartitionId(partitionId, this.timeout, this.tokenSource.Token);

            var FabricBackupResourceType = UtilityHelper.GetApplicationAndServicePartitionName(fabricUri, out applicationName,
                                                                                               out serviceName, out partitionID);

            Debug.Assert(partitionId == partitionID);
            var storeManager = RecoveryPointManagerFactory.GetRecoveryPointManager(storage);

            this.tokenSource.Token.ThrowIfCancellationRequested();
            BRSContinuationToken bRSContinuationToken = new BRSContinuationToken();
            List <string>        allBackupFiles       = storeManager.EnumerateRecoveryPointMetadataFiles(storage.GetRelativeStorePath(applicationName, serviceName, partitionId),
                                                                                                         DateTime.MinValue, DateTime.MaxValue, false, bRSContinuationToken, 0);

            List <RestorePoint> restorePoints = new List <RestorePoint>();

            if ((allBackupFiles != null) && (allBackupFiles.Count > 0))
            {
                restorePoints = await storeManager.GetRecoveryPointDetailsAsync(allBackupFiles, this.tokenSource.Token);
            }

            this.tokenSource.Token.ThrowIfCancellationRequested();

            int backupCount = allBackupFiles.Count;

            if (backupCount <= minimumNumberOfBackups)
            {
                return;
            }

            restorePoints = restorePoints.OrderBy(restorePoint => restorePoint.CreationTimeUtc).ToList();
            restorePoints = restorePoints.Where(restorePoint => restorePoint.CreationTimeUtc < endDateFilter).ToList();

            restorePoints.Reverse();
            bool lastFullBackupFound            = false;
            RetentionMetadata retentionMetadata = await this.RetentionStore.GetValueAsync(backupPolicyName, this.timeout, this.tokenSource.Token);

            if (isCleanupTask)
            {
                lastFullBackupFound = true;
            }
            if (!isCleanupTask && retentionMetadata.OnGoingRetentionFile.ContainsKey(partitionId) &&
                retentionMetadata.OnGoingRetentionFile[partitionId] != null)
            {
                storeManager.DeleteBackupFiles(retentionMetadata.OnGoingRetentionFile[partitionId]);
            }
            foreach (var restorePoint in restorePoints)
            {
                this.tokenSource.Token.ThrowIfCancellationRequested();
                BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " Trying to Delete Restore point with backupLocation: {0}", restorePoint.BackupLocation);
                if (!isCleanupTask)
                {
                    BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " Updating OnGoing RetentionFile in the metadata for backupPolicy : {0} with partitionId : {1} and BackupLocation {2}"
                                                             , backupPolicyName, partitionId, restorePoint.BackupLocation);
                    retentionMetadata.UpdateOnGoingRetentionFile(partitionId, restorePoint.BackupLocation);
                    await this.RetentionStore.UpdateValueAsync(backupPolicyName, retentionMetadata, this.timeout, this.tokenSource.Token, null);
                }

                if (!lastFullBackupFound)
                {
                    BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " Skipping RestorePoint with location : {0} as full backup is not found", restorePoint.BackupLocation);
                    if (restorePoint.BackupType == BackupOptionType.Full)
                    {
                        BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " Full Backup found so, after restore points after :{0} will be deleted. ", restorePoint.BackupLocation);
                        lastFullBackupFound = true;
                    }
                }
                else
                {
                    if (backupCount <= minimumNumberOfBackups)
                    {
                        break;
                    }

                    if (storeManager.DeleteBackupFiles(restorePoint.BackupLocation))
                    {
                        BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " Deleted Restore point with backupLocation: {0}", restorePoint.BackupLocation);
                        backupCount--;
                    }
                    else
                    {
                        BackupRestoreTrace.TraceSource.WriteWarning(TraceType, " Not able to delete Restore point with backupLocation: {0}", restorePoint.BackupLocation);
                    }
                }
                await IntroduceRandomDelay();
            }

            // Deletion for a partition is completed.
            if (!isCleanupTask)
            {
                BackupRestoreTrace.TraceSource.WriteInfo(TraceType, " Updating OnGoing RetentionFile in the metadata for backupPolicy : {0}", backupPolicyName);
                retentionMetadata.UpdateOnGoingRetentionFile(partitionId);
                await this.RetentionStore.UpdateValueAsync(backupPolicyName, retentionMetadata, this.timeout, this.tokenSource.Token, null);
            }
        }