// 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());
        }
        internal static bool IsJsonConfigModelValid(StandAloneInstallerJsonModelBase config, StandAloneInstallerJsonModelBase oldConfig, bool validateDownNodes, bool throwIfError = false)
        {
            try
            {
                config.ThrowValidationExceptionIfNull(StringResources.Error_BPAJsonModelInvalid);
                config.ValidateModel();
                var settingsValidator = new StandaloneSettingsValidator(config);
                settingsValidator.Validate(validateDownNodes);

                // UOS validates upgrade config diffs by calling ValidateUpdateFrom() method directly. Test-Configuration invokes IsJsonConfigModelValid() and it calls ValidateUpdateFrom inside.
                // The reason is from Test-Configuration, there is no cluster connection, so that we ignore ValidateTopologyAsync(). Therefore in the ValidateUpdateFrom here there is no need
                // to await the async call. However in UOS, we should call ValidateUpdateFrom in an async manner. That's why I am not trying to have the UOS/TestConfiguration going down the same path.
                if (oldConfig != null)
                {
                    settingsValidator.ValidateUpdateFrom(oldConfig.GetUserConfig(), oldConfig.GetClusterTopology(), connectedToCluster: false).GetAwaiter().GetResult();
                }
            }
            catch (FileNotFoundException ex)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPAPackageFileNotFound, ex.ToString());
                return(false);
            }
            catch (ValidationException ex)
            {
                SFDeployerTrace.WriteError(StringResources.Error_BPAModelSettingsValidationFailed, ex.GetMessage(System.Globalization.CultureInfo.InvariantCulture));
                if (throwIfError)
                {
                    throw;
                }

                return(false);
            }

            return(true);
        }
Esempio n. 3
0
        internal static void UpdateStandAloneClusterForRemoveNode(string targetJsonFilePath, StandAloneCluster existingCluster)
        {
            StandAloneInstallerJsonModelBase targetJsonConfig = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(Path.Combine(Utility.TestDirectory, targetJsonFilePath));
            StandaloneSettingsValidator      validator        = new StandaloneSettingsValidator(targetJsonConfig);

            existingCluster.TargetCsmConfig = validator.ClusterProperties;
            existingCluster.Topology        = validator.Topology;
            List <NodeStatus> nodeStatus = new List <NodeStatus>();

            foreach (var node in existingCluster.Current.NodeConfig.NodesStatus)
            {
                NodeStatus ns = new NodeStatus();
                ns.NodeName  = node.NodeName;
                ns.NodeState = targetJsonConfig.Nodes.Select(n => n.NodeName).Contains(node.NodeName) ? NodeState.Enabled : NodeState.Removed;
                ns.NodeDeactivationIntent = targetJsonConfig.Nodes.Select(n => n.NodeName).Contains(node.NodeName) ? WrpNodeDeactivationIntent.Invalid : WrpNodeDeactivationIntent.RemoveNode;
                ns.NodeType   = node.NodeType;
                ns.InstanceId = 0;
                nodeStatus.Add(ns);
            }

            existingCluster.TargetNodeConfig = new ClusterNodeConfig
            {
                NodesStatus = nodeStatus,
                Version     = 3
            };
        }
