예제 #1
0
 public void TestCleanup()
 {
     if (FabricDirectory.Exists(this.testPath))
     {
         FabricDirectory.Delete(this.testPath, true);
     }
 }
예제 #2
0
 public static void ClassSetup(object testContext)
 {
     if (FabricDirectory.Exists(DefaultWorkDirectory))
     {
         FabricDirectory.Delete(DefaultWorkDirectory, true);
     }
 }
        /// <summary>
        /// Post-processing of copying (from XStore to SMB)
        /// </summary>
        /// <param name="task">The task to end.</param>
        private static void EndCopyFromXStoreToSMB(XStoreFileOperationTask task)
        {
            if (task.IsSucceeded)
            {
                // Step 3, 4 and 5 for atomic copy
                // 3. delete dstFolder.old
                // 4. rename dstFolder -> dstFolder.old
                // 5. rename dstFolder.new -> dstFolder

                // get the original destination path
                string newDstRootUri = task.DstUri + NewExtension;
                string oldDstRootUri = task.DstUri + OldExtension;

                // Step 3, 4 & 5
                if (FabricDirectory.Exists(oldDstRootUri))
                {
                    // delete dstFolder.old
                    FabricDirectory.Delete(oldDstRootUri, recursive: true, deleteReadOnlyFiles: true);
                }

                if (FabricDirectory.Exists(task.DstUri))
                {
                    // rename dstFolder -> dstFolder.old
                    RenameFolder(task.DstUri, oldDstRootUri);
                }

                // rename dstFolder.new -> dstFolder; and clean up
                RenameFolder(newDstRootUri, task.DstUri);
                if (FabricDirectory.Exists(oldDstRootUri))
                {
                    FabricDirectory.Delete(oldDstRootUri, recursive: true, deleteReadOnlyFiles: true);
                }
            }
        }
예제 #4
0
        public void FabricDirectory_DeleteNonRecursiveEmptyFolder()
        {
            Directory.CreateDirectory(this.testPath);

            LogHelper.Log("FabricDirectory.Delete {0}", this.testPath);
            FabricDirectory.Delete(this.testPath, false, false);
            Assert.IsFalse(FabricDirectory.Exists(this.testPath));
        }
예제 #5
0
        private void DeleteDirectoryIfOld(DirectoryDeletionInfo delInfo)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(delInfo.DirName);

            if (dirInfo.LastWriteTimeUtc.CompareTo(delInfo.CutoffTime) < 0)
            {
                FabricDirectory.Delete(delInfo.DirName, true);
            }
        }
        internal async Task GenerateWithValueType <ValueType>(string logFolder, ValueType value, IStateSerializer <ValueType> valueSerializer)
        {
            // directory setup
            if (FabricDirectory.Exists(logFolder))
            {
                FabricDirectory.Delete(logFolder, true);
            }
            FabricDirectory.CreateDirectory(logFolder);

            var rand = new Random();

            var reliabilitySimulator = new ReliabilitySimulator(
                logFolder,
                new Uri("fabric:/unittest/service" + rand.Next()), // random service name.
                OnDataLossCallback,                                // we are never calling OnDataLossAsync on this ReliabilitySimulator.
                CreateStateProvider);

            reliabilitySimulator.CreateReplica(true, false);

            var replicator = reliabilitySimulator.GetTransactionalReplicator();

            replicator.TryAddStateSerializer <ValueType>(valueSerializer);

            // Constants
            var distributedDictionary = new DistributedDictionary <long, ValueType>();
            var distributedQueue      = new DistributedQueue <ValueType>();
            var concurrentQueue       = new ReliableConcurrentQueue <ValueType>();

            // Setup
            await reliabilitySimulator.OpenReplicaAsync(ReplicaOpenMode.New).ConfigureAwait(false);

            await reliabilitySimulator.PromoteReplicaAsync(false).ConfigureAwait(false);

            var result = replicator.CreateAsyncEnumerable(false, false);

            Assert.AreEqual(0, result.ToEnumerable().Count(), "State Manager must be empty");

            // Write data.
            using (var txn = replicator.CreateTransaction())
            {
                await replicator.AddStateProviderAsync(txn, DictionaryName, distributedDictionary).ConfigureAwait(false);

                await txn.CommitAsync().ConfigureAwait(false);
            }

            result = replicator.CreateAsyncEnumerable(false, false);
            Assert.AreEqual(2, result.ToEnumerable().Count(), "State Manager must include all the state providers");

            await PopulateDictionaryAsync(replicator, DictionaryName, 0, 8, 8, value).ConfigureAwait(false);

            // Take backup
            await replicator.BackupAsync(ComplexDataBackupCallbackAsync).ConfigureAwait(false);

            // Clean up.
            await reliabilitySimulator.DropReplicaAsync();
        }
예제 #7
0
        /// <summary>
        /// Async copy method that begins the copy operation.  Wait on AsyncWaitHandle to be notified of completion.
        /// </summary>
        /// <param name="source">
        /// Source folder that needs to be copied
        /// </param>
        /// <param name="destination">
        /// Destination folder
        /// </param>
        public void BeginCopy(string source, string destination)
        {
            this.ThrowIfDisposed();

            // make sure that the source folder exists
            if (!FabricDirectory.Exists(source))
            {
                throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, StringResources.ImageStoreError_DoesNotExistError, source));
            }

            // make sure that the event indicating completion is non-signalled
            this.asyncEvent.Reset();
            this.internalCopyAsyncEvent.Reset();

            // To make folder copy atomic, the sequence of actions are as below.
            // 1. delete dstFolder.new
            // 2. copy srcFolder -> dstFolder.new
            // 3. delete dstFolder.old
            // 4. rename dstFolder -> dstFolder.old
            // 5. rename dstFolder.new -> dstFolder
            string newDstFolder = destination;

            if (this.copyFlag == CopyFlag.AtomicCopySkipIfExists && FabricDirectory.Exists(newDstFolder))
            {
                // We will skip the copy because the final destination exists
                this.skipCopy = true;
            }
            else if (this.copyFlag == CopyFlag.AtomicCopy || this.copyFlag == CopyFlag.AtomicCopySkipIfExists)
            {
                newDstFolder = destination + FolderCopy.NewExtension;

                // Step 1.
                if (FabricDirectory.Exists(newDstFolder))
                {
                    FabricDirectory.Delete(newDstFolder, recursive: true, deleteReadOnlyFiles: true);
                }
            }

            // Queue up post copy completion task that needs to perform steps 3,4 & 5 mentioned above.
            ThreadPool.QueueUserWorkItem(this.EndCopy, new CopyArgs(source, destination, true));

            // set the work items to 1 and enqueue the first item to be copied
            this.workItemsInProgress = 1;

            if (!this.skipCopy)
            {
                ThreadPool.QueueUserWorkItem(this.CopyItem, new CopyArgs(source, newDstFolder, true));
            }
            else
            {
                // If we are skipping then just decrement and signal immediately.
                // We still Queue up the EndCopy because it translates the inner event into the outer event.
                this.DecrementWorkItem();
            }
        }
