/// <summary> /// Cleans up the application. /// </summary> /// <param name="applicationPath">The path.</param> public void CleanupApplication(string applicationPath) { // Remove the uhurufs servers from the system host file. var services = this.parsedData.GetServices(); foreach (ApplicationService serv in services) { if (serv.ServiceLabel.StartsWith("uhurufs", StringComparison.Ordinal)) { string shareHost = GenerateUhurufsHost(this.parsedData.AppInfo.InstanceId, serv.InstanceName, serv.User); string remotePath = string.Format(CultureInfo.InvariantCulture, @"\\{0}\{1}", shareHost, serv.InstanceName); SambaWindowsClient.Unmount(remotePath); SystemHosts.TryRemove(shareHost); } } Cleanup(applicationPath); }
/// <summary> /// Persists a resource on a mounted share, and then links it. /// This method will make sure the folder and file structure remains the same on the local file system, while also persisting data on a share. /// </summary> /// <param name="instancePath">The directory considered to be the "root" of the resources that have to be persisted.</param> /// <param name="persistentItem">The directory or file that has to be persisted.</param> /// <param name="mountPath">The mounted directory that points to a share.</param> private void PersistFileSystemItem(string instancePath, string persistentItem, string mountPath) { if (string.IsNullOrEmpty(instancePath)) { throw new ArgumentNullException("instancePath"); } if (string.IsNullOrEmpty(persistentItem)) { throw new ArgumentNullException("instancePath"); } if (string.IsNullOrEmpty(mountPath)) { throw new ArgumentNullException("instancePath"); } string mountItem = Path.Combine(mountPath, persistentItem); string instanceItem = Path.Combine(instancePath, persistentItem); bool isDirectory, isFile; using (new UserImpersonator(this.parsedData.AppInfo.WindowsUserName, ".", this.parsedData.AppInfo.WindowsPassword, true)) { isDirectory = Directory.Exists(mountItem) || Directory.Exists(instanceItem); if (isDirectory) { Directory.CreateDirectory(mountItem); Directory.CreateDirectory(instanceItem); CopyFolderRecursively(instanceItem, mountItem); try { Directory.Delete(instanceItem, true); } catch (DirectoryNotFoundException) { } } } if (isDirectory) { // Creating links without an admin user is not allowed by default // ExecuteCommand("mklink" + " /d " + instanceItem + " " + mountItem); SambaWindowsClient.CreateDirectorySymbolicLink(instanceItem, mountItem); } using (new UserImpersonator(this.parsedData.AppInfo.WindowsUserName, ".", this.parsedData.AppInfo.WindowsPassword, true)) { isFile = File.Exists(mountItem) || File.Exists(instanceItem); if (isFile) { Directory.CreateDirectory(new DirectoryInfo(mountItem).Parent.FullName); Directory.CreateDirectory(new DirectoryInfo(instanceItem).Parent.FullName); try { File.Copy(instanceItem, mountItem); } catch (IOException) { } try { File.Delete(instanceItem); } catch (DirectoryNotFoundException) { } } } if (isFile) { // Creating links without an admin user is not allowed by default // ExecuteCommand("mklink" + " " + instanceItem + " " + mountItem); SambaWindowsClient.CreateFileSymbolicLink(instanceItem, mountItem); } }
private void AutowireUhurufs(ApplicationInfo appInfo, ApplicationVariable[] variables, ApplicationService[] services, string homeAppPath) { this.startupLogger.Info(Strings.StartingApplicationAutoWiring); Dictionary <string, HashSet <string> > persistentFiles = new Dictionary <string, HashSet <string> >(); foreach (ApplicationVariable var in variables) { if (var.Name.StartsWith("uhurufs_", StringComparison.Ordinal)) { string serviceName = var.Name.Split(new string[] { "uhurufs_" }, 2, StringSplitOptions.RemoveEmptyEntries)[0]; if (!persistentFiles.ContainsKey(serviceName)) { persistentFiles[serviceName] = new HashSet <string>(); } string[] persistedItems = var.Value.Trim(new char[] { '"' }).Split(new char[] { ';', ',', ':' }); foreach (string item in persistedItems) { persistentFiles[serviceName].Add(item.Replace('/', '\\')); } } } foreach (ApplicationService serv in services) { if (serv.ServiceLabel.StartsWith("uhurufs", StringComparison.Ordinal)) { string shareHost = GenerateUhurufsHost(appInfo.InstanceId, serv.InstanceName, serv.User); try { if (!SystemHosts.Exists(shareHost)) { // Note: delete the host after the app is deleted SystemHosts.Add(shareHost, serv.Host); } } catch (ArgumentException) { // If the service host cannot be added to hosts connect shareHost = serv.Host; } string remotePath = string.Format(CultureInfo.InvariantCulture, @"\\{0}\{1}", shareHost, serv.InstanceName); string mountPath = GenerateMountPath(homeAppPath, serv.Name); Directory.CreateDirectory(Path.Combine(mountPath, @"..")); // Add the share users credentials to the application user. // This way the application can use the share directly without invoking `net use` with the credentials. using (new UserImpersonator(appInfo.WindowsUserName, ".", appInfo.WindowsPassword, true)) { SaveCredentials.AddDomainUserCredential(shareHost, serv.User, serv.Password); } // The impersonated user cannot create links // Note: unmount the share after the app is deleted SambaWindowsClient.Mount(remotePath, serv.User, serv.Password); SambaWindowsClient.LinkDirectory(remotePath, mountPath); if (persistentFiles.ContainsKey(serv.Name)) { foreach (string fileSystemItem in persistentFiles[serv.Name]) { try { this.PersistFileSystemItem(appInfo.Path, fileSystemItem, Path.Combine(mountPath, appInfo.Name)); } catch (Exception ex) { this.startupLogger.Error("Failed linking file/directory: {0}. Exception: {1}", fileSystemItem, ex.ToString()); } } } } } }