private void ValidateNodeList() { if (this.infrastructureInformation == null) { FabricValidator.TraceSource.WriteWarning( FabricValidatorUtility.TraceTag, "Skipping node list validation as it is empty"); return; } //Validate StartPort and EndPort number and range if (clusterManifest.Infrastructure.Item is ClusterManifestTypeInfrastructureWindowsAzure) { foreach (InfrastructureNodeType infra in this.infrastructureInformation) { try { if (infra.Endpoints.ApplicationEndpoints.StartPort < 0 || infra.Endpoints.ApplicationEndpoints.EndPort < 0) { throw new ArgumentException( string.Format( StringResources.Warning_FabricValidatorStartEndPortNegative, infra.NodeName)); } if (infra.Endpoints.ApplicationEndpoints.StartPort > infra.Endpoints.ApplicationEndpoints.EndPort) { throw new ArgumentException( string.Format( StringResources.Warning_FabricValidatorPortRangeInvalid, infra.NodeName)); } //Validate the other five ports ValidateEndpointsPortsHelper(infra.Endpoints.ClientConnectionEndpoint.Port, infra.NodeName, "ClientConnectionEndpoint"); ValidateEndpointsPortsHelper(infra.Endpoints.LeaseDriverEndpoint.Port, infra.NodeName, "LeaseDriverEndpoint"); ValidateEndpointsPortsHelper(infra.Endpoints.ClusterConnectionEndpoint.Port, infra.NodeName, "ClusterConnectionEndpoint"); ValidateEndpointsPortsHelper(infra.Endpoints.HttpGatewayEndpoint.Port, infra.NodeName, "HttpGatewayEndpoint"); // TODO add validation for http app gateway endpoint // ValidateEndpointsPortsHelper(infra.Endpoints.HttpApplicationGatewayEndpoint.Port, infra.NodeName, "HttpApplicationGatewayEndpoint"); ValidateEndpointsPortsHelper(infra.Endpoints.ServiceConnectionEndpoint.Port, infra.NodeName, "ServiceConnectionEndpoint"); } catch (NullReferenceException) { FabricValidator.TraceSource.WriteWarning( FabricValidatorUtility.TraceTag, StringResources.Info_FabricValidatorPortsNull); return; } } } #if DotNetCoreClrLinux var isServer = clusterManifest.Infrastructure.Item is ClusterManifestTypeInfrastructureLinux; #else var isServer = clusterManifest.Infrastructure.Item is ClusterManifestTypeInfrastructureWindowsServer; #endif if (isServer || clusterManifest.Infrastructure.Item is ClusterManifestTypeInfrastructureWindowsAzureStaticTopology) { foreach (InfrastructureNodeType infra in this.infrastructureInformation) { if (Helpers.isIPV6AddressAndNoBracket(infra.IPAddressOrFQDN)) { throw new ArgumentException(StringResources.Error_BracketsAroundIPV6AddressAreMandatory, infra.NodeName); } } } int voteCount = this.NonSeedVoteCount; ClusterManifestTypeInfrastructurePaaS paasInfrastructure = clusterManifest.Infrastructure.Item as ClusterManifestTypeInfrastructurePaaS; if (paasInfrastructure != null) { voteCount += paasInfrastructure.Votes.Count(); } bool matchingLocalNodeFound = false; string prevMachine = this.infrastructureInformation[0].IPAddressOrFQDN; if (this.IsScaleMin && !NetworkApiHelper.IsNodeForThisMachine(this.infrastructureInformation[0])) { this.DoMachineAndNodeHaveSameIPInScaleMin = false; } bool hasLoopbackAddressDefined = false; HashSet <string> nodeNameDuplicateDetector = new HashSet <string>(); List <string> faultDomains = new List <string>(); foreach (InfrastructureNodeType fabricNode in this.infrastructureInformation) { ClusterManifestTypeNodeType nodeType = this.clusterManifest.NodeTypes.FirstOrDefault(nodeTypeVar => FabricValidatorUtility.EqualsIgnoreCase(nodeTypeVar.Name, fabricNode.NodeTypeRef)); if (nodeType == null) { if (!(this.DeploymentOperation == DeploymentOperations.Update && this.clusterManifest.Infrastructure.Item is ClusterManifestTypeInfrastructurePaaS)) { throw new ArgumentException( string.Format( "Node '{0}' has attribute NodeTypeRef='{1}'. However, no NodeType with name {1} exists.", fabricNode.NodeName, fabricNode.NodeTypeRef)); } } if (fabricNode.IsSeedNode) { voteCount++; } faultDomains.Add(fabricNode.FaultDomain); if (!FabricValidatorUtility.IsValidFileName(fabricNode.NodeName)) { throw new ArgumentException( string.Format( "Invalid character found in node name {0}. Node name should be a valid file name.", fabricNode.NodeName)); } if (!FabricValidatorUtility.IsValidIPAddressOrFQDN(fabricNode.IPAddressOrFQDN)) { throw new ArgumentException( string.Format( "Malformed IPAddressOrFQDN found {0}.", fabricNode.IPAddressOrFQDN)); } if (nodeNameDuplicateDetector.Contains(fabricNode.NodeName)) { throw new ArgumentException( string.Format( "Duplicate node name {0} found.", fabricNode.NodeName)); } else { nodeNameDuplicateDetector.Add(fabricNode.NodeName); } if (fabricNode.IPAddressOrFQDN != prevMachine && !FabricValidatorUtility.IsNodeAddressLoopback(fabricNode)) { this.IsSingleMachineDeployment = false; } if (!hasLoopbackAddressDefined) { hasLoopbackAddressDefined = FabricValidatorUtility.IsNodeAddressLoopback(fabricNode); } FabricValidator.TraceSource.WriteNoise( FabricValidatorUtility.TraceTag, "fabricNode is {0}", fabricNode); if (!FabricValidatorUtility.IsNodeForThisMachine(fabricNode)) { continue; } if (matchingLocalNodeFound && !this.IsScaleMin) { throw new ArgumentException( string.Format( "The IPAddressorFQDN value in node '{0}' is {1}. Another node is also configured to run on the same machine. " + "Running multiple nodes on the same machine is not valid in the specified infrastructure.", fabricNode.NodeName, fabricNode.IPAddressOrFQDN)); } else { matchingLocalNodeFound = true; FabricValidatorUtility.ValidateDomainUri(fabricNode.FaultDomain, fabricNode.NodeName); } } int fdPathCount = -1; foreach (string faultDomain in faultDomains) { if (!string.IsNullOrEmpty(faultDomain)) { int currentfdPathCount = faultDomain.Split('/').Length; if (fdPathCount == -1) { fdPathCount = currentfdPathCount; } if (fdPathCount != currentfdPathCount) { throw new ArgumentException("All FaultDomains should have the same depth."); } } } if (!matchingLocalNodeFound) { FabricValidator.TraceSource.WriteWarning( FabricValidatorUtility.TraceTag, "None of the declared nodes is for the current machine."); } if (!this.IsSingleMachineDeployment && hasLoopbackAddressDefined) { throw new ArgumentException("Even though the deployment is split over multiple machines there is at least one node with a loopback address"); } if (voteCount == 0) { throw new ArgumentException("No votes specified. Either seed nodes or sql vote specification is required for cluster to bootstrap"); } if (!this.DoMachineAndNodeHaveSameIPInScaleMin) { FabricValidator.TraceSource.WriteWarning( FabricValidatorUtility.TraceTag, StringResources.Warning_FirstNodeAndMachineHaveDifferentIP); return; } }
public ServerInfrastructure(ClusterManifestTypeInfrastructure cmInfrastructure, InfrastructureNodeType[] infrastructureNodes, Dictionary <string, ClusterManifestTypeNodeType> nameToNodeTypeMap) { this.votes = new List <SettingsTypeSectionParameter>(); this.seedNodeClientConnectionAddresses = new List <SettingsTypeSectionParameter>(); this.nodes = new List <InfrastructureNodeType>(); #if DotNetCoreClrLinux var infrastructure = cmInfrastructure.Item as ClusterManifestTypeInfrastructureLinux; #else var infrastructure = cmInfrastructure.Item as ClusterManifestTypeInfrastructureWindowsServer; #endif foreach (var nodeInfo in infrastructure.NodeList) { if (!nameToNodeTypeMap.ContainsKey(nodeInfo.NodeTypeRef)) { throw new ArgumentException( string.Format(CultureInfo.InvariantCulture, "Node {0} has NodeType {1}, which is not present in node types definition", nodeInfo.NodeName, nodeInfo.NodeTypeRef)); } var nodeType = nameToNodeTypeMap[nodeInfo.NodeTypeRef]; var node = (new InfrastructureNodeType() { Certificates = nodeType.Certificates, Endpoints = nodeType.Endpoints, FaultDomain = nodeInfo.FaultDomain, IPAddressOrFQDN = Helpers.isIPV6AddressAndNoBracket(nodeInfo.IPAddressOrFQDN) ? Helpers.AddBracketsAroundIPV6(nodeInfo.IPAddressOrFQDN) : nodeInfo.IPAddressOrFQDN, IsSeedNode = nodeInfo.IsSeedNode, NodeName = nodeInfo.NodeName, NodeTypeRef = nodeInfo.NodeTypeRef, RoleOrTierName = nodeInfo.NodeTypeRef, UpgradeDomain = nodeInfo.UpgradeDomain }); this.nodes.Add(node); if (node.IsSeedNode) { string key = node.NodeName; string connectionAddress = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", node.IPAddressOrFQDN, node.Endpoints.ClusterConnectionEndpoint.Port); string value = string.Format(CultureInfo.InvariantCulture, "{0},{1}", "SeedNode", connectionAddress); this.votes.Add(new SettingsTypeSectionParameter() { Name = key, Value = value, MustOverride = false }); FabricValidator.TraceSource.WriteNoise(FabricValidatorUtility.TraceTag, "Vote {0}-{1} added", key, value); string clientConnectionAddress = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", node.IPAddressOrFQDN, node.Endpoints.ClientConnectionEndpoint.Port); this.seedNodeClientConnectionAddresses.Add(new SettingsTypeSectionParameter() { Name = key, Value = clientConnectionAddress, MustOverride = false }); FabricValidator.TraceSource.WriteNoise(FabricValidatorUtility.TraceTag, "Seed Nodes {0}-{1} added", key, clientConnectionAddress); } } if (infrastructureNodes != null) { foreach (var infraNode in infrastructureNodes) { /* If the current machine node name is present in the infrastructure manifest but not present in the cluster manifest, then * it should be added back to this.nodes */ if (this.nodes.Find(node => infraNode.NodeName == node.NodeName) == null && NetworkApiHelper.IsNodeForThisMachine(infraNode)) { this.nodes.Add(infraNode); } } } this.isScaleMin = infrastructure.IsScaleMin; }