예제 #8
0
 public static void DeleteTempLocation(string location)
 {
     if (!string.IsNullOrEmpty(location) && FabricDirectory.Exists(location))
     {
         FabricDirectory.Delete(location, recursive: true, deleteReadOnlyFiles: true);
     }
     else if (!string.IsNullOrEmpty(location) && FabricFile.Exists(location))
     {
         FabricFile.Delete(location, deleteReadonly: true);
     }
 }
예제 #9
0
        public void FabricDirectory_Rename()
        {
            string renameFolderName = Path.Combine(Environment.ExpandEnvironmentVariables(TestPathPrefix), TestRenameFolderName);

            CreateNonEmptyDirectory(this.testPath);

            LogHelper.Log("FabricDirectory.Rename {0}", this.testPath);
            FabricDirectory.Rename(this.testPath, renameFolderName, true);
            Assert.IsFalse(FabricDirectory.Exists(this.testPath));
            Assert.IsTrue(FabricDirectory.Exists(renameFolderName));
            FabricDirectory.Delete(renameFolderName, true, false);
            Assert.IsFalse(FabricDirectory.Exists(renameFolderName));
        }
예제 #10
0
 public void FabricDirectory_DeleteNegative()
 {
     try
     {
         LogHelper.Log("FabricDirectory.Delete {0}", BadPath);
         FabricDirectory.Delete(BadPath, true, false);
         Assert.Fail("should never reach here");
     }
     catch (Exception e)
     {
         LogHelper.Log("caught exception {0}", e);
         Assert.IsTrue(e is IOException);
     }
 }
예제 #11
0
 public void FabricDirectory_DeleteRecursiveNonExistentFolder()
 {
     try
     {
         LogHelper.Log("FabricDirectory.Delete {0}", this.testPath);
         FabricDirectory.Delete(this.testPath, true, false);
         Assert.Fail("A DirectoryNotFoundException is expected before this.");
     }
     catch (Exception e)
     {
         LogHelper.Log("caught exception {0}", e);
         Assert.IsTrue(e is DirectoryNotFoundException);
     }
 }
예제 #12
0
        public void FabricDirectory_DeleteNonRecursiveNonEmptyFolder()
        {
            try
            {
                CreateNonEmptyDirectory(this.testPath);

                LogHelper.Log("FabricDirectory.Delete {0}", this.testPath);
                FabricDirectory.Delete(this.testPath, false, false);
                Assert.Fail("An IOException is expected before this.");
            }
            catch (Exception e)
            {
                LogHelper.Log("caught exception {0}", e);
                Assert.IsTrue(e is IOException);
            }
        }
예제 #13
0
        public void TestApplicationPackage(string connectionEndpoint, string applicationPackagePath, string applicationParameter, string imageStoreConnectionString, string certThumbprint)
        {
            string[] parameters = applicationParameter.Split(',');
            IDictionary <string, string> dictionary = new Dictionary <string, string>();

            for (int i = 0; i < parameters.Length / 2; i += 2)
            {
                dictionary.Add(parameters[i], parameters[i + 1]);
            }

            var testRootPath = Path.Combine(Path.GetTempPath(), string.Format(CultureInfo.InvariantCulture, "{0}_{1}", "TestApplicationPackage", DateTime.Now.Ticks));

            try
            {
                var applicationName         = new DirectoryInfo(applicationPackagePath).Name;
                var testRootApplicationPath = Path.Combine(testRootPath, applicationName);
                FabricDirectory.Copy(applicationPackagePath, testRootApplicationPath, true);
                ImageBuilderUtility.RemoveReadOnlyFlag(testRootApplicationPath);

                var fileImageStoreConnectionString = string.Format(CultureInfo.InvariantCulture, "{0}{1}", "file:", testRootPath.TrimEnd(Path.DirectorySeparatorChar));
                var sourceImageStore = ImageStoreFactoryProxy.CreateImageStore(fileImageStoreConnectionString);

                IImageStore destinationImageStore = null;
                if (string.IsNullOrEmpty(imageStoreConnectionString))
                {
                    destinationImageStore = sourceImageStore;
                }
                else
                {
                    destinationImageStore = this.CreateImageStore(connectionEndpoint, imageStoreConnectionString, testRootPath, certThumbprint);
                }

                var imagebuilder = new ImageBuilder(sourceImageStore, destinationImageStore, this.GetFabricFilePath("ServiceFabricServiceModel.xsd"), testRootPath);

                imagebuilder.ValidateApplicationPackage(
                    applicationName,
                    dictionary);
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                FabricDirectory.Delete(testRootPath, true, true);
            }
        }
예제 #14
0
        private string CreateAndAclDirectory()
        {
            string tempDirectory = Path.GetRandomFileName();

            if (FabricDirectory.Exists(tempDirectory))
            {
                throw new InvalidOperationException("Could not generate temporary local directory");
            }

            try
            {
                // DirectoryInfo does not support long path names. Since this is only used
                // when the ImageStoreConnectionString is for a file share and specifies
                // user account information (ImageStoreFactory.ParseFileImageStoreConnectionString),
                // we can leave this usage here until it's absolutely needed (file share is not
                // supported in production).
                //
                DirectoryInfo tempDirectoryInfo = new DirectoryInfo(tempDirectory);
                tempDirectoryInfo.Create();
#if !DotNetCoreClr
                DirectorySecurity directorySecurity = tempDirectoryInfo.GetAccessControl();
                directorySecurity.AddAccessRule(
                    new FileSystemAccessRule(accessDescription.WindowsIdentity.Name, FileSystemRights.Read | FileSystemRights.Write, AccessControlType.Allow));
                Directory.SetAccessControl(tempDirectory, directorySecurity);
#endif
                return(tempDirectory);
            }
            catch (Exception)
            {
                if (FabricDirectory.Exists(tempDirectory))
                {
                    FabricDirectory.Delete(tempDirectory, recursive: true, deleteReadOnlyFiles: true);
                }

                throw;
            }
        }
