private static bool CheckNoMachineIsDomainController(MachineHealthContainer machineHealthContainer)
        {
            Parallel.ForEach(
                machineHealthContainer.GetHealthyMachineNames(),
                (string machineName) =>
            {
                bool result = true;
                try
                {
                    if (StandaloneUtility.IsMachineDomainController(machineName))
                    {
                        SFDeployerTrace.WriteError(StringResources.Error_BPAMachineIsDomainController, machineName);
                        result = false;
                    }
                }
                catch (System.ComponentModel.Win32Exception ex)
                {
                    SFDeployerTrace.WriteError(StringResources.Error_BPADomainControllerQueryException, machineName, ex.NativeErrorCode, ex.Message);
                    result = false;
                }

                if (!result)
                {
                    machineHealthContainer.MarkMachineAsUnhealthy(machineName);
                }
            });

            return(machineHealthContainer.EnoughHealthyMachines());
        }
        // Clean install requires machine be free of previous Fabric installations
        private static bool CheckForCleanInstall(StandAloneInstallerJsonModelBase config, MachineHealthContainer machineHealthContainer, bool isForcedRun = false)
        {
            SFDeployerTrace.WriteNoise(StringResources.Info_BPANoFabric);

            List <string> machineNamesTemp  = StandaloneUtility.GetMachineNamesIncludingClient(machineHealthContainer.GetHealthyMachineNames());
            var           importantSettings = config.GetFabricSystemSettings();
            string        fabricDataRoot    = importantSettings.ContainsKey(DMConstants.FabricDataRootString) ?
                                              importantSettings[DMConstants.FabricDataRootString] :
                                              null;

            bool localMachineFailed = false;

            Parallel.ForEach(
                machineNamesTemp,
                (string machineName) =>
            {
                bool result = true;
                if (StandaloneUtility.IsFabricInstalled(machineName))
                {
                    SFDeployerTrace.WriteError(StringResources.Error_BPAPreviousFabricExists, machineName);
                    result = false;
                }

                if (!isForcedRun)
                {
                    if (fabricDataRoot != null)
                    {
                        IEnumerable <string> machineNodes = config.Nodes.Where(n => n.IPAddress == machineName).Select(n => n.NodeName);
                        foreach (string node in machineNodes)
                        {
                            string nodeDirectory;
                            if (StandaloneUtility.DataRootNodeExists(machineName, node, fabricDataRoot, out nodeDirectory))
                            {
                                SFDeployerTrace.WriteError(StringResources.Error_BPADataRootNodeExists, node, machineName, nodeDirectory);
                                result = false;
                            }
                        }
                    }
                }

                if (!result)
                {
                    if (Helpers.IsLocalIpAddress(machineName))
                    {
                        localMachineFailed = true;
                    }
                    else
                    {
                        machineHealthContainer.MarkMachineAsUnhealthy(machineName);
                    }
                }
            });

            if (localMachineFailed)
            {
                return(false);
            }

            return(machineHealthContainer.EnoughHealthyMachines());
        }
        public async Task <string> ProcessSetUpgradeOrchestrationServiceStateAsync(string inputBlob, TimeSpan timeout, CancellationToken cancellationToken)
        {
            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Entering ProcessSetUpgradeOrchestrationServiceStateAsync.");
            try
            {
                // data validation
                StandAloneCluster cluster = null;
                if (!string.IsNullOrWhiteSpace(inputBlob))
                {
                    JsonSerializerSettings settings = StandaloneUtility.GetStandAloneClusterDeserializerSettings();

                    cluster = JsonConvert.DeserializeObject <StandAloneCluster>(
                        inputBlob,
                        settings);
                }

                await this.storeManager.SetStorageObjectAsync(Constants.ClusterReliableDictionaryKey, inputBlob, this.cancellationToken).ConfigureAwait(false);

                FabricUpgradeOrchestrationServiceState result = UpgradeOrchestrationMessageProcessor.ConstructServiceStateFromCluster(cluster);

                return(JsonConvert.SerializeObject(
                           result,
                           new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                    NullValueHandling = NullValueHandling.Ignore,
                }));
            }
            catch (Exception e)
            {
                UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "ProcessSetUpgradeOrchestrationServiceStateAsync exception: {0}", e);
                throw UpgradeOrchestrationMessageProcessor.ConvertToComException(e);
            }
        }
        public async Task <string> ProcessGetClusterConfigurationAsync(string apiVersion, TimeSpan timeout, CancellationToken cancellationToken)
        {
            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Entering ProcessGetClusterConfigurationAsync.");
            try
            {
                UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Retrieve current cluster resource from StoreManager.");
                StandAloneCluster cluster = await this.storeManager.GetClusterResourceAsync(
                    Constants.ClusterReliableDictionaryKey, this.cancellationToken).ConfigureAwait(false);

                if (cluster == null || cluster.Current == null)
                {
                    // read from fabric data root
                    string fabricDataRoot = FabricEnvironment.GetDataRoot();
                    string jsonConfigPath = Path.Combine(fabricDataRoot, System.Fabric.FabricDeployer.Constants.FileNames.BaselineJsonClusterConfig); // TODO: Needs to come from image store
                    return(File.ReadAllText(jsonConfigPath));
                }
                else
                {
                    var      nodesFromFM = new Dictionary <string, NodeDescription>();
                    NodeList nodes       = await StandaloneUtility.GetNodesFromFMAsync(this.fabricClient, this.cancellationToken).ConfigureAwait(false);

                    for (int i = 0; i < nodes.Count; ++i)
                    {
                        if (nodes[i].NodeStatus != System.Fabric.Query.NodeStatus.Invalid && !UpgradeOrchestrationMessageProcessor.IsGhostNode(nodes[i]))
                        {
                            NodeDescription nodeDesc = new NodeDescription()
                            {
                                FaultDomain   = nodes[i].FaultDomain.ToString(),
                                UpgradeDomain = nodes[i].UpgradeDomain,
                                IPAddress     = nodes[i].IpAddressOrFQDN,
                                NodeTypeRef   = nodes[i].NodeType,
                                NodeName      = nodes[i].NodeName
                            };
                            nodesFromFM.Add(nodes[i].NodeName, nodeDesc);
                        }
                    }

                    cluster.Topology.Nodes = nodesFromFM;

                    UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Construct StandAloneJsonModel from current cluster resource.");
                    var jsonModel = StandAloneInstallerJsonModelBase.ConstructByApiVersion(cluster.Current.CSMConfig, cluster.Topology, cluster.Current.CSMConfig.Version.Version, apiVersion);
                    UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Serializing current json model.");
                    var serializerSettings = new JsonSerializerSettings
                    {
                        Formatting                 = Formatting.Indented,
                        NullValueHandling          = NullValueHandling.Ignore,
                        PreserveReferencesHandling = PreserveReferencesHandling.None
                    };
                    serializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
                    return(JsonConvert.SerializeObject(jsonModel, serializerSettings));
                }
            }
            catch (Exception e)
            {
                UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "ProcessStartUpgradeAsync exception: {0}", e);
                throw UpgradeOrchestrationMessageProcessor.ConvertToComException(e);
            }
        }
