private void DoPrepareDeploymentToStandardEnvironment(EnvironmentInfo environmentInfo, Lazy<string> artifactsBinariesDirPathProvider)
        {
            Func<CollectedCredentials> collectCredentialsFunc =
            () =>
            {
              if (UseLocalSystemUser)
              {
            return new CollectedCredentials(LocalSystemUserName);
              }

              EnvironmentUser environmentUser =
            environmentInfo.GetEnvironmentUser(_projectInfo.NtServiceUserId);

              string environmentUserPassword =
            PasswordCollectorHelper.CollectPasssword(
              _passwordCollector,
              DeploymentInfo.DeploymentId,
              environmentInfo,
              environmentInfo.AppServerMachineName,
              environmentUser,
              OnDiagnosticMessagePosted);

              return
            new CollectedCredentials(
              environmentUser.UserName,
              environmentUserPassword);
            };

              DoPrepareCommonDeploymentSteps(
            _projectInfo.NtServiceName,
            environmentInfo.AppServerMachineName,
            environmentInfo.NtServicesBaseDirPath,
            environmentInfo.GetAppServerNetworkPath,
            artifactsBinariesDirPathProvider,
            collectCredentialsFunc,
            true);
        }
        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);
        }