예제 #15
0
        private static void SafeDeleteDirectory(string directoryName, string directoryFilter, string fileFilter)
        {
#if DotNetCoreClr // Disable compiling on windows for now. Need to correct when porting FabricDeployer for windows.
            if (!Directory.Exists(directoryName) ||
                IsDirectorySymbolicLink(directoryName) ||
                string.Equals(directoryName, directoryFilter, StringComparison.OrdinalIgnoreCase))
            {
                return;
            }
            // Avoid deleting any file locks
            var files = Directory.GetFiles(directoryName).Where(
                (f => !f.EndsWith(FileLock.ReaderLockExtension, StringComparison.OrdinalIgnoreCase) && !f.EndsWith(FileLock.WriterLockExtension, StringComparison.CurrentCultureIgnoreCase)));
#else
            if (!Directory.Exists(directoryName) ||
                IsDirectorySymbolicLink(directoryName) ||
                string.Equals(directoryName, directoryFilter, StringComparison.InvariantCultureIgnoreCase))
            {
                return;
            }
            // Avoid deleting any file locks
            var files = Directory.GetFiles(directoryName).Where(
                (f => !f.EndsWith(FileLock.ReaderLockExtension, StringComparison.InvariantCultureIgnoreCase) && !f.EndsWith(FileLock.WriterLockExtension, StringComparison.InvariantCultureIgnoreCase)));
#endif

            foreach (var file in files)
            {
                if (FabricFile.Exists(file) && !string.Equals(file, fileFilter, StringComparison.OrdinalIgnoreCase))
                {
                    try
                    {
                        FabricFile.Delete(file, true);
                    }
                    catch (Exception ex)
                    {
                        DeployerTrace.WriteError("SafeDeleteDirectory failed deleting file: {0}. Exception: {1}.", file, ex);
                        throw;
                    }
                }
            }

            foreach (var subDirectoryName in Directory.GetDirectories(directoryName))
            {
                SafeDeleteDirectory(subDirectoryName, directoryFilter, fileFilter);
            }

            if (!Directory.GetDirectories(directoryName).Any() && !Directory.GetFiles(directoryName).Any())
            {
                try
                {
                    TimeSpan retryInterval  = TimeSpan.FromSeconds(5);
                    int      retryCount     = 12;
                    Type[]   exceptionTypes = { typeof(System.IO.FileLoadException) };
                    Helpers.PerformWithRetry(() =>
                    {
                        try
                        {
                            FabricDirectory.Delete(directoryName);
                        }
                        catch (Exception ex)
                        {
                            DeployerTrace.WriteWarning("Directory Delete failed for {0} due to: {1}.", directoryName, ex.Message);
                            throw;
                        }
                    },
                                             exceptionTypes,
                                             retryInterval,
                                             retryCount);
                }
                catch (Exception ex)
                {
                    DeployerTrace.WriteError("SafeDeleteDirectory failed deleting directory: {0}. Exception: {1}.", directoryName, ex);
                    throw;
                }
            }

            DeployerTrace.WriteInfo("Removed folder: {0}", directoryName);
        }
        /// <summary>
        /// Processing folder
        /// </summary>
        /// <param name="blobContainer">The blob container.</param>
        /// <param name="task">The task to be performed.</param>
        private void HandleFolder(CloudBlobContainer blobContainer, XStoreFileOperationTask task)
        {
            // expand the task and enqueue new tasks
            string[] files;
            string[] subFolders;

            // See if we need to handle the folder
            if (task.OpType == XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToSMB)
            {
                if (task.FileCopyFlag == CopyFlag.AtomicCopySkipIfExists && FabricDirectory.Exists(task.DstUri))
                {
                    // We will skip the copy because the final destination exists
                    return;
                }
                else if ((task.FileCopyFlag == CopyFlag.AtomicCopy ||
                          task.FileCopyFlag == CopyFlag.AtomicCopySkipIfExists) &&
                         task.IsRoot)
                {
                    XStoreFileOperationTask endTask = new XStoreFileOperationTask(
                        XStoreFileOperationTask.XStoreTaskType.EndCopyFromXStoreToSMB,
                        task.SrcUri,
                        task.DstUri,
                        true,
                        0,
                        task.TimeoutHelper);

                    endTask.IsSucceeded  = true;
                    endTask.FileCopyFlag = task.FileCopyFlag;
                    this.xstoreTaskPool.AddTaskToEndTaskQueue(endTask);
                    task.DstUri = task.DstUri + NewExtension;

                    // step1: delete dstFolder.new
                    if (FabricDirectory.Exists(task.DstUri))
                    {
                        FabricDirectory.Delete(task.DstUri, recursive: true, deleteReadOnlyFiles: true);
                    }
                }
            }
            else if (task.OpType == XStoreFileOperationTask.XStoreTaskType.CopyFromSMBToXStore)
            {
                if (task.FileCopyFlag == CopyFlag.AtomicCopySkipIfExists &&
                    XStoreCommon.XStoreFolderExists(blobContainer, task.DstUri, false, task.TimeoutHelper != null ? GetRequestOptions(task.TimeoutHelper) : null))
                {
                    // We will skip the copy because the final destination exists
                    return;
                }
                else if (task.IsRoot)
                {
                    // if this is the root uri of this operation
                    XStoreFileOperationTask endTask = new XStoreFileOperationTask(
                        XStoreFileOperationTask.XStoreTaskType.EndCopyFromSMBToXStore,
                        task.SrcUri,
                        task.DstUri,
                        true,
                        0,
                        task.TimeoutHelper);

                    endTask.IsSucceeded  = true;
                    endTask.FileCopyFlag = task.FileCopyFlag;
                    this.xstoreTaskPool.AddTaskToEndTaskQueue(endTask);

                    // remove the manifest of this folder
                    var blob = blobContainer.GetBlockBlobReference(XStoreCommon.GetXStoreFolderManifest(task.DstUri));
#if !DotNetCoreClr
                    blob.DeleteIfExists(DeleteSnapshotsOption.None, null, task.TimeoutHelper != null ? GetRequestOptions(task.TimeoutHelper) : null);
#else
                    blob.DeleteIfExistsAsync(DeleteSnapshotsOption.None, null, task.TimeoutHelper != null ? GetRequestOptions(task.TimeoutHelper) : null, null).Wait();
#endif
                }
            }
            else if (task.OpType == XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToXStore)
            {
                if (task.FileCopyFlag == CopyFlag.AtomicCopySkipIfExists &&
                    XStoreCommon.XStoreFolderExists(blobContainer, task.DstUri, false, task.TimeoutHelper != null ? GetRequestOptions(task.TimeoutHelper) : null))
                {
                    // We will skip the copy because the final destination exists
                    return;
                }
                else if (task.IsRoot)
                {
                    // if this is the root uri of this operation
                    XStoreFileOperationTask endTask = new XStoreFileOperationTask(
                        XStoreFileOperationTask.XStoreTaskType.EndCopyFromXStoreToXStore,
                        task.SrcUri,
                        task.DstUri,
                        true,
                        0,
                        task.TimeoutHelper);

                    endTask.IsSucceeded  = true;
                    endTask.FileCopyFlag = task.FileCopyFlag;

                    this.xstoreTaskPool.AddTaskToEndTaskQueue(endTask);

                    // remove the manifest of this folder
                    var blob = blobContainer.GetBlockBlobReference(XStoreCommon.GetXStoreFolderManifest(task.DstUri));

#if !DotNetCoreClr
                    blob.DeleteIfExists(DeleteSnapshotsOption.None, null, task.TimeoutHelper == null ? null : GetRequestOptions(task.TimeoutHelper));
#else
                    blob.DeleteIfExistsAsync(DeleteSnapshotsOption.None, null, task.TimeoutHelper == null ? null : GetRequestOptions(task.TimeoutHelper), null).Wait();
#endif
                }
            }

            string dstUri = null;

            switch (task.OpType)
            {
            case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToSMB:
            case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToXStore:
            case XStoreFileOperationTask.XStoreTaskType.RemoveFromXStore:
                this.GetFilesAndSubfoldersFromXStore(blobContainer, task.SrcUri, out files, out subFolders, task.TimeoutHelper);
                break;

            case XStoreFileOperationTask.XStoreTaskType.CopyFromSMBToXStore:
            default:
                GetFilesAndSubfoldersFromSMB(task.SrcUri, out files, out subFolders);
                break;
            }

            Queue <XStoreFileOperationTask> tasks = new Queue <XStoreFileOperationTask>();
            foreach (var file in files)
            {
                switch (task.OpType)
                {
                case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToSMB:
                    dstUri = ConvertBlobReferenceToSMBPath(file, task.SrcUri, task.DstUri);
                    if (task.OperationId != null)
                    {
                        XStoreCommon.AddDownloadContentEntry(task.OperationId.GetValueOrDefault(), file, dstUri);
                    }
                    break;

                case XStoreFileOperationTask.XStoreTaskType.CopyFromSMBToXStore:
                    dstUri = ConvertSMBPathToBlobReference(file, task.SrcUri, task.DstUri);
                    break;

                case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToXStore:
                    dstUri = ConvertBlobReferenceToBlobReference(file, task.SrcUri, task.DstUri);
                    break;
                }

                XStoreFileOperationTask newTask = new XStoreFileOperationTask(task.OpType, file, dstUri, false, 0, task.TimeoutHelper, task.OperationId);
                newTask.FileCopyFlag = task.FileCopyFlag;
                tasks.Enqueue(newTask);
            }

            foreach (var folder in subFolders)
            {
                switch (task.OpType)
                {
                case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToSMB:
                    dstUri = ConvertBlobReferenceToSMBPath(folder, task.SrcUri, task.DstUri);
                    break;

                case XStoreFileOperationTask.XStoreTaskType.CopyFromSMBToXStore:
                    dstUri = ConvertSMBPathToBlobReference(folder, task.SrcUri, task.DstUri);
                    break;

                case XStoreFileOperationTask.XStoreTaskType.CopyFromXStoreToXStore:
                    dstUri = ConvertBlobReferenceToBlobReference(folder, task.SrcUri, task.DstUri);
                    break;
                }

                XStoreFileOperationTask newTask = new XStoreFileOperationTask(task.OpType, folder, dstUri, true, 0, task.TimeoutHelper);
                newTask.FileCopyFlag = task.FileCopyFlag;
                tasks.Enqueue(newTask);
            }

            this.xstoreTaskPool.AddTaskToTaskQueue(tasks);
        }