Esempio n. 4
0
        public void ConstructorTest()
        {
            StandAloneInstallerJsonModelBase jsonConfig;

            jsonConfig = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(Path.Combine(Utility.TestDirectory, TestFiles.GAv1));
            Assert.IsInstanceOfType(jsonConfig, typeof(StandAloneInstallerJsonModelGA));

            jsonConfig = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(Path.Combine(Utility.TestDirectory, TestFiles.Jan2017v1));
            Assert.IsInstanceOfType(jsonConfig, typeof(StandAloneInstallerJSONModelJan2017));

            this.AddonConstructorTest(TestFiles.April2017HasAddon, new AddonFeature[] { AddonFeature.RepairManager, AddonFeature.DnsService }, typeof(StandAloneInstallerJSONModelApril2017));
            this.AddonConstructorTest(TestFiles.April2017NoAddon, new AddonFeature[0], typeof(StandAloneInstallerJSONModelApril2017));
            this.AddonConstructorTest(TestFiles.April2017HasUnsupportedAddon, new AddonFeature[0], typeof(StandAloneInstallerJSONModelApril2017), expectError: true);

            this.AddonConstructorTest(TestFiles.May2017HasAddon, new AddonFeature[] { AddonFeature.RepairManager, AddonFeature.DnsService }, typeof(StandAloneInstallerJSONModelMay2017));
            this.AddonConstructorTest(TestFiles.May2017NoAddon, new AddonFeature[0], typeof(StandAloneInstallerJSONModelMay2017));
            this.AddonConstructorTest(TestFiles.May2017HasUnsupportedAddon, new AddonFeature[0], typeof(StandAloneInstallerJSONModelMay2017), expectError: true);

            this.AddonConstructorTest(TestFiles.Aug2017HasAddon, new AddonFeature[] { AddonFeature.RepairManager, AddonFeature.DnsService, AddonFeature.BackupRestoreService }, typeof(StandAloneInstallerJSONModelAugust2017));
            this.AddonConstructorTest(TestFiles.Aug2017NoAddon, new AddonFeature[0], typeof(StandAloneInstallerJSONModelAugust2017));
            this.AddonConstructorTest(TestFiles.Aug2017HasUnsupportedAddon, new AddonFeature[0], typeof(StandAloneInstallerJSONModelAugust2017), expectError: true);

            this.AddonConstructorTest(TestFiles.Oct2017HasAddon, new AddonFeature[] { AddonFeature.RepairManager, AddonFeature.DnsService, AddonFeature.BackupRestoreService }, typeof(StandAloneInstallerJSONModelOctober2017));
            this.AddonConstructorTest(TestFiles.Oct2017NoAddon, new AddonFeature[0], typeof(StandAloneInstallerJSONModelOctober2017));
            this.AddonConstructorTest(TestFiles.Oct2017HasUnsupportedAddon, new AddonFeature[0], typeof(StandAloneInstallerJSONModelOctober2017), expectError: true);
        }
        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);
            }
        }
        internal static async Task ValidateModel(StandAloneInstallerJsonModelBase targetJsonConfig, StandaloneSettingsValidator validator, StandAloneCluster cluster, bool validateUpgrade)
        {
            BestPracticesAnalyzer.IsJsonConfigModelValid(targetJsonConfig, oldConfig: null, validateDownNodes: false, throwIfError: true);

            if (validateUpgrade)
            {
                await validator.ValidateUpdateFrom(cluster.Current.CSMConfig, cluster.Topology, connectedToCluster : true).ConfigureAwait(false);
            }
        }
Esempio n. 7
0
        public void DeploymentManagerTest_DefaultUosConfigValuesMultibox()
        {
            string clusterConfigPath = Path.Combine(BaseDir, JsonConfigMultiboxFilename);

            Assert.IsTrue(File.Exists(clusterConfigPath), string.Format("Config file {0} did not exist.", clusterConfigPath));
            var configModel = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(clusterConfigPath);
            var userConfig  = configModel.GetUserConfig();

            Assert.IsTrue(userConfig.AutoupgradeEnabled == true, "Multibox AutoupgradeEnabled should be defaulted to false.");
        }
Esempio n. 8
0
        public void DeploymentManagerTest_ValidateJsonConfigCodeUpgradeJune2018()
        {
            string clusterConfigPath = Path.Combine(BaseDir, JsonConfigCodeUpgradeJune2018Filename);
            var    configModel       = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(clusterConfigPath);

            Assert.IsTrue(File.Exists(clusterConfigPath), string.Format("Config file {0} did not exist.", clusterConfigPath));
            Assert.IsNotNull(configModel, "JSON config was invalid.");

            var userConfig = configModel.GetUserConfig();

            Assert.IsTrue(userConfig.CodeVersion == "5.5.0.0", "Code version should be 5.5.0.0.");
        }