示例#5
0
        internal static void UpdateStandAloneClusterWRPSettings(string clusterSettingsFilePath, string version, StandAloneCluster existingCluster)
        {
            string fabricSettingFilePath = StandaloneUtility.FindFabricResourceFile("Configurations.csv");
            FabricSettingsMetadata fabricSettingsMetadata = FabricSettingsMetadata.Create(fabricSettingFilePath);
            AdminConfigVersion     adminConfigVersion     = new AdminConfigVersion("Baseline", version);

            StandAloneClusterManifestSettings standAloneClusterManifestSettings = JsonConvert.DeserializeObject <StandAloneClusterManifestSettings>(
                File.ReadAllText(clusterSettingsFilePath));

            existingCluster.TargetWrpConfig = new StandaloneAdminConfig(fabricSettingsMetadata, standAloneClusterManifestSettings, adminConfigVersion, false);
        }
        // This function check whether dotnet exe exists in %PATH% on IOT device.
        // It will read %PATH% from registry and expand %systemroot% if found
        // Currently it doesn't support expanding other variables.
        internal static bool IsDotNetExeInPath(MachineHealthContainer machineHealthContainer)
        {
            bool result = true;

            Parallel.ForEach(
                machineHealthContainer.GetHealthyMachineNames(),
                (string machineName) =>
            {
                // Currently we only need to check for IOTCore environment
                if (StandaloneUtility.IsIOTCore(machineName))
                {
                    string remotePath       = string.Empty;
                    string remoteSystemRoot = string.Empty;

                    // Read %Path% variable
                    using (RegistryKey regKey = StandaloneUtility.GetHklm(machineName))
                    {
                        RegistryKey envKey = regKey.OpenSubKey(DMConstants.EnvironmentRegKeyPath);
                        if (envKey != null)
                        {
                            remotePath = (string)envKey.GetValue(DMConstants.Path, string.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames);
                        }

                        RegistryKey versionKey = regKey.OpenSubKey(DMConstants.IOTCurrentVersionRegKeyPath);
                        if (versionKey != null)
                        {
                            remoteSystemRoot = (string)versionKey.GetValue(DMConstants.SystemRoot, string.Empty);
                        }
                    }

                    bool found     = false;
                    string[] paths = remotePath.Split(';');
                    foreach (string path in paths)
                    {
                        // Replace %SystemRoot%
                        string absolutePath  = Regex.Replace(path, "%SYSTEMROOT%", remoteSystemRoot, RegexOptions.IgnoreCase);
                        absolutePath         = Path.Combine(absolutePath, "dotnet.exe");
                        string dotNetExePath = Helpers.GetRemotePathIfNotLocalMachine(absolutePath, machineName);
                        if (File.Exists(dotNetExePath))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        result = false;
                    }
                }
            });

            return(result);
        }