예제 #17
0
        protected void TestComposeDeploymentPackage(
            string dockerComposeFilePath,
            string registryUserName,
            string registryPassword,
            bool isEncrypted,
            string imageStoreConnectionString)
        {
            var testRootPath = Path.Combine(Path.GetTempPath(), string.Format(CultureInfo.InvariantCulture, "{0}_{1}", Constants.BaseTestRootFolderName, Stopwatch.GetTimestamp()));

            try
            {
                var composeAbsolutePath            = this.GetAbsolutePath(dockerComposeFilePath);
                var fileImageStoreConnectionString =
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "{0}{1}",
                        Constants.ImageStoreConnectionFileType,
                        testRootPath.TrimEnd(Path.DirectorySeparatorChar));

                FabricDirectory.CreateDirectory(testRootPath);
                var sourceImageStore = ImageStoreFactoryProxy.CreateImageStore(fileImageStoreConnectionString);

                IImageStore destinationImageStore = null;
                if (string.IsNullOrEmpty(imageStoreConnectionString))
                {
                    destinationImageStore = sourceImageStore;
                }
                else
                {
                    destinationImageStore = this.CreateImageStore(imageStoreConnectionString, testRootPath);
                }

                var imagebuilder = new ImageBuilder(
                    sourceImageStore,
                    destinationImageStore,
                    this.GetFabricFilePath(Constants.ServiceModelSchemaFileName),
                    testRootPath);

                HashSet <string> ignoredKeys;
                imagebuilder.ValidateComposeDeployment(
                    composeAbsolutePath,
                    null,
                    null,
                    "Compose_",
                    DateTime.Now.Ticks.ToString(),
                    TimeSpan.MaxValue,
                    out ignoredKeys,
                    false);

                if (ignoredKeys.Count > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    sb.Append("The Docker compose file contains the following 'keys' which are not supported. They will be ignored. ");
                    sb.Append(Environment.NewLine);
                    foreach (var key in ignoredKeys)
                    {
                        sb.Append(string.Format("'{0}' ", key));
                    }

                    this.WriteWarning(sb.ToString());
                }

                this.WriteObject(true);
            }
            catch (AggregateException exception)
            {
                exception.Handle((ae) =>
                {
                    this.WriteObject(false);
                    this.ThrowTerminatingError(
                        ae,
                        Constants.TestApplicationPackageErrorId,
                        null);
                    return(true);
                });
            }
            catch (Exception exception)
            {
                this.WriteObject(false);
                this.ThrowTerminatingError(
                    exception,
                    Constants.TestApplicationPackageErrorId,
                    null);
            }
            finally
            {
                FabricDirectory.Delete(testRootPath, true, true);
            }
        }