Esempio n. 9
0
        protected void NewCluster(string clusterConfigurationFilePath, string fabricPackageSourcePath, bool noCleanupOnFailure, bool force, int maxPercentFailedNodes, uint timeoutInSeconds)
        {
            this.ChangeCurrentDirectoryToSession();
            clusterConfigurationFilePath = this.GetAbsolutePath(clusterConfigurationFilePath);
            fabricPackageSourcePath      = this.GetAbsolutePath(fabricPackageSourcePath);

            ClusterCreationOptions creationOptions = ClusterCreationOptions.None;

            if (noCleanupOnFailure)
            {
                creationOptions |= ClusterCreationOptions.OptOutCleanupOnFailure;
            }

            if (force)
            {
                creationOptions |= ClusterCreationOptions.Force;
            }

            TimeSpan?timeout = null;

            if (timeoutInSeconds > 0)
            {
                timeout = TimeSpan.FromSeconds(timeoutInSeconds);
            }

            try
            {
                this.WriteObject(StringResources.Info_CreatingServiceFabricCluster);
                this.WriteObject(StringResources.Info_CreatingServiceFabricClusterDebugDetails);
                DeploymentManager.CreateClusterAsync(
                    clusterConfigurationFilePath,
                    fabricPackageSourcePath,
                    creationOptions,
                    maxPercentFailedNodes,
                    timeout).Wait();

                var standAloneModel = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(clusterConfigurationFilePath);
                var node            = standAloneModel.Nodes[0];
                var nodeType        = standAloneModel.GetUserConfig().NodeTypes.Find(type => type.Name == node.NodeTypeRef);
                this.WriteObject(string.Format(StringResources.Info_CreateServiceFabricClusterSucceeded, node.IPAddress, nodeType.ClientConnectionEndpointPort));
            }
            catch (Exception exception)
            {
                this.WriteObject(StringResources.Error_CreateServiceFabricClusterFailed);
                this.WriteObject(exception.InnerException != null ? exception.InnerException.Message : exception.Message);
                this.ThrowTerminatingError(
                    exception,
                    Constants.NewNodeConfigurationErrorId,
                    null);
            }
        }
Esempio n. 10
0
        internal static void UpdateStandAloneCluster(string targetJsonFilePath, StandAloneCluster existingCluster, bool isUserSet = false)
        {
            StandAloneInstallerJsonModelBase targetJsonConfig = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(Path.Combine(Utility.TestDirectory, targetJsonFilePath));
            StandaloneSettingsValidator      validator        = new StandaloneSettingsValidator(targetJsonConfig);

            existingCluster.TargetCsmConfig = validator.ClusterProperties;
            existingCluster.Topology        = validator.Topology;

            if (!string.IsNullOrEmpty(validator.ClusterProperties.CodeVersion))
            {
                var adminConfigVersion = new StandaloneAdminConfig(null, isUserSet);
                adminConfigVersion.Version.MsiVersion = validator.ClusterProperties.CodeVersion;
                existingCluster.TargetWrpConfig       = adminConfigVersion;
            }
        }
        internal static StandAloneCluster ConstructClusterFromJson(StandAloneInstallerJsonModelBase jsonModel, FabricNativeConfigStore configStore)
        {
            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Creating userconfig, cluster topology, adminconfig.");

            var userConfig      = jsonModel.GetUserConfig();
            var clusterTopology = jsonModel.GetClusterTopology();
            var adminConfig     = new StandaloneAdminConfig();
            var logger          = new StandAloneTraceLogger("StandAloneDeploymentManager");

            UpgradeOrchestrationTrace.TraceSource.WriteInfo(TraceType, "Creating new StandAlone cluster resource.");

            var clusterId       = configStore.ReadUnencryptedString(Constants.SectionName, Constants.ClusterIdParameterName);
            var clusterResource = new StandAloneCluster(adminConfig, userConfig, clusterTopology, clusterId, logger);

            return(clusterResource);
        }