示例#7
0
        public void DeploymentManagerTest_GetDevMachinesIsLocalhost()
        {
            string manifestPath = Path.Combine(BaseDir, XmlManifestFilename);

            Assert.IsTrue(File.Exists(manifestPath), string.Format("Manifest file {0} did not exist.", manifestPath));
            List <string> machines = StandaloneUtility.GetMachineNamesFromClusterManifest(manifestPath);

            Assert.IsNotNull(machines);
            Assert.AreEqual(machines.Count, 1);
            Assert.IsTrue("localhost".CompareTo(machines[0]) == 0,
                          "Expected to find the machine localhost, but found {0} instead", machines[0]);
        }
        internal async Task PerformAddNodeOperationGMSAAsync(List <NodeDescription> addedNodes, FabricClient fabricClient, List <NodeTypeDescription> allNodeTypes)
        {
            string destinationPackagePath = await this.DownloadProvisionedPackage().ConfigureAwait(false);

            var nodesFromFM = await StandaloneUtility.GetNodesFromFMAsync(fabricClient, this.cancellationToken).ConfigureAwait(false);

            string clusterManifestPath = await this.GenerateClusterManifestWithAddedNodes(addedNodes, nodesFromFM, allNodeTypes);

            List <string> machines = new List <string>();

            foreach (var addednode in addedNodes)
            {
                if (!nodesFromFM.Any(nodeFromFM => nodeFromFM.NodeName == addednode.NodeName))
                {
                    machines.Add(addednode.IPAddress);
                }
            }

            bool             successfulRun = true;
            List <Exception> exceptions    = new List <Exception>();

            try
            {
                await this.AddNodesAsync(clusterManifestPath, destinationPackagePath, machines, addedNodes);
            }
            catch (Exception ex)
            {
                successfulRun = false;
                exceptions.Add(ex);
                UpgradeOrchestrationTrace.TraceSource.WriteError("Adding nodes failed with exception {0}.", ex.ToString());
            }

            if (!successfulRun)
            {
                // Best-Effort Rollback
                try
                {
                    await DeploymentManagerInternal.RemoveNodeConfigurationAsync(machines, false, FabricPackageType.XCopyPackage, true);
                }
                catch (Exception ex)
                {
                    UpgradeOrchestrationTrace.TraceSource.WriteError("Rollback failed with {0}.", ex.ToString());
                    exceptions.Add(ex);
                }

                AggregateException ae = new AggregateException(exceptions);
                throw ae;
            }

            this.CleanUp(clusterManifestPath, destinationPackagePath);
            UpgradeOrchestrationTrace.TraceSource.WriteInfo("Nodes were succesfully added to the GMSA secured cluster");
        }
        private async Task <ReliabilityLevel> GetActualReliabilityLevelForCluster(CancellationToken cancellationToken)
        {
            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Entering GetCurrentReliabilityLevelForCluster");
            System.Fabric.Query.NodeList nodes = await StandaloneUtility.GetNodesFromFMAsync(this.fabricClient, cancellationToken).ConfigureAwait(false);

            int seedNodeCount = nodes.Count(p => p.IsSeedNode);

            ReliabilityLevel actualReliabilityLevelInCluster = ReliabilityLevelExtension.GetReliabilityLevel(seedNodeCount);

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "SeedNodeCount from cluster {0}, actualReliabilityLevelInCluster {1}", seedNodeCount, actualReliabilityLevelInCluster);

            return(actualReliabilityLevelInCluster);
        }
示例#10
0
        internal static async Task <string> GetGoalStateFileJsonAsync(Uri goalStateUri)
        {
            string goalStateJson = null;

            try
            {
                goalStateJson = await StandaloneUtility.GetContentsFromUriAsyncWithRetry(goalStateUri, TimeSpan.FromMinutes(Constants.FabricOperationTimeoutInMinutes), CancellationToken.None);
            }
            catch (FabricValidationException ex)
            {
                SFDeployerTrace.WriteError(StringResources.Error_SFGoalStateFileNotDownloaded, goalStateUri, ex.ToString());
            }

            return(goalStateJson);
        }
        internal static bool ValidateRemoveNode(string machineName)
        {
            SFDeployerTrace.WriteInfo(StringResources.Info_BPAStart);

            //// TODO: (maburlik) Validate FabricClient connection

            var summary = new AnalysisSummary();

            summary.LocalAdminPrivilege = CheckLocalAdminPrivilege();

            IEnumerable <string> machineContainer = new List <string>()
            {
                machineName
            };
            MachineHealthContainer machineHealthContainer = new MachineHealthContainer(machineContainer);

            summary.RequiredPortsOpen = StandaloneUtility.CheckRequiredPorts(machineHealthContainer);

            // Below depends on machines being reachable
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(false);
            }

            summary.RpcCheckPassed = CheckRPCAccess(machineHealthContainer);

            // Below depend on remote registry access
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(false);
            }

            bool hasFabricInstalled = StandaloneUtility.IsFabricInstalled(machineName);

            if (!hasFabricInstalled)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPARemoveNodeNeedsFabric, machineName);
            }

            LogResult(summary, hasFabricInstalled);

            return(summary.Passed && hasFabricInstalled);
        }
        internal static bool ValidateClusterRemoval(
            string configPath,
            bool usingClusterManifest = false)
        {
            SFDeployerTrace.WriteInfo(StringResources.Info_BPAStart);
            var summary = new AnalysisSummary();

            // Check user has local admin privilege
            summary.LocalAdminPrivilege = CheckLocalAdminPrivilege();
            StandAloneInstallerJsonModelBase standAloneModel = null;

            if (!usingClusterManifest)
            {
                standAloneModel     = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(configPath);
                summary.IsJsonValid = IsJsonConfigModelValid(standAloneModel, null, validateDownNodes: false, throwIfError: false);
            }

            // Below depends on JSON being valid
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(false);
            }

            // Get machine names from JSON config
            IEnumerable <string> machineNames = usingClusterManifest
                                        ? StandaloneUtility.GetMachineNamesFromClusterManifest(configPath)
                                        : standAloneModel.GetClusterTopology().Machines;

            MachineHealthContainer machineHealthContainer = new MachineHealthContainer(machineNames);

            // Log validations but don't fail
            StandaloneUtility.CheckRequiredPorts(machineHealthContainer);
            CheckRPCAccess(machineHealthContainer);

            // At least one machine should be removable
            bool anyMachinesRemovable = CheckAnyMachinesRemovable(machineNames);

            LogResult(summary, anyMachinesRemovable);

            return(summary.Passed);
        }