예제 #18
0
        protected void TestSFApplicationPackage(string applicationPackagePath, Hashtable applicationParameters, string imageStoreConnectionString)
        {
            var testRootPath = Path.Combine(Path.GetTempPath(), string.Format(CultureInfo.InvariantCulture, "{0}_{1}", Constants.BaseTestRootFolderName, Stopwatch.GetTimestamp()));

            try
            {
                var absolutePath            = this.GetAbsolutePath(applicationPackagePath);
                var applicationName         = this.GetPackageName(absolutePath);
                var testRootApplicationPath = Path.Combine(testRootPath, applicationName);
                FabricDirectory.Copy(absolutePath, testRootApplicationPath, true);
                ImageBuilderUtility.RemoveReadOnlyFlag(testRootApplicationPath);

                var fileImageStoreConnectionString =
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "{0}{1}",
                        Constants.ImageStoreConnectionFileType,
                        testRootPath.TrimEnd(Path.DirectorySeparatorChar));
                var sourceImageStore = ImageStoreFactoryProxy.CreateImageStore(fileImageStoreConnectionString);

                IImageStore destinationImageStore = null;
                if (string.IsNullOrEmpty(imageStoreConnectionString))
                {
                    destinationImageStore = sourceImageStore;
                }
                else
                {
                    destinationImageStore = this.CreateImageStore(imageStoreConnectionString, testRootPath);
                }

                var imagebuilder = new ImageBuilder(
                    sourceImageStore,
                    destinationImageStore,
                    this.GetFabricFilePath(Constants.ServiceModelSchemaFileName),
                    testRootPath);

                // Set SFVolumeDiskServiceEnabled to true so that client side validation does the right thing
                // if corresponding UseServiceFabricReplicatedStore attribute is set.
                //
                // We always have a final validation at runtime to catch any issues.
                imagebuilder.IsSFVolumeDiskServiceEnabled = true;

                imagebuilder.ValidateApplicationPackage(
                    applicationName,
                    this.GetDictionary(applicationParameters));

                this.WriteObject(true);
            }
            catch (AggregateException exception)
            {
                exception.Handle((ae) =>
                {
                    this.WriteObject(false);
                    this.ThrowTerminatingError(
                        ae,
                        Constants.TestApplicationPackageErrorId,
                        null);
                    return(true);
                });
            }
            catch (Exception exception)
            {
                this.WriteObject(false);
                this.ThrowTerminatingError(
                    exception,
                    Constants.TestApplicationPackageErrorId,
                    null);
            }
            finally
            {
                FabricDirectory.Delete(testRootPath, true, true);
            }
        }
예제 #19
0
        /// <summary>
        /// End copy delegate that is used to perform post copy completion task.
        /// </summary>
        /// <param name="state">
        /// Instance of CopyArgs that contains the source and destination folders
        /// </param>
        private void EndCopy(object state)
        {
            this.internalCopyAsyncEvent.WaitOne();

            CopyArgs args = state as CopyArgs;
            string   oldDstFolderOriginal = args.Destination + FolderCopy.OldExtension;
            string   oldDstFolderNew      = args.Destination + FolderCopy.OldExtension;

            string newDstFolderNew = args.Destination + FolderCopy.NewExtension;

            string dstFolderOld = args.Destination;
            string dstFolderNew = args.Destination;

            try
            {
                if (!this.skipCopy && (this.copyFlag == CopyFlag.AtomicCopy || this.copyFlag == CopyFlag.AtomicCopySkipIfExists) &&
                    this.failedItems == 0 /* rename only if copying all items is successfull */)
                {
                    for (int i = 1; i <= MaxRetryAttempts; i++)
                    {
                        try
                        {
                            // Step 3, 4 & 5
                            if (oldDstFolderOriginal != null && FabricDirectory.Exists(oldDstFolderOriginal))
                            {
                                FabricDirectory.Delete(oldDstFolderOriginal, recursive: true, deleteReadOnlyFiles: true);
                                oldDstFolderOriginal = null;
                            }

                            if (dstFolderOld != null && FabricDirectory.Exists(dstFolderOld))
                            {
                                this.RenameFolder(dstFolderOld, oldDstFolderNew);
                                dstFolderOld = null;
                            }

                            if (dstFolderNew != null)
                            {
                                this.RenameFolder(newDstFolderNew, dstFolderNew);
                                dstFolderNew = null;
                            }

                            if (oldDstFolderNew != null && FabricDirectory.Exists(oldDstFolderNew))
                            {
                                FabricDirectory.Delete(oldDstFolderNew, recursive: true, deleteReadOnlyFiles: true);
                                oldDstFolderNew = null;
                            }

                            break;
                        }
                        catch (Exception ex)
                        {
                            this.traceSource.WriteError(
                                ClassName,
                                "EndCopy exception: destination {0}, current object {1} exception {2}\r\n",
                                args.Destination,
                                oldDstFolderOriginal ?? dstFolderOld ?? dstFolderNew ?? oldDstFolderNew ?? "(null)",
                                ex);

                            if (ExceptionHandler.IsFatalException(ex))
                            {
                                throw;
                            }

                            if (i >= MaxRetryAttempts)
                            {
                                Interlocked.Increment(ref this.failedItems);
                            }
                            else
                            {
                                Thread.Sleep(500);
                            }
                        }
                    }
                }
            }
            finally
            {
                if (newDstFolderNew != null && FabricDirectory.Exists(newDstFolderNew))
                {
                    FabricDirectory.Delete(newDstFolderNew, recursive: true, deleteReadOnlyFiles: true);
                }
            }

            // Signal completion of copy task.
            this.asyncEvent.Set();
        }