Esempio n. 12
0
        public void DeploymentManagerTest_ValidateIncorrectJsonConfig()
        {
            string jsonFilePath = Path.Combine(BaseDir, XmlManifestFilename);
            var    configModel  = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(jsonFilePath);

            Assert.IsTrue(File.Exists(jsonFilePath), string.Format("Manifest file {0} did not exist.", jsonFilePath));
            Assert.IsNull(configModel, "Cluster manifest should not have been valid JSON.");

            foreach (string fileName in unsupportedApiVersionJsonConfigFileNames)
            {
                jsonFilePath = Path.Combine(BaseDir, fileName);
                Assert.IsTrue(File.Exists(jsonFilePath));
                configModel = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(jsonFilePath);
                Assert.IsNull(configModel);
            }
        }
        private static bool ValidateCodeVersionExists(StandAloneInstallerJsonModelBase config)
        {
            var userConfig = config.GetUserConfig();

            if (!string.IsNullOrEmpty(userConfig.CodeVersion))
            {
                Version ver;
                if (userConfig.CodeVersion != DMConstants.AutoupgradeCodeVersion && !Version.TryParse(userConfig.CodeVersion, out ver))
                {
                    SFDeployerTrace.WriteError(StringResources.Error_SFCodeVersionUnsupportedForDeployment);
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 14
0
        public void DeploymentManagerTest_InvalidJsonConfigWindowsGMSAOct2017()
        {
            string clusterConfigPath = Path.Combine(BaseDir, JsonConfigWindowsGMSAInvalidOct2017Filename);
            var    configModel       = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(clusterConfigPath);

            Assert.IsTrue(File.Exists(clusterConfigPath), string.Format("Config file {0} did not exist.", clusterConfigPath));
            Assert.IsNotNull(configModel, "JSON config was invalid.");

            var settingsValidator = new StandaloneSettingsValidator(configModel);

            Utility.ValidateExpectedValidationException(
                delegate
            {
                settingsValidator.Validate(false);
            },
                ClusterManagementErrorCode.BestPracticesAnalyzerModelInvalid);
        }
Esempio n. 15
0
        internal static StandAloneCluster PopulateStandAloneClusterWithBaselineJson(string jsonFilePath)
        {
            StandAloneInstallerJsonModelBase jsonConfig = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(Path.Combine(Utility.TestDirectory, jsonFilePath));

            var userConfig      = jsonConfig.GetUserConfig();
            var clusterTopology = jsonConfig.GetClusterTopology();
            var adminConfig     = new StandaloneAdminConfig();
            var logger          = new StandAloneTraceLogger("StandAloneDeploymentManager");

            string customizedClusterId = jsonConfig.GetClusterRegistrationId();

            return(new StandAloneCluster(
                       adminConfig,
                       userConfig,
                       clusterTopology,
                       customizedClusterId ?? "acf4dc93-9b64-4504-8b6f-0b7fd052e096",
                       logger));
        }
        private async Task <string> GetCurrentJsonConfigVersionAsync(CancellationToken cancellationToken)
        {
            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
                string jsonConfigString = File.ReadAllText(jsonConfigPath);
                StandAloneInstallerJsonModelBase targetJsonConfig = StandAloneInstallerJsonModelBase.GetJsonConfigFromString(jsonConfigString);
                return(targetJsonConfig.ClusterConfigurationVersion);
            }
            else
            {
                return(cluster.Current.CSMConfig.Version.Version);
            }
        }
Esempio n. 17
0
        public void DeploymentManagerTest_ValidateJsonConfigUnsecureJan2017()
        {
            string clusterConfigPath = Path.Combine(BaseDir, JsonConfigUnsecureJan2017Filename);
            var    configModel       = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(clusterConfigPath);

            Assert.IsTrue(File.Exists(clusterConfigPath), string.Format("Config file {0} did not exist.", clusterConfigPath));
            Assert.IsNotNull(configModel, "JSON config was invalid.");

            var userConfig = configModel.GetUserConfig();

            Assert.IsNull(userConfig.Security, "Security must be null.");

            var clusterTopology = configModel.GetClusterTopology();

            Assert.IsNotNull(clusterTopology.Nodes);
            Assert.IsNotNull(clusterTopology.Machines);
            Assert.IsTrue(clusterTopology.Nodes.Count > 0, "Cluster JSON config was not written correctly. Nodes missing.");
            Assert.IsTrue(clusterTopology.Machines.Count > 0, "Cluster JSON config was not written correctly. Machines missing.");
        }
        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);
        }