示例#13
0
        public void DeploymentManagerTest_ConvertJsonToXml()
        {
            Console.WriteLine("Current directory: {0}", Environment.CurrentDirectory);
            string clusterConfigPath = Path.Combine(BaseDir, JsonConfigUnsecureJan2017Filename);

            Directory.SetCurrentDirectory(BaseDir);
            Console.WriteLine("New current directory changed to: {0}", Environment.CurrentDirectory);
            Assert.IsTrue(File.Exists(clusterConfigPath), string.Format("Config file {0} did not exist.", clusterConfigPath));
            string clusterManifestPath = Path.Combine(Path.GetTempPath(), "cmtest.xml");
            var    clusterResource     = DeploymentManagerInternal.GetClusterResource(clusterConfigPath, System.Guid.NewGuid().ToString());
            var    cm = clusterResource.Current.ExternalState.ClusterManifest;

            Assert.IsNotNull(cm, "Cluster manifest was null.");
            XMLHelper.WriteXmlExclusive <ClusterManifestType>(clusterManifestPath, cm);
            Assert.IsTrue(File.Exists(clusterManifestPath), "Cluster manifest was not written.");
            List <string> machines = StandaloneUtility.GetMachineNamesFromClusterManifest(clusterManifestPath);

            Assert.IsNotNull(machines);
            Assert.IsTrue(machines.Count > 0, "Cluster manifest was not written correctly. Machines missing.");
        }
        private static bool CheckAnyMachinesRemovable(IEnumerable <string> machineNames)
        {
            bool result = false;

            Parallel.ForEach(
                machineNames,
                (string machineName) =>
            {
                if (StandaloneUtility.IsFabricInstalled(machineName))
                {
                    result = true;
                }
            });

            if (!result)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPANoMachinesHaveFabricInstalled);
            }

            return(result);
        }
示例#15
0
        internal static StandAloneCluster DeserializeClusterResource(string str)
        {
            StandAloneCluster      result;
            JsonSerializerSettings settings = StandaloneUtility.GetStandAloneClusterDeserializerSettings();

            try
            {
                result = JsonConvert.DeserializeObject <StandAloneCluster>(str, settings);
                isVersionChangedFrom5To6 = false;
            }
            catch (JsonSerializationException ex)
            {
                UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "GetClusterResourceAsync: Deserialization error. Error is {0}. Will begin best-effort attempt.", ex.ToString());

                var normalizedString = NormalizeClusterResource(str, Assembly.GetExecutingAssembly().GetName().Version.ToString());
                result = JsonConvert.DeserializeObject <StandAloneCluster>(normalizedString, settings);
                isVersionChangedFrom5To6 = true;

                UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "GetClusterResourceAsync: Deserialization succeeds after best-effort normalization.");
            }

            result.PersistedClusterString = str;
            return(result);
        }
        private static bool CheckDrivesAvailableSpace(MachineHealthContainer machineHealthContainer, string fabricDataRoot, string fabricLogRoot)
        {
            List <string> drives                       = new List <string>();
            string        candidateMachine             = machineHealthContainer.GetHealthyMachineNames().ElementAt(0);
            string        fabricPackageDestinationPath = Utility.GetDefaultPackageDestination(candidateMachine);
            string        fabricRootDrive              = Path.GetPathRoot(fabricPackageDestinationPath);

            drives.Add(fabricRootDrive);

            if (fabricDataRoot != null)
            {
                drives.Add(Path.GetPathRoot(fabricDataRoot));
            }

            if (fabricLogRoot != null)
            {
                drives.Add(Path.GetPathRoot(fabricLogRoot));
            }

            foreach (string drive in drives.Distinct())
            {
                Parallel.ForEach(
                    machineHealthContainer.GetHealthyMachineNames(),
                    (string machineName) =>
                {
                    string remoteRootDrive = Helpers.GetRemotePathIfNotLocalMachine(drive, machineName);
                    if (!StandaloneUtility.EnoughAvailableSpaceOnDrive(remoteRootDrive))
                    {
                        SFDeployerTrace.WriteError(StringResources.Error_BPANotEnoughSpaceOnDrive, drive, machineName);
                        machineHealthContainer.MarkMachineAsUnhealthy(machineName);
                    }
                });
            }

            return(machineHealthContainer.EnoughHealthyMachines());
        }
        private static StandAloneCluster InitClusterResource(FabricNativeConfigStore configStore)
        {
            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Enter InitClusterResource");

            string fabricDataRoot = FabricEnvironment.GetDataRoot();
            string jsonConfigPath = Path.Combine(fabricDataRoot, Microsoft.ServiceFabric.DeploymentManager.Constants.BaselineJsonMetadataFileName);

            ReleaseAssert.AssertIf(!File.Exists(jsonConfigPath), "Baseline upgrade JsonClusterConfigMetadata not found at {0}.", jsonConfigPath);

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Deserializing Json config.");
            string jsonConfig = File.ReadAllText(jsonConfigPath);

            if (string.IsNullOrEmpty(jsonConfig))
            {
                throw new FabricValidationException(StringResources.Error_SFJsonConfigInvalid, FabricErrorCode.OperationCanceled);
            }

            JsonSerializerSettings settings = StandaloneUtility.GetStandAloneClusterDeserializerSettings();

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Exit InitClusterResource");
            return(JsonConvert.DeserializeObject <StandAloneCluster>(
                       jsonConfig,
                       settings));
        }
        internal static bool ValidateAddNode(string machineName, string nodeName, string cabPath, string fabricDataRoot, string fabricLogRoot)
        {
            SFDeployerTrace.WriteInfo(StringResources.Info_BPAStart);

            //// TODO: (maburlik) Validate FabricClient connection

            var summary = new AnalysisSummary();

            // Check user has local admin privilege
            summary.LocalAdminPrivilege = CheckLocalAdminPrivilege();
            summary.IsCabValid          = CheckIsCabFile(cabPath);

            // Below depends on JSON being valid
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(false);
            }

            IEnumerable <string> machineContainer = new List <string>()
            {
                machineName
            };
            MachineHealthContainer machineHealthContainer = new MachineHealthContainer(machineContainer);

            summary.RequiredPortsOpen = StandaloneUtility.CheckRequiredPorts(machineHealthContainer);

            // Below depends on machines being reachable
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(false);
            }

            summary.RpcCheckPassed = CheckRPCAccess(machineHealthContainer);

            // Below depend on remote registry access
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(false);
            }

            summary.NoDomainController = CheckNoMachineIsDomainController(machineHealthContainer);

            // Below depends on machine not being domain controller
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(false);
            }

            summary.NoConflictingInstallations = !StandaloneUtility.IsMsiInstalled(machineHealthContainer);
            summary.FabricInstallable          = StandaloneUtility.CheckForCleanInstall(machineName, nodeName, fabricDataRoot);

            summary.DataDrivesAvailable = CheckDataSystemDrives(machineHealthContainer, fabricDataRoot, fabricLogRoot);

            // Below depend on data system drives
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(false);
            }

            summary.DrivesEnoughAvailableSpace = CheckDrivesAvailableSpace(machineHealthContainer, fabricDataRoot, fabricLogRoot);

            // Below depend on root drives having enough space available
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(false);
            }

            LogResult(summary);

            return(summary.Passed);
        }
