private void DoPrepareDeploymentToClusteredEnvironment(EnvironmentInfo environmentInfo, Lazy <string> artifactsBinariesDirPathProvider) { string clusterGroupName = environmentInfo.GetFailoverClusterGroupNameForProject(DeploymentInfo.ProjectName); if (string.IsNullOrEmpty(clusterGroupName)) { throw new InvalidOperationException(string.Format("There is no cluster group defined for project '{0}' in environment '{1}'.", DeploymentInfo.ProjectName, environmentInfo.Name)); } string failoverClusterMachineName = environmentInfo.FailoverClusterMachineName; if (string.IsNullOrEmpty(failoverClusterMachineName)) { throw new InvalidOperationException(string.Format("Environment '{0}' has no failover cluster machine name defined.", environmentInfo.Name)); } string currentNodeName = _failoverClusterManager.GetCurrentNodeName(failoverClusterMachineName, clusterGroupName); if (string.IsNullOrEmpty(currentNodeName)) { throw new InvalidOperationException(string.Format("Cluster group '{0}' has no current node in a cluster '{1}' in environment '{2}'.", clusterGroupName, environmentInfo.FailoverClusterMachineName, environmentInfo.Name)); } PostDiagnosticMessage(string.Format("Current node: '{0}'.", currentNodeName), DiagnosticMessageType.Trace); List <string> possibleNodeNames = _failoverClusterManager.GetPossibleNodeNames(failoverClusterMachineName, clusterGroupName) .ToList(); PostDiagnosticMessage(string.Format("Possible nodes: {0}.", string.Join(", ", possibleNodeNames.Select(n => string.Format("'{0}'", n)))), DiagnosticMessageType.Trace); if (possibleNodeNames.Count < 2) { throw new InvalidOperationException(string.Format("There is only one possible node for cluster group '{0}' in a cluster '{1}' in environment '{2}'.", clusterGroupName, environmentInfo.FailoverClusterMachineName, environmentInfo.Name)); } // update nt service on all machines other than current owner node CollectedCredentials cachedCollectedCredentials = null; Func <string, Func <CollectedCredentials> > collectCredentialsFunc = machineName => () => { // ReSharper disable AccessToModifiedClosure if (cachedCollectedCredentials != null) { return(cachedCollectedCredentials); } // ReSharper restore AccessToModifiedClosure if (UseLocalSystemUser) { cachedCollectedCredentials = new CollectedCredentials(LocalSystemUserName); } else { EnvironmentUser environmentUser = environmentInfo.GetEnvironmentUser(_projectInfo.NtServiceUserId); string environmentUserPassword = PasswordCollectorHelper.CollectPasssword( _passwordCollector, DeploymentInfo.DeploymentId, environmentInfo, machineName, environmentUser, OnDiagnosticMessagePosted); cachedCollectedCredentials = new CollectedCredentials( environmentUser.UserName, environmentUserPassword); } return(cachedCollectedCredentials); }; foreach (string possibleNodeName in possibleNodeNames) { string machineName = possibleNodeName; if (string.Equals(machineName, currentNodeName, StringComparison.OrdinalIgnoreCase)) { continue; } DoPrepareCommonDeploymentSteps( _projectInfo.NtServiceName, machineName, environmentInfo.NtServicesBaseDirPath, absoluteLocalPath => EnvironmentInfo.GetNetworkPath(machineName, absoluteLocalPath), artifactsBinariesDirPathProvider, collectCredentialsFunc(machineName), false); } // move cluster group to another node string targetNodeName = possibleNodeNames.FirstOrDefault(nodeName => nodeName != currentNodeName); PostDiagnosticMessage(string.Format("Target node: '{0}'.", targetNodeName), DiagnosticMessageType.Trace); if (string.IsNullOrEmpty(targetNodeName)) { throw new InvalidOperationException(string.Format("There is no node in cluster '{0}' that we can move cluster group '{1}' to.", failoverClusterMachineName, clusterGroupName)); } AddSubTask( new MoveClusterGroupToAnotherNodeDeploymentStep( _failoverClusterManager, failoverClusterMachineName, clusterGroupName, targetNodeName)); // update nt service on the machine that was the previous owner node string previousMachineName = currentNodeName; DoPrepareCommonDeploymentSteps( _projectInfo.NtServiceName, previousMachineName, environmentInfo.NtServicesBaseDirPath, absoluteLocalPath => EnvironmentInfo.GetNetworkPath(previousMachineName, absoluteLocalPath), artifactsBinariesDirPathProvider, collectCredentialsFunc(previousMachineName), false); }
private void DoPrepareCommonDeploymentSteps(string ntServiceName, string appServerMachineName, string ntServicesBaseDirPath, Func <string, string> getAppServerNetworkPathFunc, Lazy <string> artifactsBinariesDirPathProvider, Func <CollectedCredentials> collectCredentialsFunc, bool startServiceAfterDeployment) { // check if the service is present on the target machine bool serviceExists = _ntServiceManager .DoesServiceExist(appServerMachineName, ntServiceName); if (serviceExists) { // create a step for stopping the service AddSubTask( new StopNtServiceDeploymentStep( _ntServiceManager, appServerMachineName, _projectInfo.NtServiceName)); } // create a step for copying the binaries to the target machine string targetDirPath = Path.Combine(ntServicesBaseDirPath, _projectInfo.NtServiceDirName); /* // TODO IMM HI: xxx we don't need this for now - should we parameterize this somehow? * // create a backup step if needed * string targetDirNetworkPath = getAppServerNetworkPathFunc(targetDirPath); * * if (Directory.Exists(targetDirNetworkPath)) * { * AddSubTask( * new BackupFilesDeploymentStep( * targetDirNetworkPath)); * } */ string[] excludedDirs = string.IsNullOrEmpty(_projectInfo.ExtensionsDirName) ? new string[0] : new string[] { _projectInfo.ExtensionsDirName }; AddSubTask( new CleanDirectoryDeploymentStep( _directoryAdapter, _fileAdapter, new Lazy <string>(() => getAppServerNetworkPathFunc(targetDirPath)), excludedDirs: excludedDirs)); AddSubTask( new CopyFilesDeploymentStep( _directoryAdapter, artifactsBinariesDirPathProvider, new Lazy <string>(() => getAppServerNetworkPathFunc(targetDirPath)))); if (!serviceExists) { // collect credentials CollectedCredentials collectedCredentials = collectCredentialsFunc(); // create a step for installing the service, string serviceExecutablePath = Path.Combine(targetDirPath, _projectInfo.NtServiceExeName); var ntServiceDescriptor = new NtServiceDescriptor( _projectInfo.NtServiceName, serviceExecutablePath, ServiceAccount.NetworkService, ServiceStartMode.Automatic, _projectInfo.NtServiceDisplayName, collectedCredentials.UserName, collectedCredentials.Password); AddSubTask( new InstallNtServiceDeploymentStep( _ntServiceManager, appServerMachineName, ntServiceDescriptor)); } if (startServiceAfterDeployment) { // create a step for starting the service AddSubTask( new StartNtServiceDeploymentStep( _ntServiceManager, appServerMachineName, _projectInfo.NtServiceName)); } }
private void DoPrepareDeploymentToClusteredEnvironment(EnvironmentInfo environmentInfo, Lazy<string> artifactsBinariesDirPathProvider) { string clusterGroupName = environmentInfo.GetFailoverClusterGroupNameForProject(DeploymentInfo.ProjectName); if (string.IsNullOrEmpty(clusterGroupName)) { throw new InvalidOperationException(string.Format("There is no cluster group defined for project '{0}' in environment '{1}'.", DeploymentInfo.ProjectName, environmentInfo.Name)); } string failoverClusterMachineName = environmentInfo.FailoverClusterMachineName; if (string.IsNullOrEmpty(failoverClusterMachineName)) { throw new InvalidOperationException(string.Format("Environment '{0}' has no failover cluster machine name defined.", environmentInfo.Name)); } string currentNodeName = _failoverClusterManager.GetCurrentNodeName(failoverClusterMachineName, clusterGroupName); if (string.IsNullOrEmpty(currentNodeName)) { throw new InvalidOperationException(string.Format("Cluster group '{0}' has no current node in a cluster '{1}' in environment '{2}'.", clusterGroupName, environmentInfo.FailoverClusterMachineName, environmentInfo.Name)); } PostDiagnosticMessage(string.Format("Current node: '{0}'.", currentNodeName), DiagnosticMessageType.Trace); List<string> possibleNodeNames = _failoverClusterManager.GetPossibleNodeNames(failoverClusterMachineName, clusterGroupName) .ToList(); PostDiagnosticMessage(string.Format("Possible nodes: {0}.", string.Join(", ", possibleNodeNames.Select(n => string.Format("'{0}'", n)))), DiagnosticMessageType.Trace); if (possibleNodeNames.Count < 2) { throw new InvalidOperationException(string.Format("There is only one possible node for cluster group '{0}' in a cluster '{1}' in environment '{2}'.", clusterGroupName, environmentInfo.FailoverClusterMachineName, environmentInfo.Name)); } // update nt service on all machines other than current owner node CollectedCredentials cachedCollectedCredentials = null; Func<string, Func<CollectedCredentials>> collectCredentialsFunc = machineName => () => { // ReSharper disable AccessToModifiedClosure if (cachedCollectedCredentials != null) { return cachedCollectedCredentials; } // ReSharper restore AccessToModifiedClosure if (UseLocalSystemUser) { cachedCollectedCredentials = new CollectedCredentials(LocalSystemUserName); } else { EnvironmentUser environmentUser = environmentInfo.GetEnvironmentUser(_projectInfo.NtServiceUserId); string environmentUserPassword = PasswordCollectorHelper.CollectPasssword( _passwordCollector, DeploymentInfo.DeploymentId, environmentInfo, machineName, environmentUser, OnDiagnosticMessagePosted); cachedCollectedCredentials = new CollectedCredentials( environmentUser.UserName, environmentUserPassword); } return cachedCollectedCredentials; }; foreach (string possibleNodeName in possibleNodeNames) { string machineName = possibleNodeName; if (string.Equals(machineName, currentNodeName, StringComparison.OrdinalIgnoreCase)) { continue; } DoPrepareCommonDeploymentSteps( _projectInfo.NtServiceName, machineName, environmentInfo.NtServicesBaseDirPath, absoluteLocalPath => EnvironmentInfo.GetNetworkPath(machineName, absoluteLocalPath), artifactsBinariesDirPathProvider, collectCredentialsFunc(machineName), false); } // move cluster group to another node string targetNodeName = possibleNodeNames.FirstOrDefault(nodeName => nodeName != currentNodeName); PostDiagnosticMessage(string.Format("Target node: '{0}'.", targetNodeName), DiagnosticMessageType.Trace); if (string.IsNullOrEmpty(targetNodeName)) { throw new InvalidOperationException(string.Format("There is no node in cluster '{0}' that we can move cluster group '{1}' to.", failoverClusterMachineName, clusterGroupName)); } AddSubTask( new MoveClusterGroupToAnotherNodeDeploymentStep( _failoverClusterManager, failoverClusterMachineName, clusterGroupName, targetNodeName)); // update nt service on the machine that was the previous owner node string previousMachineName = currentNodeName; DoPrepareCommonDeploymentSteps( _projectInfo.NtServiceName, previousMachineName, environmentInfo.NtServicesBaseDirPath, absoluteLocalPath => EnvironmentInfo.GetNetworkPath(previousMachineName, absoluteLocalPath), artifactsBinariesDirPathProvider, collectCredentialsFunc(previousMachineName), false); }