Esempio n. 19
0
        public void DeploymentManagerTest_ValidateJsonConfigWindowsSecureGA()
        {
            string clusterConfigPath = Path.Combine(BaseDir, JsonConfigWindowsSecureGAFilename);
            var    configModel       = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(clusterConfigPath);

            Assert.IsTrue(File.Exists(clusterConfigPath), string.Format("Config file {0} did not exist.", clusterConfigPath));
            Assert.IsNotNull(configModel, "JSON config was invalid.");

            var userConfig = configModel.GetUserConfig();

            Assert.IsNotNull(userConfig.Security.WindowsIdentities, "Windows Identities should be provided.");
            Assert.IsNotNull(userConfig.Security.ClusterCredentialType == Microsoft.ServiceFabric.ClusterManagementCommon.CredentialType.Windows, "ClusterCredentialType must be Windows.");

            var clusterTopology = configModel.GetClusterTopology();

            Assert.IsNotNull(clusterTopology.Nodes);
            Assert.IsNotNull(clusterTopology.Machines);
            Assert.IsTrue(clusterTopology.Nodes.Count > 0, "Cluster JSON config was not written correctly. Nodes missing.");
            Assert.IsTrue(clusterTopology.Machines.Count > 0, "Cluster JSON config was not written correctly. Machines missing.");
        }
Esempio n. 20
0
        public void DeploymentManagerTest_ValidateJsonConfigX509SecureJan2017()
        {
            string clusterConfigPath = Path.Combine(BaseDir, JsonConfigX509SecureJan2017Filename);
            var    configModel       = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(clusterConfigPath);

            Assert.IsTrue(File.Exists(clusterConfigPath), string.Format("Config file {0} did not exist.", clusterConfigPath));
            Assert.IsNotNull(configModel, "JSON config was invalid.");

            var userConfig = configModel.GetUserConfig();

            Assert.IsNotNull(userConfig.Security.CertificateInformation, "X509 Certificate information must not be null");
            Assert.IsNotNull(userConfig.Security.ClusterCredentialType == Microsoft.ServiceFabric.ClusterManagementCommon.CredentialType.X509, "ClusterCredentialType must be X509.");

            var clusterTopology = configModel.GetClusterTopology();

            Assert.IsNotNull(clusterTopology.Nodes);
            Assert.IsNotNull(clusterTopology.Machines);
            Assert.IsTrue(clusterTopology.Nodes.Count > 0, "Cluster JSON config was not written correctly. Nodes missing.");
            Assert.IsTrue(clusterTopology.Machines.Count > 0, "Cluster JSON config was not written correctly. Machines missing.");
        }
Esempio n. 21
0
        public void DeploymentManagerTest_ValidateJsonConfigNodeTypePortCollision()
        {
            string jsonFilePath = Path.Combine(BaseDir, JsonConfigUnsecureGAFilename);
            var    configModel  = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(jsonFilePath);

            Assert.IsTrue(File.Exists(jsonFilePath), string.Format("Config file {0} did not exist.", jsonFilePath));
            configModel.ValidateModel();

            foreach (string fileName in portCollissionJsonConfigFileNames)
            {
                jsonFilePath = Path.Combine(BaseDir, fileName);
                Assert.IsTrue(File.Exists(jsonFilePath), string.Format("Config file {0} did not exist.", jsonFilePath));
                configModel = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(jsonFilePath);

                Utility.ValidateExpectedValidationException(
                    delegate
                {
                    configModel.ValidateModel();
                },
                    ClusterManagementErrorCode.BestPracticesAnalyzerModelInvalid);
            }
        }