示例#19
0
        internal void ConvertDevJsonToXml_Utility(int expectedReplicaSize, string inputFile, string outputFile, string sectionToChangeWin7, bool isSecure = false, bool testOverride = false)
        {
            Console.WriteLine("Current directory: {0}", Environment.CurrentDirectory);
            string clusterConfigPath = Path.Combine(DevJsonModelTest.BaseDir, inputFile);

            Directory.SetCurrentDirectory(DevJsonModelTest.BaseDir);
            Console.WriteLine("New current directory changed to: {0}", Environment.CurrentDirectory);
            string clusterManifestPath = Path.Combine(Path.GetTempPath(), outputFile);
            var    clusterResource     = DeploymentManagerInternal.GetClusterResource(clusterConfigPath, System.Guid.NewGuid().ToString());
            var    cm = clusterResource.Current.ExternalState.ClusterManifest;

            Assert.IsNotNull(cm, "Cluster manifest was null.");

            File.Delete(clusterManifestPath);
            XMLHelper.WriteXmlExclusive <ClusterManifestType>(clusterManifestPath, cm);
            List <string> machines = StandaloneUtility.GetMachineNamesFromClusterManifest(clusterManifestPath);

            Assert.IsNotNull(machines);

            Assert.AreEqual(expectedReplicaSize, ((WindowsInfrastructureType)cm.Infrastructure.Item).NodeList.ToList().Where(node => node.IsSeedNode).Count());

            if (isSecure)
            {
                Assert.AreEqual(InputEndpointTypeProtocol.https, cm.NodeTypes[0].Endpoints.HttpGatewayEndpoint.Protocol);
                Assert.IsNotNull(cm.NodeTypes[0].Certificates.ClientCertificate, "Client certificate was null.");
            }

            foreach (SettingsOverridesTypeSection setting in cm.FabricSettings)
            {
                Assert.IsTrue(IsSectionAllowed(cm.NodeTypes.Count(), setting.Name));
                if (setting.Name == StringConstants.SectionName.Setup)
                {
                    foreach (SettingsOverridesTypeSectionParameter param in setting.Parameter)
                    {
                        Assert.AreNotEqual(StringConstants.ParameterName.IsDevCluster, param.Name);
                        if (param.Name == StringConstants.ParameterName.FabricDataRoot)
                        {
                            Assert.AreEqual(Environment.ExpandEnvironmentVariables("%systemdrive%\\SfDevCluster\\Data"), param.Value);
                        }
                    }
                }
                if (setting.Name == StringConstants.SectionName.ClusterManager)
                {
                    SettingsOverridesTypeSectionParameter TargetReplicaSetSizeParam = setting.Parameter.FirstOrDefault(x => x.Name == StringConstants.ParameterName.TargetReplicaSetSize);
                    Assert.IsNotNull(TargetReplicaSetSizeParam, "Cannot find TargetReplicaSetSize for Cluster Manager");
                    Assert.AreEqual(expectedReplicaSize.ToString(), TargetReplicaSetSizeParam.Value);
                }
                if (DevJsonModel.IsWin7() && setting.Name == sectionToChangeWin7)
                {
                    SettingsOverridesTypeSectionParameter isEnabledParam = setting.Parameter.FirstOrDefault(x => x.Name == StringConstants.ParameterName.IsEnabled);
                    Assert.IsNotNull(isEnabledParam, "Cannot find isEnabled for " + sectionToChangeWin7);
                    Assert.AreEqual("false", isEnabledParam.Value);
                }
                if (setting.Name == StringConstants.SectionName.Diagnostics && testOverride)
                {
                    SettingsOverridesTypeSectionParameter isEnabledTraceSessionParam = setting.Parameter.FirstOrDefault(x => x.Name == StringConstants.ParameterName.EnableCircularTraceSession);
                    Assert.IsNotNull(isEnabledTraceSessionParam, "Cannot find isEnabled for EnableCircularTraceSession");
                    Assert.AreEqual("false", isEnabledTraceSessionParam.Value);
                }
                if (setting.Name == StringConstants.SectionName.FailoverManager && expectedReplicaSize == 1)
                {
                    SettingsOverridesTypeSectionParameter IsSingletonReplicaMoveAllowedDuringUpgradeParam = setting.Parameter.FirstOrDefault(x => x.Name == StringConstants.ParameterName.IsSingletonReplicaMoveAllowedDuringUpgrade);
                    Assert.IsNotNull(IsSingletonReplicaMoveAllowedDuringUpgradeParam, "Cannot find isEnabled for EnableCircularTraceSession");
                    Assert.AreEqual("false", IsSingletonReplicaMoveAllowedDuringUpgradeParam.Value);
                }
            }

            //DevCluster should have one distinct IPaddress, i.e. localhost
            Assert.AreEqual(1, machines.Count);
        }
        private static bool CheckRPCAccess(MachineHealthContainer machineHealthContainer)
        {
            var retryTimeout = new System.Fabric.Common.TimeoutHelper(DMConstants.BpaRpcRetryTimeout);

            SFDeployerTrace.WriteNoise(StringResources.Info_SFRpcInfo);

            Parallel.ForEach <string>(
                machineHealthContainer.GetHealthyMachineNames(),
                (string machine) =>
            {
                bool result = true;
                bool willRetry;

                do
                {
                    willRetry = false;

                    try
                    {
                        Utility.GetTempPath(machine);
                    }
                    catch (Exception ex)
                    {
                        string message;
                        if (ex is System.IO.IOException)
                        {
                            switch (ex.HResult)
                            {
                            // If new failures are discovered: https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
                            case 53:         // ERROR_BAD_NETPATH
                                message   = string.Format(StringResources.Error_SFRpcIoNetpath, machine, ex.HResult);
                                willRetry = true;
                                break;

                            case 1723:         // RPC_S_SERVER_TOO_BUSY
                                message   = string.Format(StringResources.Error_SFRpcIoTooBusy, machine, ex.HResult);
                                willRetry = true;
                                break;

                            case 1727:         // RPC_S_CALL_FAILED_DNE
                                message = string.Format(StringResources.Error_SFRpcIoFailedDne, machine, ex.HResult);
                                break;

                            default:
                                message = string.Format(StringResources.Error_SFRpcIoGeneric, machine, ex.HResult);
                                break;
                            }
                        }
                        else if (ex is System.Security.SecurityException)
                        {
                            switch (ex.HResult)
                            {
                            case -2146233078:         // COR_E_SECURITY
                                message = string.Format(StringResources.Error_SFRpcSecAccess, machine, ex.HResult);
                                break;

                            default:
                                message = string.Format(StringResources.Error_SFRpcSecGeneric, machine, ex.HResult);
                                break;
                            }
                        }
                        else if (ex is NullReferenceException)
                        {
                            switch (ex.HResult)
                            {
                            case -2146232828:         // COR_E_TARGETINVOCATION
                                message = string.Format(StringResources.Error_SFRpcNullRegAccess, machine, ex.HResult);
                                break;

                            default:
                                message = string.Format(StringResources.Error_SFRpcNullGeneric, machine, ex.HResult);
                                break;
                            }
                        }
                        else
                        {
                            // This is to catch coding errors.
                            message = string.Format(StringResources.Error_SFRpcGeneric, machine, ex.HResult);
                        }

                        willRetry &= !System.Fabric.Common.TimeoutHelper.HasExpired(retryTimeout);

                        if (willRetry)
                        {
                            SFDeployerTrace.WriteWarning(message);

                            StandaloneUtility.OpenRemoteRegistryNamedPipe(machine, retryTimeout.GetRemainingTime());

                            Thread.Sleep(TimeSpan.FromSeconds(5));
                        }
                        else
                        {
                            SFDeployerTrace.WriteError(message);

                            result = false;
                        }
                    }
                }while (willRetry);

                if (!result)
                {
                    machineHealthContainer.MarkMachineAsUnhealthy(machine);
                }
            });

            return(machineHealthContainer.EnoughHealthyMachines());
        }
        internal static AnalysisSummary AnalyzeClusterSetup(
            string configPath,
            string oldConfigPath,
            string cabPath,
            bool usingClusterManifest           = false,
            FabricPackageType fabricPackageType = FabricPackageType.XCopyPackage,
            bool isForcedRun          = false,
            int maxPercentFailedNodes = 0)
        {
            SFDeployerTrace.WriteInfo(StringResources.Info_BPAStart);
            var summary = new AnalysisSummary();

            // Check user has local admin privilege
            summary.LocalAdminPrivilege = CheckLocalAdminPrivilege();

            // Validate JSON config
            StandAloneInstallerJsonModelBase standAloneModel    = null;
            StandAloneInstallerJsonModelBase oldStandAloneModel = null;

            if (!usingClusterManifest)
            {
                standAloneModel = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(configPath);

                if (!string.IsNullOrEmpty(oldConfigPath))
                {
                    oldStandAloneModel = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(oldConfigPath);
                }

                summary.IsJsonValid = IsJsonConfigModelValid(standAloneModel, oldStandAloneModel, validateDownNodes: true, throwIfError: false) && ValidateCodeVersionExists(standAloneModel);
            }

            // Deliberately not checking empty. Some invocations aren't intended to test cabPath.
            if (cabPath != null)
            {
                summary.IsCabValid = CheckIsCabFile(cabPath);
            }

            // Below depends on JSON being valid
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(summary);
            }

            // Get machine names from JSON config
            IEnumerable <string> healthyMachineNames = usingClusterManifest
                                        ? StandaloneUtility.GetMachineNamesFromClusterManifest(configPath)
                                        : standAloneModel.GetClusterTopology().Machines;

            MachineHealthContainer machineHealthContainer = new MachineHealthContainer(healthyMachineNames, maxPercentFailedNodes);

            // Validate machine FQDNs, Check SMB ports opened
            summary.RequiredPortsOpen = StandaloneUtility.CheckRequiredPorts(machineHealthContainer);

            // Below depends on machines being reachable
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(summary);
            }

            // Validate Remote Registry Service is not disabled on all machines
            summary.RemoteRegistryAvailable = CheckRemoteRegistryEnabled(machineHealthContainer);

            // Below depends on remote registry service
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(summary);
            }

            summary.FirewallAvailable = CheckFirewallEnabled(machineHealthContainer);

            // Below depends on firewall service
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(summary);
            }

            // Run RPC check to validate end-to-end registry access to all machines
            summary.RpcCheckPassed = CheckRPCAccess(machineHealthContainer);

            // Below depend on remote registry access
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(summary);
            }

            summary.NoDomainController = CheckNoMachineIsDomainController(machineHealthContainer);

            // Below depends on machines not being domain controller
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(summary);
            }

            if (fabricPackageType == FabricPackageType.XCopyPackage)
            {
                // Validate that Fabric runtime MSI is not installed since this will be conflicting with Standalone
                summary.NoConflictingInstallations = !StandaloneUtility.IsMsiInstalled(machineHealthContainer);
            }

            string fabricDataRoot = null;
            string fabricLogRoot  = null;

            if (!usingClusterManifest)
            {
                if (string.IsNullOrEmpty(oldConfigPath))
                {
                    summary.FabricInstallable = CheckForCleanInstall(standAloneModel, machineHealthContainer, isForcedRun); // Fabric is not installed on target machines
                }

                var importantSettings = standAloneModel.GetFabricSystemSettings();
                fabricDataRoot = importantSettings.ContainsKey(DMConstants.FabricDataRootString) ?
                                 importantSettings[DMConstants.FabricDataRootString] :
                                 null;
                fabricLogRoot = importantSettings.ContainsKey(DMConstants.FabricLogRootString) ?
                                importantSettings[DMConstants.FabricLogRootString] :
                                null;

                summary.DataDrivesAvailable = CheckDataSystemDrives(machineHealthContainer, fabricDataRoot, fabricLogRoot); // System drives for path-based settings, exist on target machines

                // Below depend on data system drives
                if (!summary.Passed)
                {
                    SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                    return(summary);
                }
            }

            summary.DrivesEnoughAvailableSpace = CheckDrivesAvailableSpace(machineHealthContainer, fabricDataRoot, fabricLogRoot);

            // Below depend on root drives having enough space available
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(summary);
            }

            summary.IsAllOrNoneIOTDevice = CheckAllIOTDevices(machineHealthContainer);

            // Below depend on all or none machines being IOT Devices
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(summary);
            }

            // Check dotnet.exe exists in %Path%
            // Currently we only need to check for IOTCore environment.
            summary.DotNetExeInPath = IsDotNetExeInPath(machineHealthContainer);

            // Below depend on IOT Devices having dotnet.exe in path
            if (!summary.Passed)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPABailing);
                return(summary);
            }

            summary.MachineHealthContainer = machineHealthContainer;
            LogResult(summary);

            return(summary);
        }