예제 #20
0
        public void DeploymentManagerTest_ProductionGoalState()
        {
            Console.WriteLine("test begins: {0}", DateTime.UtcNow);

            string goalStateFilepath = Path.Combine(BaseDir, GoalStateFilename);

            Assert.IsTrue(File.Exists(goalStateFilepath), string.Format("GoalStateFile {0} did not exist.", goalStateFilepath));
            string         goalStateJson = File.ReadAllText(goalStateFilepath);
            GoalStateModel model         = GoalStateModel.GetGoalStateModelFromJson(goalStateJson);

            Assert.IsTrue(model != null, "Goal state JSON could not be deserialized.");
            Assert.IsTrue(model.Packages != null, "Goal state model must have a packages element.");

            if (model.Packages.Count() == 0)
            {
                return;
            }

            // There can only be one goal package
            int countGoalpackages = model.Packages.Where(package => package.IsGoalPackage).Count();

            Assert.IsTrue(countGoalpackages == 1, "Exactly one goal package may be marked as IsGoalPackage in the goal state file.");

            // Validate each package link is reachable
            string errorMessage = string.Empty;

            foreach (PackageDetails package in model.Packages)
            {
                Uri packageUri;
                if (!Uri.TryCreate(package.TargetPackageLocation, UriKind.Absolute, out packageUri))
                {
                    errorMessage = string.Format("Cannot parse packageUri: {0}", package.TargetPackageLocation);
                    Assert.Fail(errorMessage);
                }

                if (!StandaloneUtility.IsUriReachable(packageUri))
                {
                    errorMessage = string.Format("Package uri is not reachable: {0}", packageUri.AbsoluteUri);
                }
            }

            if (!string.IsNullOrEmpty(errorMessage))
            {
                Assert.Fail(errorMessage);
            }

            // Validate that goal state downloaded package is the correct version
            string         packageDropDir = System.Fabric.Common.Helpers.GetNewTempPath();
            PackageDetails goalPackage    = model.Packages.First(package => package.IsGoalPackage);

            Assert.IsTrue(goalPackage != null, "goalPackage null");

            // Validate package downloadable
            Console.WriteLine("download begins for {0}: {1}", goalPackage.Version, DateTime.UtcNow);
            string packageLocalDownloadPath = Path.Combine(packageDropDir, string.Format(Microsoft.ServiceFabric.DeploymentManager.Constants.SFPackageDropNameFormat, goalPackage.Version));
            bool   packageDownloaded        = StandaloneUtility.DownloadPackageAsync(goalPackage.Version, goalPackage.TargetPackageLocation, packageLocalDownloadPath).Result;

            Assert.IsTrue(packageDownloaded, string.Format("Package {0} failed to download from {1}.", goalPackage.Version, goalPackage.TargetPackageLocation));

            // Validate downloaded package matches version of version in goal state file
            string cabVersion = CabFileOperations.GetCabVersion(packageLocalDownloadPath);

            Assert.IsTrue(goalPackage.Version == cabVersion, string.Format("Goal state package version {0} doesn't match downloaded package version {1}.", goalPackage.Version, cabVersion));

            if (Directory.Exists(packageDropDir))
            {
                try
                {
                    FabricDirectory.Delete(packageDropDir, true, true);
                }
                catch { }
            }

            Console.WriteLine("test ends: {0}", DateTime.UtcNow);
        }