Esempio n. 22
0
        public void DeploymentManagerTest_ValidateJsonConfigIssuerCertStoreOctober2017()
        {
            string clusterConfigPath = Path.Combine(BaseDir, JsonConfigX509SecureIssuerCNOct2017Filename);
            var    configModel       = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(clusterConfigPath);

            Assert.IsTrue(File.Exists(clusterConfigPath), string.Format("Config file {0} did not exist.", clusterConfigPath));
            Assert.IsNotNull(configModel, "JSON config was invalid.");

            var userConfig = configModel.GetUserConfig();

            Assert.IsTrue(userConfig.Security.CertificateInformation.ClusterCertificateIssuerStores.Count() == 2, "ClusterCertificateIssuerStore count should be 2.");
            Assert.IsTrue(userConfig.Security.CertificateInformation.ServerCertificateIssuerStores.Count() == 1, "ServerCertificateIssuerStore count should be 1.");
            Assert.IsTrue(userConfig.Security.CertificateInformation.ClientCertificateIssuerStores.Count() == 1, "ClientCertificateIssuerStore count should be 1.");

            var clusterResource = DeploymentManagerInternal.GetClusterResource(clusterConfigPath, System.Guid.NewGuid().ToString());
            var cm = clusterResource.Current.ExternalState.ClusterManifest;
            var clusterCertificateIssuerStore = cm.FabricSettings.ToList().Where(section => section.Name == StringConstants.SectionName.SecurityClusterCertificateIssuerStores).ToList();

            Assert.IsTrue(clusterCertificateIssuerStore.Count() == 1, "clusterCertificateIssuerStore count should be 1");
            Assert.IsTrue(clusterCertificateIssuerStore[0].Parameter.ToList().Count == 2, "clusterCertificateIssuerStore parameter count should be 2");
            Assert.AreEqual(clusterCertificateIssuerStore[0].Parameter[0].Name, "");
            Assert.AreEqual(clusterCertificateIssuerStore[0].Parameter[0].Value, "My");
            Assert.AreEqual(clusterCertificateIssuerStore[0].Parameter[1].Name, "ClusterIssuer");
            Assert.AreEqual(clusterCertificateIssuerStore[0].Parameter[1].Value, "My, Root");

            var serverCertificateIssuerStore = cm.FabricSettings.ToList().Where(section => section.Name == StringConstants.SectionName.SecurityServerCertificateIssuerStores).ToList();

            Assert.IsTrue(serverCertificateIssuerStore.Count() == 1, "serverCertificateIssuerStore count should be 1");
            Assert.IsTrue(serverCertificateIssuerStore[0].Parameter.ToList().Count == 1, "serverCertificateIssuerStore parameter count should be 1");
            Assert.AreEqual(serverCertificateIssuerStore[0].Parameter[0].Name, "ServerIssuer");
            Assert.AreEqual(serverCertificateIssuerStore[0].Parameter[0].Value, "My");

            var clientCertificateIssuerStore = cm.FabricSettings.ToList().Where(section => section.Name == StringConstants.SectionName.SecurityClientCertificateIssuerStores).ToList();

            Assert.IsTrue(clientCertificateIssuerStore.Count() == 1, "clientCertificateIssuerStore count should be 1");
            Assert.IsTrue(clientCertificateIssuerStore[0].Parameter.ToList().Count == 1, "clientCertificateIssuerStore parameter count should be 1");
            Assert.AreEqual(clientCertificateIssuerStore[0].Parameter[0].Name, "ClientIssuer");
            Assert.AreEqual(clientCertificateIssuerStore[0].Parameter[0].Value, "My");
        }