示例#22
0
        public async Task PersistClusterResourceAsync(string key, StandAloneCluster cluster, CancellationToken cancellationToken)
        {
            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Enter PersistClusterResourceAsync.");
            var clusterStateTable = await this.stateManager.GetOrAddAsync <IReliableDictionary <string, string> >(Constants.ClusterReliableDictionaryName);

            try
            {
                UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Serialize cluster resource into string format.");
                string clusterString = JsonConvert.SerializeObject(
                    cluster,
                    StandaloneUtility.GetStandAloneClusterSerializerSettings());

                using (var tx = this.stateManager.CreateTransaction())
                {
                    UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Enter transaction inside PersistClusterResourceAsync");

                    if (string.IsNullOrEmpty(cluster.PersistedClusterString))
                    {
                        await clusterStateTable.AddAsync(
                            tx,
                            key,
                            clusterString,
                            Constants.DefaultDictionaryTimeout,
                            cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        /* This is a workaround for scenarios where clusters were upgraded from 5.x->6.x. During deserealization, we change the version in UOSState from 5.0.0.0 to 6.0.0.0. This is needed for
                         * newtonsoft deserealization to work with the new assembly versions. Here we revert 6.0.0.0 back to 5.0.0.0 before persisting it so that users can downgrade succesfully from 6.x -> 5.x
                         * versions. Once 5.x is deprecated, we can remove this workaround and persist 6.0.0.0 in UOS state */
                        if (isVersionChangedFrom5To6)
                        {
                            clusterString = NormalizeClusterResource(clusterString, Version5);
                        }

                        bool success = await clusterStateTable.TryUpdateAsync(
                            tx,
                            key,
                            clusterString,
                            cluster.PersistedClusterString).ConfigureAwait(false);

                        if (!success)
                        {
                            UpgradeOrchestrationTrace.TraceSource.WriteWarning(
                                TraceType,
                                "PersistClusterResourceAsync: StandAloneCluster data is not updated. The reason is {0}",
                                string.Equals(clusterString, cluster.PersistedClusterString, StringComparison.OrdinalIgnoreCase) ? "the value is not changed." : "to be investigated.");
                            return;
                        }
                    }

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

                UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Exit transaction inside PersistClusterResourceAsync");
            }
            catch (Exception e)
            {
                UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "PersistClusterResourceAsync: {0}", e.ToString());
                throw;
            }
        }
示例#23
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);
        }