예제 #21
0
        private async Task PollGoalStateForCodePackagesAsync(CancellationToken cancellationToken)
        {
            var fabricClient = new FabricClient();

            //// region: Initialization Parameters

            FabricUpgradeProgress upgradeProgress;

            try
            {
                upgradeProgress = await FabricClientRetryHelper.ExecuteFabricActionWithRetryAsync <FabricUpgradeProgress>(
                    () =>
                    fabricClient.ClusterManager.GetFabricUpgradeProgressAsync(TimeSpan.FromMinutes(DMConstants.FabricOperationTimeoutInMinutes), cancellationToken),
                    TimeSpan.FromMinutes(DMConstants.FabricOperationTimeoutInMinutes),
                    cancellationToken).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                this.traceSource.WriteError(TraceType, "GetFabricUpgradeProgressAsync threw: {0}", ex.ToString());
                this.timerInterval = TimeSpan.FromMinutes(DMConstants.FabricUpgradeStatePollIntervalInMinutes);
                return;
            }

            if (!FabricClientWrapper.IsUpgradeCompleted(upgradeProgress.UpgradeState))
            {
                this.timerInterval = TimeSpan.FromMinutes(DMConstants.FabricUpgradeStatePollIntervalInMinutes);
                this.traceSource.WriteInfo(TraceType, "Cannot retrieve cluster version; FabricUpgradeState is currently: {0}. Will retry in {1}.", upgradeProgress.UpgradeState.ToString(), this.timerInterval.ToString());
                return;
            }

            string            currentVersionStr = upgradeProgress.TargetCodeVersion;
            Version           currentVersion    = Version.Parse(currentVersionStr);
            string            packageDropDir    = System.Fabric.Common.Helpers.GetNewTempPath();
            NativeConfigStore configStore       = NativeConfigStore.FabricGetConfigStore();
            string            goalStateUriStr   = configStore.ReadUnencryptedString(DMConstants.UpgradeOrchestrationServiceConfigSectionName, DMConstants.GoalStateFileUrlName);

            if (string.IsNullOrEmpty(goalStateUriStr))
            {
                goalStateUriStr = DMConstants.DefaultGoalStateFileUrl;
            }

            //// endregion

            this.traceSource.WriteInfo(TraceType, "PollCodePackagesFromGoalState currentVersion: {0}, packageDropDir: {1} goalStateUri: {2}", currentVersionStr, packageDropDir, goalStateUriStr);
            try
            {
                Uri    goalStateUri  = null;
                string goalStateJson = null;
                if (!Uri.TryCreate(goalStateUriStr, UriKind.Absolute, out goalStateUri))
                {
                    string errorMessage = string.Format("Cannot parse GoalStateUri: {0}", goalStateUriStr);
                    this.traceSource.WriteError(TraceType, errorMessage);
                    ReleaseAssert.Fail(errorMessage);
                    return;
                }

                if (!(await StandaloneUtility.IsUriReachableAsync(goalStateUri).ConfigureAwait(false)))
                {
                    this.timerInterval = TimeSpan.FromMinutes(DMConstants.FabricGoalStateReachablePollIntervalInMinutes);
                    this.traceSource.WriteWarning(TraceType, "Cannot reach download uri for goal state file: {0}. Will retry in {1}.", goalStateUri.AbsoluteUri, this.timerInterval.ToString());
                    this.EmitGoalStateReachableHealth(fabricClient, false);
                    return;
                }
                else
                {
                    this.EmitGoalStateReachableHealth(fabricClient, true);
                }

                goalStateJson = await GoalStateModel.GetGoalStateFileJsonAsync(goalStateUri).ConfigureAwait(false);

                if (string.IsNullOrEmpty(goalStateJson))
                {
                    this.traceSource.WriteWarning(TraceType, "Loaded goal state JSON is empty.");
                    return;
                }

                GoalStateModel model = GoalStateModel.GetGoalStateModelFromJson(goalStateJson);
                if (model == null || model.Packages == null)
                {
                    this.traceSource.WriteWarning(TraceType, "Goal state JSON could not be deserialized:\n{0}", goalStateJson);
                    return;
                }

                string availableGoalStateVersions = string.Format("Available versions in goal state file: {0}", model.ToString());
                this.traceSource.WriteInfo(TraceType, availableGoalStateVersions);

                IEnumerable <PackageDetails> candidatePackages = model.Packages.Where(
                    package => currentVersion < Version.Parse(package.Version));

                if (candidatePackages.Count() == 0)
                {
                    this.traceSource.WriteInfo(TraceType, "No upgrades available.");
                }

                string         versionCurrentStr = currentVersionStr;
                Version        versionCurrent    = currentVersion;
                PackageDetails targetPackage     = null;
                for (IEnumerable <PackageDetails> availableCandidatePackages = candidatePackages.Where(
                         package => (package.MinVersion == null || Version.Parse(package.MinVersion) <= versionCurrent));
                     availableCandidatePackages.Count() > 0;
                     versionCurrentStr = targetPackage.Version,
                     versionCurrent = Version.Parse(versionCurrentStr),
                     availableCandidatePackages = candidatePackages.Where(
                         package => (versionCurrent < Version.Parse(package.Version) &&
                                     (package.MinVersion == null || Version.Parse(package.MinVersion) <= versionCurrent))))
                {
                    if (!IsVersionUpgradeable(versionCurrentStr, model))
                    {
                        this.traceSource.WriteInfo(TraceType, "Version {0} is not upgradeable.", versionCurrentStr);
                        break;
                    }

                    int numPackages = availableCandidatePackages.Count();
                    if (numPackages == 0)
                    {
                        this.traceSource.WriteInfo(TraceType, "No upgrade available.");
                        return;
                    }
                    else if (numPackages == 1)
                    {
                        targetPackage = availableCandidatePackages.First();
                    }
                    else
                    {
                        Version maxVersion = StandaloneGoalStateProvisioner.ZeroVersion;
                        foreach (PackageDetails package in availableCandidatePackages)
                        {
                            Version targetVersion;
                            if (!Version.TryParse(package.Version, out targetVersion))
                            {
                                this.traceSource.WriteWarning(TraceType, "Package {0} version could not be parsed. Trying another one.", package.Version);
                                continue;
                            }

                            if (targetVersion > maxVersion)
                            {
                                targetPackage = package;
                                maxVersion    = targetVersion;
                            }
                        }
                    }

                    try
                    {
                        if (await this.IsPackageProvisionedAsync(targetPackage.Version, fabricClient, cancellationToken).ConfigureAwait(false))
                        {
                            this.traceSource.WriteInfo(TraceType, "Package {0} is already provisioned.", targetPackage.Version);
                            continue;
                        }
                    }
                    catch (Exception ex)
                    {
                        this.traceSource.WriteError(TraceType, "PackageIsProvisioned for {0} threw: {1}", targetPackage.Version, ex.ToString());
                    }

                    string packageLocalDownloadPath = Path.Combine(packageDropDir, string.Format(DMConstants.SFPackageDropNameFormat, targetPackage.Version));
                    if (await StandaloneUtility.DownloadPackageAsync(targetPackage.Version, targetPackage.TargetPackageLocation, packageLocalDownloadPath).ConfigureAwait(false))
                    {
                        try
                        {
                            this.traceSource.WriteInfo(TraceType, "Copying and provisioning version {0} from {1}.", targetPackage.Version, packageLocalDownloadPath);
                            await ProvisionPackageAsync(targetPackage.Version, packageLocalDownloadPath, cancellationToken).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            this.traceSource.WriteError(TraceType, "ProvisionPackageAsync for {0}, package {1} threw: {2}", targetPackage.Version, packageLocalDownloadPath, ex.ToString());
                        }
                    }
                }

                // Determine if current version is latest/doesn't have expiry date. If package expiring, post cluster health warning.
                PackageDetails currentPackage = model.Packages.Where(package => package.Version == currentVersionStr).FirstOrDefault();
                if (currentPackage != null && currentPackage.SupportExpiryDate != null && !currentPackage.IsGoalPackage && !this.IsAutoupgradeInstallEnabled() && this.IsPackageNearExpiry(currentPackage))
                {
                    this.traceSource.WriteWarning(TraceType, "Current version {0} expires {1}; emitting cluster warning.", currentVersionStr, currentPackage.SupportExpiryDate);
                    this.EmitClusterVersionSupportedHealth(fabricClient, false, currentVersionStr, currentPackage.SupportExpiryDate);
                }
                else
                {
                    this.traceSource.WriteInfo(TraceType, "Current version {0} is supported. Cluster health OK.", currentVersionStr);
                    this.EmitClusterVersionSupportedHealth(fabricClient, true, null, null);
                }

                if (targetPackage != null &&
                    !string.IsNullOrEmpty(targetPackage.Version) &&
                    this.IsAutoupgradeInstallEnabled())
                {
                    try
                    {
                        // fire off an upgrade.
                        this.StartCodeUpgrade(targetPackage.Version, fabricClient);
                    }
                    catch (Exception ex)
                    {
                        this.traceSource.WriteError(TraceType, "StartCodeUpgrade for version {0} threw: {1}", targetPackage.Version, ex.ToString());
                    }
                }
            }
            finally
            {
                if (Directory.Exists(packageDropDir))
                {
                    try
                    {
                        FabricDirectory.Delete(packageDropDir, true, true);
                    }
                    catch
                    {
                    }
                }
            }
        }
예제 #22
0
        private void CopyFileToDestinationBlobWorker(FileCopyInfo fileCopyInfo, CloudBlockBlob destinationBlob)
        {
            // First let's try to copy directly from the source location. This should work fine if the
            // source file is not in use.
            bool exceptionWithDirectCopy = false;

            try
            {
                CreateStreamAndUploadToBlob(fileCopyInfo.SourceFullPath, destinationBlob);
                this.TraceSource.WriteInfo(
                    this.LogSourceId,
                    "Uploaded file {0} to destination blob {1}",
                    fileCopyInfo.SourceFullPath,
                    destinationBlob.Name);
            }
            catch (Exception e)
            {
                if ((false == (e is IOException)) && (false == (e is FabricException)))
                {
                    throw;
                }

                exceptionWithDirectCopy = true;
            }

            if (exceptionWithDirectCopy)
            {
                // We couldn't copy the file directly to blob. This can happen when the file is in use,
                // because we would be unable to open a handle to the file in that case. Therefore,
                // we make a copy of the file to a temp location and then open a handle to that temp
                // copy for uploading to blob.
                string tempDir  = Utility.GetTempDirName();
                string tempDest = Path.Combine(tempDir, fileCopyInfo.SourceFileName);
                FabricDirectory.CreateDirectory(tempDir);
                try
                {
                    FabricFile.Copy(fileCopyInfo.SourceFullPath, tempDest, true);
                    CreateStreamAndUploadToBlob(tempDest, destinationBlob);
                    this.TraceSource.WriteInfo(
                        this.LogSourceId,
                        "Uploaded file {0} to destination blob {1}",
                        fileCopyInfo.SourceFullPath,
                        destinationBlob.Name);
                }
                finally
                {
                    try
                    {
                        Utility.PerformIOWithRetries(
                            () =>
                        {
                            FabricDirectory.Delete(tempDir, true);
                        });
                    }
                    catch (Exception e)
                    {
                        this.TraceSource.WriteExceptionAsError(
                            this.LogSourceId,
                            e,
                            "Failed to delete temporary directory {0}.",
                            tempDir);
                    }
                }
            }
        }