Esempio n. 23
0
        private void AddonConstructorTest(string jsonFile, AddonFeature[] expectedAddonFeatures, Type modelType, bool expectError = false)
        {
            StandAloneInstallerJsonModelBase jsonConfig;

            try
            {
                jsonConfig = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(Path.Combine(Utility.TestDirectory, jsonFile));
                if (expectError)
                {
                    if (jsonConfig != null)
                    {
                        throw new Exception("test failure");
                    }
                    else
                    {
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                if (!expectError)
                {
                    throw new Exception("test failure", ex);
                }

                return;
            }

            bool isAprilModel = jsonConfig.GetType() == typeof(StandAloneInstallerJSONModelApril2017);
            bool isMayModel   = jsonConfig.GetType() == typeof(StandAloneInstallerJSONModelMay2017);
            bool isAugModel   = jsonConfig.GetType() == typeof(StandAloneInstallerJSONModelAugust2017);
            bool isOctModel   = jsonConfig.GetType() == typeof(StandAloneInstallerJSONModelOctober2017);

            PropertyApril2017   aprilProperty = null;
            PropertyMay2017     mayProperty   = null;
            PropertyAugust2017  augProperty   = null;
            PropertyOctober2017 octProperty   = null;

            // deserialization test
            Assert.IsInstanceOfType(jsonConfig, modelType);

            if (isAprilModel)
            {
                aprilProperty = (PropertyApril2017)((StandAloneInstallerJSONModelApril2017)jsonConfig).Properties;
                Assert.AreEqual(expectedAddonFeatures.Length, aprilProperty.AddonFeatures.Count);
                Assert.IsTrue(aprilProperty.AddonFeatures.All(p => expectedAddonFeatures.Contains(p)));
                Assert.IsTrue(expectedAddonFeatures.All(p => aprilProperty.AddonFeatures.Contains(p)));
                Assert.IsNull(aprilProperty.TestHookReliabilityLevel);
            }
            else if (isMayModel)
            {
                mayProperty = (PropertyMay2017)((StandAloneInstallerJSONModelMay2017)jsonConfig).Properties;
                Assert.AreEqual(expectedAddonFeatures.Length, mayProperty.AddonFeatures.Count);
                Assert.IsTrue(mayProperty.AddonFeatures.All(p => expectedAddonFeatures.Contains(p)));
                Assert.IsTrue(expectedAddonFeatures.All(p => mayProperty.AddonFeatures.Contains(p)));
                Assert.IsNull(mayProperty.TestHookReliabilityLevel);
            }
            else if (isAugModel)
            {
                augProperty = (PropertyAugust2017)((StandAloneInstallerJSONModelAugust2017)jsonConfig).Properties;
                Assert.AreEqual(expectedAddonFeatures.Length, augProperty.AddonFeatures.Count);
                Assert.IsTrue(augProperty.AddonFeatures.All(p => expectedAddonFeatures.Contains(p)));
                Assert.IsTrue(expectedAddonFeatures.All(p => augProperty.AddonFeatures.Contains(p)));
                Assert.IsNull(augProperty.TestHookReliabilityLevel);
            }
            else if (isOctModel)
            {
                octProperty = (PropertyOctober2017)((StandAloneInstallerJSONModelOctober2017)jsonConfig).Properties;
                Assert.AreEqual(expectedAddonFeatures.Length, octProperty.AddonFeatures.Count);
                Assert.IsTrue(octProperty.AddonFeatures.All(p => expectedAddonFeatures.Contains(p)));
                Assert.IsTrue(expectedAddonFeatures.All(p => octProperty.AddonFeatures.Contains(p)));
                Assert.IsNull(octProperty.TestHookReliabilityLevel);
            }

            // serialization test
            string newJsonFilePath = Path.Combine(Utility.TestDirectory, "AddonFeatureTestTmpJson.json");

            File.WriteAllText(newJsonFilePath, JsonConvert.SerializeObject(jsonConfig, new JsonSerializerSettings()
            {
                DefaultValueHandling       = DefaultValueHandling.Populate,
                PreserveReferencesHandling = PreserveReferencesHandling.None
            }));
            StandAloneInstallerJsonModelBase newJsonConfig = StandAloneInstallerJsonModelBase.GetJsonConfigFromFile(newJsonFilePath);

            File.Delete(newJsonFilePath);

            if (isAprilModel)
            {
                PropertyApril2017 newAprilProperty = (PropertyApril2017)((StandAloneInstallerJSONModelApril2017)newJsonConfig).Properties;
                Assert.AreEqual(aprilProperty.AddonFeatures.Count, newAprilProperty.AddonFeatures.Count);
            }
            else if (isMayModel)
            {
                PropertyMay2017 newMayProperty = (PropertyMay2017)((StandAloneInstallerJSONModelMay2017)newJsonConfig).Properties;
                Assert.AreEqual(mayProperty.AddonFeatures.Count, newMayProperty.AddonFeatures.Count);
            }
            else if (isAugModel)
            {
                PropertyAugust2017 newAugProperty = (PropertyAugust2017)((StandAloneInstallerJSONModelAugust2017)newJsonConfig).Properties;
                Assert.AreEqual(augProperty.AddonFeatures.Count, newAugProperty.AddonFeatures.Count);
            }
            else if (isOctModel)
            {
                PropertyOctober2017 newOctProperty = (PropertyOctober2017)((StandAloneInstallerJSONModelOctober2017)newJsonConfig).Properties;
                Assert.AreEqual(octProperty.AddonFeatures.Count, newOctProperty.AddonFeatures.Count);
            }
        }
        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 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);
        }