示例#24
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
                    {
                    }
                }
            }
        }
        public async Task ProcessStartClusterConfigurationUpgradeAsync(ConfigurationUpgradeDescription configUpgradeDesc, TimeSpan timeout, CancellationToken cancellationToken)
        {
            /* The cancellation token passed in this API call is not used (by design). This token corresponds to the client side call.
             * The global this.cancellationToken is initialised in RunAsync() and is honored in every API call. */

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Entering ProcessStartUpgradeAsync.");
            try
            {
                UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Deserializing input json config string.");
                StandAloneInstallerJsonModelBase targetJsonConfig = StandAloneInstallerJsonModelBase.GetJsonConfigFromString(configUpgradeDesc.ClusterConfiguration);
                if (targetJsonConfig == null)
                {
                    throw new ArgumentException("The input cluster configuration is not in a valid json format or supported apiVersion.");
                }

                UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Retrieve current cluster resource from StoreManager.");
                StandAloneCluster cluster = await this.storeManager.GetClusterResourceAsync(
                    Constants.ClusterReliableDictionaryKey, this.cancellationToken).ConfigureAwait(false);

                bool isInDataLossState = await DatalossHelper.IsInDatalossStateAsync(this.cancellationToken).ConfigureAwait(false);

                if (!isInDataLossState)
                {
                    if (cluster == null || cluster.Current == null)
                    {
                        UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "Persisted cluster resource is not ready: {0}", cluster == null ? "null" : "current = null");
                        throw new FabricException("UpgradeOrchestrationService is not ready.");
                    }

                    UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Setting target config and topology based on new input json config.");

                    if (cluster.Pending != null && !this.IsInterruptibleAsync(cluster.Pending).Result)
                    {
                        throw new FabricException(string.Format("Cluster configuration upgrade of type {0} is already in progress and cannot be interrupted.", cluster.Pending.GetType().Name));
                    }

                    StandaloneSettingsValidator validator = new StandaloneSettingsValidator(targetJsonConfig);

                    await UpgradeOrchestrationMessageProcessor.ValidateModel(targetJsonConfig, validator, cluster, true).ConfigureAwait(false);

                    var removedNodes = validator.GetRemovedNodes(cluster.Topology);
                    var addedNodes   = validator.GetAddedNodes(cluster.Topology);

                    if (addedNodes.Any() && StandaloneUtility.CheckFabricRunningAsGMSA(cluster.Current.CSMConfig))
                    {
                        /* Need to resolve assembly so that FabricDeployer can load the right binaries from FabricCodePath since not all binaries required by FabricDeployer are present in UOS.Current folder.*/
                        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(this.LoadFromFabricCodePath);
                        try
                        {
                            await this.PerformAddNodeOperationGMSAAsync(addedNodes, this.fabricClient, validator.ClusterProperties.NodeTypes).ConfigureAwait(false);
                        }
                        catch (AggregateException ex)
                        {
                            UpgradeOrchestrationTrace.TraceSource.WriteError(TraceType, "Adding nodes for GMSA scenario failed with exception: {0}", ex);
                            throw;
                        }
                        finally
                        {
                            AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(this.LoadFromFabricCodePath);
                        }
                    }

                    if (addedNodes.Any())
                    {
                        cluster.TargetNodeConfig = GetTargetNodeConfigAddNode(validator.Topology, cluster.Current.NodeConfig.Version);
                    }

                    if (removedNodes.Any())
                    {
                        cluster.TargetNodeConfig = GetTargetNodeConfigRemoveNode(cluster.Topology, removedNodes, cluster.Current.NodeConfig.Version);
                    }
                    else
                    {
                        cluster.Topology = validator.Topology;
                    }

                    cluster.TargetCsmConfig = validator.ClusterProperties;

                    // Cluster is updated above so persist it.
                    await this.storeManager.PersistClusterResourceAsync(Constants.ClusterReliableDictionaryKey, cluster, cancellationToken).ConfigureAwait(false);

                    await this.UpdatePersistedCodeUpgradePackage(validator).ConfigureAwait(false);

                    UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Invoking Orchestrator");

                    await this.orchestrator.StartUpgradeAsync(cluster, this.cancellationToken, configUpgradeDesc).ContinueWith(t =>
                    {
                        if (t.Exception != null)
                        {
                            UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "Orchestrator completed with status: {0} exception: {1}", t.Status, t.Exception);
                        }
                        else
                        {
                            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Orchestrator completed with status: {0}", t.Status);
                        }
                    });
                }
                else
                {
                    StandaloneSettingsValidator validator = new StandaloneSettingsValidator(targetJsonConfig);
                    await UpgradeOrchestrationMessageProcessor.ValidateModel(targetJsonConfig, validator, cluster, false).ConfigureAwait(false);

                    cluster = FabricUpgradeOrchestrationService.ConstructClusterFromJson(targetJsonConfig, FabricNativeConfigStore.FabricGetConfigStore());

                    DatalossHelper.DryRunConfigUpgrade(cluster);
                    await this.storeManager.PersistClusterResourceAsync(Constants.ClusterReliableDictionaryKey, cluster, this.cancellationToken);

                    await DatalossHelper.UpdateHeathStateAsync(isHealthy : true).ConfigureAwait(false);
                }
            }
            catch (Exception e)
            {
                UpgradeOrchestrationTrace.TraceSource.WriteWarning(TraceType, "ProcessStartUpgradeAsync exception: {0}", e);
                throw UpgradeOrchestrationMessageProcessor.ConvertToComException(e);
            }

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Exiting ProcessStartUpgradeAsync.");
        }
        internal static bool CheckAllIOTDevices(MachineHealthContainer machineHealthContainer)
        {
            int numOfIOTCores = StandaloneUtility.IOTDevicesCount(machineHealthContainer.GetHealthyMachineNames());

            return(numOfIOTCores == 0 || numOfIOTCores == machineHealthContainer.GetHealthyMachineNames().Count());
        }