예제 #23
0
        /// <summary>
        /// Downloads content from the file image store to local destination.
        /// </summary>
        /// <param name="storeSource">The relative path of source file image store to be downloaded from.</param>
        /// <param name="localDestination">The local destination path to download the content.</param>
        /// <param name="handler">The image store progress handler which is not supported at the file image store.</param>
        /// <param name="timeout">The timeout for performing the downloading operation.</param>
        /// <param name="copyFlag">The copying control information to specify how file can be overwritten.</param>
        public void DownloadContent(string storeSource, string localDestination, IImageStoreProgressHandler handler, TimeSpan timeout, CopyFlag copyFlag)
        {
            TimeoutHelper helper = timeout == TimeSpan.MaxValue ? null : new TimeoutHelper(timeout);

            localDestination = this.GetLocalPath(localDestination);
            string         tempDirectory = null;
            FileReaderLock readerLock    = null;

            try
            {
                string smbTag = this.ConvertTagToSMBPath(storeSource);
                if ((!FabricFile.Exists(smbTag)) &&
                    (!FabricDirectory.Exists(smbTag)))
                {
                    throw new IOException(string.Format(CultureInfo.CurrentCulture, StringResources.ImageStoreError_DoesNotExistError, smbTag));
                }

                readerLock = new FileReaderLock(smbTag);
                if (!readerLock.Acquire())
                {
                    throw new FabricTransientException(StringResources.Error_ImageStoreAcquireFileLockFailed, FabricErrorCode.ImageStoreAcquireFileLockFailed);
                }

                if (helper != null)
                {
                    helper.ThrowIfExpired();
                }

                if (accessDescription != null && !accessDescription.HasWriteAccess)
                {
                    // Copy the content from the remote Store to a temp location using the ImpersonationContext
                    string tempLocalResource = null;
#if !DotNetCoreClr
                    using (WindowsImpersonationContext impersonationContext = accessDescription.WindowsIdentity.Impersonate())
#endif
                    {
                        tempDirectory     = CreateAndAclDirectory();
                        tempLocalResource = Path.Combine(tempDirectory, Path.GetRandomFileName());
                        CopyCallerHoldsReaderLock(smbTag, tempLocalResource, CopyFlag.AtomicCopy, helper);
                    }

                    readerLock.Release();

                    // Copy the content from the temp location to the local destination outside the ImpersonationContext
                    CopyCallerHoldsReaderLock(tempLocalResource, localDestination, copyFlag, helper);
                }

#if !DotNetCoreClr
                using (WindowsImpersonationContext impersonationContext = this.GetImpersonationContext())
#endif
                {
                    CopyCallerHoldsReaderLock(smbTag, localDestination, copyFlag, helper);
                }
            }
            catch (IOException exception)
            {
                if (exception.GetType() == typeof(IOException))
                {
                    throw new FabricImageStoreException(StringResources.Error_ImageStoreIOException, exception);
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                if (readerLock != null)
                {
                    readerLock.Dispose();
                }

                if (tempDirectory != null && FabricDirectory.Exists(tempDirectory))
                {
                    FabricDirectory.Delete(tempDirectory, recursive: true, deleteReadOnlyFiles: true);
                }
            }
        }
예제 #24
0
        /// <summary>
        /// Remove tag from store and clear the data associated with tag.
        /// </summary>
        /// <param name="tag">Location (relative to RootUri) from where to delete the content.</param>
        /// <param name="timeout">The timeout for performing the delete operation.</param>
        public void DeleteContent(string tag, TimeSpan timeout)
        {
            TimeoutHelper helper = (timeout == TimeSpan.MaxValue) ? null : new TimeoutHelper(timeout);

#if !DotNetCoreClr
            using (WindowsImpersonationContext impersonationContext = this.GetImpersonationContext())
#endif
            {
                try
                {
                    string smbTag = this.ConvertTagToSMBPath(tag);
                    if ((!FabricFile.Exists(smbTag)) &&
                        (!FabricDirectory.Exists(smbTag)))
                    {
                        return;
                    }

                    using (FileWriterLock fileWriterLock = new FileWriterLock(smbTag))
                    {
                        if (!fileWriterLock.Acquire())
                        {
                            throw new FabricTransientException(StringResources.Error_ImageStoreAcquireFileLockFailed, FabricErrorCode.ImageStoreAcquireFileLockFailed);
                        }

                        if (helper != null)
                        {
                            helper.ThrowIfExpired();
                        }

                        if (FabricFile.Exists(smbTag))
                        {
                            FabricFile.Delete(smbTag, deleteReadonly: true);
                        }
                        else if (FabricDirectory.Exists(smbTag))
                        {
                            FabricDirectory.Delete(smbTag, recursive: true, deleteReadOnlyFiles: true);
                        }
                    }
                }
                catch (IOException exception)
                {
                    // HResult 0x80070020: THE PROCESS CANNOT ACCESS THE FILE BECAUSE IT IS BEING USED BY ANOTHER PROCESS
                    // This work-around is done here since when we read a file from a folder we only take a reader lock on the file and not the
                    // entire folder. When we delete a folder, we only take writer lock on the folder and hence we might run into scenarios
                    // where a folder is attempted to be deleted even when a file in it is being read.
                    // Returning FabricImageStoreException, causes CM to retry the delete operation.
                    int hrError = Marshal.GetHRForException(exception);
                    TraceSource.WriteWarning(
                        TraceType,
                        "Delete of {0} failed because of {1}, hrError {2:X}.",
                        tag,
                        exception.Message,
                        hrError);

                    if (hrError == unchecked ((int)0x80070020))
                    {
                        throw new FabricTransientException(StringResources.Error_ImageStoreAcquireFileLockFailed, exception, FabricErrorCode.ImageStoreAcquireFileLockFailed);
                    }

                    throw;
                }
            }
        }